585 lines
12 KiB
Vue
585 lines
12 KiB
Vue
<script setup>
|
|
// 商品详情
|
|
import {
|
|
ref,
|
|
reactive,
|
|
nextTick,
|
|
getCurrentInstance,
|
|
computed,
|
|
} from 'vue'
|
|
import {
|
|
onLoad,
|
|
onReady,
|
|
onPageScroll,
|
|
onUnload,
|
|
} from '@dcloudio/uni-app'
|
|
import {
|
|
useStore
|
|
} from 'vuex'
|
|
// 接口地址
|
|
import api from '@/api/index.js'
|
|
//
|
|
import util from '@/common/js/util.js'
|
|
// 头部
|
|
import apex from './components/jy-commodity-head';
|
|
// 商品列表
|
|
import productList from '@/components/shop/productList/productList'
|
|
//底部
|
|
import JyCommodityFoot from './components/jy-commodity-foot';
|
|
const {
|
|
proxy
|
|
} = getCurrentInstance()
|
|
const store = useStore()
|
|
// 产品详情
|
|
const detail = reactive({})
|
|
// 产品id
|
|
const id = ref('')
|
|
// 轮播图详情
|
|
const bannerIndex = ref(0)
|
|
// 商品评论
|
|
const comment = reactive({
|
|
list: [],
|
|
total: 0,
|
|
})
|
|
// 最近购买订单列表
|
|
const recentOrderList = ref([])
|
|
// 详情
|
|
const banner = computed(() => {
|
|
let result = []
|
|
if (detail.sliderImage) result = detail.sliderImage.split(',')
|
|
return result
|
|
})
|
|
// 当前登录的用户信息
|
|
const userinfo = computed(() => {
|
|
return store.state.userinfo
|
|
})
|
|
|
|
onLoad(option => {
|
|
if (option.productId) id.value = option.productId
|
|
// 获取产品详情
|
|
getDetail()
|
|
// 添加商品浏览记录
|
|
addBrowsing()
|
|
// 获取商品评论
|
|
getProComment()
|
|
// 获取最近购买
|
|
getRecentOrder()
|
|
// 开启监听
|
|
addListener()
|
|
})
|
|
|
|
onReady(() => {
|
|
//
|
|
})
|
|
|
|
// 销毁监听
|
|
onUnload(() => {
|
|
removeListener()
|
|
})
|
|
|
|
onPageScroll((ev) => {
|
|
if (ev.scrollTop > 44) proxy.$refs.apexRef.headerActive = true
|
|
else proxy.$refs.apexRef.headerActive = false
|
|
})
|
|
|
|
// 开启监听
|
|
function addListener() {
|
|
// 监听商品详情
|
|
uni.$on('commodityDetail', (data) => {
|
|
//
|
|
if (detail.id == data.id) getDetail()
|
|
})
|
|
}
|
|
|
|
// 移除监听
|
|
function removeListener() {
|
|
uni.$off('commodityDetail')
|
|
}
|
|
|
|
// 获取最近购买
|
|
function getRecentOrder() {
|
|
api.shop.recentOrder({
|
|
query: {
|
|
// 产品id
|
|
productId: id.value,
|
|
}
|
|
}).then(rs => {
|
|
if (rs.code == 200) {
|
|
// 结果
|
|
const result = rs.data
|
|
let list = []
|
|
//
|
|
for (let i = 0; i < result.length / 2; i++) {
|
|
if (!result[i * 2 + 1]) break
|
|
list.push([result[i * 2], result[i * 2 + 1]])
|
|
}
|
|
recentOrderList.value = list
|
|
return
|
|
}
|
|
util.alert({
|
|
content: rs.msg,
|
|
showCancel: false,
|
|
})
|
|
})
|
|
}
|
|
|
|
// 获取商品评论
|
|
function getProComment() {
|
|
api.shop.getProComment({
|
|
query: {
|
|
// 产品id
|
|
productId: id.value,
|
|
pageNum: 1,
|
|
pageSize: 2,
|
|
}
|
|
}).then(rs => {
|
|
if (rs.code == 200) {
|
|
comment.list = rs.rows
|
|
comment.total = rs.total
|
|
return
|
|
}
|
|
util.alert({
|
|
content: rs.msg,
|
|
showCancel: false,
|
|
})
|
|
})
|
|
}
|
|
|
|
// 添加商品浏览记录
|
|
function addBrowsing() {
|
|
// 验证登录
|
|
util.isLogin(() => {
|
|
try {
|
|
// 添加浏览记录
|
|
api.shop.addBrowsing({
|
|
data: {
|
|
userId: userinfo.value.id,
|
|
goodsId: id.value
|
|
},
|
|
}).then(rs => {
|
|
if (rs.code != 200) console.log('addbrows err', rs.msg)
|
|
})
|
|
} catch (ev) {
|
|
console.log('addBrowsing', ev)
|
|
}
|
|
})
|
|
}
|
|
|
|
// 获取详情
|
|
function getDetail() {
|
|
api.shop.productDetail({
|
|
query: {
|
|
userId: userinfo.value.id,
|
|
// 产品id
|
|
productionId: id.value
|
|
}
|
|
}).then(rs => {
|
|
if (rs.code == 200) {
|
|
Object.assign(detail, {}, rs.data)
|
|
return
|
|
}
|
|
util.alert({
|
|
content: rs.msg,
|
|
showCancel: false,
|
|
})
|
|
})
|
|
}
|
|
|
|
/**
|
|
* 跳转路径
|
|
* @param {Object} url
|
|
*/
|
|
function link(url) {
|
|
uni.navigateTo({
|
|
url,
|
|
})
|
|
}
|
|
|
|
// 收藏店铺
|
|
function handleCollectStore() {
|
|
api.shop.followShop({
|
|
data: {
|
|
shopId: detail.merId,
|
|
status: {
|
|
0: 1,
|
|
1: 0,
|
|
} [detail.isFollow]
|
|
}
|
|
}).then(rs => {
|
|
if (rs.code == 200) {
|
|
// 关注状态
|
|
detail.isFollow = {
|
|
0: 1,
|
|
1: 0,
|
|
} [detail.isFollow]
|
|
// 关注数量
|
|
detail.merFollowNumber = rs.data
|
|
return
|
|
}
|
|
util.alert({
|
|
content: rs.msg,
|
|
showCancel: false,
|
|
})
|
|
})
|
|
}
|
|
|
|
// 商品收藏
|
|
function handleCollect() {
|
|
util.isLogin().then(rs => {
|
|
//
|
|
api.shop.addProductCollect({
|
|
data: {
|
|
productId: id.value,
|
|
status: {
|
|
0: 1,
|
|
1: 0,
|
|
} [detail.isCollect]
|
|
}
|
|
}).then(rs => {
|
|
if (rs.code == 200) {
|
|
// 关注状态
|
|
detail.isCollect = {
|
|
0: 1,
|
|
1: 0,
|
|
} [detail.isCollect]
|
|
// 关注数量
|
|
detail.collectNumber = rs.data
|
|
return
|
|
}
|
|
util.alert({
|
|
content: rs.msg,
|
|
showCancel: false,
|
|
})
|
|
})
|
|
}).catch(() => {
|
|
// 登录
|
|
uni.navigateTo({
|
|
url: '/pages/login/loginPhone'
|
|
})
|
|
})
|
|
}
|
|
|
|
// 获取店铺信息
|
|
function getShop() {
|
|
api.shop.shopDetail({
|
|
query: {
|
|
shopId: detail.merId
|
|
}
|
|
}).then(rs => {
|
|
if (rs.code == 200) {
|
|
Object.assign(detail, {}, rs.data)
|
|
return
|
|
}
|
|
util.alert({
|
|
content: rs.msg,
|
|
showCancel: false,
|
|
})
|
|
})
|
|
}
|
|
|
|
/**
|
|
* 详情
|
|
* @param {Object} ev 修改的详情
|
|
*/
|
|
function handleDetail(ev) {
|
|
Object.assign(detail, {}, ev)
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<view class="app pr">
|
|
<!-- 头部 -->
|
|
<apex ref="apexRef" :detail="detail"></apex>
|
|
|
|
<!-- 轮播图 -->
|
|
<view class="banner pr" v-if="detail.sliderImage">
|
|
<swiper class="swiper" :current="bannerIndex" @change="($event) => bannerIndex = $event.detail.current">
|
|
<swiper-item v-for="(item, index) in banner" :key="index">
|
|
<image class="poster" :src="item" mode="aspectFill" />
|
|
</swiper-item>
|
|
</swiper>
|
|
|
|
<!-- 计数器 -->
|
|
<view class="text pa ptb5 plr20 cfff f24 bar">{{ bannerIndex + 1 }} / {{ banner.length }}</view>
|
|
</view>
|
|
|
|
<!-- 商品详情 -->
|
|
<view class="detail bfff ptb25 plr20">
|
|
<view class="line rows">
|
|
<view class="price">
|
|
<text class="txt">¥</text>
|
|
<text class="txt f56">{{detail.price}}</text>
|
|
</view>
|
|
|
|
<!-- 已售 -->
|
|
<view class="sold">
|
|
<text class="c999 f26">已售 {{detail.sales}}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 优惠券 -->
|
|
<view class="coupon df fdr fww f26 mtb20 cFF9B27" v-if="0">
|
|
<view class="item">
|
|
<text>限时直降0.5元</text>
|
|
</view>
|
|
<view class="item">
|
|
<text>平台立减1元</text>
|
|
</view>
|
|
<view class="item">
|
|
<text>关注店铺1元优惠券</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 商品名称 -->
|
|
<view class="name mtb20 f34 c333 t2hd">{{detail.name}}</view>
|
|
|
|
<view class="history mtb20 rows">
|
|
<view class="c666 f28">商品修改历史</view>
|
|
<uni-icons type="right" />
|
|
</view>
|
|
|
|
<!-- 福利政策 -->
|
|
<view class="gift df fdr fww c999 f24 mtb20">
|
|
<view class="item">
|
|
<text>假一赔十</text>
|
|
</view>
|
|
<view class="item">
|
|
<text>7天无理由退货</text>
|
|
</view>
|
|
<view class="item">
|
|
<text>全场包邮</text>
|
|
</view>
|
|
<view class="item">
|
|
<text>48h内发货</text>
|
|
</view>
|
|
<view class="item" v-if="0">
|
|
<text>支持先用后付</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 最近购买 -->
|
|
<view class="recently mtb20" v-if="recentOrderList[0]">
|
|
<swiper class="swiper" :autoplay="true" vertical="true">
|
|
<swiper-item v-for="(item, index) in recentOrderList" :key="index">
|
|
<view class="list plr10 bfff">
|
|
<view class="item bsb rows plr10" v-for="(secItem, secIndex) in item" :key="secIndex">
|
|
<view class="avatar">
|
|
<image class="avatar wh70 cir" :src="secItem.avatar" mode="aspectFill" />
|
|
</view>
|
|
|
|
<view class="name f1 mlr10 f28">{{secItem.nickname}}</view>
|
|
<view class="info mlr10 f26 tar">
|
|
<!-- <view class="fn">刚刚下单</view> -->
|
|
<view class="time c999">{{secItem.time}}</view>
|
|
</view>
|
|
<view class="btn sm warm plr15">立即购买</view>
|
|
</view>
|
|
</view>
|
|
</swiper-item>
|
|
</swiper>
|
|
</view>
|
|
|
|
<!-- 商品评价 -->
|
|
<view class="evaluate mtb20 plr25 bfff">
|
|
<view class="header rows ptb25"
|
|
@click="link(util.setUrl('/pages/shop/commodity/evaluate',{id: detail.id}))">
|
|
<text class="modelTitle">商品评价({{comment.total}})</text>
|
|
<uni-icons type="right" />
|
|
</view>
|
|
|
|
<!-- 部分评论 -->
|
|
<view class="list">
|
|
<view class="item ptb20" v-for="(item, index) in comment.list" :key="index">
|
|
<view class="userinfo df c666 f28">
|
|
<image class="avatar wh45 cir" :src="item.avatar" mode="aspectFill" />
|
|
<view class="name thd f32 f1 ml20">{{item.nickname}}</view>
|
|
</view>
|
|
<view class="content t2hd mt10 c333 f28">{{item.content}}</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 店铺 -->
|
|
<view class="store df aic jcsb mtb20 ptb20 plr25 bfff">
|
|
<view class="header rows">
|
|
<!-- 店铺头像 -->
|
|
<image class="wh140 br20" :src="detail.merAvatar" mode="aspectFill" />
|
|
<!-- 店铺信息 名称 评分 关注数量 -->
|
|
<view class="info f1 mlr20">
|
|
<!-- 店铺名称 -->
|
|
<view class="name thd">
|
|
<text class="f34 c333">{{detail.merName}}</text>
|
|
</view>
|
|
<view class="line df dfr aic mt10">
|
|
<!-- 评分 -->
|
|
<!-- <view class="item f24 c666 df aic ">
|
|
<uni-rate class="mr10" :value="4.5" :size="12" activeColor="#FF9B27" readonly />
|
|
<text>4.5</text>
|
|
</view> -->
|
|
<!-- 关注数量 -->
|
|
<view class="item follow c666 f24">
|
|
<text>{{detail.merFollowNumber}}关注</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 关注按钮 -->
|
|
<view @click="handleCollectStore" class="btn sm warm plr30">
|
|
<uni-icons class="mr10" color="#fff" type="plusempty" size="13" v-if="detail.isFollow != 1" />
|
|
<text class="cfff" v-else>已</text>
|
|
<text class="cfff">关注</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 宝贝详情 -->
|
|
<view class="p25 mtb240 bfff">
|
|
<view class="title">
|
|
<text class="modelTitle">宝贝详情</text>
|
|
</view>
|
|
<!-- 商品详情 -->
|
|
<view class="content mt30">
|
|
<rich-text :nodes="detail.intro" />
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 精选 -->
|
|
<view class="recommend mlr20">
|
|
<productList :choicenessTitle="true" />
|
|
</view>
|
|
|
|
<!-- 底部 -->
|
|
<JyCommodityFoot :detail="detail" @update="handleDetail" />
|
|
</view>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
// 补齐轮播图高度
|
|
.swiper {
|
|
height: 100%;
|
|
}
|
|
|
|
// 轮播图
|
|
.banner {
|
|
|
|
.swiper {
|
|
height: 800rpx;
|
|
|
|
.poster {
|
|
width: 750rpx;
|
|
height: 800rpx;
|
|
}
|
|
}
|
|
|
|
.text {
|
|
bottom: 20rpx;
|
|
right: 20rpx;
|
|
color: #fff;
|
|
background-color: #000a;
|
|
}
|
|
}
|
|
|
|
// 模块标题
|
|
.modelTitle {
|
|
color: #333;
|
|
font-size: 30rpx;
|
|
}
|
|
|
|
// 详情
|
|
.detail {
|
|
.price .txt {
|
|
color: #FF7F37;
|
|
}
|
|
|
|
// 优惠券
|
|
.coupon {
|
|
.item {
|
|
padding: 2rpx 10rpx;
|
|
margin-right: 15rpx;
|
|
margin-bottom: 15rpx;
|
|
border: 2rpx solid;
|
|
border-radius: 6rpx;
|
|
}
|
|
}
|
|
|
|
.gift {
|
|
.item {
|
|
margin-right: 20rpx;
|
|
margin-right: 20rpx;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 最近购买
|
|
.recently {
|
|
height: 220rpx;
|
|
|
|
.item {
|
|
height: 110rpx;
|
|
|
|
&+.item {
|
|
border-top: 2rpx solid #eee;
|
|
}
|
|
|
|
.info .fn {
|
|
color: #FF9B27;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 商品评价
|
|
.evaluate {
|
|
.header {
|
|
border-bottom: 2rpx solid #eee;
|
|
}
|
|
|
|
.list {
|
|
.item+.item {
|
|
border-top: 2rpx solid #eee;
|
|
}
|
|
}
|
|
}
|
|
|
|
.comment-popup {
|
|
border-radius: 20px 20px 0px 0px;
|
|
|
|
.title {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
font-weight: 600;
|
|
padding: 28rpx 0 14rpx 0;
|
|
font-size: $uni-font-size-lg;
|
|
}
|
|
|
|
.close {
|
|
position: absolute;
|
|
right: 20rpx;
|
|
top: 30rpx;
|
|
display: inline-block;
|
|
width: 50rpx;
|
|
height: 50rpx;
|
|
}
|
|
|
|
//滚动
|
|
.jy-comment-list-content {
|
|
overflow: auto;
|
|
}
|
|
}
|
|
|
|
// 店铺
|
|
.store {
|
|
|
|
.info {
|
|
.item {
|
|
margin-right: 10rpx;
|
|
}
|
|
|
|
.item+.item {
|
|
padding-left: 10rpx;
|
|
border-left: 2rpx solid #eee;
|
|
}
|
|
}
|
|
}
|
|
</style> |