| @ -0,0 +1,455 @@ | |||||
| <template> | |||||
| <uv-popup | |||||
| ref="popup" | |||||
| :overlayOpacity="0.6" | |||||
| mode="center" | |||||
| bgColor="none" | |||||
| :zIndex="1000000" | |||||
| @change="onPopupChange" | |||||
| > | |||||
| <view class="popup__view"> | |||||
| <view class="canvas" style="width: 566rpx; height: 1060rpx; overflow: hidden;"> | |||||
| <canvas id="myCanvas" canvas-id="firstCanvas1" type="2d" style="width: 100%; height: 100%;"></canvas> | |||||
| </view> | |||||
| <button class="btn" @click="saveImg"> | |||||
| <view class="content">保存到相册</view> | |||||
| </button> | |||||
| </view> | |||||
| </uv-popup> | |||||
| </template> | |||||
| <script> | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| wxCodeImage: '', | |||||
| baseUrl: 'https://image.hhlm1688.com/', | |||||
| canvas: {}, | |||||
| retry: 10, | |||||
| } | |||||
| }, | |||||
| async onLoad() { | |||||
| }, | |||||
| methods: { | |||||
| open() { | |||||
| this.retry = 10 | |||||
| this.$refs.popup.open(); | |||||
| }, | |||||
| close() { | |||||
| this.$refs.popup.close(); | |||||
| }, | |||||
| async fetchQrCode(path) { | |||||
| // todo: delete | |||||
| this.wxCodeImage = 'https://uploadfile.bizhizu.cn/up/e3/64/e0/e364e0f7f6af11f11abdafc22d17b15c.jpg' | |||||
| return | |||||
| try { | |||||
| this.wxCodeImage = (await this.$fetch('getInviteCode', { path }))?.url | |||||
| } catch (err) { | |||||
| } | |||||
| }, | |||||
| // 生成有圆角的矩形 | |||||
| drawBg(ctx, x, y, width, height, radius) { | |||||
| ctx.beginPath(); | |||||
| ctx.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2); | |||||
| ctx.lineTo(width - radius + x, y); | |||||
| ctx.arc(width - radius + x, radius + y, radius, Math.PI * 3 / 2, Math.PI * 2); | |||||
| ctx.lineTo(width + x, height + y - radius); | |||||
| ctx.arc(width - radius + x, height - radius + y, radius, 0, Math.PI * 1 / 2); | |||||
| ctx.lineTo(radius + x, height + y); | |||||
| ctx.arc(radius + x, height - radius + y, radius, Math.PI * 1 / 2, Math.PI); | |||||
| ctx.closePath(); | |||||
| ctx.fillStyle = '#fff' | |||||
| ctx.fill() | |||||
| }, | |||||
| drawCoverImg(canvas, ctx, x, y, width, height, radius, lineWidth) { | |||||
| return new Promise(resolve => { | |||||
| // 海报图片 | |||||
| const paperImage = canvas.createImage() | |||||
| console.log('paperImage', paperImage) | |||||
| // todo: fetch | |||||
| paperImage.src = 'https://i1.hdslb.com/bfs/archive/c0101b4ce06e6bdda803728408e79c8f8b8d0725.jpg' | |||||
| paperImage.onload = () => { | |||||
| console.log('paperImage onload') | |||||
| ctx.beginPath(); | |||||
| ctx.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2); | |||||
| ctx.lineTo(width - radius + x, y); | |||||
| ctx.arc(width - radius + x, radius + y, radius, Math.PI * 3 / 2, Math.PI * 2); | |||||
| ctx.lineTo(width + x, height + y); | |||||
| ctx.lineTo(x, height + y); | |||||
| ctx.closePath(); | |||||
| ctx.lineWidth = lineWidth; | |||||
| ctx.strokeStyle = '#F8F8F8'; | |||||
| ctx.stroke(); | |||||
| ctx.clip(); | |||||
| ctx.drawImage(paperImage, x, y, width, height) | |||||
| resolve() | |||||
| } | |||||
| }) | |||||
| }, | |||||
| drawContentBg(ctx, x, y, width, height, radius) { | |||||
| ctx.beginPath(); | |||||
| // ctx.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2); | |||||
| ctx.moveTo(x, y); | |||||
| ctx.lineTo(width + x, y); | |||||
| ctx.lineTo(width + x, height + y - radius); | |||||
| ctx.arc(width - radius + x, height - radius + y, radius, 0, Math.PI * 1 / 2); | |||||
| ctx.lineTo(radius + x, height + y); | |||||
| ctx.arc(radius + x, height - radius + y, radius, Math.PI * 1 / 2, Math.PI); | |||||
| ctx.closePath(); | |||||
| let gradient = ctx.createLinearGradient(x, y, x, y + height); | |||||
| gradient.addColorStop('0', '#DAF3FF'); | |||||
| gradient.addColorStop('0.2', '#FBFEFF'); | |||||
| gradient.addColorStop('1.0', '#FBFEFF'); | |||||
| ctx.fillStyle = gradient | |||||
| ctx.fill() | |||||
| }, | |||||
| drawAvatar(canvas, ctx, x, y, r) { | |||||
| console.log('drawAvatar', 'x', x, 'y', y, 'r', r) | |||||
| return new Promise(resolve => { | |||||
| // 头像图片 | |||||
| const avatarImage = canvas.createImage() | |||||
| // todo: fetch | |||||
| avatarImage.src = 'https://i1.hdslb.com/bfs/archive/c0101b4ce06e6bdda803728408e79c8f8b8d0725.jpg' | |||||
| avatarImage.onload = () => { | |||||
| console.log('avatarImage onload') | |||||
| ctx.beginPath(); | |||||
| console.log('arc', 'x', x + r, 'y', y + r, 'r', r) | |||||
| ctx.arc(x + r, y + r, r, 0, 2 * Math.PI); | |||||
| ctx.clip(); | |||||
| const size = r*2 | |||||
| console.log('size', size) | |||||
| ctx.drawImage(avatarImage, x, y, size, size) | |||||
| resolve() | |||||
| } | |||||
| }) | |||||
| }, | |||||
| drawMultilineText(ctx, text, x, y, maxWidth, lineHeight) { | |||||
| console.log('drawMultilineText', 'x', x, 'y', y) | |||||
| let line = ''; | |||||
| for (let n = 0; n < text.length; n++) { | |||||
| const testLine = line + text[n]; | |||||
| const metrics = ctx.measureText(testLine); | |||||
| const testWidth = metrics.width; | |||||
| if (testWidth > maxWidth && n > 0) { | |||||
| ctx.fillText(line, x, y); | |||||
| console.log(n, 'line', line, 'x', x, 'y', y) | |||||
| line = text[n]; | |||||
| y += lineHeight; | |||||
| } else { | |||||
| line = testLine; | |||||
| } | |||||
| } | |||||
| console.log('line', line, 'x', x, 'y', y) | |||||
| ctx.fillText(line, x, y); | |||||
| }, | |||||
| drawQrCodeImg(canvas, ctx, x, y, size) { | |||||
| return new Promise(resolve => { | |||||
| //二维码图片 | |||||
| const coderImage = canvas.createImage() | |||||
| coderImage.src = this.wxCodeImage | |||||
| coderImage.onload = () => { | |||||
| console.log('coderImage onload') | |||||
| ctx.drawImage(coderImage, x, y, size, size) | |||||
| resolve() | |||||
| } | |||||
| }) | |||||
| }, | |||||
| draw() { | |||||
| wx.createSelectorQuery().in(this) | |||||
| .select('#myCanvas') // 绘制的canvas的id | |||||
| .fields({ | |||||
| node: true, | |||||
| size: true | |||||
| }) | |||||
| .exec(async (res) => { | |||||
| console.log('res', res) | |||||
| if (!res?.[0]?.node) { | |||||
| if (!this.retry) { | |||||
| console.log('retry fail') | |||||
| return | |||||
| } | |||||
| console.log('retry') | |||||
| this.retry -= 1 | |||||
| setTimeout(() => { | |||||
| this.draw() | |||||
| }, 200) | |||||
| return | |||||
| } | |||||
| const canvas = res[0].node | |||||
| // 渲染上下文 | |||||
| const ctx = canvas.getContext('2d') | |||||
| // Canvas 画布的实际绘制宽高 | |||||
| const width = res[0].width | |||||
| const height = res[0].height | |||||
| // 初始化画布大小 | |||||
| const dpr = wx.getWindowInfo().pixelRatio | |||||
| //根据dpr调整 | |||||
| // dpr 2 4 | |||||
| // 3 6 | |||||
| console.log("--dpr", dpr) | |||||
| canvas.width = width * dpr | |||||
| canvas.height = height * dpr | |||||
| let Ratio = canvas.width / 566 | |||||
| this.canvas = canvas | |||||
| ctx.scale(dpr, dpr) | |||||
| ctx.clearRect(0, 0, width, height) | |||||
| ctx.fillStyle = 'transparent' | |||||
| ctx.fillRect(0, 0, canvas.width, canvas.height) | |||||
| ctx.save() | |||||
| let radius = 48 * Ratio / dpr | |||||
| let w = 566 * Ratio / dpr | |||||
| let h = 1060 * Ratio / dpr | |||||
| this.drawBg(ctx, 0, 0, w, h, radius) | |||||
| ctx.restore(); | |||||
| ctx.save() | |||||
| let lineWidth = 2 * Ratio / dpr | |||||
| let x = lineWidth | |||||
| let y = lineWidth | |||||
| w = 566 * Ratio / dpr - lineWidth * 2 | |||||
| h = 400 * Ratio / dpr - lineWidth * 2 | |||||
| await this.drawCoverImg(canvas, ctx, x, y, w, h, radius, lineWidth) | |||||
| ctx.restore(); | |||||
| ctx.save() | |||||
| x = lineWidth | |||||
| y = 400 * Ratio / dpr + lineWidth | |||||
| h = 660 * Ratio / dpr - lineWidth * 2 | |||||
| this.drawContentBg(ctx, x, y, w, h, radius, lineWidth) | |||||
| ctx.restore(); | |||||
| ctx.save() | |||||
| radius = Math.floor(27 * Ratio / dpr) | |||||
| x = Math.floor(40 * Ratio / dpr) | |||||
| y = Math.floor(440 * Ratio / dpr) | |||||
| await this.drawAvatar(canvas, ctx, x, y, radius) | |||||
| ctx.restore(); | |||||
| ctx.save() | |||||
| let text = '战斗世界' | |||||
| let maxWidth = 220 * Ratio / dpr | |||||
| let lineHeight = 17 * Ratio / dpr | |||||
| x = 100 * Ratio / dpr | |||||
| y = 474 * Ratio / dpr | |||||
| ctx.font = "normal normal normal 11px normal"; | |||||
| ctx.fillStyle = "#7D7D7D"; | |||||
| this.drawMultilineText(ctx, text, x, y, maxWidth, lineHeight) | |||||
| ctx.restore(); | |||||
| ctx.save() | |||||
| maxWidth = 540 * Ratio / dpr | |||||
| lineHeight = 60 * Ratio / dpr | |||||
| ctx.font = "normal normal 600 17px normal"; | |||||
| ctx.fillStyle = "#181818"; | |||||
| text = '邀请您' | |||||
| x = 40 * Ratio / dpr | |||||
| y = 564 * Ratio / dpr | |||||
| this.drawMultilineText(ctx, text, x, y, maxWidth, lineHeight) | |||||
| y += lineHeight | |||||
| text = '探索新世界,开启研学之旅!' | |||||
| this.drawMultilineText(ctx, text, x, y, maxWidth, lineHeight) | |||||
| ctx.restore(); | |||||
| ctx.save() | |||||
| text = '是否渴望一场充满知识与乐趣的冒险?现在,我们诚挚邀请你加入我们的研学小程序,开启一场别开生面的学习之旅!' | |||||
| maxWidth = 486 * Ratio / dpr | |||||
| lineHeight = 30 * Ratio / dpr | |||||
| ctx.font = "normal normal normal 10px normal"; | |||||
| ctx.fillStyle = "#7D7D7D"; | |||||
| x = 40 * Ratio / dpr | |||||
| y = 690 * Ratio / dpr | |||||
| this.drawMultilineText(ctx, text, x, y, maxWidth, lineHeight) | |||||
| ctx.restore(); | |||||
| ctx.save() | |||||
| // 设置虚线样式 | |||||
| ctx.setLineDash([4, 4]); // 第一个参数是实线长度, 第二个参数是间隔长度 | |||||
| ctx.lineDashOffset = 2; // 设置虚线的起始偏移量 | |||||
| ctx.lineWidth = lineWidth; | |||||
| ctx.strokeStyle = '#DADADA'; | |||||
| // 开始绘制 | |||||
| ctx.beginPath(); | |||||
| x = 40 * Ratio / dpr | |||||
| y = 778 * Ratio / dpr | |||||
| ctx.moveTo(x, y); | |||||
| x += 486 * Ratio / dpr | |||||
| ctx.lineTo(x, y); | |||||
| ctx.stroke(); | |||||
| ctx.restore(); | |||||
| ctx.save() | |||||
| maxWidth = 250 * Ratio / dpr | |||||
| lineHeight = 44 * Ratio / dpr | |||||
| ctx.font = "normal normal 600 13px normal"; | |||||
| ctx.fillStyle = "#181818"; | |||||
| text = '立即加入我们,' | |||||
| x = 40 * Ratio / dpr | |||||
| y = 879 * Ratio / dpr | |||||
| this.drawMultilineText(ctx, text, x, y, maxWidth, lineHeight) | |||||
| text = '开启你的研学之旅!' | |||||
| y += lineHeight | |||||
| this.drawMultilineText(ctx, text, x, y, maxWidth, lineHeight) | |||||
| ctx.restore(); | |||||
| ctx.save() | |||||
| x = 316 * Ratio / dpr | |||||
| y = 810 * Ratio / dpr | |||||
| let size = 210 * Ratio / dpr | |||||
| await this.drawQrCodeImg(canvas, ctx, x, y, size) | |||||
| uni.hideLoading() | |||||
| return | |||||
| // 海报图片 | |||||
| const paperImage = canvas.createImage() | |||||
| console.log('paperImage', paperImage) | |||||
| // todo: fetch | |||||
| paperImage.src = 'https://i1.hdslb.com/bfs/archive/c0101b4ce06e6bdda803728408e79c8f8b8d0725.jpg' | |||||
| paperImage.onload = () => { | |||||
| console.log('paperImage onload') | |||||
| const w = 566 * Ratio / dpr | |||||
| const h = 400 * Ratio / dpr | |||||
| ctx.drawImage(paperImage, 0, 0, w, h) | |||||
| //二维码图片 | |||||
| const coderImage = canvas.createImage() | |||||
| coderImage.src = this.wxCodeImage | |||||
| coderImage.onload = () => { | |||||
| console.log('coderImage onload') | |||||
| const x = 316 * Ratio / dpr | |||||
| const y = 910 * Ratio / dpr | |||||
| const size = 210 * Ratio / dpr | |||||
| ctx.drawImage(coderImage, x, y, size, size) | |||||
| uni.hideLoading() | |||||
| } | |||||
| } | |||||
| }) | |||||
| }, | |||||
| async init() { | |||||
| uni.showLoading({ | |||||
| title: '加载中...' | |||||
| }); | |||||
| await this.fetchQrCode() | |||||
| uni.hideLoading(); | |||||
| uni.showLoading({ | |||||
| title: "拼命绘画中..." | |||||
| }) | |||||
| this.draw() | |||||
| }, | |||||
| saveImg() { | |||||
| this.$authorize('scope.writePhotosAlbum').then((res) => { | |||||
| this.imgApi() | |||||
| }) | |||||
| }, | |||||
| imgApi() { | |||||
| uni.showLoading({ | |||||
| title: '保存中...' | |||||
| }); | |||||
| wx.canvasToTempFilePath({ | |||||
| x: 0, | |||||
| y: 0, | |||||
| width: this.canvas.width, | |||||
| height: this.canvas.height, | |||||
| canvas: this.canvas, | |||||
| success: (res) => { | |||||
| let tempFilePath = res.tempFilePath; | |||||
| this.saveImgToPhone(tempFilePath) | |||||
| }, | |||||
| fail: (err) => { | |||||
| console.log('--canvasToTempFilePath--fail', err) | |||||
| uni.hideLoading(); | |||||
| } | |||||
| }, this); | |||||
| }, | |||||
| saveImgToPhone(image) { | |||||
| /* 获取图片的信息 */ | |||||
| uni.getImageInfo({ | |||||
| src: image, | |||||
| success: function(image) { | |||||
| /* 保存图片到手机相册 */ | |||||
| uni.saveImageToPhotosAlbum({ | |||||
| filePath: image.path, | |||||
| success: function() { | |||||
| uni.showModal({ | |||||
| title: '保存成功', | |||||
| content: '图片已成功保存到相册', | |||||
| showCancel: false | |||||
| }); | |||||
| }, | |||||
| complete(res) { | |||||
| console.log(res); | |||||
| uni.hideLoading(); | |||||
| } | |||||
| }); | |||||
| } | |||||
| }); | |||||
| }, | |||||
| onPopupChange(e) { | |||||
| if (!e.show) { | |||||
| return | |||||
| } | |||||
| this.init() | |||||
| }, | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| .canvas { | |||||
| border-radius: 48rpx; | |||||
| } | |||||
| .btn { | |||||
| margin-top: 32rpx; | |||||
| width: 100%; | |||||
| padding: 22rpx 0; | |||||
| box-sizing: border-box; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 500; | |||||
| font-size: 36rpx; | |||||
| line-height: 1; | |||||
| color: #FFFFFF; | |||||
| background: linear-gradient(to right, #21FEEC, #019AF9); | |||||
| border: 2rpx solid #00A9FF; | |||||
| border-radius: 41rpx; | |||||
| } | |||||
| </style> | |||||
| @ -1,21 +1,453 @@ | |||||
| <template> | <template> | ||||
| <view class="page__view"> | <view class="page__view"> | ||||
| <navbar> | |||||
| <image class="icon-nav" src="@/static/image/partner/icon-nav.png" mode="widthFix"></image> | |||||
| </navbar> | |||||
| <view class="main"> | |||||
| <view class="advantage"> | |||||
| <view class="flex advantage-content"> | |||||
| <view class="flex advantage-item" v-for="(item, aIdx) in advantages" :key="aIdx"> | |||||
| <image class="icon" src="@/static/image/icon-checkmark-circle-fill.png" mode="widthFix"></image> | |||||
| <view>{{ item }}</view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <view class="card"> | |||||
| <view class="flex user"> | |||||
| <view class="avatar"> | |||||
| <image class="img" src="@/static/image/temp-30.png" mode="scaleToFill"></image> | |||||
| <view :class="['tag', `tag-1`]">家长</view> | |||||
| </view> | |||||
| <view class="flex summary"> | |||||
| <view class="flex flex-column summary-item name"> | |||||
| <view class="summary-item-content">战斗世界</view> | |||||
| <view class="summary-item-label">ID:5625354</view> | |||||
| </view> | |||||
| <template v-if="isPartner"> | |||||
| <view class="flex flex-column summary-item" @click="jumpToAchievement"> | |||||
| <view class="summary-item-content">888</view> | |||||
| <view class="summary-item-label">推广人数</view> | |||||
| </view> | |||||
| <view class="flex flex-column summary-item"> | |||||
| <view class="summary-item-content">341</view> | |||||
| <view class="summary-item-label">总佣金</view> | |||||
| </view> | |||||
| </template> | |||||
| <template v-else> | |||||
| <view class="flex summary-item operate"> | |||||
| <button class="btn" @click="onApplyPartner">成为合伙人</button> | |||||
| </view> | |||||
| </template> | |||||
| </view> | |||||
| </view> | |||||
| <view class="flex bar" v-if="isPartner"> | |||||
| <button class="flex col btn" @click="jumpToTeam"> | |||||
| <image class="icon" src="@/static/image/partner/icon-team.png" mode="widthFix"></image> | |||||
| <view>我的团队</view> | |||||
| </button> | |||||
| <view class="flex divider"> | |||||
| <view class="line"></view> | |||||
| </view> | |||||
| <button class="flex col btn" @click="openPosterPopup"> | |||||
| <image class="icon" src="@/static/image/partner/icon-qrcode.png" mode="widthFix"></image> | |||||
| <view>邀请二维码</view> | |||||
| </button> | |||||
| <view class="flex divider"> | |||||
| <view class="line"></view> | |||||
| </view> | |||||
| <button class="flex col btn" @click="jumpToWithdraw"> | |||||
| <image class="icon" src="@/static/image/partner/icon-cash.png" mode="widthFix"></image> | |||||
| <view>提现</view> | |||||
| </button> | |||||
| </view> | |||||
| <!-- todo: check --> | |||||
| <button class="btn-apply" @click="onApplyPartner"> | |||||
| <image class="bg" src="@/static/image/partner/apply.png" mode="widthFix"></image> | |||||
| </button> | |||||
| <view class="list" v-if="isPartner && list.length"> | |||||
| <view class="flex list-item" v-for="item in list" :key="item.id"> | |||||
| <view class="flex col info"> | |||||
| <view class="avatar"> | |||||
| <image class="img" :src="item.avatar" mode="scaleToFill"></image> | |||||
| </view> | |||||
| <view>{{ item.name }}</view> | |||||
| </view> | |||||
| <view class="col price">{{ `+¥${item.price}` }}</view> | |||||
| <view class="col desc">{{ item.createTime }}</view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <posterPopup ref="posterPopup"></posterPopup> | |||||
| <tabber select="partner" /> | <tabber select="partner" /> | ||||
| </view> | </view> | ||||
| </template> | </template> | ||||
| <script> | <script> | ||||
| import mixinsList from '@/mixins/list.js' | |||||
| import tabber from '@/components/base/tabbar.vue' | import tabber from '@/components/base/tabbar.vue' | ||||
| import posterPopup from '@/components/partner/posterPopup.vue' | |||||
| export default { | export default { | ||||
| mixins: [mixinsList], | |||||
| components: { | components: { | ||||
| tabber, | tabber, | ||||
| posterPopup, | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| advantages: ['收益高', '品类全', '到账快', '城市多'], | |||||
| // todo: fetch | |||||
| isPartner: true, | |||||
| // todo | |||||
| mixinsListApi: '', | |||||
| } | |||||
| }, | |||||
| onShow() { | |||||
| // todo: refresh is partner? | |||||
| }, | |||||
| methods: { | |||||
| // todo: delete | |||||
| getData() { | |||||
| this.list = [ | |||||
| { | |||||
| id: '001', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '李世海', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '002', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '周静', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '003', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '周海', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '004', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '冯启彬', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '005', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '李娉', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '006', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '李书萍', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '007', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '李世海', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '008', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '周静', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '009', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '周海', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '010', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '冯启彬', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '011', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '李娉', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '012', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '李书萍', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| ] | |||||
| }, | |||||
| onApplyPartner() { | |||||
| this.$utils.navigateTo(`/pages_order/partner/apply`) | |||||
| }, | |||||
| jumpToTeam() { | |||||
| this.$utils.navigateTo(`/pages_order/partner/team`) | |||||
| }, | |||||
| openPosterPopup() { | |||||
| this.$refs.posterPopup.open() | |||||
| }, | |||||
| jumpToWithdraw() { | |||||
| this.$utils.navigateTo(`/pages_order/partner/withdraw`) | |||||
| }, | |||||
| }, | }, | ||||
| } | } | ||||
| </script> | </script> | ||||
| <style scoped lang="scss"> | <style scoped lang="scss"> | ||||
| @import '/components/member/styles/tag.scss'; | |||||
| @import '../../components/member/styles/tag.scss'; | |||||
| .page__view { | |||||
| min-height: 100vh; | |||||
| background: linear-gradient(to right, #21FEEC, #019AF9); | |||||
| /deep/ .nav-bar__view { | |||||
| position: fixed; | |||||
| top: 0; | |||||
| left: 0; | |||||
| } | |||||
| .icon-nav { | |||||
| width: 168rpx; | |||||
| height: auto; | |||||
| } | |||||
| /deep/ .tabbar-box { | |||||
| height: auto; | |||||
| padding-bottom: 0; | |||||
| } | |||||
| } | |||||
| .main { | |||||
| // min-height: 100vh; | |||||
| // padding: calc(var(--status-bar-height) + 130rpx) 0 calc(120rpx + env(safe-area-inset-bottom)) 0; | |||||
| padding-top: calc(var(--status-bar-height) + 130rpx); | |||||
| box-sizing: border-box; | |||||
| } | |||||
| .advantage { | |||||
| padding: 0 40rpx 32rpx 40rpx; | |||||
| &-content { | |||||
| justify-content: space-between; | |||||
| padding: 16rpx; | |||||
| background: #1FB2FD99; | |||||
| border: 2rpx solid #FFFFFF4D; | |||||
| border-radius: 16rpx; | |||||
| } | |||||
| &-item { | |||||
| column-gap: 8rpx; | |||||
| padding-right: 16rpx; | |||||
| font-size: 26rpx; | |||||
| color: #FFFFFF; | |||||
| .icon { | |||||
| width: 40rpx; | |||||
| height: auto; | |||||
| } | |||||
| } | |||||
| } | |||||
| .card { | |||||
| width: 100%; | |||||
| // height: 100%; | |||||
| $advantage-height: 54px; | |||||
| // min-height: calc(100vh - #{$advantage-height} - (var(--status-bar-height) + 130rpx) - (120rpx + env(safe-area-inset-bottom))); | |||||
| min-height: calc(100vh - #{$advantage-height} - (var(--status-bar-height) + 130rpx)); | |||||
| padding: 40rpx; | |||||
| padding-bottom: calc(40rpx + 120rpx + env(safe-area-inset-bottom)); | |||||
| box-sizing: border-box; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| line-height: 1.4; | |||||
| background: linear-gradient(#DAF3FF, #FBFEFF 400rpx, #FBFEFF); | |||||
| border: 2rpx solid #FFFFFF; | |||||
| border-top-left-radius: 48rpx; | |||||
| border-top-right-radius: 48rpx; | |||||
| } | |||||
| .user { | |||||
| justify-content: space-between; | |||||
| padding: 32rpx 40rpx; | |||||
| background: linear-gradient(#DAF3FF, #FBFEFF 70%, #FBFEFF); | |||||
| border: 2rpx solid #FFFFFF; | |||||
| border-radius: 48rpx; | |||||
| column-gap: 24rpx; | |||||
| .avatar { | |||||
| flex: none; | |||||
| position: relative; | |||||
| width: 128rpx; | |||||
| height: 128rpx; | |||||
| border-radius: 24rpx; | |||||
| overflow: hidden; | |||||
| .img { | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| } | |||||
| } | |||||
| .summary { | |||||
| flex: 1; | |||||
| column-gap: 26rpx; | |||||
| &-item { | |||||
| flex: 1; | |||||
| row-gap: 8rpx; | |||||
| &.name { | |||||
| flex: none; | |||||
| align-items: flex-start; | |||||
| } | |||||
| &.operate { | |||||
| justify-content: flex-end; | |||||
| } | |||||
| &-content { | |||||
| font-size: 32rpx; | |||||
| font-weight: 600; | |||||
| color: #000000; | |||||
| } | |||||
| &-label { | |||||
| font-size: 24rpx; | |||||
| color: #939393; | |||||
| } | |||||
| } | |||||
| } | |||||
| .btn { | |||||
| padding: 8rpx 24rpx; | |||||
| font-size: 28rpx; | |||||
| font-weight: 500; | |||||
| line-height: 1.4; | |||||
| color: #FFFFFF; | |||||
| background: linear-gradient(to right, #21FEEC, #019AF9); | |||||
| border-radius: 28rpx; | |||||
| } | |||||
| } | |||||
| .btn-apply { | |||||
| margin-top: 32rpx; | |||||
| width: 100%; | |||||
| height: auto; | |||||
| padding: 0; | |||||
| background: none; | |||||
| font-size: 0; | |||||
| .bg { | |||||
| width: 100%; | |||||
| height: auto; | |||||
| } | |||||
| } | |||||
| .bar { | |||||
| margin-top: 24rpx; | |||||
| flex-wrap: nowrap; | |||||
| padding: 16rpx 24rpx; | |||||
| .col { | |||||
| flex: none; | |||||
| } | |||||
| .divider { | |||||
| flex: 1; | |||||
| .line { | |||||
| width: 2rpx; | |||||
| height: 44rpx; | |||||
| background: #00A9FF; | |||||
| } | |||||
| } | |||||
| .btn { | |||||
| column-gap: 8rpx; | |||||
| font-size: 24rpx; | |||||
| color: #181818; | |||||
| .icon { | |||||
| width: 64rpx; | |||||
| height: auto; | |||||
| } | |||||
| } | |||||
| } | |||||
| .list { | |||||
| margin-top: 32rpx; | |||||
| background: #FFFFFF; | |||||
| border: 2rpx solid #F0F0F0; | |||||
| border-radius: 24rpx; | |||||
| overflow: hidden; | |||||
| &-item { | |||||
| margin-top: 16rpx; | |||||
| padding: 16rpx 32rpx; | |||||
| font-size: 28rpx; | |||||
| color: #333333; | |||||
| background: #FFFFFF; | |||||
| border-bottom: 2rpx solid #F1F1F1; | |||||
| &:last-child { | |||||
| border: none; | |||||
| } | |||||
| .col { | |||||
| flex: 1; | |||||
| text-align: center; | |||||
| } | |||||
| .info { | |||||
| justify-content: flex-start; | |||||
| column-gap: 24rpx; | |||||
| .avatar { | |||||
| width: 72rpx; | |||||
| height: 72rpx; | |||||
| border-radius: 50%; | |||||
| overflow: hidden; | |||||
| .img { | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| } | |||||
| } | |||||
| } | |||||
| .desc { | |||||
| font-size: 26rpx; | |||||
| color: #A3A3A3; | |||||
| } | |||||
| } | |||||
| } | |||||
| </style> | </style> | ||||
| @ -0,0 +1,252 @@ | |||||
| <template> | |||||
| <view class="page__view"> | |||||
| <navbar leftClick @leftClick="$utils.navigateBack"> | |||||
| <image class="icon-nav" src="@/static/image/partner/icon-nav.png" mode="widthFix"></image> | |||||
| </navbar> | |||||
| <view class="main"> | |||||
| <view class="advantage"> | |||||
| <view class="flex advantage-content"> | |||||
| <view class="flex advantage-item" v-for="(item, aIdx) in advantages" :key="aIdx"> | |||||
| <image class="icon" src="@/static/image/icon-checkmark-circle-fill.png" mode="widthFix"></image> | |||||
| <view>{{ item }}</view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <view class="card"> | |||||
| <view class="card-header">申请合伙人</view> | |||||
| <view class="form"> | |||||
| <uv-form | |||||
| ref="form" | |||||
| :model="form" | |||||
| :rules="rules" | |||||
| errorType="toast" | |||||
| > | |||||
| <view class="form-item"> | |||||
| <uv-form-item prop="name" :customStyle="formItemStyle"> | |||||
| <view class="form-item-label"> | |||||
| <image class="icon" src="@/static/image/icon-require.png" mode="widthFix"></image> | |||||
| 姓名 | |||||
| </view> | |||||
| <view class="form-item-content"> | |||||
| <formInput v-model="form.name"></formInput> | |||||
| </view> | |||||
| </uv-form-item> | |||||
| </view> | |||||
| <view class="form-item"> | |||||
| <uv-form-item prop="phone" :customStyle="formItemStyle"> | |||||
| <view class="form-item-label"> | |||||
| <image class="icon" src="@/static/image/icon-require.png" mode="widthFix"></image> | |||||
| 电话 | |||||
| </view> | |||||
| <view class="form-item-content"> | |||||
| <formInput v-model="form.phone"></formInput> | |||||
| </view> | |||||
| </uv-form-item> | |||||
| </view> | |||||
| <view class="form-item"> | |||||
| <uv-form-item prop="recommend" :customStyle="formItemStyle"> | |||||
| <view class="form-item-label">推荐人</view> | |||||
| <view class="form-item-content"> | |||||
| <formInput v-model="form.recommend"></formInput> | |||||
| </view> | |||||
| </uv-form-item> | |||||
| </view> | |||||
| </uv-form> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <view class="bottom"> | |||||
| <view class="flex btn" @click="onSubmit">提交</view> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import formInput from '@/pages_order/components/formInput.vue' | |||||
| export default { | |||||
| components: { | |||||
| formInput, | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| advantages: ['收益高', '品类全', '到账快', '城市多'], | |||||
| form: { | |||||
| name: null, | |||||
| phone: null, | |||||
| recommend: null, | |||||
| }, | |||||
| rules: { | |||||
| 'name': { | |||||
| type: 'string', | |||||
| required: true, | |||||
| message: '请输入姓名', | |||||
| }, | |||||
| 'phone': { | |||||
| type: 'string', | |||||
| required: true, | |||||
| message: '请输入电话', | |||||
| }, | |||||
| }, | |||||
| formItemStyle: { padding: 0 }, | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| async onSubmit() { | |||||
| try { | |||||
| await this.$refs.form.validate() | |||||
| const { | |||||
| } = this.form | |||||
| const params = { | |||||
| } | |||||
| // todo: fetch | |||||
| // await this.$fetch('updateAddress', params) | |||||
| uni.showToast({ | |||||
| icon: 'success', | |||||
| title: '提交成功', | |||||
| }); | |||||
| setTimeout(() => { | |||||
| this.$utils.navigateBack() | |||||
| }, 800) | |||||
| } catch (err) { | |||||
| console.log('onSave err', err) | |||||
| } | |||||
| }, | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| .page__view { | |||||
| min-height: 100vh; | |||||
| background: linear-gradient(to right, #21FEEC, #019AF9); | |||||
| /deep/ .nav-bar__view { | |||||
| position: fixed; | |||||
| top: 0; | |||||
| left: 0; | |||||
| } | |||||
| .icon-nav { | |||||
| width: 168rpx; | |||||
| height: auto; | |||||
| } | |||||
| } | |||||
| .main { | |||||
| // min-height: 100vh; | |||||
| // padding: calc(var(--status-bar-height) + 130rpx) 0 calc(120rpx + env(safe-area-inset-bottom)) 0; | |||||
| padding-top: calc(var(--status-bar-height) + 130rpx); | |||||
| box-sizing: border-box; | |||||
| } | |||||
| .advantage { | |||||
| padding: 0 40rpx 32rpx 40rpx; | |||||
| &-content { | |||||
| justify-content: space-between; | |||||
| padding: 16rpx; | |||||
| background: #1FB2FD99; | |||||
| border: 2rpx solid #FFFFFF4D; | |||||
| border-radius: 16rpx; | |||||
| } | |||||
| &-item { | |||||
| column-gap: 8rpx; | |||||
| padding-right: 16rpx; | |||||
| font-size: 26rpx; | |||||
| color: #FFFFFF; | |||||
| .icon { | |||||
| width: 40rpx; | |||||
| height: auto; | |||||
| } | |||||
| } | |||||
| } | |||||
| .card { | |||||
| width: 100%; | |||||
| // height: 100%; | |||||
| $advantage-height: 54px; | |||||
| // min-height: calc(100vh - #{$advantage-height} - (var(--status-bar-height) + 130rpx) - (120rpx + env(safe-area-inset-bottom))); | |||||
| min-height: calc(100vh - #{$advantage-height} - (var(--status-bar-height) + 130rpx)); | |||||
| padding: 40rpx; | |||||
| box-sizing: border-box; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| line-height: 1.4; | |||||
| background: linear-gradient(#DAF3FF, #FBFEFF 400rpx, #FBFEFF); | |||||
| border: 2rpx solid #FFFFFF; | |||||
| border-top-left-radius: 48rpx; | |||||
| border-top-right-radius: 48rpx; | |||||
| &-header { | |||||
| font-family: PingFang SC; | |||||
| font-weight: 500; | |||||
| font-size: 36rpx; | |||||
| line-height: 1.4; | |||||
| color: #191919; | |||||
| } | |||||
| } | |||||
| .form { | |||||
| &-item { | |||||
| margin-top: 32rpx; | |||||
| border-bottom: 2rpx solid #EEEEEE; | |||||
| &-label { | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| font-size: 26rpx; | |||||
| line-height: 1.4; | |||||
| color: #181818; | |||||
| .icon { | |||||
| margin-right: 8rpx; | |||||
| width: 16rpx; | |||||
| height: auto; | |||||
| } | |||||
| } | |||||
| &-content { | |||||
| } | |||||
| } | |||||
| } | |||||
| .bottom { | |||||
| position: fixed; | |||||
| left: 0; | |||||
| bottom: 0; | |||||
| width: 100vw; | |||||
| background: #FFFFFF; | |||||
| box-sizing: border-box; | |||||
| padding: 32rpx 40rpx; | |||||
| padding-bottom: calc(env(safe-area-inset-bottom) + 32rpx); | |||||
| box-sizing: border-box; | |||||
| .btn { | |||||
| width: 100%; | |||||
| padding: 14rpx 0; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 500; | |||||
| font-size: 36rpx; | |||||
| line-height: 1; | |||||
| color: #FFFFFF; | |||||
| background: linear-gradient(to right, #21FEEC, #019AF9); | |||||
| border: 2rpx solid #00A9FF; | |||||
| border-radius: 41rpx; | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,242 @@ | |||||
| <template> | |||||
| <view class="page__view"> | |||||
| <navbar title="我的团队" leftClick @leftClick="$utils.navigateBack" color="#191919" bgColor="#FFFFFF" /> | |||||
| <view class="main"> | |||||
| <view class="tabs"> | |||||
| <uv-tabs | |||||
| :list="tabs" | |||||
| :current="current" | |||||
| :scrollable="false" | |||||
| lineColor="#00A9FF" | |||||
| lineWidth="48rpx" | |||||
| lineHeight="4rpx" | |||||
| :activeStyle="{ | |||||
| 'font-family': 'PingFang SC', | |||||
| 'font-weight': 500, | |||||
| 'font-size': '32rpx', | |||||
| 'line-height': 1.4, | |||||
| 'color': '#00A9FF', | |||||
| }" | |||||
| :inactiveStyle="{ | |||||
| 'font-family': 'PingFang SC', | |||||
| 'font-weight': 400, | |||||
| 'font-size': '32rpx', | |||||
| 'line-height': 1.4, | |||||
| 'color': '#181818', | |||||
| }" | |||||
| @click="clickTabs" | |||||
| ></uv-tabs> | |||||
| </view> | |||||
| <view class="list"> | |||||
| <view class="flex list-item" v-for="item in list" :key="item.id"> | |||||
| <view class="avatar"> | |||||
| <image class="img" :src="item.avatar" mode="scaleToFill"></image> | |||||
| </view> | |||||
| <view>{{ item.name }}</view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import mixinsList from '@/mixins/list.js' | |||||
| export default { | |||||
| mixins: [mixinsList], | |||||
| data() { | |||||
| return { | |||||
| tabs: [ | |||||
| { name: '直推用户列表' }, | |||||
| { name: '间推用户列表' }, | |||||
| ], | |||||
| mixinsListApi: '', | |||||
| current: 0, | |||||
| } | |||||
| }, | |||||
| onShow() { | |||||
| console.log('onShow') | |||||
| }, | |||||
| onLoad(arg) { | |||||
| this.clickTabs({ index: arg.index || 0 }) | |||||
| }, | |||||
| methods: { | |||||
| // todo: delete | |||||
| getData() { | |||||
| this.list = [ | |||||
| { | |||||
| id: '001', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '李世海', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '002', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '周静', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '003', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '周海', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '004', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '冯启彬', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '005', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '李娉', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '006', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '李书萍', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '007', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '李世海', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '008', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '周静', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '009', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '周海', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '010', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '冯启彬', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '011', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '李娉', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| { | |||||
| id: '012', | |||||
| avatar: '/static/image/temp-30.png', | |||||
| name: '李书萍', | |||||
| price: 10, | |||||
| createTime: '2025-07-15', | |||||
| }, | |||||
| ] | |||||
| }, | |||||
| //点击tab栏 | |||||
| clickTabs({ index }) { | |||||
| console.log('clickTabs') | |||||
| this.current = index | |||||
| if (index == 0) { | |||||
| delete this.queryParams.status | |||||
| } else { | |||||
| this.queryParams.status = index - 1 | |||||
| } | |||||
| this.getData() | |||||
| }, | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| .page__view { | |||||
| width: 100vw; | |||||
| min-height: 100vh; | |||||
| background-color: $uni-bg-color; | |||||
| position: relative; | |||||
| /deep/ .nav-bar__view { | |||||
| position: fixed; | |||||
| top: 0; | |||||
| left: 0; | |||||
| } | |||||
| } | |||||
| .main { | |||||
| padding: calc(var(--status-bar-height) + 244rpx) 32rpx 40rpx 32rpx; | |||||
| .tabs { | |||||
| position: fixed; | |||||
| top: calc(var(--status-bar-height) + 120rpx); | |||||
| left: 0; | |||||
| width: 100%; | |||||
| height: 84rpx; | |||||
| background: #FFFFFF; | |||||
| z-index: 1; | |||||
| /deep/ .uv-tabs__wrapper__nav__line { | |||||
| border-radius: 2rpx; | |||||
| } | |||||
| } | |||||
| } | |||||
| .list { | |||||
| background: #FFFFFF; | |||||
| border-radius: 32rpx; | |||||
| overflow: hidden; | |||||
| &-item { | |||||
| margin-top: 16rpx; | |||||
| padding: 16rpx 32rpx; | |||||
| font-size: 28rpx; | |||||
| color: #333333; | |||||
| background: #FFFFFF; | |||||
| border-bottom: 2rpx solid #F1F1F1; | |||||
| justify-content: flex-start; | |||||
| column-gap: 24rpx; | |||||
| &:last-child { | |||||
| border: none; | |||||
| } | |||||
| .avatar { | |||||
| width: 72rpx; | |||||
| height: 72rpx; | |||||
| border-radius: 50%; | |||||
| overflow: hidden; | |||||
| .img { | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,233 @@ | |||||
| <template> | |||||
| <view class="page__view"> | |||||
| <navbar title="提现" leftClick @leftClick="$utils.navigateBack" color="#191919" bgColor="#FFFFFF" /> | |||||
| <view class="main"> | |||||
| <view class="card"> | |||||
| <view class="card-header">微信提现</view> | |||||
| <view class="form"> | |||||
| <uv-form | |||||
| ref="form" | |||||
| :model="form" | |||||
| :rules="rules" | |||||
| errorType="toast" | |||||
| > | |||||
| <view class="form-item"> | |||||
| <uv-form-item prop="name" :customStyle="formItemStyle"> | |||||
| <view class="form-item-label">真实姓名</view> | |||||
| <view class="form-item-content"> | |||||
| <formInput v-model="form.name"></formInput> | |||||
| </view> | |||||
| </uv-form-item> | |||||
| </view> | |||||
| <view class="form-item"> | |||||
| <uv-form-item prop="amount" :customStyle="formItemStyle"> | |||||
| <view class="form-item-label">提现金额</view> | |||||
| <view class="form-item-content"> | |||||
| <formInput v-model="form.amount"></formInput> | |||||
| </view> | |||||
| </uv-form-item> | |||||
| </view> | |||||
| </uv-form> | |||||
| </view> | |||||
| </view> | |||||
| <view class="notice"> | |||||
| 请仔细检查并确认相关信息,因用户个人疏忽导致的充值错误。需由用户自行承担。 | |||||
| <!-- todo: 替换配置项key --> | |||||
| <text class="highlight" @click="$refs.modal.open('user_ys', '提现须知')">《提现须知》</text> | |||||
| </view> | |||||
| <agreementModal ref="modal"></agreementModal> | |||||
| </view> | |||||
| <view class="bottom"> | |||||
| <button class="btn" @click="onSubmit">提现</button> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import formInput from '@/pages_order/components/formInput.vue' | |||||
| import agreementModal from '@/pages_order/components/agreementModal.vue' | |||||
| export default { | |||||
| components: { | |||||
| formInput, | |||||
| agreementModal, | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| form: { | |||||
| name: null, | |||||
| amount: null, | |||||
| }, | |||||
| rules: { | |||||
| 'name': { | |||||
| type: 'string', | |||||
| required: true, | |||||
| message: '请输入真实姓名', | |||||
| }, | |||||
| 'amount': { | |||||
| type: 'string', | |||||
| required: true, | |||||
| message: '请输入提现金额', | |||||
| }, | |||||
| }, | |||||
| formItemStyle: { padding: 0 }, | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| async onSubmit() { | |||||
| try { | |||||
| await this.$refs.form.validate() | |||||
| const { | |||||
| } = this.form | |||||
| const params = { | |||||
| } | |||||
| // todo: fetch | |||||
| // await this.$fetch('updateAddress', params) | |||||
| uni.showToast({ | |||||
| icon: 'success', | |||||
| title: '提交成功', | |||||
| }); | |||||
| setTimeout(() => { | |||||
| this.$utils.navigateBack() | |||||
| }, 800) | |||||
| } catch (err) { | |||||
| console.log('onSave err', err) | |||||
| } | |||||
| }, | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style lang="scss" scoped> | |||||
| .page__view { | |||||
| width: 100vw; | |||||
| min-height: 100vh; | |||||
| background: unset; | |||||
| position: relative; | |||||
| /deep/ .nav-bar__view { | |||||
| position: fixed; | |||||
| top: 0; | |||||
| left: 0; | |||||
| } | |||||
| } | |||||
| .main { | |||||
| padding: calc(var(--status-bar-height) + 144rpx) 32rpx 224rpx 32rpx; | |||||
| } | |||||
| .card { | |||||
| padding: 32rpx; | |||||
| background: #FFFFFF; | |||||
| border: 2rpx solid #FFFFFF; | |||||
| border-radius: 32rpx; | |||||
| & + & { | |||||
| margin-top: 40rpx; | |||||
| } | |||||
| &-header { | |||||
| font-family: PingFang SC; | |||||
| font-weight: 500; | |||||
| font-size: 36rpx; | |||||
| line-height: 1.4; | |||||
| color: #252545; | |||||
| margin-bottom: 32rpx; | |||||
| } | |||||
| } | |||||
| .form { | |||||
| padding: 8rpx 0 0 0; | |||||
| &-item { | |||||
| border-bottom: 2rpx solid #EEEEEE; | |||||
| &:last-child { | |||||
| border: none; | |||||
| } | |||||
| & + & { | |||||
| margin-top: 40rpx; | |||||
| } | |||||
| &-label { | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| font-size: 26rpx; | |||||
| line-height: 1.4; | |||||
| color: #181818; | |||||
| } | |||||
| &-content { | |||||
| margin-top: 14rpx; | |||||
| padding: 6rpx 0; | |||||
| .text { | |||||
| padding: 2rpx 0; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| font-size: 32rpx; | |||||
| line-height: 1.4; | |||||
| &.placeholder { | |||||
| color: #C6C6C6; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .notice { | |||||
| margin-top: 40rpx; | |||||
| font-size: 24rpx; | |||||
| line-height: 1.4; | |||||
| color: #BABABA; | |||||
| .highlight { | |||||
| color: #F79400; | |||||
| } | |||||
| } | |||||
| .bottom { | |||||
| position: fixed; | |||||
| left: 0; | |||||
| bottom: 0; | |||||
| width: 100vw; | |||||
| // height: 200rpx; | |||||
| padding: 24rpx 40rpx; | |||||
| padding-bottom: calc(env(safe-area-inset-bottom) + 24rpx); | |||||
| background: #FFFFFF; | |||||
| box-sizing: border-box; | |||||
| .btn { | |||||
| width: 100%; | |||||
| padding: 14rpx 0; | |||||
| box-sizing: border-box; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 500; | |||||
| font-size: 36rpx; | |||||
| line-height: 1; | |||||
| color: #FFFFFF; | |||||
| background: linear-gradient(to right, #21FEEC, #019AF9); | |||||
| border: 2rpx solid #00A9FF; | |||||
| border-radius: 41rpx; | |||||
| } | |||||
| } | |||||
| </style> | |||||