|
|
@@ -0,0 +1,176 @@
|
|
|
+<template>
|
|
|
+ <view class="share-page">
|
|
|
+ <view class="poster-card">
|
|
|
+ <canvas canvas-id="posterCanvas" id="posterCanvas" class="poster-canvas"></canvas>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="invite-row">
|
|
|
+ <text class="invite-label">我的邀请码</text>
|
|
|
+ <text class="invite-code">{{ inviteCode || '加载中…' }}</text>
|
|
|
+ <button class="copy-btn" @click="copyCode" :disabled="!inviteCode">复制</button>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <button class="save-btn" @click="savePoster" :loading="saving" :disabled="saving || !inviteCode">保存海报图片</button>
|
|
|
+
|
|
|
+ <view class="stats-link" @click="goStats">
|
|
|
+ <text>查看我的转介绍统计</text>
|
|
|
+ <text class="arrow">›</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { getMyPoster } from '@/utils/api.js'
|
|
|
+
|
|
|
+export default {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ inviteCode: '',
|
|
|
+ posterUrl: '',
|
|
|
+ saving: false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onLoad() {
|
|
|
+ this.loadPoster()
|
|
|
+ },
|
|
|
+ onReady() {
|
|
|
+ // canvas 就绪后绘制海报
|
|
|
+ this.drawPoster()
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ loadPoster() {
|
|
|
+ var self = this
|
|
|
+ getMyPoster().then(function(resp) {
|
|
|
+ var data = resp.data || {}
|
|
|
+ self.inviteCode = data.inviteCode || ''
|
|
|
+ self.posterUrl = data.posterUrl || ''
|
|
|
+ if (self.inviteCode) {
|
|
|
+ // 重新绘制带邀请码的海报
|
|
|
+ setTimeout(function() {
|
|
|
+ self.drawPoster()
|
|
|
+ }, 300)
|
|
|
+ }
|
|
|
+ }).catch(function() {})
|
|
|
+ },
|
|
|
+ drawPoster() {
|
|
|
+ var self = this
|
|
|
+ var ctx = uni.createCanvasContext('posterCanvas', self)
|
|
|
+ var width = 300
|
|
|
+ var height = 450
|
|
|
+ // 背景
|
|
|
+ var gradient = ctx.createLinearGradient(0, 0, 0, height)
|
|
|
+ gradient.addColorStop(0, '#FFF7ED')
|
|
|
+ gradient.addColorStop(1, '#FED7AA')
|
|
|
+ ctx.setFillStyle(gradient)
|
|
|
+ ctx.fillRect(0, 0, width, height)
|
|
|
+ // 顶部品牌区
|
|
|
+ ctx.setFillStyle('#EA580C')
|
|
|
+ ctx.fillRect(0, 0, width, 8)
|
|
|
+ ctx.setFillStyle('#1E293B')
|
|
|
+ ctx.setFontSize(22)
|
|
|
+ ctx.setTextAlign('center')
|
|
|
+ ctx.fillText('爱伴·AI之旅', width / 2, 60)
|
|
|
+ ctx.setFillStyle('#64748B')
|
|
|
+ ctx.setFontSize(13)
|
|
|
+ ctx.fillText('邀请你一起加入 AI 成长营', width / 2, 90)
|
|
|
+ // 中央邀请码卡片
|
|
|
+ ctx.setFillStyle('#FFFFFF')
|
|
|
+ this.roundRect(ctx, 40, 130, width - 80, 120, 12)
|
|
|
+ ctx.setFillStyle('#F97316')
|
|
|
+ ctx.setFontSize(15)
|
|
|
+ ctx.fillText('我的邀请码', width / 2, 165)
|
|
|
+ ctx.setFillStyle('#1E293B')
|
|
|
+ ctx.setFontSize(34)
|
|
|
+ ctx.fillText(self.inviteCode || '------', width / 2, 215)
|
|
|
+ // 底部提示
|
|
|
+ ctx.setFillStyle('#EA580C')
|
|
|
+ ctx.setFontSize(14)
|
|
|
+ ctx.fillText('报名时填写邀请码,一起享受专属权益', width / 2, 320)
|
|
|
+ ctx.setFillStyle('#94A3B8')
|
|
|
+ ctx.setFontSize(12)
|
|
|
+ ctx.fillText('爱伴·AI之旅训练营', width / 2, 400)
|
|
|
+ ctx.draw(false)
|
|
|
+ },
|
|
|
+ roundRect(ctx, x, y, w, h, r) {
|
|
|
+ ctx.beginPath()
|
|
|
+ ctx.moveTo(x + r, y)
|
|
|
+ ctx.lineTo(x + w - r, y)
|
|
|
+ ctx.arcTo(x + w, y, x + w, y + r, r)
|
|
|
+ ctx.lineTo(x + w, y + h - r)
|
|
|
+ ctx.arcTo(x + w, y + h, x + w - r, y + h, r)
|
|
|
+ ctx.lineTo(x + r, y + h)
|
|
|
+ ctx.arcTo(x, y + h, x, y + h - r, r)
|
|
|
+ ctx.lineTo(x, y + r)
|
|
|
+ ctx.arcTo(x, y, x + r, y, r)
|
|
|
+ ctx.closePath()
|
|
|
+ ctx.fill()
|
|
|
+ },
|
|
|
+ copyCode() {
|
|
|
+ if (!this.inviteCode) return
|
|
|
+ uni.setClipboardData({
|
|
|
+ data: this.inviteCode,
|
|
|
+ success: function() {
|
|
|
+ uni.showToast({ title: '邀请码已复制', icon: 'success' })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ savePoster() {
|
|
|
+ var self = this
|
|
|
+ if (this.saving) return
|
|
|
+ this.saving = true
|
|
|
+ uni.canvasToTempFilePath({
|
|
|
+ canvasId: 'posterCanvas',
|
|
|
+ success: function(res) {
|
|
|
+ uni.saveImageToPhotosAlbum({
|
|
|
+ filePath: res.tempFilePath,
|
|
|
+ success: function() {
|
|
|
+ uni.showToast({ title: '海报已保存到相册', icon: 'success' })
|
|
|
+ },
|
|
|
+ fail: function(err) {
|
|
|
+ if (err && (err.errMsg || '').indexOf('auth') > -1) {
|
|
|
+ uni.showModal({
|
|
|
+ title: '需要相册权限',
|
|
|
+ content: '请在设置中开启「保存到相册」权限',
|
|
|
+ confirmText: '去设置',
|
|
|
+ success: function(r) {
|
|
|
+ if (r.confirm) {
|
|
|
+ uni.openSetting({})
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ uni.showToast({ title: '保存失败,请稍后重试', icon: 'none' })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ complete: function() {
|
|
|
+ self.saving = false
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ fail: function() {
|
|
|
+ self.saving = false
|
|
|
+ uni.showToast({ title: '海报生成失败', icon: 'none' })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ goStats() {
|
|
|
+ uni.navigateTo({ url: '/pages/share/stats' })
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.share-page { min-height: 100vh; background: #F5F5F5; padding: 24rpx 32rpx; }
|
|
|
+.poster-card { background: #FFF; border-radius: 16rpx; padding: 24rpx; margin-bottom: 24rpx; display: flex; justify-content: center; }
|
|
|
+.poster-canvas { width: 300px; height: 450px; border-radius: 12rpx; }
|
|
|
+.invite-row { background: #FFF; border-radius: 16rpx; padding: 32rpx; margin-bottom: 24rpx; display: flex; align-items: center; }
|
|
|
+.invite-label { font-size: 28rpx; color: #1E293B; font-weight: 600; flex-shrink: 0; }
|
|
|
+.invite-code { flex: 1; font-size: 32rpx; color: #F97316; font-weight: 700; font-family: monospace; margin-left: 24rpx; letter-spacing: 4rpx; }
|
|
|
+.copy-btn { flex-shrink: 0; height: 60rpx; line-height: 60rpx; padding: 0 32rpx; background: #F97316; color: #FFF; font-size: 26rpx; border-radius: 30rpx; border: none; }
|
|
|
+.copy-btn[disabled] { background: #FDBA74; color: #FFF; }
|
|
|
+.save-btn { width: 100%; height: 88rpx; line-height: 88rpx; background: #F97316; color: #FFF; font-size: 30rpx; font-weight: 600; border-radius: 44rpx; border: none; margin-top: 8rpx; }
|
|
|
+.save-btn:active { opacity: 0.85; }
|
|
|
+.stats-link { display: flex; align-items: center; justify-content: center; padding: 32rpx 0; color: #64748B; font-size: 28rpx; }
|
|
|
+.stats-link .arrow { color: #94A3B8; font-size: 32rpx; margin-left: 8rpx; }
|
|
|
+</style>
|