From e3c019754f508ee7744493f108d58d1a4bacc163 Mon Sep 17 00:00:00 2001 From: xuxueyang <xuxy@fengyuntec.com> Date: 星期五, 02 八月 2024 14:54:50 +0800 Subject: [PATCH] fix bug 接口对接和样式调整 --- /dev/null | 56 ---- pages.json | 9 sub_pages/partner/partner-info/partner-code.vue | 16 + sub_pages/partner/partner-info/partner-code-v2.vue | 688 ++++++++++++++++++++++++++++++++++++++++++++++++++++ pages/user/supplier-user.vue | 9 5 files changed, 719 insertions(+), 59 deletions(-) diff --git a/detail.vue b/detail.vue deleted file mode 100644 index 2198b28..0000000 --- a/detail.vue +++ /dev/null @@ -1,56 +0,0 @@ -<template> - <view class="shop-detail"> - <view v-if="dto.id"> - <!-- 图片+2个icon --> - <view> - - </view> - - </view> - </view> -</template> - -<script> - export default { - data() { - return { - dto: { - - }, - id: '' - }; - }, - async onLoad(options) { - this.id = options.id || '' - await this.init() - - }, - async onPullDownRefresh() { - await this.init() - uni.stopPullDownRefresh() - }, - methods: { - async init() { - this.$message.showLoading() - const { - data - } = await this.$http.request('get', '/api/customer/flower/list/view' + this.id, { - - }) - - this.$message.hideLoading() - this.dto = { - ...data - } - - }, - } - } -</script> - -<style lang="scss" scoped> - .shop-detail{ - - } - -</style> \ No newline at end of file diff --git a/pages.json b/pages.json index dcbeb32..e292dca 100644 --- a/pages.json +++ b/pages.json @@ -239,9 +239,16 @@ { "path": "partner-info/partner-code", "style": { - "navigationBarTitleText": "二维码", + "navigationBarTitleText": "合伙人推广二维码", "enablePullDownRefresh": false } + }, + { + "path": "partner-info/partner-code-v2", + "style": { + "navigationBarTitleText": "合伙人推广二维码", + "enablePullDownRefresh": false + } }, { diff --git a/pages/user/supplier-user.vue b/pages/user/supplier-user.vue index 7d2002c..1f9cdfa 100644 --- a/pages/user/supplier-user.vue +++ b/pages/user/supplier-user.vue @@ -179,7 +179,14 @@ <view class="right-icon"> <uni-icons type="right"></uni-icons> </view> - </view> + </view> + <!-- <view class="user-util m-t-12 flex" v-if="selftype==='partner'" + @click="goto('/sub_pages/partner/partner-info/partner-code-v2',true)"> + <view class="title">测试二维码</view> + <view class="right-icon"> + <uni-icons type="right"></uni-icons> + </view> + </view> --> <!-- #endif --> <!-- #ifdef PUB_CUSTOMER --> <view class="user-util m-t-12 flex" diff --git a/sub_pages/partner/partner-info/partner-code-v2.vue b/sub_pages/partner/partner-info/partner-code-v2.vue new file mode 100644 index 0000000..9746ae6 --- /dev/null +++ b/sub_pages/partner/partner-info/partner-code-v2.vue @@ -0,0 +1,688 @@ +<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> diff --git a/sub_pages/partner/partner-info/partner-code.vue b/sub_pages/partner/partner-info/partner-code.vue index 223308c..4041000 100644 --- a/sub_pages/partner/partner-info/partner-code.vue +++ b/sub_pages/partner/partner-info/partner-code.vue @@ -3,7 +3,7 @@ <!-- --> <view class="contact-container"> <view class="container" @click="saveCode"> - <!-- <image src="../../../static/uni.png" mode="aspectFit" class="code"></image> --> + <canvas type="2d" id="myQrcode" class="code"></canvas> <view class="info"> <view class="desc"> @@ -26,6 +26,20 @@ canvas: undefined, } }, + // 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 + // } + // } onLoad(options) { if (!this.currentInfo.partnerDTO) { this.$message.showToast('请先完善合伙人信息') -- Gitblit v1.9.3