Files
hupeng d0b337c596 v1.0
2023-10-11 11:27:47 +08:00

698 lines
15 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<layout class="goodsDetail">
<uv-navbar
fixed
:safeAreaInsetTop="true"
autoBack
title=""
bg-color="transparent"
/>
<view v-if="detailData">
<swiper
class="swiper detail"
circular
indicator-dots
autoplay
>
<swiper-item
v-for="(item, index) in sliderImageData"
:key="index"
>
<view class="swiper-item">
<image
class="image"
:src="item"
mode="widthFix"
/>
</view>
</swiper-item>
</swiper>
<view class="goodsDetail-info">
<view class="goodsDetail-price-row">
<view class="goodsDetail-price goodsDetail-price-primary">
¥{{ storeInfo.price }}
</view>
<view
class="goodsDetail-price goodsDetail-price-original"
v-if="storeInfo.otPrice"
>
¥{{ storeInfo.otPrice }}
</view>
</view>
<view class="goodsDetail-storeName">{{ storeInfo.storeName }}</view>
<view class="goodsDetail-info-action">
<view class="goodsDetail-info-action-tag">
<!-- <space>
<uv-tags
plain
type="primary"
text="满100减10"
></uv-tags>
<uv-tags
plain
type="primary"
text="满100减10"
></uv-tags>
</space> -->
</view>
<view
class="goodsDetail-info-action-desc"
v-if="storeInfo.stock"
>
仅剩{{ storeInfo.stock }}
</view>
</view>
</view>
<blank size="15"></blank>
<view class="y-list min">
<uv-list border>
<uv-list-item border>
<view class="y-list-content">
<view class="y-list-label">运费</view>
<view class="y-list-default">{{ detailData.tempName }}</view>
</view>
</uv-list-item>
</uv-list>
</view>
<view class="y-list min">
<uv-list border>
<uv-list-item
border
clickable
show-arrow
@click="handleOpenSelect('select')"
>
<view class="y-list-content">
<view class="y-list-label">选择</view>
<view
class="y-list-select-placeholder"
v-if="!storeAttr"
>请选择商品规格</view>
<view
class="y-list-select"
v-if="storeAttr"
>{{ storeAttr.sku }}</view>
</view>
</uv-list-item>
</uv-list>
</view>
<view class="card full">
<view class="card-head">
<view class="card-title">商品评价({{ detailData.replyCount }})</view>
<view
class="card-more"
@tap="$yrouter.navigateTo({
url: '/pages/goodsReply/goodsReply', query: {
id: detailData.storeInfo.id
}
})"
><span>
查看更多
</span>
<uv-icon
name="arrow-right"
color="rgb(187, 187, 187)"
size="10"
/>
</view>
</view>
<view
class="card-content"
v-if="detailData.reply"
>
<reply :data="detailData.reply" />
</view>
</view>
<blank size="15"></blank>
<view class="card full">
<view class="card-head">
<view class="card-title">
商品详情
</view>
</view>
<rich-text
:nodes="storeInfo.description"
bindtap="onOpenLink"
/>
</view>
<blank size="15"></blank>
<container min>
<view class="center-title">
<view class="center-title-line"></view>
<view class="title">热门推荐</view>
<view class="center-title-line"></view>
</view>
</container>
<good-attr-select
ref="selectAttrPanel"
:id="storeInfo.id"
:storeInfo="storeInfo"
:productAttr="detailData.productAttr"
:productValue="detailData.productValue"
@select="handleSelectAttr"
/>
</view>
<view
class="action-bar"
v-if="detailData"
>
<view class="action-icons">
<view class="action-icons-item">
<view
class="action-icon"
@click="goToShopCart"
>
<img
class="action-icon-img"
src="@/static/images/icon-kefu.png"
/>
<text class="action-icon-label">客服</text>
</view>
</view>
<view class="action-icons-item">
<view
class="action-icon"
@click="goToShopCart"
>
<view class="action-icon-badge">
<uv-badge
type="error"
max="99"
:value="cardCount"
></uv-badge>
</view>
<img
class="action-icon-img"
src="@/static/images/icon-gouwuche.png"
/>
<text class="action-icon-label">购物车</text>
</view>
</view>
<view class="action-icons-item">
<view
class="action-icon"
@click="handleCollect"
>
<img
v-if="!storeInfo?.userCollect"
class="action-icon-img"
src="@/static/images/icon-shouceng.png"
/>
<img
v-if="storeInfo?.userCollect"
class="action-icon-img"
src="@/static/images/icon-shouceng-o.png"
/>
<text class="action-icon-label">收藏</text>
</view>
</view>
</view>
<view class="action-btns">
<uv-button
type="info"
text="加入购物车"
plain
@click="handleOpenSelect('cart')"
></uv-button>
<uv-button
type="primary"
text="立即购买"
@click="handleOpenSelect('buy')"
></uv-button>
</view>
</view>
</layout>
</template>
<script setup>
import { ref } from 'vue'
import { getProductDetail, getProductAddCollect, getProductDelCollect } from '@/api/product'
import { getCartAdd, getCartCount } from '@/api/cart'
import { switchTab } from '@/utils/router'
import { onLoad } from '@dcloudio/uni-app'
import { useGlobalProperties } from '@/hooks';
const { $yrouter } = useGlobalProperties()
const detailData = ref(null)
const sliderImageData = ref([])
const storeInfo = ref(null)
const actionType = ref(null)
const storeAttr = ref(null)
const storeNum = ref(null)
const cardCount = ref(null)
const selectAttrPanel = ref(false)
const handleGetDetail = async (id) => {
try {
const detail = await getProductDetail(id)
uni.hideLoading();
if (detail) {
detailData.value = detail
sliderImageData.value = detail.storeInfo.sliderImage.split(',')
storeInfo.value = detail.storeInfo
}
} catch (error) {
uni.hideLoading();
}
}
onLoad(({ id }) => {
uni.showLoading({
title: '加载中'
});
handleGetDetail(id)
handleGetCartCount(id)
})
const goToShopCart = () => {
switchTab({
url: '/pages/shoppingCart/shoppingCart',
})
}
const handleOpenSelect = (action) => {
actionType.value = action
selectAttrPanel.value.open()
}
const handleSelectAttr = (attr) => {
selectAttrPanel.value.close()
storeAttr.value = attr.store
storeNum.value = attr.num
switch (actionType.value) {
case 'select':
break;
case 'cart':
handleCardAdd()
break;
case 'buy':
handleBuy()
break;
}
actionType.value = ''
}
const handleCardAdd = async () => {
let res = await getCartAdd({
cartNum: storeNum.value,
productId: storeAttr.value.productId,
uniqueId: storeAttr.value.unique,
new: 0
})
handleGetCartCount()
uni.showToast({
title: '已加入购物车',
duration: 2000
});
}
const handleBuy = async () => {
uni.showLoading({
title: '加载中'
});
let res = await getCartAdd({
cartNum: storeNum.value,
productId: storeAttr.value.productId,
uniqueId: storeAttr.value.unique,
new: 1
})
uni.hideLoading();
$yrouter.navigateTo({
url: '/pages/submitOrder/submitOrder',
query: {
cartId: res.cartId
}
})
}
const handleCollect = async () => {
storeInfo.value.userCollect = !storeInfo.value.userCollect
if (storeInfo.value.userCollect) {
let res = await getProductAddCollect({
id: storeInfo.value.id,
})
uni.showToast({
title: '已收藏',
duration: 2000
});
if (!res) {
storeInfo.value.userCollect = !storeInfo.value.userCollect
}
} else {
await getProductDelCollect({
id: storeInfo.value.id,
})
uni.showToast({
title: '取消收藏',
duration: 2000
});
if (!res) {
storeInfo.value.userCollect = !storeInfo.value.userCollect
}
}
}
const handleGetCartCount = async () => {
const count = await getCartCount()
console.log("gxs --> % handleGetCartCount % count:\n", count)
cardCount.value = count.count
}
</script>
<style lang="less">
.search {
padding: 0 17px;
}
.logo {
width: 63px;
height: 25px;
.image {
width: 63px;
height: 25px;
display: block;
}
}
.swiper {
width: 100%;
.image {
width: 100%;
display: block;
}
}
.goodsDetail {
width: 100%;
&-storeName {
line-height: 40rpx;
font-size: 32rpx;
color: #333333;
margin-bottom: 20rpx;
}
&-price {
&-row {
margin-bottom: 17rpx;
display: flex;
align-items: center;
.goods-price {}
}
&-primary {
line-height: 50rpx;
font-size: 50rpx;
color: #EE6D46;
}
&-default {
line-height: 40rpx;
font-size: 28rpx;
color: #333333;
}
&-original {
margin-left: 20rpx;
line-height: 28rpx;
font-size: 28rpx;
color: #999999;
text-decoration: line-through;
}
}
&-info {
background-color: #fff;
padding: 30rpx 35rpx;
// display: flex;
// align-items: flex-end;
// justify-content: space-between;
&-left {}
&-action {
display: flex;
justify-content: space-between;
&-tags {
.uv-tags {
margin-right: 10rpx;
}
}
&-desc {
line-height: 28rpx;
font-size: 20rpx;
color: #999999;
}
}
}
&-image {
&-img {}
}
&-list {
width: 100%;
display: flex;
flex-direction: row;
padding: 14rpx;
.goods {
&-thumb {
margin-bottom: 0;
width: 220rpx;
height: 220rpx;
&-img {
width: 100%;
height: 100%;
display: block;
}
}
&-content {
padding-right: 40rpx;
margin-left: 30rpx;
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
}
}
// .goods {
// padding: 16rpx 14rpx;
// &-header {
// display: flex;
// align-items: flex-start;
// }
// &-thumb {
// width: 220rpx;
// height: 220rpx;
// &-img {
// width: 100%;
// height: 100%;
// display: block;
// }
// }
// &-content {
// margin-top: 24rpx;
// margin-left: 40rpx;
// flex: 1
// }
// &-storeName {
// line-height: 40rpx;
// font-size: 28rpx;
// font-weight: 500;
// color: #333333;
// margin-bottom: 35rpx;
// }
// &-info {
// display: flex;
// align-items: center;
// justify-content: space-between;
// &-left {
// display: flex;
// align-items: flex-end;
// }
// &-action {
// &-btn {}
// &-desc {
// color: #999999;
// font-size: 24rpx;
// line-height: 40rpx;
// }
// }
// }
// &-price {
// &-default {
// line-height: 28rpx;
// font-size: 20rpx;
// color: #999999;
// }
// &-primary {
// line-height: 42rpx;
// font-size: 30rpx;
// font-weight: 500;
// color: #EE6D46;
// margin-left: 5rpx;
// }
// }
// &-desc {
// color: #999999;
// font-size: 24rpx;
// line-height: 40rpx;
// }
// &-model {
// display: inline-flex;
// align-items: center;
// width: auto;
// height: 40rpx;
// border: 1px solid #CCCCCC;
// opacity: 1;
// border-radius: 0rpx;
// padding: 0 10rpx;
// margin-bottom: 28rpx;
// &-label {
// line-height: 38rpx;
// font-size: 24rpx;
// color: #999999;
// }
// &-value {
// line-height: 38rpx;
// font-size: 24rpx;
// color: #333333;
// margin-right: 10rpx;
// }
// &-action {
// width: 11rpx;
// height: 7rpx;
// }
// }
// &-model-info {
// display: inline-flex;
// align-items: center;
// width: auto;
// height: 40rpx;
// opacity: 1;
// border-radius: 0rpx;
// margin-bottom: 28rpx;
// &-label {
// line-height: 38rpx;
// font-size: 24rpx;
// color: #999999;
// }
// &-value {
// line-height: 38rpx;
// font-size: 24rpx;
// color: #333333;
// margin-right: 10rpx;
// }
// &-action {
// width: 11rpx;
// height: 7rpx;
// }
// }
// }
}
.buy-progress {
display: flex;
align-items: center;
justify-content: space-between;
&-info {
flex: 1;
&-desc {
color: #999999;
font-size: 24rpx;
line-height: 32rpx;
}
}
&-action {
margin-left: 17rpx;
}
}
.buy-num {
&-info-desc {
color: #999999;
font-size: 24rpx;
line-height: 32rpx;
}
}
</style>