dingdong-mall/pages/product/product-detail.vue

409 lines
14 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>
<page-meta :page-style="'overflow:'+(ifShowPageMeta?'hidden':'visible')"></page-meta>
<view>
<!-- 顶部操作条 -->
<cu-custom :bgColor="'bg-white'" :isBack="true" :isBackHome="false" :homePageUrl="'/pages/index/index'">
<block slot="backText">返回</block>
<!-- <block slot="backHomeText">首页</block> -->
<block slot="content">商品详情</block>
</cu-custom>
<!-- 导航栏 -->
<uni-transition class="fixed-top-bar" mode-class="fade" :show="showTopNav">
<view class="grid text-center col-3 solid-top solid-bottom bg-white">
<view class="padding" :class="curTopNav == 0 ? 'bg-blue' : ''" @click.stop="clickNav(0)">服务</view>
<!-- <view class="padding" :class="curTopNav == 1 ? 'bg-blue' : ''" @click.stop="clickNav(1)">评价</view> -->
<view class="padding" :class="curTopNav == 2 ? 'bg-blue' : ''" @click.stop="clickNav(2)">详情</view>
</view>
</uni-transition>
<!-- 轮播图视频 -->
<swiper :class="changeSwiperHeight ? 'sm-screen-swiper' : 'sm-screen-swiper lg-screen-swiper'" @change="changeSwiper">
<swiper-item v-if="productDetail.goodsVideoUrl">
<video style="width: 100%; height: 100%;" id="productVideo" :src="productDetail.goodsVideoUrl" :controls="true" :autoplay="false"
:show-center-play-btn="true" :show-fullscreen-btn="false" @click="clickSwiper($event, item, 0)"></video>
</swiper-item>
<swiper-item v-for="(item,index) in swiperList" :key="item.goodsImgsId" @click="clickSwiper($event, item, 1)">
<image style="width: 100%; height: 100%;" :src="item.imgUrl" mode="aspectFit"></image>
</swiper-item>
</swiper>
<!-- 价格及活动栏 -->
<view class="bg-gradual-color padding-sm margin-bottom-xs shadow-blur">
<view class="flex justify-between align-center">
<view v-if="curProductSpecs.discountPrice">
<text class="text-sl text-price">{{curProductSpecs.discountPrice}}</text>
<text class="text-del">
<text class="text-xxl">¥{{curProductSpecs.goodsPrice}}</text>
</text>
<text class="margin-left-xs text-xxl">/{{curProductSpecs.goodsUnit}}</text>
</view>
<view v-else>
<text class="text-sl text-price">{{curProductSpecs.goodsPrice}}</text>
<text class="margin-left-xs text-xxl">/{{curProductSpecs.goodsUnit}}</text>
</view>
<view>
<text class="text-df">已售:{{curProductSpecs.saleNum}}</text>
</view>
</view>
<view id="pageAnchor0" class="flex justify-between align-end">
<view class="text-df">
<!-- 佣金:<text class="text-price margin-right-sm">{{curProductSpecs.groupPrice}}</text> -->
<!-- <text class="cuIcon-share"></text> -->
</view>
<!-- <view class="text-df">
距结束:<uni-countdown style="float: right;" :day="1" :hour="1" :minute="12" :second="40" background-color="#fff" splitorColor="#fff"></uni-countdown>
</view> -->
<view class="flex justify-end text-df align-center">
<!-- <view>距结束:</view> -->
<!-- <uni-countdown style="float: right;" :day="1" :hour="1" :minute="12" :second="40"
background-color="#fff" splitorColor="#fff"></uni-countdown> -->
</view>
</view>
</view>
<!-- 产品概要 -->
<view class="bg-white padding-sm">
<view class="flex justify-between text-df align-center">
<view class="padding-right-sm text-left solid-right">
<view class="text-xl">
<view class='cu-tag round bg-orange light' v-if="productInfo.isGoldServ">
<text class="cuIcon-medal">金牌服务</text>
</view>
{{productDetail.goodsName}}
</view>
<view class="text-sm text-gray margin-top-xs">{{productDetail.goodsDesc}}</view>
</view>
<view class="text-xl text-right padding-lr">
<!-- <view class="margin-tb-xs"><text class="cuIcon-share"></text></view> -->
<view v-if="productInfo.isGoldServ" class="margin-tb-xs text-orange"><text
class="cuIcon-friendfamous"></text></view>
</view>
</view>
</view>
<!-- 服务保障和规格 -->
<view class="margin-lr-sm padding margin-top-sm bg-white">
<view>
<view class="cu-capsule margin-tb-xs">
<view class='cu-tag bg-main-color'>
<text class="cuIcon-repairfill"></text>
</view>
<view class="cu-tag line-main-color">
服务保障
</view>
</view>
<text v-for="(item,index) in productDetail.guaranteeList">
<text class="margin-lr-xs text-sm">{{item.areaName}}<text v-if="index != productDetail.servAreaList.length - 1">,</text></text>
</text>
</view>
<view>
<view class="cu-capsule margin-tb-xs">
<view class='cu-tag bg-main-color'>
<text class="cuIcon-deliver_fill"></text>
</view>
<view class="cu-tag line-main-color">
服务区域
</view>
</view>
<text v-for="(item,index) in productDetail.goodsAreaList">
<text class="margin-lr-xs text-sm">{{item.areaName}}<text v-if="index != productDetail.goodsAreaList.length - 1">,</text></text>
</text>
</view>
<view v-if="productDetail.remark">
<view class="cu-capsule margin-tb-xs">
<view class='cu-tag bg-main-color'>
<text class="cuIcon-commentfill"></text>
</view>
<view class="cu-tag line-main-color">
备注
</view>
</view>
<text class="margin-lr-xs text-sm">{{productDetail.remark}}</text>
</view>
<view class="solid-top text-lg padding-tb-sm">
<text class="text-black">选择品类</text>
</view>
<view class="flex flex-wrap" :class="isShowAllSpecs ? '' : 'certern-height'">
<view class="margin-tb-xs margin-right-xs" v-for="(item,index) in productDetail.goodsStandardList" :key="item.goodsStandardId">
<view class='cu-tag round padding'
:class="curProductSpecs.goodsStandardId === item.goodsStandardId ? 'line-main-color' : 'line-default'"
@click="chooseSpecs(item)">{{item.goodsStandardName}}</view>
</view>
</view>
<view class="text-bold text-gray text-lg text-center bg-white padding-top-sm" @click="showAllSpecs()"><text
:class="'cuIcon-' + (isShowAllSpecs ? 'fold' : 'unfold')"></text></view>
</view>
<!-- 服务评价 -->
<!-- <view id="pageAnchor1" class="margin-lr-sm margin-top-sm bg-white"> -->
<!-- <view class="flex justify-between align-end padding"> -->
<!-- <view class="text-black text-lg">商品评价</view> -->
<!-- <view class="text-red text-sm">好评率95%<text class="text-bold text-gray cuIcon-right"></text></view> -->
<!-- </view> -->
<!-- <view class="text-center padding-bottom">开发中,敬请期待</view> -->
<!-- <comments-card :reviewers="reviewers"></comments-card> -->
<!-- </view> -->
<!-- 店家链接 -->
<view class="margin-lr-sm margin-top-sm padding bg-white">
<view class="flex justify-between align-center">
<view class="flex justify-start align-center">
<view class="cu-avatar round" :style="'background-image:url(' + shopInfo.workerLogoUrl + ');'"></view>
<view class="content flex-sub margin-lr-sm">
<view class="text-black">{{shopInfo.name}}</view>
<uni-rate :size="15" :readonly="true" allow-half :value="5" />
</view>
</view>
<view class="text-sm" @click="showShopDetail(shopInfo)">店铺查看<text class="text-bold text-gray cuIcon-right"></text></view>
</view>
</view>
<!-- 服务详情 -->
<view id="pageAnchor2" class="margin-lr-sm margin-top-sm bg-white margin-bottom-with-bar image">
<image v-for="(item,index) in detailPicList" :src="item.imgUrl" mode="widthFix" style="width: 100%;"></image>
</view>
<!-- 底部操作条 -->
<view class="cu-bar bg-white tabbar border shop fixed-bottom-bar">
<view class="action" @click="showIndex">
<view class="cuIcon-homefill"></view>
首页
</view>
<button class="action" open-type="contact">
<view class="cuIcon-servicefill text-green">
<!-- <view class="cu-tag badge" v-if="ifHasCsMsg"></view> -->
</view>
客服
</button>
<view class="action" @click="showShopDetail(shopInfo)">
<view class="cuIcon-taoxiaopu text-orange"></view>
店铺
</view>
<!-- <view class="action">
<view class=" cuIcon-shop"></view> 店铺
</view> -->
<!-- <view class="action" @click="showCart">
<view class="cuIcon-cart">
<view class="cu-tag badge" v-if="totalPickCount > 0">{{totalPickCount}}</view>
</view>
购物车
</view> -->
<!-- <view class="bg-main-color light submit" @click="toggleProductPickModal">加入购物车</view> -->
<view class="bg-main-color submit" @tap="checkLogin" @click="toggleProductPickModal($event, true)">立即订购</view>
</view>
<!-- 底部弹窗 -->
<uni-popup ref="productPickPopup" type="bottom" @change="changePopupState">
<view class="text-bold text-gray text-lg text-center left-top-sm-bar" @click="toggleProductPickModal"><text
class="cuIcon-close"></text></view>
<product-pick :shopInfo="shopInfo" :productInfo="productDetail" :specsList="productDetail.goodsStandardList" :orderNow="orderNow"></product-pick>
</uni-popup>
<!-- 登录校验弹窗 -->
<vertify-login ref="vertifyLogin" @reload="checkLogin"></vertify-login>
<vertify-phone ref="vertifyPhone" @reload="checkLogin"></vertify-phone>
</view>
</template>
<script>
import commentsCard from '@/components/goods-card/comments-card.vue';
import productPick from '@/pages/product/product-pick.vue';
export default {
components: {
commentsCard,
productPick
},
data() {
return {
inParam: {},
productDetail: {},
detailPicList: [],
swiperList: [],
curProductSpecs: {},
productInfo: {},
guaranteeList: [],
isShowAllSpecs: false,
reviewers: [],
productVideoPlaying: false,
showTopNav: false,
changeSwiperHeight: false,
curTopNav: 0,
shopInfo: {},
ifShowPageMeta: false,
orderNow: false,
totalPickCount: 0,
ifHasCsMsg: true,
picUrls: []
}
},
onLoad(options) {
let params = JSON.parse(decodeURIComponent(options.params));
this.inParam = params;
this.loadData();
this.bindEvent();
},
onUnload() {
this.offBindEvent();
},
onReady() {
this.productVideoContext = uni.createVideoContext('productVideo');
},
onPageScroll(e) {
this.showTopNav = e.scrollTop > 250 ? true : false;
this.changeSwiperHeight = e.scrollTop > 50 ? true: false;
},
methods: {
async loadData() {
let productDetailMock = await this.$api.data('productDetail');
this.productDetail = await this.$request.getGoodsDetail({
goodsId: this.inParam.goodsId
});
// 默认规格
this.curProductSpecs = this.productDetail.goodsStandardList[0];
// 轮播图
this.swiperList = this.productDetail.goodsImgsMap["0"];
// 详情图
this.detailPicList = this.productDetail.goodsImgsMap["1"];
// 用于点击放大查看图片
this.swiperList.forEach((picItem) => {
this.picUrls.push(picItem.imgUrl);
})
this.detailPicList.forEach((picItem) => {
this.picUrls.push(picItem.imgUrl);
})
let res = await this.$request.getWorkerAllDetailById({
workerId: this.productDetail.workerId
})
this.shopInfo = res.data;
this.guaranteeList = productDetailMock.guaranteeList;
this.productInfo = productDetailMock.productInfo;
this.reviewers = productDetailMock.reviewers;
// this.shopInfo = productDetailMock.shopInfo;
},
async checkLogin() {
let loginRes = await this.authLogin();
if (!loginRes) {
return;
}
this.loadData();
},
async authLogin() {
// 更新缓存中的userInfo
let res = await this.$request.storageExistUser();
// 获取缓存中的userInfo
let curUserInfo = this.$request.getCurUserInfo();
// 校验提示登录
if (!curUserInfo || !curUserInfo.openId) {
this.$refs.vertifyLogin.showModal();
return false;
} else {
this.$refs.vertifyLogin.hideModal();
}
// 校验提示获取手机号码
if (!curUserInfo.phone) {
this.$refs.vertifyPhone.showModal();
return false;
} else {
this.$refs.vertifyPhone.hideModal();
}
return true;
},
bindEvent() {
uni.$on('product-detail_add2Cart', this.add2Cart);
},
offBindEvent() {
uni.$off('product-detail_add2Cart');
},
chooseSpecs(item) {
this.curProductSpecs = item;
},
showAllSpecs() {
this.isShowAllSpecs = !this.isShowAllSpecs;
},
clickSwiper(e, item, type) {
if (type === 1) {
this.viewImage(item.imgUrl);
} else if (type === 0) {
this.pauseVideo(e);
}
},
viewImage(url) {
uni.previewImage({
urls: this.picUrls,
current: url
});
},
pauseVideo(e) {
if (this.productVideoPlaying) {
this.productVideoContext.pause();
} else {
this.productVideoContext.play();
}
this.productVideoPlaying = !this.productVideoPlaying;
},
changeSwiper(e) {
// 只有第一个是视频,如果是切换到图片就停止播放
if (e.detail.current !== 0) {
this.productVideoContext.pause();
this.productVideoPlaying = false;
}
},
clickNav(index) {
// 修改聚焦时的样式
this.curTopNav = index;
// 跳转到指定目录
uni.pageScrollTo({
selector: '#pageAnchor' + index
})
},
async toggleProductPickModal(e, orderNow) {
this.orderNow = orderNow ? true : false;
if (this.ifShowPageMeta) {
this.$refs.productPickPopup.close();
} else {
this.$refs.productPickPopup.open();
}
},
changePopupState(e) {
this.ifShowPageMeta = e.show;
},
add2Cart(totalPickCount) {
this.totalPickCount = totalPickCount;
this.toggleProductPickModal();
},
showShopDetail(shopInfo) {
uni.navigateTo({
url: '../product/shop-detail?shopInfo=' + encodeURIComponent(JSON.stringify(shopInfo))
});
},
showCart() {
let myCartInfo = {};
uni.navigateTo({
url: '/pages/my/my-cart?myCartInfo=' + encodeURIComponent(JSON.stringify(myCartInfo))
});
},
showIndex() {
uni.navigateTo({
url: '/pages/index/index'
});
}
}
}
</script>
<style scoped>
.certern-height {
max-height: 300rpx;
overflow: hidden;
}
.left-top-sm-bar {
position: absolute;
right: 25rpx;
top: 25rpx;
z-index: 99;
}
.sm-screen-swiper {
height: 400rpx;
transition: all 0.5s ease-in-out;
}
.lg-screen-swiper {
height: 900rpx;
transition: all 0.5s ease-in-out;
}
</style>