<template>
|
<view class="product-detail-page">
|
<scroll-view enable-back-to-top scroll-y="true" class="product-detail-page__scroll">
|
<view class="product-detail-page__scroll__swiper" v-if="info.ImageUrlList&&info.ImageUrlList.length>0">
|
<swiper @change="onSwiperChange" :current="currentIndex" class="product-detail-page__scroll__swiper__target">
|
<swiper-item class="product-detail-page__scroll__swiper__target__item" v-for="(item,index) in info.ImageUrlList"
|
:key="index">
|
<image mode="aspectFit" :src="item" class="product-detail-page__scroll__swiper__target__item__img" lazy-load></image>
|
</swiper-item>
|
</swiper>
|
<view class="product-detail-page__scroll__swiper__page">{{currentIndex+1}}/{{info.ImageUrlList.length}}</view>
|
<button v-if="info.Id" @click="shareDetail" class="evan-share">
|
<image src="/static/images/common/share_icon.png" class="evan-share__icon"></image>
|
<view class="evan-share__text">分享</view>
|
</button>
|
</view>
|
<image v-else mode="aspectFill" class="product-detail-page__scroll__default-image" src="/static/images/common/default_image_horizontal.png"></image>
|
<view class="product-detail-page__scroll__info">
|
<view class="product-detail-page__scroll__info__title">{{info.Name||''}}</view>
|
<view class="product-detail-page__scroll__info__desc">{{info.Introduction||''}}</view>
|
<!-- <view class="product-detail-page__scroll__info__bulter">管家提成比例:</view> -->
|
<view class="product-detail-page__scroll__info__tags">
|
<view class="product-detail-page__scroll__info__tags__item" v-for="(item,index) in tags" :key="index">
|
<image class="product-detail-page__scroll__info__tags__item__icon" :src="item.icon"></image>
|
<view class="product-detail-page__scroll__info__tags__item__text">{{item.text}}</view>
|
</view>
|
<view v-if="!isGroup" class="product-detail-page__scroll__info__tags__count">已售{{info.SaleCount||0}}</view>
|
</view>
|
</view>
|
<view class="product-detail-page__scroll__team" v-if="isGroup">
|
<view class="product-detail-page__scroll__team__title">批购进度及商品价格区间</view>
|
<view class="product-detail-page__scroll__team__main">
|
<view v-if="!info.GroupRules||info.GroupRules.length===0" class="product-detail-page__scroll__team__main__progress"></view>
|
<view v-else class="product-detail-page__scroll__team__main__progress">
|
<view class="product-detail-page__scroll__team__main__progress__active" :style="{width:getPercent()+'rpx'}"></view>
|
</view>
|
<!-- <template v-if="info.GroupRules&&info.GroupRules.length>0">
|
<view v-for="(item,index) in info.GroupRules" :key="index" class="product-detail-page__scroll__team__main__price"
|
:style="{top:'80rpx',left:`${630 * 0.8 / lastInfo.GroupCountStart * item.GroupCountStart}rpx`}">
|
<view class="product-detail-page__scroll__team__main__price__line"></view>
|
<view class="product-detail-page__scroll__team__main__price__target">{{item.GroupCountStart}}件</view>
|
<view class="product-detail-page__scroll__team__main__price__target">{{item.Amount}}元</view>
|
</view>
|
</template> -->
|
<view v-if="!$utils.isTrueEmpty(info.GroupCount)" class="product-detail-page__scroll__team__main__price" :style="{bottom:'80rpx',left:getLeftValue()+'rpx'}">
|
<view class="product-detail-page__scroll__team__main__price__current">已批{{info.GroupCount}}件</view>
|
<view class="product-detail-page__scroll__team__main__price__line current"></view>
|
</view>
|
</view>
|
</view>
|
<view class="product-detail-page__scroll__team-intro" v-if="isGroup">
|
<view class="product-detail-page__scroll__team-intro__target">批购说明:参与购买的人数越多,商品价格越实惠</view>
|
<view class="product-detail-page__scroll__team-intro__target">根据批购最终参与购买的人数,来确定你需要支付的最终价格</view>
|
</view>
|
<view class="product-detail-page__scroll__desc">
|
<view class="product-detail-page__scroll__desc__title">商品详情</view>
|
<u-parse :content="info.ProductDesc" />
|
</view>
|
</scroll-view>
|
<view class="evan-buy-bottom">
|
<view class="evan-buy-bottom__item evan-buy-bottom__item--left">
|
<view class="evan-buy-bottom__item__price">
|
<view v-if="isGroup||info.PayType===1" class="evan-buy-bottom__item__price__unit">¥</view>
|
<!-- <view class="evan-buy-bottom__item__price__current">{{showPrice}}</view> -->
|
<view v-if="!isGroup&&info.PayType===1&&info.MarketPrice" class="evan-buy-bottom__item__price__old">¥{{info.MarketPrice}}</view>
|
</view>
|
<view v-if="info.GiveAwayHuidouCount" class="evan-buy-bottom__item__tip">赠送{{info.GiveAwayHuidouCount}}汇豆</view>
|
</view>
|
<view @tap="buy" class="evan-buy-bottom__item evan-buy-bottom__item--right">立即购买</view>
|
</view>
|
<hjg-spec @confirm="onSpecConfirm" :changeCount="!isNewUserProduct" :specs="info.SpecInfos" ref="spec"></hjg-spec>
|
<view @tap="hideBarcode" class="evan-poster__mask" :class="{hide:!showBarcode}" :style="{paddingTop:posterPadding}">
|
<canvas class="evan-poster__mask__canvas" :style="{width:canvasWidth+'px',height:canvasHeight+'px'}" canvas-id="barcode"></canvas>
|
<view @tap.stop.prevent="stopPop" class="evan-poster__mask__bottom">
|
<button open-type="share" class="evan-poster__mask__bottom__item">
|
<view class="evan-poster__mask__bottom__item__text">分享好友</view>
|
</button>
|
<button @tap="saveToAlbum" class="evan-poster__mask__bottom__item">
|
<view class="evan-poster__mask__bottom__item__text">保存海报</view>
|
</button>
|
</view>
|
</view>
|
</view>
|
</template>
|
|
<script>
|
|
import {
|
mapGetters,
|
mapState
|
} from 'vuex'
|
let ENV = 'prod'
|
export default {
|
components: {
|
|
},
|
computed: {
|
|
|
},
|
data() {
|
return {
|
memberId: '',
|
headUrl: '',
|
nickName: '',
|
id: null,
|
info: {},
|
currentIndex: 0,
|
tags: [{
|
icon: '/static/images/home/qqzx.png',
|
text: '全球精品'
|
},
|
{
|
icon: '/static/images/home/jyps.png',
|
text: '正品保证'
|
},
|
{
|
icon: '/static/images/home/shwy.png',
|
text: '商品包邮'
|
}
|
],
|
isGroup: false,
|
groupId: null,
|
canvasWidth: 242,
|
canvasHeight: 430,
|
showBarcode: false,
|
ratio: 430 / 1920,
|
posterPadding: 0,
|
filePath: '',
|
isNewUserProduct: false,
|
canBuy: false
|
}
|
},
|
methods: {
|
async getDetail() {
|
// const {
|
// code,
|
// data
|
// } = await productService.getDetail(this.id)
|
// if (code === 0) {
|
// this.info = data
|
// this.isNewUserProduct = data.IsNewUserTopic === 1
|
// }
|
},
|
async getGroupDetail() {
|
const {
|
code,
|
data
|
} = await assembleService.getAssembleDetail(this.id, this.groupId)
|
if (code === 0) {
|
this.info = data
|
}
|
},
|
onSwiperChange(e) {
|
this.currentIndex = e.detail.current
|
},
|
async buy() {
|
|
},
|
onSpecConfirm(e) {
|
let specList = []
|
if (Array.isArray(e.specs)) {
|
specList = e.specs.map((item) => {
|
return {
|
SpecName: item.SpecName,
|
SpecValue: item.SpecValue
|
}
|
})
|
}
|
let orderInfo = {
|
ProductId: this.info.Id,
|
ProductSpecList: specList,
|
ProductCount: e.count,
|
ProductSaleType: this.isGroup ? 2 : 1,
|
ProductPayType: this.isGroup ? 1 : this.info.PayType
|
}
|
if (this.isGroup) {
|
orderInfo.GroupId = this.groupId
|
orderInfo.BookAmount = this.info.BookAmount
|
} else {
|
if (orderInfo.ProductPayType === 1) {
|
orderInfo.SaleAmount = this.info.SalePrice
|
} else {
|
orderInfo.SaleAmount = this.info.HuidouCount
|
}
|
}
|
uni.navigateTo({
|
url: `./order?orderInfo=${JSON.stringify(orderInfo)}`
|
})
|
},
|
getPercent() {
|
if (!this.info.GroupRules || this.info.GroupRules.length === 0) {
|
return 0
|
}
|
if (this.info.GroupCount > this.info.GroupRules[this.info.GroupRules.length - 1].GroupCountStart) {
|
return 0.85 * 630
|
} else {
|
return this.info.GroupCount / this.info.GroupRules[this.info.GroupRules.length - 1].GroupCountStart *
|
0.8 * 630
|
}
|
},
|
getLeftValue() {
|
if (!this.info.GroupRules || this.info.GroupRules.length === 0) {
|
if (this.info.GroupCount === 0) {
|
return 0
|
} else {
|
return 630 * 0.8
|
}
|
} else {
|
if (this.info.GroupCount > this.info.GroupRules[this.info.GroupRules.length - 1].GroupCountStart) {
|
return 630 * 0.85
|
} else {
|
return 630 * 0.8 / Math.max(this.info.GroupRules[this.info.GroupRules.length - 1].GroupCountStart /
|
this.info.GroupCount, 1)
|
}
|
}
|
},
|
formatCanvasSize(size) {
|
return Math.floor(this.ratio * size)
|
},
|
async shareDetail() {
|
if (this.memberId) {
|
// #ifdef MP-WEIXIN
|
let params = `id=${this.info.Id}`
|
if (this.isGroup) {
|
params += `&groupId=${this.groupId}`
|
}
|
if (this.memberId) {
|
params += `&inviteId=${this.memberId}`
|
}
|
const {
|
code: sceneCode,
|
data: sceneData
|
} = await commonService.saveScene(encodeURIComponent(params))
|
if (sceneCode === 0) {
|
const {
|
code,
|
data
|
} = await commonService.getUnlimitedBarcode('pages/home/product/detail', `posterId=${sceneData}`)
|
if (code === 0) {
|
const fsm = wx.getFileSystemManager()
|
this.filePath = `${wx.env.USER_DATA_PATH}/barcode_tmp_${(new Date).getTime()}.png`
|
fsm.writeFile({
|
filePath: this.filePath,
|
data: data,
|
encoding: 'binary',
|
success: async () => {
|
const context = uni.createCanvasContext('barcode')
|
const headSize = this.formatCanvasSize(105)
|
const productSize = this.formatCanvasSize(540)
|
const canvasWidth = this.canvasWidth
|
const canvasHeight = this.canvasHeight
|
const headPath = await this.getImageInfo(this.headUrl)
|
const productPath = await this.getImageInfo(this.info.ImageUrlList[0])
|
// 背景
|
context.drawImage('/pages/home/static/images/sharebg.jpg', 0, 0, canvasWidth,
|
canvasHeight)
|
// 头像
|
context.drawImage(headPath, this.formatCanvasSize(80), this.formatCanvasSize(70), headSize, headSize)
|
// 昵称
|
context.font = `bold ${this.formatCanvasSize(40)}px system-ui`
|
context.setFillStyle('#000')
|
this.fillTextByLength(context, this.nickName, 20, this.formatCanvasSize(198),
|
this.formatCanvasSize(110))
|
// 产品图
|
context.drawImage(productPath, this.formatCanvasSize(260), this.formatCanvasSize(440), productSize,
|
productSize)
|
// 价格
|
const priceWidth = this.formatCanvasSize(150)
|
const priceTop = this.formatCanvasSize(1240)
|
const priceLeft = this.formatCanvasSize(141)
|
// 当前价格
|
if (this.showPrice) {
|
const price = (this.isGroup || this.info.PayType === 1) ? `¥${this.showPrice}` : this.showPrice
|
context.font = `bold ${this.formatCanvasSize(84)}px system-ui`
|
context.setFillStyle('#d92c21')
|
context.fillText(price, priceLeft, priceTop, priceWidth)
|
}
|
// 市场价格
|
if (!this.isGroup && this.info.PayType === 1 && this.info.MarketPrice) {
|
context.font = `normal ${this.formatCanvasSize(54)}px system-ui`
|
context.setFillStyle('#61605e')
|
context.fillText(`¥${this.info.MarketPrice}`, priceLeft + priceWidth + 5, priceTop, priceWidth)
|
context.moveTo(priceLeft + priceWidth + 5, priceTop - this.formatCanvasSize(20))
|
context.lineTo(priceLeft + priceWidth + 5 + context.measureText(`¥${this.info.MarketPrice}`).width + 2,
|
priceTop - this.formatCanvasSize(20))
|
context.setStrokeStyle('#61605e')
|
context.stroke()
|
}
|
// 赠送汇豆
|
if (this.info.GiveAwayHuidouCount) {
|
context.font = `normal ${this.formatCanvasSize(36)}px system-ui`
|
context.setFillStyle('#61605e')
|
context.fillText(`赠送${this.info.GiveAwayHuidouCount}汇豆`, priceLeft, priceTop + this.formatCanvasSize(36) +
|
5,
|
priceWidth * 2)
|
}
|
// 商品名称
|
let nameLeft = priceLeft + 2 * priceWidth + 10
|
let nameTop = this.formatCanvasSize(1230)
|
context.font = `bold ${this.formatCanvasSize(50)}px system-ui`
|
context.setFillStyle('#000')
|
let nameWidth = 0
|
// 换行次数
|
let breakLineCount = 0
|
for (let i = 0; i < this.info.Name.length; i++) {
|
const str = this.info.Name[i]
|
nameWidth += context.measureText(str).width
|
if (nameWidth > 80 && breakLineCount > 0) {
|
context.fillText('...', nameLeft, nameTop)
|
break
|
}
|
if (nameWidth > 90) {
|
nameTop += this.formatCanvasSize(74)
|
nameLeft = priceLeft + 2 * priceWidth + 10
|
nameWidth = context.measureText(str).width
|
breakLineCount++
|
}
|
context.fillText(str, nameLeft, nameTop)
|
nameLeft += context.measureText(str).width + 2
|
}
|
// 二维码
|
const barcodeSize = this.formatCanvasSize(250)
|
const barcodeLeft = this.formatCanvasSize(740)
|
const barcodeTop = this.formatCanvasSize(1500)
|
context.drawImage(this.filePath, barcodeLeft, barcodeTop,
|
barcodeSize,
|
barcodeSize)
|
this.showBarcode = true
|
this.$nextTick(() => {
|
context.draw(false, () => {})
|
})
|
},
|
fail: (err) => {
|
this.$message.showToast('写入文件失败')
|
}
|
})
|
}
|
}
|
// #endif
|
} else {
|
this.$message.confirm('登录后才能分享,是否立即登录?').then(() => {
|
uni.navigateTo({
|
url: '/pages/account/login'
|
})
|
}).catch(() => {})
|
}
|
},
|
fillTextSingleLine(context, text, maxLength, startLeft, startTop) {
|
let nameWidth = 0
|
for (let i = 0; i < text.length; i++) {
|
const str = text[i]
|
nameWidth += context.measureText(str).width
|
if (nameWidth > maxLength - 10) {
|
context.fillText('...', startLeft, startTop)
|
break
|
} else {
|
context.fillText(str, startLeft, startTop)
|
startLeft += context.measureText(str).width + 2
|
}
|
}
|
},
|
fillTextByLength(context, text, len, startLeft, startTop) {
|
if (text.length > len - 3) {
|
text = text.substr(0, len - 3) + '...'
|
}
|
context.fillText(text, startLeft, startTop)
|
},
|
getImageInfo(url) {
|
if (ENV === 'prod') {
|
url = url.replace(/http:\/\//g, 'https://')
|
}
|
return new Promise((resolve, reject) => {
|
uni.getImageInfo({
|
src: url,
|
success: (res) => {
|
resolve(res.path)
|
},
|
fail: (e) => {
|
reject(e)
|
}
|
})
|
})
|
},
|
saveToAlbum() {
|
uni.canvasToTempFilePath({
|
x: 0,
|
y: 0,
|
width: this.canvasWidth,
|
height: this.canvasHeight,
|
canvasId: 'barcode',
|
success: (res) => {
|
uni.saveImageToPhotosAlbum({
|
filePath: res.tempFilePath,
|
success: () => {
|
this.$message.showToast('已为您保存至相册')
|
}
|
})
|
}
|
})
|
},
|
hideBarcode() {
|
this.showBarcode = false
|
if (this.filePath) {
|
const fsm = wx.getFileSystemManager()
|
fsm.unlink({
|
filePath: this.filePath,
|
success: () => {
|
this.filePath = ''
|
}
|
})
|
}
|
},
|
stopPop() {
|
// do nothing
|
},
|
async getScene(id) {
|
const {
|
code,
|
data
|
} = await commonService.getScene(id)
|
if (code === 0) {
|
const productId = this.$utils.getBarcodeQueryString(data, 'id')
|
const inviteId = this.$utils.getBarcodeQueryString(data, 'inviteId')
|
const groupId = this.$utils.getBarcodeQueryString(data, 'groupId')
|
if (productId) {
|
this.id = productId
|
if (inviteId) {
|
this.$store.commit('account/SET_INVITEID', inviteId)
|
}
|
if (groupId) {
|
this.isGroup = true
|
this.groupId = groupId
|
this.getGroupDetail()
|
} else {
|
this.getDetail()
|
}
|
}
|
}
|
},
|
setPosterPadding() {
|
const windowHeight = uni.getSystemInfoSync().windowHeight
|
this.posterPadding = (windowHeight - 126 - this.canvasHeight) / 2 + 'px'
|
}
|
},
|
async onLoad(options) {
|
this.setPosterPadding()
|
this.id = options.id || ''
|
},
|
onUnload() {
|
},
|
onShareAppMessage() {
|
let params = `id=${this.info.Id}`
|
if (this.isGroup) {
|
params += `&groupId=${this.groupId}`
|
}
|
if (this.memberId) {
|
params += `&inviteId=${this.memberId}`
|
}
|
let path = `/pages/home/product/detail?${params}`
|
return {
|
title: this.info.Name,
|
path: path
|
}
|
}
|
}
|
</script>
|
|
<style lang="scss">
|
.product-detail-page {
|
height: 100%;
|
display: flex;
|
flex-direction: column;
|
|
&__scroll {
|
flex: 1;
|
overflow: auto;
|
|
&__swiper {
|
position: relative;
|
width: 100%;
|
height: 446rpx;
|
background-color: #fff;
|
|
&__target {
|
height: 100%;
|
|
&__item {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
|
&__img {
|
width: 400rpx;
|
height: 400rpx;
|
}
|
}
|
}
|
|
&__page {
|
position: absolute;
|
bottom: 14rpx;
|
right: 40rpx;
|
height: 40rpx;
|
border-radius: 20rpx;
|
background-color: rgba(0, 0, 0, 0.6);
|
padding: 0 14rpx;
|
font-size: 28rpx;
|
color: #fff;
|
}
|
}
|
|
&__default-image {
|
width: 100%;
|
height: 446rpx;
|
}
|
|
&__info {
|
background-color: #fff;
|
padding: 18rpx 30rpx 28rpx 30rpx;
|
|
&__title {
|
font-size: 32rpx;
|
color: #000;
|
font-weight: 500;
|
line-height: 44rpx;
|
margin-bottom: 14rpx;
|
}
|
|
&__desc {
|
font-size: 28rpx;
|
color: #666;
|
line-height: 40rpx;
|
margin-bottom: 10rpx;
|
}
|
|
&__bulter {
|
font-size: 28rpx;
|
color: #000;
|
line-height: 40rpx;
|
}
|
|
&__tags {
|
display: flex;
|
align-items: center;
|
margin-top: 10rpx;
|
|
&__item {
|
display: flex;
|
align-items: center;
|
margin-right: 44rpx;
|
|
&__icon {
|
width: 28rpx;
|
height: 28rpx;
|
margin-right: 4rpx;
|
}
|
|
&__text {
|
font-size: 24rpx;
|
color: #000;
|
}
|
}
|
|
&__count {
|
flex: 1;
|
text-align: right;
|
font-size: 24rpx;
|
color: #666;
|
}
|
}
|
}
|
|
&__desc {
|
padding: 30rpx;
|
background-color: #fff;
|
margin-top: 24rpx;
|
|
&__title {
|
font-size: 36rpx;
|
color: #000;
|
font-weight: 500;
|
line-height: 50rpx;
|
margin-bottom: 26rpx;
|
}
|
}
|
|
&__team {
|
background-color: #fff;
|
padding-bottom: 48rpx;
|
|
&__title {
|
font-size: 28rpx;
|
color: #000;
|
padding: 0 30rpx;
|
font-weight: bold;
|
}
|
|
&__main {
|
width: 750rpx;
|
padding: 60rpx 0;
|
position: relative;
|
display: flex;
|
justify-content: center;
|
|
&__progress {
|
width: 630rpx;
|
height: 20rpx;
|
background-color: #d8d8d8;
|
border-radius: 16rpx;
|
|
&__active {
|
height: 100%;
|
background-color: #d51d1d;
|
border-radius: 16rpx;
|
}
|
}
|
|
&__price {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
position: absolute;
|
min-width: 120rpx;
|
|
&__line {
|
width: 2rpx;
|
height: 24rpx;
|
background-color: #979797;
|
|
&.current {
|
background-color: #d51d1d;
|
}
|
}
|
|
&__target {
|
font-size: 24rpx;
|
color: #000;
|
font-weight: bold;
|
}
|
|
&__current {
|
font-size: 20rpx;
|
color: #d51d1d;
|
}
|
}
|
}
|
}
|
|
&__team-intro {
|
padding: 8rpx 30rpx;
|
background-color: #EDE0CC;
|
margin-top: 24rpx;
|
|
&__target {
|
font-size: 24rpx;
|
color: #9C753B;
|
font-weight: bold;
|
|
&:not(:first-child) {
|
margin-top: 8rpx;
|
}
|
}
|
}
|
|
&__team-info {
|
padding: 16rpx 30rpx 0 16rpx;
|
|
&__line {
|
display: flex;
|
align-items: flex-start;
|
margin-bottom: 8rpx;
|
|
&__label {
|
font-size: 28rpx;
|
color: #000;
|
}
|
|
&__value {
|
font-size: 28rpx;
|
color: #000;
|
flex: 1;
|
}
|
}
|
}
|
}
|
}
|
</style>
|