Files

698 lines
15 KiB
Vue
Raw Normal View History

2023-10-11 11:27:47 +08:00
<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>