|
@@ -1,29 +1,66 @@
|
|
|
<!-- 商品详情 -->
|
|
|
<template>
|
|
|
- <div class="default-width py-5" v-if="goodsInfo && Object.keys(goodsInfo).length">
|
|
|
- <v-card class="carousel border-radius-8 white-bgc pa-5 d-flex" style="width: 100%;">
|
|
|
- <!-- 图片展示-轮播 -->
|
|
|
- <div style="width: 500px; height: 500px;">
|
|
|
- <v-carousel show-arrows="hover" cycle :model-value="0" :hide-delimiters="!carouselHover" @mouseover="carouselHover = true" @mouseleave="carouselHover = false">
|
|
|
- <v-carousel-item v-for="(imgUrl, i) in goodsInfo.sliderPicUrls" :key="'wareImg'+i" @click="null">
|
|
|
- <v-img :src="imgUrl" :aspect-ratio="1" style="border-radius: 8px;"></v-img>
|
|
|
- </v-carousel-item>
|
|
|
- </v-carousel>
|
|
|
+ <div class="default-width py-5" v-if="state.goodsInfo && Object.keys(state.goodsInfo).length">
|
|
|
+ <v-card class="carousel border-radius-8 white-bgc pa-5" style="width: 100%;">
|
|
|
+ <div class=" d-flex">
|
|
|
+ <!-- 图片展示-轮播 -->
|
|
|
+ <div style="width: 500px; height: 500px;">
|
|
|
+ <div v-if="selectedSkuPicUrl" class="selectedSkuImgBox" @mouseover="showSelectedSkuImg = true" @mouseleave="showSelectedSkuImg = false">
|
|
|
+ <v-img :src="selectedSkuPicUrl" :aspect-ratio="1" style="border-radius: 8px;"></v-img>
|
|
|
+ <v-btn
|
|
|
+ v-show="showSelectedSkuImg"
|
|
|
+ size="x-small"
|
|
|
+ class="close px-3"
|
|
|
+ :disabled="inputValue <= min || disabled"
|
|
|
+ @click="selectedSkuPicUrl = ''"
|
|
|
+ >关闭</v-btn>
|
|
|
+ </div>
|
|
|
+ <v-carousel v-else show-arrows="hover" cycle :model-value="0" :hide-delimiters="!carouselHover" @mouseover="carouselHover = true" @mouseleave="carouselHover = false">
|
|
|
+ <v-carousel-item v-for="(imgUrl, i) in state.goodsInfo.sliderPicUrls" :key="'wareImg'+i" @click="null">
|
|
|
+ <v-img :src="imgUrl" :aspect-ratio="1" style="border-radius: 8px;"></v-img>
|
|
|
+ </v-carousel-item>
|
|
|
+ </v-carousel>
|
|
|
+ </div>
|
|
|
+ <!-- s-select-sku 商品属性选择 -->
|
|
|
+ <div style="flex: 1;" class="pl-10">
|
|
|
+ <!-- 大标题 -->
|
|
|
+ <div class="title-name">{{ state.goodsInfo?.name || '--' }}</div>
|
|
|
+ <!-- 小标题 -->
|
|
|
+ <div class="title-introduction">{{ state.goodsInfo?.introduction || '--' }}</div>
|
|
|
+ <!-- 价格 -->
|
|
|
+ <div class="prices my-5">
|
|
|
+ <div class="price mr-3"><span>¥</span>{{ selectedSkuPrice}}</div>
|
|
|
+ <div class="marketPrice" v-if="state.goodsInfo?.marketPrice">{{ selectedSkuMarketPrice}}</div>
|
|
|
+ </div>
|
|
|
+ <!-- 销量 -->
|
|
|
+ <div class="salesCount mb-5 parameterColor"><span class="l-s-10">已售</span>:{{ state.goodsInfo?.salesCount || 0 }}</div>
|
|
|
+ <!-- 属性选择组件 -->
|
|
|
+ <selectSku
|
|
|
+ v-if="showSelectSku"
|
|
|
+ class="mb-7"
|
|
|
+ :goodsInfo="state.goodsInfo"
|
|
|
+ @change="onSkuChange"
|
|
|
+ @buy="onBuy"
|
|
|
+ ></selectSku>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <div style="flex: 1;" class="pl-10">
|
|
|
- <!-- 大标题 -->
|
|
|
- <div class="title-name">{{ goodsInfo?.name || '--' }}</div>
|
|
|
- <!-- 小标题 -->
|
|
|
- <div class="title-introduction">{{ goodsInfo?.introduction || '--' }}</div>
|
|
|
- <!-- 价格 -->
|
|
|
- <div class="prices my-5">
|
|
|
- <div class="price mr-3"><span>¥</span>{{ calcPrice(goodsInfo?.price)}}</div>
|
|
|
- <div class="marketPrice" v-if="goodsInfo?.marketPrice">{{ calcPrice(goodsInfo?.marketPrice)}}</div>
|
|
|
+ </v-card>
|
|
|
+ <!-- 详情描述 detail-content-card -->
|
|
|
+ <v-card class="carousel border-radius-8 white-bgc pa-5 mt-3" style="width: 100%;">
|
|
|
+ <!-- <div class="resume-header">
|
|
|
+ <div class="resume-title">
|
|
|
+ 详情
|
|
|
</div>
|
|
|
- <!-- 销量 -->
|
|
|
- <div class="salesCount mb-5 parameterColor"><span class="l-s-10">已售</span>:{{ goodsInfo?.salesCount || 0 }}</div>
|
|
|
- <!-- 属性选择组件 -->
|
|
|
- <selectSku v-if="skus?.length" :goodsInfo="goodsInfo" class="mb-7"></selectSku>
|
|
|
+ </div> -->
|
|
|
+ <div>
|
|
|
+ <div class="mb-3">
|
|
|
+ <v-tabs v-model="describeTab" align-tabs="start" color="primary" bg-color="#f7f8fa" @update:model-value="null">
|
|
|
+ <v-tab :value="0">商品介绍</v-tab>
|
|
|
+ <v-tab :value="1">商品评价</v-tab>
|
|
|
+ </v-tabs>
|
|
|
+ </div>
|
|
|
+ <describe v-if="describeTab === 0 && state.goodsInfo?.description" :content="state.goodsInfo.description"></describe>
|
|
|
+ <comment v-if="describeTab === 0 && state.goodsId" class="detail-comment-selector" :goodsId="state.goodsId" />
|
|
|
</div>
|
|
|
</v-card>
|
|
|
</div>
|
|
@@ -33,26 +70,89 @@
|
|
|
defineOptions({name: 'goods-details'})
|
|
|
import { getProductDetail } from '@/api/mall'
|
|
|
import selectSku from './detailsComponents/s-select-sku.vue'
|
|
|
-import { ref } from 'vue'
|
|
|
+import describe from './detailsComponents/describe.vue'
|
|
|
+import comment from './detailsComponents/comment.vue'
|
|
|
+import { ref, reactive } from 'vue'
|
|
|
import { useRouter } from 'vue-router'
|
|
|
+import Snackbar from '@/plugins/snackbar'
|
|
|
|
|
|
const router = useRouter()
|
|
|
const { id } = router.currentRoute.value.params
|
|
|
|
|
|
+const describeTab = ref(0)
|
|
|
+const selectedSkuPicUrl = ref('')
|
|
|
+const selectedSkuPrice = ref('')
|
|
|
+const selectedSkuMarketPrice = ref('')
|
|
|
+const showSelectSku = ref(false)
|
|
|
const carouselHover = ref(false)
|
|
|
-const goodsInfo = ref({})
|
|
|
-const skus = ref([])
|
|
|
+const showSelectedSkuImg = ref(false)
|
|
|
// 获取商品详情
|
|
|
const getData = async () => {
|
|
|
const obj = await getProductDetail({ id })
|
|
|
+ if (!obj) return Snackbar.warning('未找到商品!')
|
|
|
+ //
|
|
|
+ // 加载到商品
|
|
|
obj.sliderPicUrls = obj.sliderPicUrls || []
|
|
|
- skus.value = obj.skus || []
|
|
|
- goodsInfo.value = obj
|
|
|
- // console.log('getProductDetail:', goodsInfo.value)
|
|
|
+ state.skeletonLoading = false;
|
|
|
+ state.goodsInfo = obj
|
|
|
+ showSelectSku.value = true
|
|
|
+ // // 加载是否收藏
|
|
|
+ // if (isLogin.value) {
|
|
|
+ // FavoriteApi.isFavoriteExists(state.goodsId, 'goods').then((res) => {
|
|
|
+ // if (res.code !== 0) {
|
|
|
+ // return;
|
|
|
+ // }
|
|
|
+ // state.goodsInfo.favorite = res.data;
|
|
|
+ // });
|
|
|
+ // }
|
|
|
}
|
|
|
getData()
|
|
|
|
|
|
-const calcPrice = (price) => { return price && (price-0) ? (price-0)/100 : '' }
|
|
|
+const calcPrice = (price) => { return price && (price-0) ? (price-0)/100 : '--' }
|
|
|
+
|
|
|
+const state = reactive({
|
|
|
+ goodsId: 0,
|
|
|
+ skeletonLoading: true, // SPU 加载中
|
|
|
+ goodsInfo: {}, // SPU 信息
|
|
|
+ showSelectSku: false, // 是否展示 SKU 选择弹窗
|
|
|
+ selectedSku: {}, // 选中的 SKU
|
|
|
+ settlementSku: {}, // 结算的 SKU:由于 selectedSku 不进行默认选中,所以初始使用结算价格最低的 SKU 作为基础展示
|
|
|
+ showModel: false, // 是否展示 Coupon 优惠劵的弹窗
|
|
|
+ couponInfo: [], // 可领取的 Coupon 优惠劵的列表
|
|
|
+ showActivityModel: false, // 【满减送/限时折扣】是否展示 Activity 营销活动的弹窗
|
|
|
+ rewardActivity: {}, // 【满减送】活动
|
|
|
+ activityList: [], // 【秒杀/拼团/砍价】可参与的 Activity 营销活动的列表
|
|
|
+});
|
|
|
+
|
|
|
+// 规格变更
|
|
|
+function onSkuChange(e) {
|
|
|
+ state.selectedSku = e;
|
|
|
+ state.settlementSku = e;
|
|
|
+ // console.log('onSkuChange:', e)
|
|
|
+ selectedSkuPicUrl.value = state.selectedSku?.picUrl || ''
|
|
|
+ if (selectedSkuPicUrl.value) showSelectedSkuImg.value = true
|
|
|
+ selectedSkuPrice.value = calcPrice(state.selectedSku?.price || state.goodsInfo.price)
|
|
|
+ selectedSkuMarketPrice.value = calcPrice(state.selectedSku?.marketPrice || state.goodsInfo.marketPrice)
|
|
|
+}
|
|
|
+
|
|
|
+const onBuy = async () => {
|
|
|
+ Snackbar.warning('购买功能暂未开放,敬请期待!')
|
|
|
+}
|
|
|
+// function onBuy(sku) {
|
|
|
+// sheep.$router.go('/pages/order/confirm', {
|
|
|
+// data: JSON.stringify({
|
|
|
+// order_type: 'goods',
|
|
|
+// combinationActivityId: state.activity.id,
|
|
|
+// combinationHeadId: state.combinationHeadId,
|
|
|
+// items: [
|
|
|
+// {
|
|
|
+// skuId: sku.id,
|
|
|
+// count: sku.count,
|
|
|
+// },
|
|
|
+// ],
|
|
|
+// }),
|
|
|
+// });
|
|
|
+// }
|
|
|
|
|
|
</script>
|
|
|
<style lang="scss" scoped>
|
|
@@ -93,4 +193,12 @@ const calcPrice = (price) => { return price && (price-0) ? (price-0)/100 : '' }
|
|
|
line-height: 34px;
|
|
|
text-decoration: line-through;
|
|
|
}
|
|
|
+.selectedSkuImgBox {
|
|
|
+ position: relative;
|
|
|
+ .close {
|
|
|
+ position: absolute;
|
|
|
+ bottom: 10px;
|
|
|
+ right: 10px;
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|