You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1562 lines
42 KiB
1562 lines
42 KiB
<script setup lang="ts"> |
|
import { PageQuery } from '~/types/global' |
|
import { |
|
cartAddApi, |
|
collectAddApi, |
|
collectCancelApi, |
|
productDetailApi, |
|
} from '~/server/goodsApi' |
|
import { ProductsInfo } from '~/types/goods' |
|
import useOrder from '~/composables/useOrder' |
|
import { shallowRef, watch,ref, reactive} from 'vue' |
|
const { handlerNuxtLink } = useOrder() |
|
const {getMerId} = useAppStore() |
|
|
|
const route = useRoute() |
|
const loading = ref(false) |
|
|
|
/** |
|
* 商品详情 |
|
*/ |
|
onMounted(() => { |
|
getProductDetail() |
|
}) |
|
const unique = ref('') |
|
const stock = ref(1) |
|
const count = ref(1) |
|
const couponList = ref<Array<string>>([]) |
|
const attrSelected = ref<Array<string>>([]) |
|
const productAttr = ref<Array<string>>([]) |
|
const productValue = ref({}) //规格数据 |
|
const attrValueSelected = reactive({}) //选中规格的数据 |
|
const productInfo = reactive<ProductsInfo>({}) //商品信息 |
|
const merchantInfo = reactive({}) //商户信息 |
|
const productId = Number(route.params.id) //商品id |
|
const masterProductId = ref(0) // 秒杀商品中普通商品id |
|
const sliderImage = ref<Array<string>>([]) |
|
const slideIndex = ref(0) |
|
const type = ref<string>(<string>route.query.type) |
|
const userCollect = ref(false) //是否收藏 |
|
const merId = ref(0) //店铺id |
|
const guaranteeList = ref<FromData[]>([]) //协议 |
|
const oneQuota = ref(0) // 活动单次限购 |
|
const queryParams = reactive<FromData>({ |
|
id: Number(route.params.id), |
|
type: type.value, |
|
}) |
|
const router = useRouter() |
|
const { getSeckillInfo, seckillStatus, seckillTime, replyInfo, getReplyList, productReplyConfig, replyList } = |
|
useProductDetail() //秒杀详情 |
|
const where = reactive<PageQuery>({ page: 1, limit: 10, type: 0 }) //评论列表 |
|
const getProductDetail = async () => { |
|
//loading.value = true |
|
try { |
|
const data = await productDetailApi(queryParams) |
|
if (data) Object.assign(productInfo, data.productInfo) |
|
masterProductId.value = data.masterProductId |
|
//秒杀 |
|
await getSeckillInfo(data, route.query) |
|
|
|
Object.assign(productValue, data.productValue) |
|
Object.assign(merchantInfo, data.merchantInfo) |
|
//评论数据 |
|
await productReplyConfig(masterProductId.value > 0 ? masterProductId.value : queryParams.id) |
|
//评论列表 |
|
await getReplyList(where, masterProductId.value > 0 ? masterProductId.value : queryParams.id) |
|
guaranteeList.value = data.guaranteeList ? data.guaranteeList : [] |
|
productAttr.value = data.productAttr |
|
userCollect.value = data.userCollect |
|
oneQuota.value = data.oneQuota |
|
couponList.value = data.couponList ? data.couponList : [] |
|
merId.value = data.productInfo.merId |
|
await getMerId(merId.value) |
|
let arrayImg = productInfo.sliderImage |
|
sliderImage.value = JSON.parse(arrayImg) |
|
loading.value = false |
|
} catch (e) { |
|
loading.value = false |
|
await router.back() |
|
} |
|
} |
|
|
|
//评论切换 |
|
const replyTypeChange = (type: number) => { |
|
where.type = type |
|
getReplyList(where, masterProductId.value > 0 ? masterProductId.value : queryParams.id) |
|
} |
|
const callPaginate = (num: number) => { |
|
where.page = num |
|
getReplyList(where, masterProductId.value > 0 ? masterProductId.value : queryParams.id) |
|
} |
|
|
|
//轮播 |
|
const swiperData = reactive({ |
|
spaceBetween: 14, |
|
slidesPerView: 5, |
|
boxWidth: 'w-486px', |
|
slideWidth: 'w-86px', |
|
navigationColor: 'color:#999', |
|
navigationBgColor: '' |
|
}) |
|
|
|
watch( |
|
productAttr, |
|
(newValue, oldValue) => { |
|
if (newValue) { |
|
let attr = newValue |
|
let checked = []; |
|
for (const key of Object.keys(productValue)) { |
|
if(productValue[key]){ |
|
if (productValue[key].stock > 0) { |
|
checked = attr.length ? key.split(",") : []; |
|
break; |
|
}else{ |
|
checked = attr.length ? key.split(",") : []; |
|
} |
|
} |
|
} |
|
for (let i = 0; i < checked.length; i++) { |
|
attrSelected.value[i] = checked[i] |
|
} |
|
|
|
|
|
} else { |
|
unique.value = productValue[''].unique |
|
} |
|
}, |
|
) |
|
watch( |
|
attrSelected, |
|
(newValue, oldValue) => { |
|
if (newValue) { |
|
let name = newValue.join() |
|
let checked = productValue[name] |
|
|
|
if (checked) { |
|
Object.assign(attrValueSelected, checked) |
|
stock.value = checked.stock |
|
unique.value = checked.id |
|
// this.unique = value.id; |
|
} else { |
|
Object.assign(attrValueSelected, null) |
|
stock.value = 0 |
|
unique.value = '' |
|
} |
|
} else { |
|
unique.value = productValue[''].id |
|
stock.value = productInfo.value.stock; |
|
unique.value = productValue[""].value.id |
|
} |
|
}, |
|
{ deep: true }, |
|
) |
|
watch( |
|
attrValueSelected, |
|
(newValue, oldValue) => { |
|
if (newValue) { |
|
let sliderImage = productInfo.value ? JSON.parse(productInfo.value.sliderImage) : [] |
|
sliderImage[0] = newValue.image |
|
slideIndex.value = 0 |
|
} |
|
}, |
|
{ deep: true }, |
|
) |
|
|
|
const getFileType = (fileName: string) => { |
|
//后缀获取 |
|
// let suffix = '' |
|
// 获取类型结果 |
|
let result = '' |
|
try { |
|
const flieArr = fileName.split('.') |
|
suffix = flieArr[flieArr.length - 1] |
|
} catch (err) { |
|
suffix = '' |
|
} |
|
// fileName无后缀返回 false |
|
if (!suffix) { |
|
return false |
|
} |
|
suffix = suffix.toLocaleLowerCase() |
|
// 图片格式 |
|
const imglist = ['png', 'jpg', 'jpeg', 'bmp', 'gif'] |
|
// 进行图片匹配 |
|
result = imglist.find((item) => item === suffix) |
|
if (result) { |
|
return 'image' |
|
} |
|
// 匹配 视频 |
|
const videolist = ['mp4', 'm2v', 'mkv', 'rmvb', 'wmv', 'avi', 'flv', 'mov', 'm4v'] |
|
result = videolist.find((item) => item === suffix) |
|
if (result) { |
|
return 'video' |
|
} |
|
// 其他 文件类型 |
|
return 'other' |
|
} |
|
|
|
const swiperMouseover = (index) => { |
|
slideIndex.value = index |
|
} |
|
|
|
/** |
|
* 详情、评论切换 |
|
*/ |
|
const tabIndex = ref<number>(0) |
|
const handleChangeTab = (type: number) => { |
|
tabIndex.value = type |
|
} |
|
|
|
/** |
|
* 收藏 |
|
*/ |
|
const handleCollect = Debounce(async () => { |
|
let id = type.value === 'seckill' ? masterProductId.value : route.params.id |
|
if (userCollect.value) { |
|
await collectCancelApi({ ids: id }) |
|
userCollect.value = !userCollect.value |
|
await feedback.msgSuccess('取消成功') |
|
} else { |
|
await collectAddApi({ |
|
productId: id, |
|
category: 0, |
|
}) |
|
userCollect.value = !userCollect.value |
|
await feedback.msgSuccess('收藏成功') |
|
} |
|
},500) |
|
|
|
/** |
|
* 立即购买 |
|
*/ |
|
import { useUserStore } from '@/stores/user' |
|
const { onGetCartCount } = useOrder() |
|
const userStore = useUserStore() |
|
const btnloading = ref<boolean>(false) |
|
const nuxtApp = useNuxtApp() |
|
const handleBuy = Debounce(async (type: number, event: any) => { |
|
if (!userStore.isLogin) { |
|
nuxtApp.$onHandlerLogin() |
|
} else { |
|
await onGoCat(type) |
|
} |
|
},500) |
|
|
|
/** |
|
* 加入购物车、立即购买 |
|
* @param type:1加入购物车,0立即购买 |
|
*/ |
|
const goBuyloading = ref<boolean>(false) |
|
const onGoCat = async (type: number) => { |
|
if (type === 1) { |
|
let data = { |
|
productId: parseFloat(route.params.id), |
|
cartNum: parseFloat(count.value), |
|
isNew: false, |
|
productAttrUnique: parseFloat(unique.value), |
|
} |
|
goBuyloading.value = true |
|
await cartAddApi(data) |
|
.then((res) => { |
|
feedback.msgSuccess('添加购物车成功') |
|
//购物车数量 |
|
onGetCartCount() |
|
goBuyloading.value = false |
|
}) |
|
.catch((res) => { |
|
goBuyloading.value = false |
|
}) |
|
} else { |
|
onPreOrder() |
|
} |
|
} |
|
//立即购买 |
|
import { Mul, Debounce } from '~/utils/util' |
|
import SeckillCard from '~/pages/product/seckillCard.vue' |
|
import ReceiveCouponList from '~/pages/product/receiveCouponList.vue' |
|
import MerchantNews from '~/components/merchantNews.vue' |
|
import {useAppStore} from "~/stores/app"; |
|
const { getPreOrder } = useOrder() |
|
const onPreOrder = () => { |
|
let types = '' |
|
switch (type.value) { |
|
case 'normal': |
|
types = 'buyNow' |
|
break |
|
case 'video': |
|
types = 'video' |
|
break |
|
case 'seckill': |
|
types = 'seckill' |
|
break |
|
} |
|
getPreOrder( |
|
types, |
|
[ |
|
{ |
|
attrValueId: parseFloat(unique.value), |
|
productId: parseFloat(route.params.id), |
|
productNum: parseFloat(count.value), |
|
}, |
|
], |
|
seckillStatus?.value, |
|
seckillTime?.value, |
|
) |
|
} |
|
|
|
/** |
|
* 加购数量加减变化 |
|
*/ |
|
const handleMinus = () => { |
|
count.value-- |
|
} |
|
const handlePlus = () => { |
|
count.value++ |
|
} |
|
const inputNum = () => { |
|
count.value = parseInt(count.value) >= stock.value ? stock.value : count.value |
|
count.value = parseInt(count.value) <= 1 ? 1 : count.value |
|
} |
|
|
|
/** |
|
* 优惠券弹窗 |
|
*/ |
|
const receiveCouponRef = shallowRef() //成功弹窗 |
|
// const dialogVisibleCoupon = ref<boolean>(false) |
|
const handleGetCoupon = () => { |
|
receiveCouponRef.value.DialogOpen() |
|
nuxtApp.$onHandlerCoupon() |
|
} |
|
|
|
//关注店铺回调 |
|
const handleSubmitSuccess = () => { |
|
merchantInfo.isCollect = !merchantInfo.isCollect |
|
} |
|
</script> |
|
|
|
<template> |
|
<div class="goods_count"> |
|
<div class="goods-detail pt-30px" v-loading="loading"> |
|
<div class="wrapper_1200 acea-row"> |
|
<div class="goods-main"> |
|
<!--上边--> |
|
<div class="acea-row row-top" style="position: relative"> |
|
<!--轮播图--> |
|
<div class="carousel w-530px"> |
|
<el-image :src="sliderImage[slideIndex]" class="w-530px h-530px borRadius mb-20px" lazy></el-image> |
|
<div class="w-530px"> |
|
<swiper-index :swiperSlideList="sliderImage" :swiperData="swiperData" ref="swiperRef"> |
|
<template v-slot:default="slotProps"> |
|
<el-image |
|
@click="swiperMouseover(slotProps.value.swiperIndex)" |
|
:src="slotProps.value.swiperItem" |
|
class="w-86px h-86px b-rd-6px cursors" |
|
></el-image> |
|
</template> |
|
</swiper-index> |
|
</div> |
|
</div> |
|
<!--商品价格--> |
|
<div class="text-wrapper pt-20px"> |
|
<div class="flex flex-justify-between mbtom20"> |
|
<div class="title text-#333 text-18px w570px lh-28px font-400">{{ productInfo.name }}</div> |
|
</div> |
|
<div class="w-630px priceCard bg-#F3F3F3 b-rd-12px overflow-hidden mb-20px pb-20px"> |
|
<seckill-card |
|
v-if="type === 'seckill'" |
|
:seckillStatus="seckillStatus" |
|
:seckillTime="seckillTime" |
|
:productInfo="productInfo" |
|
></seckill-card> |
|
<!--价格--> |
|
<div class="flex-between-center px-20px pt-20px"> |
|
<div class="acea-row" style="align-items: end"> |
|
<div class="price font-color text-14px font-600 mr-14px dinProSemiBold"> |
|
¥<span class="text-30px lh-30px inline-block dinProSemiBold">{{ |
|
attrValueSelected ? attrValueSelected.price : productInfo.price |
|
}}</span> |
|
</div> |
|
<div class="money-wrap text-14px fontColor6 dinProRegular"> |
|
<del class="dinProRegular">¥{{ attrValueSelected ? attrValueSelected.otPrice : productInfo.otPrice }}</del> |
|
</div> |
|
</div> |
|
<div class="text-12px fontColor6"> |
|
销量 |
|
{{ Math.floor(productInfo.sales) + Math.floor(productInfo.ficti) || 0 }} |
|
</div> |
|
</div> |
|
<!--优惠券--> |
|
<div v-if="couponList.length" class="flex flex-justify-between px-20px items-center"> |
|
<div class="acea-row"> |
|
<span |
|
v-for="item in couponList" |
|
:key="item.id" |
|
class="square text-14px text-#fff lh-25px px-10px mt-20px mr-10px" |
|
> |
|
{{ item.minPrice === 0 ? '无门槛减' + item.money : '满' + item.minPrice + '减' + item.money }} |
|
</span> |
|
</div> |
|
<div class="text-12px font-color cursors mt-20px" @click="handleGetCoupon">领券</div> |
|
</div> |
|
</div> |
|
<div class="attribute mb-6px"> |
|
<div v-for="(item, index) in productAttr" :key="index" class="size-wrapper mb-6px"> |
|
<div class="text-14px fontColor6 m-b-15px">{{ item.attrName }}</div> |
|
<div class="acea-row list"> |
|
<label v-for="(itm, idx) in item.attrValues.split(',')" :key="idx" class="item cursors"> |
|
|
|
<input v-model="attrSelected[index]" |
|
type="radio" |
|
:name="index" |
|
:value="itm" |
|
:checked="attrSelected[index] ===itm" |
|
hidden |
|
/> |
|
<div class="acea-row cont h-36px b-rd-6px mr14px"> |
|
<div class="acea-row row-middle name">{{ itm }}</div> |
|
</div> |
|
</label> |
|
</div> |
|
</div> |
|
</div> |
|
<div class="number-wrapper mb-20px"> |
|
<div class="text-14px fontColor6 m-b-15px">数量</div> |
|
<div class="counter-wrap acea-row"> |
|
<div class="counter"> |
|
<button |
|
class="iconfont cursors icon-shangpinshuliang-jian h-36px w-36px b-rd-6px" |
|
:disabled="count === 1 || !stock" |
|
@click="handleMinus" |
|
> |
|
— |
|
</button> |
|
<input v-model="count" @input="inputNum" /> |
|
<button |
|
style="font-size: 20px" |
|
class="iconfont cursors icon-shangpinshuliang-jia h-36px w-36px b-rd-6px" |
|
:disabled="count === stock || !stock || count === oneQuota" |
|
@click="handlePlus" |
|
> |
|
+ |
|
</button> |
|
</div> |
|
<span>( 库存:{{ stock || 0 }}{{ productInfo.unitName || '' }} )</span> |
|
</div> |
|
</div> |
|
<!--按钮--> |
|
<div class="acea-row items-center"> |
|
<!--普通商品--> |
|
<template v-if="type === 'normal'"> |
|
<div class="acea-row" v-if="stock"> |
|
<div class="button-wrapper mr-20px"> |
|
<button |
|
class="btn cursors" |
|
v-loading="goBuyloading" |
|
:disabled="!stock" |
|
@click="handleBuy(1, $event)" |
|
> |
|
加入购物车 |
|
</button> |
|
</div> |
|
<div class="button-wrapper"> |
|
<button |
|
class="handleBtn cursors h-50px lh-50px w-150px borderSolE9" |
|
v-loading="btnloading" |
|
:disabled="!stock" |
|
@click="handleBuy(0, $event)" |
|
> |
|
立即购买 |
|
</button> |
|
</div> |
|
</div> |
|
<div class="button-wrapper" v-else> |
|
<button class="btn btn-out" disabled>已售罄</button> |
|
</div> |
|
</template> |
|
<!--秒杀商品--> |
|
<template v-if="type === 'seckill'"> |
|
<div class="button-wrapper" v-if="seckillStatus === 1 && stock"> |
|
<button |
|
class="handleBtn cursors h-50px lh-50px w-150px borderSolE9" |
|
v-loading="btnloading" |
|
:disabled="!stock" |
|
@click="handleBuy(0, $event)" |
|
> |
|
立即购买 |
|
</button> |
|
</div> |
|
<div class="button-wrapper" v-if="seckillStatus === 1 && !stock"> |
|
<button class="btn btn-out" disabled>已售罄</button> |
|
</div> |
|
<div class="button-wrapper" v-if="seckillStatus !== 1"> |
|
<button class="btn btn-out" disabled>{{ seckillStatus === 0 ? '活动已结束' : '活动未开始' }}</button> |
|
</div> |
|
</template> |
|
<!--收藏--> |
|
<el-divider direction="vertical" /> |
|
|
|
<div |
|
class="iconfont cursors mr-6px" |
|
:class="!userCollect ? 'text-#333 icon-baobeishoucang' : 'font-color icon-yishoucang'" |
|
@click="handleCollect" |
|
> |
|
</div> |
|
<div :class="!userCollect ? 'text-#333' : 'font-color'" @click="handleCollect" class="text-14px oppoSans-R cursors">{{!userCollect?'收藏':'已收藏'}}</div> |
|
</div> |
|
|
|
<div class="acea-row mt-40px"> |
|
<div v-for="item in guaranteeList" :key="item.id"> |
|
<el-popover |
|
placement="bottom-start" |
|
:width="200" |
|
trigger="hover" |
|
:content="item.content" |
|
popper-class="text-19px c-\#999" |
|
> |
|
<template #reference> |
|
<div class="text-14px fontColor333 mr-20px cursors"> |
|
<span class="iconfont icon-yanzhengma"></span> |
|
{{ item.name }} |
|
</div> |
|
</template> |
|
</el-popover> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
<!--下边--> |
|
<div class="detail-wrapper acea-row"> |
|
<div class="w-210px mr-20px"> |
|
<MerchantNews |
|
:merchantInfo="merchantInfo" |
|
:merId="merId" |
|
fromType="productDetail" |
|
@handleSubmitSuccess="handleSubmitSuccess" |
|
></MerchantNews> |
|
<div class="borderSol-eee b-rd-12px w-210px px-20px pt-20px mt-20px mb-20px"> |
|
<el-divider><div class="text-16px text-#333 w-64px">好物推荐</div></el-divider> |
|
<div v-if="merchantInfo.proList && merchantInfo.proList.length" class="cursors"> |
|
<div v-for="item in merchantInfo.proList" class="mb-25px" @click="handlerNuxtLink(item.id, 'normal')"> |
|
<el-image :src="item.image" class="w-170px h-170px b-rd-8px"></el-image> |
|
<div class="line1 w-170px text-14px text-#333 mt-15px lh-14px">{{ item.name }}</div> |
|
<div class="flex-between-center mt-15px"> |
|
<div class="text-12px font-color"> |
|
<span class="oppoSans-M">¥</span><span class="text-20px lh-20px dinProRegular">{{ item.price }}</span> |
|
</div> |
|
<div class="text-12px text-#999">已售{{ item.sales }}{{ item.unitName }}</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
<div class="w-970px"> |
|
<div class="detail-hd acea-row"> |
|
<div class="acea-row"> |
|
<div |
|
class="item acea-row row-center-wrapper" |
|
:class="tabIndex === 0 ? 'on' : 'text-16px'" |
|
@click="handleChangeTab(0)" |
|
> |
|
详情 |
|
</div> |
|
<div |
|
class="item acea-row row-center-wrapper" |
|
:class="tabIndex === 1 ? 'on' : 'text-16px'" |
|
@click="handleChangeTab(1)" |
|
> |
|
评论({{ replyInfo.sumCount }}) |
|
</div> |
|
</div> |
|
</div> |
|
<el-divider border-style="double" /> |
|
<div class="w-100%"> |
|
<div v-show="tabIndex === 0"> |
|
<div v-if="productInfo.content" class="w-100% detail-bd"> |
|
<div v-html="productInfo.content"></div> |
|
</div> |
|
<div v-else> |
|
<empty-page title="暂无商品详情~" m-top="2%"> |
|
<template v-slot:emptyImage> |
|
<img src="@/assets/images/wudizhi.png" /> |
|
</template> |
|
</empty-page> |
|
</div> |
|
</div> |
|
<!--评论--> |
|
<div v-show="tabIndex === 1"> |
|
<div class="flex-between-center"> |
|
<div class="flex comment"> |
|
<div |
|
@click="replyTypeChange(0)" |
|
:class="where.type === 0 ? 'check-color' : ''" |
|
class="item px-15px b-rd-17px h-34px lh-32px text-14px mr-10px cursors" |
|
> |
|
全部({{ replyInfo.sumCount || 0 }}) |
|
</div> |
|
<div |
|
@click="replyTypeChange(1)" |
|
:class="where.type === 1 ? 'check-color' : ''" |
|
class="item px-15px b-rd-17px h-34px lh-32px text-14px mr-10px cursors" |
|
> |
|
好评({{ replyInfo.goodCount || 0 }}) |
|
</div> |
|
<div |
|
@click="replyTypeChange(2)" |
|
:class="where.type === 2 ? 'check-color' : ''" |
|
class="item px-15px b-rd-17px h-34px lh-32px text-14px mr-10px cursors" |
|
> |
|
中评({{ replyInfo.inCount || 0 }}) |
|
</div> |
|
<div |
|
@click="replyTypeChange(3)" |
|
:class="where.type === 3 ? 'check-color' : ''" |
|
class="item px-15px b-rd-17px h-34px lh-32px text-14px cursors" |
|
> |
|
差评({{ replyInfo.poorCount || 0 }}) |
|
</div> |
|
</div> |
|
<div class="flex-y-center text-14px fontColor6"> |
|
评分 |
|
<el-rate |
|
class="ml-10px" |
|
v-model="replyInfo.replyStar" |
|
disabled |
|
:colors="['#e93323', '#e93323', '#e93323']" |
|
score-template="{replyInfo.replyStar}" |
|
> |
|
</el-rate> |
|
<div class="rate ml-20px"> |
|
<span class="text-14px text-#666">好评率</span><span class="font-color ml-10px">{{ Mul(replyInfo.replyChance, 100) }}%</span> |
|
</div> |
|
</div> |
|
</div> |
|
<div class="comment-bd mt-30px"> |
|
<div v-if="replyList && replyList.total > 0"> |
|
<div v-for="item in replyList.list" :key="item.id" class="item"> |
|
<div class="acea-row row-middle item-hd flex-justify-between"> |
|
<div class="acea-row"> |
|
<div class="image mr-10px"> |
|
<img v-if="item.avatar" :src="item.avatar" /> |
|
<!-- <img v-else src="~assets/images/f.png" alt="">--> |
|
</div> |
|
<div class="text"> |
|
<div class="flex-between-center text-16px text-#333 mb-8px lh-16px"> |
|
{{ item.nickname }} |
|
</div> |
|
<div class="text-#999999 text-12px"> |
|
{{ item.createTime }} <span class="ml-10px">{{ item.sku }}</span> |
|
</div> |
|
</div> |
|
</div> |
|
<div class="star"> |
|
<el-rate |
|
v-model="item.star" |
|
disabled |
|
:colors="['#e93323', '#e93323', '#e93323']" |
|
score-template="{item.star}" |
|
> |
|
</el-rate> |
|
</div> |
|
</div> |
|
<div class="item-bd"> |
|
<div class="mt-20px mb-20px">{{ item.comment }}</div> |
|
<div class="image-wrapper" v-if="item.pics && item.pics.length && item.pics[0]"> |
|
<div v-for="(itm, idx) in item.pics" :key="idx" class="image" @click="isDialog = true"> |
|
<el-image |
|
style="width: 86px; height: 86px; border-radius: 8px" |
|
:src="itm" |
|
:preview-src-list="item.pics" |
|
lazy |
|
></el-image> |
|
</div> |
|
</div> |
|
<div v-if="item.merchantReplyContent" class="reply mb-30px"> |
|
<div class="item"><span>回复:</span>{{ item.merchantReplyContent }}</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
<div v-else> |
|
<empty-page title="暂无评论~" m-top="2%"> |
|
<template v-slot:emptyImage> |
|
<img src="@/assets/images/wupinlun.png" /> |
|
</template> |
|
</empty-page> |
|
</div> |
|
<div v-if="replyList && replyList.total > 0" class="acea-row row-middle mt-20px pb-20px"> |
|
<el-pagination |
|
background |
|
layout="prev, pager, next" |
|
:total="replyList.total" |
|
class="page-item" |
|
:page-size="where.limit" |
|
:current-page="where.page" |
|
@update:current-page="callPaginate" |
|
/> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<!-- 优惠券抽屉--> |
|
<receive-coupon-list ref="receiveCouponRef" :productId="productId"></receive-coupon-list> |
|
</div> |
|
</template> |
|
|
|
<style lang="scss" scoped> |
|
:deep(.el-divider--vertical){ |
|
margin: 0 20px !important; |
|
} |
|
:deep(.merchantNews) { |
|
border-radius: 12px 12px 12px 12px; |
|
border: 1px solid #eeeeee; |
|
} |
|
:deep(.el-drawer__header) { |
|
margin-bottom: 0 !important; |
|
padding: 10px !important; |
|
border-bottom: 1px solid #dddddd; |
|
font-size: 14px; |
|
color: #3d3d3d; |
|
} |
|
.detail-wrapper { |
|
:deep(.el-divider--horizontal) { |
|
margin: 20px 0 20px 0 !important; |
|
} |
|
:deep(.el-divider__text) { |
|
--el-bg-color: #fff !important; |
|
} |
|
} |
|
.goods_count { |
|
:deep(.el-drawer__body) { |
|
padding: 0 15px 20px 15px !important; |
|
} |
|
} |
|
|
|
:deep(.el-drawer) { |
|
box-shadow: none; |
|
--el-drawer-bg-color: #f5f5f5; |
|
--el-transition-duration: 1s; |
|
} |
|
|
|
.bbbbb { |
|
z-index: 2011; |
|
position: fixed; |
|
inset: 0px; |
|
} |
|
.drawerCoupon { |
|
right: 0; |
|
height: 100%; |
|
top: 0; |
|
bottom: 0; |
|
position: absolute; |
|
box-sizing: border-box; |
|
background-color: var(--el-drawer-bg-color); |
|
display: flex; |
|
flex-direction: column; |
|
box-shadow: var(--el-box-shadow-dark); |
|
overflow: hidden; |
|
transition: all var(--el-transition-duration); |
|
animation: slideOut 1s ease-in-out forwards; |
|
} |
|
@keyframes slideOut { |
|
from { |
|
right: 0%; |
|
} |
|
to { |
|
right: 278px; |
|
} |
|
} |
|
.square { |
|
height: 26px; |
|
background-color: #e93323; |
|
position: relative; |
|
display: inline-block; |
|
} |
|
.square::before, |
|
.square::after { |
|
content: ''; |
|
width: 6px; |
|
height: 6px; |
|
border-radius: 50%; |
|
background-color: #f3f3f3; |
|
position: absolute; |
|
top: 9px; |
|
} |
|
.square::before { |
|
left: -3px; |
|
} |
|
|
|
.square::after { |
|
right: -3px; /* 右侧 */ |
|
} |
|
.priceCard { |
|
width: 630px; |
|
background-image: url('@/assets/images/spb.png'); |
|
} |
|
.goods_count { |
|
background: #fff; |
|
} |
|
.comment { |
|
.item { |
|
color: #282828; |
|
background: #f7f7f7; |
|
} |
|
.check-color { |
|
color: #ffffff !important; |
|
background: #e93323 !important; |
|
} |
|
} |
|
.detail-bd { |
|
:deep div { |
|
width: 100% !important; |
|
} |
|
:deep img { |
|
display: block; |
|
width: 100% !important; |
|
} |
|
} |
|
.coupons-get { |
|
font-size: 14px; |
|
font-weight: 400; |
|
color: #666666; |
|
} |
|
.coupon_list { |
|
padding: 5px 10px 5px 30px; |
|
.list { |
|
flex-direction: column; |
|
} |
|
} |
|
.ml30 { |
|
margin-left: 30px; |
|
} |
|
.mb22 { |
|
margin-bottom: 22px; |
|
} |
|
.mb12 { |
|
margin-bottom: 12px; |
|
} |
|
.activity { |
|
height: 24px; |
|
padding: 0 10px; |
|
background: #e93323; |
|
color: #fff; |
|
font-size: 14px; |
|
line-height: 24px; |
|
position: relative; |
|
margin: 0 10px 5px 0; |
|
} |
|
.activity:before { |
|
content: ' '; |
|
position: absolute; |
|
width: 3px; |
|
height: 5px; |
|
border-radius: 0 3px 3px 0; |
|
border: 1px solid #e93323; |
|
background-color: #fff !important; |
|
bottom: 50%; |
|
left: -2px; |
|
margin-bottom: -3px; |
|
border-left-color: #fff !important; |
|
} |
|
.activity:after { |
|
content: ' '; |
|
position: absolute; |
|
width: 3px; |
|
height: 5px; |
|
border-radius: 3px 0 0 3px; |
|
border: 1px solid #e93323; |
|
background-color: #fff; |
|
right: -2px; |
|
bottom: 50%; |
|
margin-bottom: -3px; |
|
border-right-color: #fff !important; |
|
} |
|
.store-banner { |
|
width: 100%; |
|
height: 130px; |
|
img { |
|
object-fit: none; |
|
width: 100%; |
|
height: 100%; |
|
} |
|
} |
|
.menu-count { |
|
width: 100%; |
|
height: 40px; |
|
background: #dfdfdf; |
|
} |
|
.store-name { |
|
display: inline-block; |
|
width: 117px; |
|
position: relative; |
|
top: 11px; |
|
font-size: 16px; |
|
margin-bottom: 10px; |
|
} |
|
.user-menu { |
|
position: relative; |
|
-webkit-justify-content: space-between; |
|
justify-content: space-between; |
|
width: 1200px; |
|
margin: 0 auto; |
|
.category { |
|
position: absolute; |
|
top: 40px; |
|
left: 0; |
|
background-color: rgba(254, 248, 248, 0.96); |
|
width: 100%; |
|
padding: 40px 20px 20px; |
|
z-index: 10; |
|
|
|
.name { |
|
width: 130px; |
|
position: relative; |
|
padding-right: 20px; |
|
margin-right: 30px; |
|
cursor: pointer; |
|
.iconfont { |
|
font-size: 10px; |
|
position: absolute; |
|
right: 0; |
|
top: 3px; |
|
color: #282828; |
|
} |
|
} |
|
.sortCon { |
|
width: 1000px; |
|
.sub-item { |
|
margin: 0 15px 15px; |
|
color: #666666; |
|
cursor: pointer; |
|
} |
|
} |
|
.erSort { |
|
align-items: center; |
|
} |
|
.item { |
|
margin-bottom: 20px; |
|
align-items: baseline; |
|
} |
|
.moreBtn { |
|
color: #282828; |
|
font-size: 12px; |
|
width: 100px; |
|
height: 26px; |
|
line-height: 26px; |
|
text-align: center; |
|
border-radius: 13px; |
|
border: 1px solid #666666; |
|
} |
|
} |
|
.menu-main { |
|
width: 300px; |
|
height: 40px; |
|
-webkit-justify-content: space-between; |
|
justify-content: space-between; |
|
.menu-item { |
|
display: inline-block; |
|
height: 26px; |
|
line-height: 26px; |
|
color: #282828; |
|
padding: 0 10px; |
|
cursor: pointer; |
|
&.active { |
|
color: #fff; |
|
background: #282828; |
|
color: #fff; |
|
border-radius: 15px; |
|
} |
|
} |
|
} |
|
.menu-search { |
|
width: 220px; |
|
height: 24px; |
|
background-color: #fff; |
|
border-radius: 17px; |
|
.text { |
|
width: 175px; |
|
} |
|
input { |
|
border: none; |
|
height: 24px; |
|
line-height: 24px; |
|
color: #999999; |
|
padding: 0 15px; |
|
border-radius: 17px 0 0 17px; |
|
&:focus { |
|
border: none; |
|
outline: none; |
|
} |
|
} |
|
.bnt { |
|
width: 44px; |
|
background-color: #282828; |
|
color: #fff; |
|
border-radius: 0 17px 17px 0; |
|
line-height: 24px; |
|
text-align: center; |
|
cursor: pointer; |
|
} |
|
} |
|
} |
|
.product_content .title { |
|
text-align: center; |
|
font-size: 18px; |
|
margin: 5px 0; |
|
} |
|
.dropdown-box { |
|
.el-dropdown-menu { |
|
z-index: 10 !important; |
|
} |
|
} |
|
.goods-detail { |
|
.goods-main { |
|
flex: 1; |
|
min-width: 0; |
|
} |
|
.carousel { |
|
.btn { |
|
margin-right: 30px; |
|
font-size: 12px; |
|
color: #4b4b4b; |
|
cursor: pointer; |
|
position: relative; |
|
|
|
.qrcode1 { |
|
display: none; |
|
box-shadow: 0px 3px 16px rgba(0, 0, 0, 0.08); |
|
background: #fff; |
|
padding: 6px; |
|
position: relative; |
|
width: 100px; |
|
img { |
|
width: 100%; |
|
} |
|
|
|
&.contactService { |
|
position: absolute; |
|
left: 50%; |
|
top: 25px; |
|
z-index: 10; |
|
width: 100px; |
|
height: 100px; |
|
margin-left: -50px; |
|
} |
|
} |
|
} |
|
|
|
.contactBtn:hover { |
|
.qrcode1 { |
|
display: inline; |
|
} |
|
} |
|
|
|
.iconfont { |
|
margin-right: 6px; |
|
font-size: 14px; |
|
color: #e93323; |
|
} |
|
} |
|
|
|
.text-wrapper { |
|
flex: 1; |
|
min-width: 0; |
|
margin-left: 40px; |
|
width: 735px; |
|
|
|
.integral_count { |
|
display: inline-block; |
|
margin-top: 18px; |
|
color: #ff6200; |
|
line-height: 27px; |
|
background: #fff4e6; |
|
padding: 0 15px; |
|
border-radius: 2px; |
|
} |
|
.money-wrapper { |
|
width: 730px; |
|
margin-top: 6px; |
|
border-radius: 1px; |
|
color: #ffffff; |
|
justify-content: space-between; |
|
.priceBox { |
|
padding: 14px 0; |
|
} |
|
.prict-title { |
|
width: 119px; |
|
font-size: 14px; |
|
font-family: ArialMT; |
|
color: #666666; |
|
padding-left: 13px; |
|
} |
|
|
|
.vip { |
|
width: 100px; |
|
height: 25px; |
|
border-radius: 2px; |
|
margin-left: 14px; |
|
background: linear-gradient(205deg, #fdcaa4 0%, #fce3c3 100%); |
|
overflow: hidden; |
|
font-size: 12px; |
|
color: #0f0f0f; |
|
|
|
.iconfont { |
|
width: 32px; |
|
height: 25px; |
|
} |
|
|
|
.iconfontVip { |
|
width: 32px; |
|
height: 25px; |
|
} |
|
|
|
.money { |
|
flex: 1; |
|
min-width: 0; |
|
|
|
span { |
|
font-size: 14px; |
|
} |
|
} |
|
} |
|
.saleBox { |
|
.el-divider--vertical { |
|
height: 70px; |
|
background: #e93323; |
|
border-radius: 1px; |
|
opacity: 0.2; |
|
} |
|
} |
|
.sales { |
|
position: relative; |
|
height: 100%; |
|
padding-right: 20px; |
|
padding-left: 12px; |
|
font-size: 14px; |
|
color: #e93323; |
|
|
|
&::before { |
|
content: ''; |
|
position: absolute; |
|
top: 14px; |
|
bottom: 12px; |
|
left: 0; |
|
width: 1px; |
|
border-left: 1px solid rgba(255, 255, 255, 0.24); |
|
} |
|
|
|
.num { |
|
margin-bottom: 3px; |
|
font-weight: bold; |
|
font-size: 20px; |
|
} |
|
} |
|
|
|
.timer-wrapper { |
|
width: 180px; |
|
margin-right: 15px; |
|
font-size: 12px; |
|
color: #ffffff; |
|
|
|
.styleAll { |
|
font-size: 22px; |
|
} |
|
.progress-group { |
|
margin-top: 10px; |
|
} |
|
|
|
.progress { |
|
width: 120px; |
|
height: 8px; |
|
border: 1px solid #ffffff; |
|
border-radius: 4px; |
|
font-size: 0; |
|
|
|
span { |
|
display: inline-block; |
|
width: 50%; |
|
height: 100%; |
|
border-radius: 4px; |
|
background-color: #ffffff; |
|
} |
|
} |
|
} |
|
} |
|
|
|
.attribute { |
|
.size-wrapper { |
|
.label { |
|
width: 119px; |
|
font-size: 14px; |
|
color: #5a5a5a; |
|
margin-right: 2px; |
|
word-break: break-all; |
|
padding-top: 2px; |
|
padding-left: 13px; |
|
} |
|
|
|
.list { |
|
flex: 1; |
|
min-width: 0; |
|
} |
|
|
|
.item { |
|
margin-bottom: 14px; |
|
.cont { |
|
border: 1px solid #d3d3d3; |
|
} |
|
|
|
&:hover { |
|
.cont { |
|
border-color: #e93323; |
|
color: #e93323; |
|
} |
|
} |
|
|
|
input:checked { |
|
+ .cont { |
|
border-color: #e93323; |
|
color: #e93323; |
|
|
|
.iconfont { |
|
display: block; |
|
} |
|
} |
|
} |
|
} |
|
|
|
.image { |
|
width: 36px; |
|
height: 36px; |
|
} |
|
|
|
img { |
|
display: block; |
|
width: 100%; |
|
height: 100%; |
|
} |
|
|
|
.name { |
|
padding-right: 20px; |
|
padding-left: 20px; |
|
font-size: 12px; |
|
} |
|
|
|
.iconfont { |
|
position: absolute; |
|
right: -3px; |
|
bottom: -3px; |
|
display: none; |
|
font-size: 22px; |
|
} |
|
} |
|
} |
|
.guaranteeList { |
|
margin-top: 24px !important; |
|
} |
|
.number-wrapper { |
|
.guaranee_tel { |
|
position: absolute; |
|
top: 20px; |
|
left: 0; |
|
background: #ffffff; |
|
z-index: 10; |
|
padding: 0 24px 24px; |
|
display: none; |
|
box-shadow: 0px 3px 16px rgba(0, 0, 0, 0.08); |
|
.item { |
|
margin-top: 24px; |
|
.name { |
|
font-size: 16px; |
|
color: #000000; |
|
} |
|
.info { |
|
font-size: 12px; |
|
color: #969696; |
|
margin-top: 6px; |
|
} |
|
} |
|
} |
|
.icon-duoshanghupc-shuomingdanchuang { |
|
color: #e93323; |
|
font-size: 12px; |
|
position: relative; |
|
} |
|
.label { |
|
cursor: pointer; |
|
} |
|
.guaranteeAttr { |
|
display: inline-block; |
|
width: 445px; |
|
} |
|
.atterTxt1 { |
|
margin-bottom: 9px; |
|
.icon-gou { |
|
display: inline-block; |
|
font-size: 12px; |
|
color: #e93323; |
|
margin-right: 2px; |
|
} |
|
} |
|
|
|
.label { |
|
width: 119px; |
|
font-size: 14px; |
|
color: #5a5a5a; |
|
margin-right: 2px; |
|
word-break: break-all; |
|
padding-top: 2px; |
|
padding-left: 13px; |
|
} |
|
|
|
.counter-wrap { |
|
flex: 1; |
|
min-width: 0; |
|
|
|
span { |
|
vertical-align: bottom; |
|
font-size: 14px; |
|
color: #5a5a5a; |
|
margin-top: 9px; |
|
margin-left: 15px; |
|
} |
|
} |
|
|
|
.counter { |
|
button { |
|
border: none; |
|
outline: none; |
|
font-weight: inherit; |
|
font-size: 12px; |
|
font-family: inherit; |
|
vertical-align: middle; |
|
background: #f7f7f7; |
|
&:disabled { |
|
color: #d0d0d0; |
|
cursor: not-allowed; |
|
} |
|
} |
|
|
|
input { |
|
width: 64px; |
|
height: 36px; |
|
border: none; |
|
outline: none; |
|
font-weight: inherit; |
|
font-size: 14px; |
|
font-family: inherit; |
|
text-align: center; |
|
color: #5a5a5a; |
|
vertical-align: middle; |
|
} |
|
} |
|
} |
|
|
|
.button-wrapper { |
|
.btn { |
|
width: 150px; |
|
height: 50px; |
|
border-radius: 25px 25px 25px 25px; |
|
opacity: 1; |
|
border: 1px solid #cccccc; |
|
font-size: 16px; |
|
color: #333; |
|
&.btn-out { |
|
width: 120px; |
|
color: #ffffff; |
|
background: #d0d0d0; |
|
} |
|
&.btn-notify { |
|
width: 120px; |
|
border-color: #e93323; |
|
color: #e93323; |
|
} |
|
|
|
~ .btn { |
|
margin-left: 18px; |
|
} |
|
} |
|
|
|
button { |
|
font-size: 16px !important; |
|
background: none; |
|
outline: none; |
|
vertical-align: middle; |
|
|
|
&:disabled { |
|
border-color: #ebeef5; |
|
color: #c0c4cc; |
|
cursor: not-allowed; |
|
} |
|
|
|
&.cart { |
|
background-color: #e93323; |
|
color: #ffffff; |
|
|
|
&:disabled { |
|
border-color: #fab6b6; |
|
background-color: #fab6b6; |
|
} |
|
} |
|
|
|
~ button { |
|
margin-left: 18px; |
|
} |
|
} |
|
|
|
a { |
|
display: inline-block; |
|
background-color: #e93323; |
|
vertical-align: middle; |
|
line-height: 50px; |
|
text-align: center; |
|
|
|
&.btn { |
|
color: #ffffff; |
|
} |
|
} |
|
} |
|
} |
|
|
|
.detail-wrapper { |
|
margin-top: 70px; |
|
.detail-hd { |
|
.item { |
|
position: relative; |
|
padding-right: 30px; |
|
padding-left: 30px; |
|
cursor: pointer; |
|
line-height: 16px; |
|
|
|
&.on { |
|
color: #e93323; |
|
font-size: 18px; |
|
font-weight: 500 !important; |
|
//&::before { |
|
// content: ''; |
|
// position: absolute; |
|
// top: 31px; |
|
// bottom: 18px; |
|
// height: 2px; |
|
// width: 22px; |
|
// background: #e93323; |
|
//} |
|
} |
|
|
|
&:hover { |
|
color: #e93323; |
|
} |
|
} |
|
} |
|
|
|
.comment-bd { |
|
> img { |
|
width: 200px; |
|
margin: 50px auto; |
|
} |
|
|
|
.item { |
|
padding-bottom: 20px; |
|
|
|
.item-hd { |
|
.image { |
|
width: 40px; |
|
height: 40px; |
|
border-radius: 50%; |
|
overflow: hidden; |
|
} |
|
|
|
img { |
|
display: block; |
|
width: 100%; |
|
height: 100%; |
|
} |
|
|
|
.star { |
|
margin-left: 12px; |
|
font-size: 0; |
|
} |
|
|
|
.iconfont { |
|
font-size: 12px; |
|
color: #e6e6e6; |
|
|
|
&.on { |
|
color: #e93323; |
|
} |
|
|
|
~ .iconfont { |
|
margin-left: 5px; |
|
} |
|
} |
|
} |
|
|
|
.item-bd { |
|
border-bottom: 1px dashed #e3e3e3; |
|
margin-left: 52px; |
|
font-size: 14px; |
|
color: #333333; |
|
|
|
.image-wrapper { |
|
font-size: 0; |
|
} |
|
|
|
.image { |
|
display: inline-block; |
|
margin-right: 8px; |
|
margin-bottom: 10px; |
|
} |
|
|
|
.reply { |
|
margin-top: 10px !important; |
|
background: #f7f7f7; |
|
border-radius: 6px 6px 6px 6px; |
|
.item { |
|
padding: 7px 10px; |
|
font-size: 14px; |
|
color: #333333; |
|
|
|
span { |
|
color: #e93323; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
.nothing { |
|
margin-top: 100px; |
|
font-size: 16px; |
|
text-align: center; |
|
color: #999999; |
|
|
|
img { |
|
margin: 0 auto; |
|
} |
|
} |
|
} |
|
.store-favorites { |
|
margin-top: 20px; |
|
.collection { |
|
width: 180px; |
|
height: 30px; |
|
line-height: 30px; |
|
text-align: center; |
|
color: #333333; |
|
border: 1px solid #c8c8c8; |
|
border-radius: 2px; |
|
background: #fff; |
|
&.care { |
|
color: #e93323; |
|
border-color: #e93323; |
|
} |
|
} |
|
} |
|
</style>
|
|
|