jiuyiUniapp/jiuyi2/components/shop/detail/detail.vue

605 lines
12 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.

<script setup>
/**
* 商品详情
*/
import {
ref,
reactive,
nextTick,
getCurrentInstance,
computed,
onMounted,
onUnmounted,
defineProps,
} from 'vue'
import {
useStore
} from 'vuex'
// 接口地址
import api from '@/api/index.js'
//
import util from '@/common/js/util.js'
// 传参
const props = defineProps({
id: {
type: [Number, String],
default: ''
},
detail: {
type: Object,
default: {}
},
})
const {
proxy
} = getCurrentInstance()
// 在这里设置swiper高度补足多端差异
const bannerHeight = ref('800rpx')
// 轮播图详情
const bannerIndex = ref(0)
// 商品评论
const comment = reactive({
list: [],
total: 0,
})
// 最近购买订单列表
const recentOrderList = ref([])
//
const menuFn = {
// 店铺
store() {
link('/pages/shop/store/index')
},
// 客服
customerService() {
link('/pages/news/question-answer/index')
},
// 收藏
heibianStar() {
//
}
}
// 已选择的规格下标
const spaceIndex = ref(0)
// 数量
const payNum = ref(1)
// 当前选择的规格
const currentSpec = computed(() => {
let spec = props.detail.specs || []
return spec[spaceIndex.value] || {}
})
// 应付总价
const total = computed(() => {
let price = parseFloat(props.detail.price) * 100
let result = parseInt(price * payNum.value) / 100
return result
})
// 详情
const banner = computed(() => {
let result = []
if (props.detail.sliderImage) result = props.detail.sliderImage.split(',')
return result
})
// 当前登录的用户信息
const userinfo = computed(() => {
return uni.$store.state.userinfo
})
onMounted(() => {
// 获取商品评论
getProComment()
// 获取最近购买
getRecentOrder()
})
// 获取最近购买
function getRecentOrder() {
api.shop.recentOrder({
query: {
// 产品id
productId: props.id,
}
}).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: props.id,
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,
})
})
}
/**
* 跳转路径
* @param {Object} url
*/
function link(url) {
uni.navigateTo({
url,
})
}
// 收藏店铺
function handleCollectStore() {
api.shop.followShop({
data: {
shopId: props.detail.merId,
status: {
0: 1,
1: 0,
} [props.detail.isFollow]
}
}).then(rs => {
if (rs.code == 200) {
// 关注状态
props.detail.isFollow = {
0: 1,
1: 0,
} [props.detail.isFollow]
// 关注数量
props.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,
} [props.detail.isCollect]
}
}).then(rs => {
if (rs.code == 200) {
// 关注状态
props.detail.isCollect = {
0: 1,
1: 0,
} [props.detail.isCollect]
// 关注数量
props.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: props.detail.merId
}
}).then(rs => {
if (rs.code == 200) {
Object.assign(props.detail, {}, rs.data)
return
}
util.alert({
content: rs.msg,
showCancel: false,
})
})
}
/**
* 立即下单
*/
function handlePay(event) {
// 产生待付款订单
api.shop.addOrder({
data: [{
// 地址id
addressId: event.address.id,
// 产品id
productId: props.detail.id,
// 规格id
attrValueId: event.spec.id,
// 数量
payNum: event.payNum,
// 0-普通订单1-视频号订单
orderType: 0,
// 分享人id
// shareId: userinfo.id,
}],
}).then(rs => {
if (rs.code === 200) {
// 跳转
if (rs.data && rs.data[0]) uni.navigateTo({
url: util.setUrl('/pages/shop/commodity/payment', {
orderId: rs.data[0].orderId,
})
})
return
}
util.alert({
content: rs.msg,
showCancel: false,
})
})
}
</script>
<template>
<view class="container">
<!-- 轮播图 -->
<view class="banner pr" v-if="detail.sliderImage">
<swiper class="swiper" :style="{height: bannerHeight,}" :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="count pa ptb5 plr20 bar">
<text class="text cfff f24">{{ bannerIndex + 1 }} / {{ banner.length }}</text>
</view>
</view>
<!-- 商品详情 -->
<view class="detail bfff ptb25 plr20">
<view class="line df fdr jcsb">
<view class="price df fdr aic">
<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 t2hd">
<text class="c333 f34">{{detail.name}}</text>
</view>
<view class="history mtb20 df fdr jcsb aic">
<text class="c666 f28">商品修改历史</text>
<uni-icons type="right" color="#999" size="30rpx" />
</view>
<!-- 福利政策 -->
<view class="gift df fdr fww mtb20">
<view class="item">
<text class="text">假一赔十</text>
</view>
<view class="item">
<text class="text">7天无理由退货</text>
</view>
<view class="item">
<text class="text">全场包邮</text>
</view>
<view class="item">
<text class="text">48h内发货</text>
</view>
<view class="item" v-if="0">
<text class="text">支持先用后付</text>
</view>
</view>
</view>
<!-- 最近购买 -->
<view class="recently mtb20" v-if="recentOrderList[0]">
<swiper class="swiper" style="height: 220rpx;" :autoplay="true" vertical="true">
<swiper-item v-for="(item, index) in recentOrderList" :key="index">
<view class="list plr10 bfff">
<view class="item bsb df fdr jcsb aic 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">
<text class="name c666 f28">{{secItem.nickname}}</text>
</view>
<view class="info mlr10 tar">
<!-- <view class="fn">刚刚下单</view> -->
<view class="time">
<text class="c999 f26">{{secItem.time}}</text>
</view>
</view>
<view class="btn sm warm plr15">
<text class="cfff f26">立即购买</text>
</view>
</view>
</view>
</swiper-item>
</swiper>
</view>
<!-- 商品评价 -->
<view class="evaluate mtb20 plr25 bfff">
<view class="header df fdr jcsb aic 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 fdr aic">
<image class="avatar wh45 cir" :src="item.avatar" mode="aspectFill" />
<view class="name thd f32 f1 ml20">
<text class="c666 f28">{{item.nickname}}</text>
</view>
</view>
<view class="content t2hd mt10">
<text class="c333 f28">{{item.content}}</text>
</view>
</view>
</view>
</view>
<!-- 店铺 -->
<view class="store df fdr aic jcsb mtb20 ptb20 plr25 bfff">
<view class="header df fdr jcsb aic">
<!-- 店铺头像 -->
<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 fdr 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">
<text class=" c666 f24">{{detail.merFollowNumber}}关注</text>
</view>
</view>
</view>
</view>
<!-- 关注按钮 -->
<view @click="handleCollectStore" class="btn sm warm fmid fdr plr30">
<uni-icons class="mr10" color="#fff" type="plusempty" size="13" v-if="detail.isFollow != 1" />
<text class="cfff f28" v-else>已</text>
<text class="cfff f28">关注</text>
</view>
</view>
<!-- 宝贝详情 -->
<view class="p25 mtb240 bfff">
<view class="title">
<text class="modelTitle">宝贝详情</text>
</view>
<!-- 商品详情 -->
<view class="content mt30">
<rich-text :nodes="detail.infoRichText || ''" />
</view>
</view>
<!-- 填充 -->
<view class="fill" style="height: 180rpx;"></view>
<!-- 底部 -->
<view class="footerMneu pa rows plr20 shadow bfff">
<view class="menu df fdr jcsb aic">
<view class="option ver">
<image class="wh30" src="/static/store.png" mode="widthFix" />
<view class="f24 c999 mt10">店铺</view>
</view>
<view class="option ver " @click="handleCollect">
<view class="wh30 fmid">
<uni-icons type="star-filled" size="45rpx" color="#FF9B27" v-if="detail.isCollect == 1" />
<uni-icons type="star" size="45rpx" color="#666" v-else />
</view>
<view class="f24 c999 mt10">
<text v-if="detail.isCollect == 1">已</text>
<text>收藏</text>
</view>
</view>
<!-- <view class="option ver ">
<image class="wh30" src="/static/customer-service.png" mode="widthFix" />
<view class="f24 c999 mt10">客服</view>
</view> -->
</view>
<!-- 下单 -->
<view class="btn lg primary f1 ml30" @click="$refs.makeOrderRef.open()">
<text>立即购买</text>
</view>
</view>
</view>
</template>
<style lang="scss">
.container {
overflow: hidden;
}
// 轮播图
.banner {
.swiper {
.poster {
width: 750rpx;
height: 800rpx;
}
}
.count {
bottom: 20rpx;
right: 20rpx;
background-color: rgba(0, 0, 0, .4);
.text {
color: #fff;
}
}
}
// 模块标题
.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;
}
.text {
color: #999;
font-size: 24rpx;
}
}
}
// 最近购买
.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;
}
}
}
// 店铺
.store {
.info {
.item {
margin-right: 10rpx;
}
.item+.item {
padding-left: 10rpx;
border-left: 2rpx solid #eee;
}
}
}
// 底部菜单
.footerMneu {
left: 0;
right: 0;
bottom: 0;
// 选项
.option {
width: 80rpx;
}
}
</style>