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.
532 lines
13 KiB
532 lines
13 KiB
<template>
|
|
<view class="app">
|
|
<pageHeader ref="pageHeader"></pageHeader>
|
|
<!-- 轮播图 -->
|
|
<mix-swiper :list="data.images"></mix-swiper>
|
|
<view class="introduce column">
|
|
<text class="title">{{ data.title }}</text>
|
|
<view class="price-wrap row">
|
|
<mix-price-view :price="data.price" :size="40"></mix-price-view>
|
|
<text v-if="data.market_price > data.price" class="m-price">¥{{ data.market_price }}</text>
|
|
<text v-if="loaded && !data.freight_template" class="tag">免邮费</text>
|
|
</view>
|
|
<view class="bot row">
|
|
<text class="fill">销量: {{ data.sales || 0 }}</text>
|
|
<text class="fill">库存: {{ data.stock || 0 }}</text>
|
|
<text class="fill">浏览量: {{ data.look_num || 0 }}</text>
|
|
</view>
|
|
</view>
|
|
<!-- 分享 -->
|
|
<view class="share-wrap row">
|
|
<view class="icon row">
|
|
<text class="mix-icon icon-iconfontxingxing"></text>
|
|
<text>分享</text>
|
|
</view>
|
|
<text class="tit">发给好友看看吧~</text>
|
|
<text class="mix-icon icon-bangzhu1"></text>
|
|
|
|
<!-- #ifdef MP-WEIXIN -->
|
|
<button type="primary" open-type="share">
|
|
<view class="btn">
|
|
立即分享
|
|
<text class="mix-icon icon-you"></text>
|
|
</view>
|
|
</button>
|
|
<!-- #endif -->
|
|
<!-- #ifndef MP-WEIXIN -->
|
|
<view class="btn" @click="doAppShare">
|
|
立即分享
|
|
<text class="mix-icon icon-you"></text>
|
|
</view>
|
|
<!-- #endif -->
|
|
</view>
|
|
<view class="c-list">
|
|
<view v-if="data.skuData" class="row b-b" @click="showPopup('skuPopup')">
|
|
<text class="tit">购买类型</text>
|
|
<view class="con">
|
|
<text class="attr">{{ currentSku.name || '' }}</text>
|
|
</view>
|
|
<text class="mix-icon icon-you"></text>
|
|
</view>
|
|
<view class="row b-b" @click="navTo('/pages/coupon/receiveCoupon', {login: true})">
|
|
<text class="tit">优惠券</text>
|
|
<text class="con red">领取优惠券</text>
|
|
<text class="mix-icon icon-you"></text>
|
|
</view>
|
|
<!-- <view class="row b-b">
|
|
<text class="tit">促销活动</text>
|
|
<view class="con-list fill column">
|
|
<text>新人首单送20元无门槛代金券</text>
|
|
<text>订单满50减10</text>
|
|
<text>订单满100减30</text>
|
|
<text>单笔购买满两件免邮费</text>
|
|
</view>
|
|
</view> -->
|
|
<view class="row b-b">
|
|
<text class="tit">服务</text>
|
|
<view class="con">
|
|
<text class="service">7天无理由退换货 ·</text>
|
|
<text class="service">假一赔十 ·</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<!-- 评价 -->
|
|
<view id="rating" class="rating-wrap column" :class="{'no-data': !ratingData.data}">
|
|
<view class="e-header" @click="navTo('/pages/rating/rating?id='+data._id)">
|
|
<text class="tit">商品评价</text>
|
|
<text>({{ ratingData.count || 0 }})</text>
|
|
<text class="tip">好评率 {{ data.rating_ratio || 100 }}%</text>
|
|
<text class="mix-icon icon-you"></text>
|
|
</view>
|
|
<rating-item v-if="ratingData.data" :item="ratingData.data"></rating-item>
|
|
</view>
|
|
<view class="detail-desc">
|
|
<view class="d-header center">
|
|
<text>图文详情</text>
|
|
</view>
|
|
<jyf-parser
|
|
ref="article"
|
|
:html="data.content"
|
|
lazy-load
|
|
show-with-animation
|
|
></jyf-parser>
|
|
<!-- <rich-text :nodes="data.content"></rich-text> -->
|
|
</view>
|
|
<!-- 底部操作菜单 -->
|
|
<bottom-operation :infoData="data" @onOprationClick="onOprationClick"></bottom-operation>
|
|
<!-- 规格面板 -->
|
|
<sku v-if="data._id" ref="skuPopup" :infoData="data" @setSku="setCurrentSku" @addToCart="addToCart" @buyNow="buyNow"></sku>
|
|
<!-- loading -->
|
|
<mix-loading v-if="isLoading" :mask="true"></mix-loading>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import jyfParser from '@/components/jyf-parser/jyf-parser.vue'
|
|
import pageHeader from './components/detail-page-header'//页面头
|
|
import mixSwiper from './components/mix-swiper'//轮播图
|
|
import ratingItem from '@/pages/rating/components/rating-item'//评价
|
|
import bottomOperation from './components/bottom-operation'//底部栏
|
|
import sku from './components/sku'//sku面板
|
|
let _anchorList = [];
|
|
export default{
|
|
components: {
|
|
jyfParser,
|
|
pageHeader,
|
|
mixSwiper,
|
|
ratingItem,
|
|
bottomOperation,
|
|
sku
|
|
},
|
|
data() {
|
|
return {
|
|
currentSku: {},
|
|
data: {
|
|
images: [],
|
|
},
|
|
ratingData: {}, //评价
|
|
};
|
|
},
|
|
onLoad(options){
|
|
this.id = options.id;
|
|
this.loadRating(); //加载评价
|
|
},
|
|
onShow() {
|
|
this.loadData();
|
|
},
|
|
onPageScroll(e) {
|
|
this.$refs.pageHeader && this.$refs.pageHeader.pageScroll(e);
|
|
},
|
|
// #ifdef MP-WEIXIN
|
|
onShareAppMessage(res) {
|
|
return {
|
|
title: this.data.title,
|
|
path: '/pages/product/detail?id='+this.data._id,
|
|
imageUrl: this.data.thumb
|
|
}
|
|
},
|
|
// #endif
|
|
methods:{
|
|
async loadData(){
|
|
const res = await this.$request('product', 'getDetail', {
|
|
id: this.id
|
|
})
|
|
if(res.status === 0){
|
|
this.$util.msg(res.msg || '产品不存在或已下架');
|
|
setTimeout(()=>{
|
|
uni.navigateBack();
|
|
}, 1000)
|
|
return;
|
|
}
|
|
const data = res.data;
|
|
data.content = data.content.replace(/img src="/g, 'img style="display:block;width:100%;height:auto" src="');
|
|
this.data = data;
|
|
this.$nextTick(()=>{
|
|
this.calcAnchor();//计算锚点参数
|
|
})
|
|
//添加浏览历史
|
|
this.addProductHistory();
|
|
},
|
|
//加载评价
|
|
async loadRating(){
|
|
const res = await this.$request('rating', 'getDetailRating', {
|
|
product_id: this.id,
|
|
})
|
|
this.ratingData = res;
|
|
this.$nextTick(()=>{
|
|
this.calcAnchor();//计算锚点参数
|
|
})
|
|
},
|
|
//加入购物车
|
|
addToCart(){
|
|
this.$util.throttle(async ()=>{
|
|
const data = this.getConfirmData();
|
|
if(!data){
|
|
return;
|
|
}
|
|
const res = await this.$request('cart', 'add', data, {
|
|
showLoading: true,
|
|
login: true
|
|
})
|
|
if(!res){
|
|
return;
|
|
}
|
|
this.log(res)
|
|
this.$util.msg(res.msg);
|
|
if(res.status === 1){
|
|
this.hidePopup('skuPopup');
|
|
this.$store.dispatch('getCartCount');//更新购物车数量
|
|
uni.$emit('refreshCart');//更新购物车
|
|
}
|
|
})
|
|
},
|
|
//立即购买
|
|
buyNow(){
|
|
const data = this.getConfirmData();
|
|
if(!data){
|
|
return;
|
|
}
|
|
this.hidePopup('skuPopup');
|
|
this.navTo('/pages/order/createOrder?data='+JSON.stringify(data), {
|
|
login: true
|
|
})
|
|
},
|
|
//设置当前选择sku
|
|
setCurrentSku(data){
|
|
this.currentSku = data;
|
|
},
|
|
//获取当前sku 如果没有sku返回默认规格
|
|
getConfirmData(){
|
|
const sku = this.currentSku._id ? this.currentSku: this.data.sku[0];
|
|
if(sku.stock <= 0 || this.data.stock <= 0){
|
|
this.$util.msg('库存不足');
|
|
return false;
|
|
}
|
|
const data = {
|
|
product_id: this.data._id,
|
|
number: this.$refs.skuPopup.buyNumber || 1,
|
|
sku: this.currentSku._id ? this.currentSku: this.data.sku[0]
|
|
}
|
|
return data;
|
|
},
|
|
//计算锚点参数
|
|
async calcAnchor(){
|
|
const size = await new Promise(res => {
|
|
uni.createSelectorQuery().select('#rating').boundingClientRect(data => {
|
|
res(data);
|
|
}).exec();
|
|
});
|
|
const headerHeight = this.systemInfo.statusBarHeight + this.systemInfo.navigationBarHeight;
|
|
const a1 = (size ? size.top : 0) - headerHeight;
|
|
const a2 = (size ? size.bottom : 0) + uni.upx2px(12) - headerHeight;
|
|
this.$refs.pageHeader.anchorList[1].top = a1;
|
|
this.$refs.pageHeader.anchorList[2].top = a2;
|
|
_anchorList = [0, a1, a2];
|
|
},
|
|
//添加浏览历史
|
|
addProductHistory(){
|
|
const data = this.data;
|
|
let list = uni.getStorageSync('productHistory');
|
|
if(!list){
|
|
list = [];
|
|
}
|
|
const index = list.findIndex(item=> item.id === data._id);
|
|
if(index !== -1){
|
|
list.splice(index, 1);
|
|
}
|
|
list.unshift({
|
|
id: data._id,
|
|
thumb: data.thumb
|
|
})
|
|
uni.setStorageSync('productHistory', list);
|
|
},
|
|
//删除当前浏览历史
|
|
delHistory(){
|
|
let list = uni.getStorageSync('productHistory');
|
|
if(!list){
|
|
return;
|
|
}
|
|
const index = list.findIndex(item=> item._id === data._id);
|
|
if(index === -1){
|
|
return;
|
|
}
|
|
list.splice(index, 1);
|
|
uni.setStorageSync('productHistory', list);
|
|
},
|
|
showPopup(key, type){
|
|
this.$refs[key].open(type);
|
|
},
|
|
onOprationClick(type){
|
|
this.showPopup('skuPopup', type);
|
|
},
|
|
doAppShare(){
|
|
this.$util.throttle(async ()=>{
|
|
const data = {
|
|
provider: "weixin",
|
|
scene: 'WXSceneSession',
|
|
type: 5,
|
|
imageUrl: this.data.thumb,
|
|
title: this.data.title,
|
|
miniProgram: {
|
|
id: 'gh_3dada2e0f833',
|
|
path: '/pages/product/detail?id='+this.data._id,
|
|
type: 0,
|
|
webUrl: 'http://guoyunnet.com'
|
|
},
|
|
success: res=> {
|
|
console.log("success:" + JSON.stringify(res));
|
|
},
|
|
fail: err=> {
|
|
console.log("fail:" + JSON.stringify(err));
|
|
}
|
|
}
|
|
uni.share(data);
|
|
})
|
|
},
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
page{
|
|
background-color: #f5f5f5;
|
|
}
|
|
</style>
|
|
<style scoped lang='scss'>
|
|
.app{
|
|
padding-bottom: constant(safe-area-inset-bottom);
|
|
padding-bottom: env(safe-area-inset-bottom);
|
|
|
|
&:after{
|
|
content: '';
|
|
display: block;
|
|
width: 100%;
|
|
height: 100rpx;
|
|
}
|
|
}
|
|
/* 标题简介 */
|
|
.introduce{
|
|
background: #fff;
|
|
padding: 20rpx 30rpx;
|
|
|
|
.title{
|
|
min-height: 44rpx;
|
|
font-size: 32rpx;
|
|
color: #333;
|
|
line-height: 44rpx;
|
|
font-weight: 700;
|
|
}
|
|
.price-wrap{
|
|
min-height: 40rpx;
|
|
margin-top: 28rpx;
|
|
font-size: 26rpx;
|
|
}
|
|
.m-price{
|
|
margin-left: 10rpx;
|
|
margin-right: 16rpx;
|
|
color: #999;
|
|
text-decoration: line-through;
|
|
}
|
|
.tag{
|
|
transform: translateY(4rpx);
|
|
padding: 0 10rpx;
|
|
margin-left: 8rpx;
|
|
background: $base-color;
|
|
font-size: 20rpx;
|
|
color: #fff;
|
|
line-height: 32rpx;
|
|
border-radius: 4rpx;
|
|
position: relative;
|
|
bottom: 8rpx;
|
|
}
|
|
.bot{
|
|
padding: 28rpx 0 10rpx 4rpx;
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
/* 分享 */
|
|
.share-wrap{
|
|
background: linear-gradient(to right, #fdf5f6, #fbebf6);
|
|
height: 76rpx;
|
|
padding: 0 30rpx;
|
|
color: $base-color;
|
|
|
|
.icon{
|
|
width: 90rpx;
|
|
height: 30rpx;
|
|
border: 1px solid $base-color;
|
|
border-radius: 4rpx;
|
|
position: relative;
|
|
overflow: hidden;
|
|
font-size: 22rpx;
|
|
|
|
&:after{
|
|
position:absolute;
|
|
left: -20rpx;
|
|
top: -12rpx;
|
|
content: '';
|
|
width: 50rpx;
|
|
height: 50rpx;
|
|
border-radius: 50%;
|
|
background-color: $base-color;
|
|
}
|
|
}
|
|
.icon-iconfontxingxing{
|
|
position:relative;
|
|
z-index: 1;
|
|
font-size: 24rpx;
|
|
margin-left: 2rpx;
|
|
margin-right: 10rpx;
|
|
color: #fff;
|
|
}
|
|
.tit{
|
|
flex: 1;
|
|
font-size: 26rpx;
|
|
color: #666;
|
|
margin-left:14rpx;
|
|
}
|
|
.icon-bangzhu1{
|
|
padding: 10rpx;
|
|
font-size: 30rpx;
|
|
display: none;
|
|
}
|
|
.btn{
|
|
padding-left: 20rpx;
|
|
font-size: 24rpx;
|
|
color: $base-color;
|
|
}
|
|
.icon-you{
|
|
font-size: 22rpx;
|
|
margin-left: 4rpx;
|
|
color: $base-color;
|
|
}
|
|
}
|
|
.c-list{
|
|
font-size: 26rpx;
|
|
color: #888;
|
|
background: #fff;
|
|
|
|
.row{
|
|
min-height: 82rpx;
|
|
padding: 16rpx 30rpx;
|
|
position:relative;
|
|
|
|
&:after{
|
|
border-color: #eaeaea;
|
|
}
|
|
&:last-child:after{
|
|
border: 0;
|
|
}
|
|
}
|
|
.tit{
|
|
width: 140rpx;
|
|
}
|
|
.con{
|
|
flex: 1;
|
|
color: #333;
|
|
|
|
.attr{
|
|
margin-right: 10rpx;
|
|
}
|
|
.service{
|
|
margin-right: 30rpx;
|
|
|
|
&:last-child{
|
|
margin: 0;
|
|
}
|
|
}
|
|
}
|
|
.con-list{
|
|
color: #333;
|
|
|
|
text{
|
|
line-height: 40rpx;
|
|
}
|
|
}
|
|
.red{
|
|
color: $base-color;
|
|
}
|
|
.icon-you{
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
/* 评价 */
|
|
.rating-wrap{
|
|
padding: 20rpx 30rpx 0rpx;
|
|
background: #fff;
|
|
margin-top: 12rpx;
|
|
|
|
&.no-data{
|
|
padding: 10rpx 30rpx 10rpx;
|
|
}
|
|
.e-header{
|
|
display: flex;
|
|
align-items: center;
|
|
height: 70rpx;
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
}
|
|
.tit{
|
|
font-size: 32rpx;
|
|
color: #333;
|
|
font-weight: 700;
|
|
margin-right: 4rpx;
|
|
}
|
|
.tip{
|
|
flex: 1;
|
|
font-size: 26rpx;
|
|
color: #999;
|
|
text-align: right;
|
|
}
|
|
.icon-you{
|
|
margin-left: 8rpx;
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
.mix-rating-item::after{
|
|
border: 0;
|
|
}
|
|
}
|
|
/* 详情 */
|
|
.detail-desc{
|
|
margin-top: 12rpx;
|
|
background: #fff;
|
|
|
|
.d-header{
|
|
height: 80rpx;
|
|
font-size: 30rpx;
|
|
color: #333;
|
|
|
|
text{
|
|
margin: 0 20rpx;
|
|
}
|
|
&:before, &:after{
|
|
content: '';
|
|
width: 60rpx;
|
|
border-bottom: 1px solid #ccc;
|
|
}
|
|
}
|
|
}
|
|
</style>
|