feat: 海报生成功能+推广优化

1. 阅读页:
   - 添加"生成海报"和"分享给好友"按钮
   - 海报包含章节摘要+邀请码+小程序码占位
   - 优化推广提示区域,添加推广中心入口

2. 分销中心:
   - 完善海报生成功能(推广海报)
   - 去掉"更多分享方式",改为"复制朋友圈文案"
   - 添加"分享给好友"小程序卡片按钮

3. 分享链接自动带分销ID
This commit is contained in:
卡若
2026-01-25 19:52:38 +08:00
parent 4dd2f9f4a7
commit a702cd9086
6 changed files with 551 additions and 56 deletions

View File

@@ -47,7 +47,9 @@ Page({
// 弹窗
showShareModal: false,
showLoginModal: false,
showPosterModal: false,
isPaying: false,
isGeneratingPoster: false,
// 免费章节
freeIds: ['preface', 'epilogue', '1.1', 'appendix-1', 'appendix-2', 'appendix-3']
@@ -530,6 +532,160 @@ Page({
wx.navigateTo({ url: '/pages/referral/referral' })
},
// 生成海报
async generatePoster() {
wx.showLoading({ title: '生成中...' })
this.setData({ showPosterModal: true, isGeneratingPoster: true })
try {
const ctx = wx.createCanvasContext('posterCanvas', this)
const { section, contentParagraphs } = this.data
const userInfo = app.globalData.userInfo
const referralCode = userInfo?.referralCode || 'SOUL'
// 海报尺寸 300x450
const width = 300
const height = 450
// 背景渐变
const grd = ctx.createLinearGradient(0, 0, 0, height)
grd.addColorStop(0, '#1a1a2e')
grd.addColorStop(1, '#16213e')
ctx.setFillStyle(grd)
ctx.fillRect(0, 0, width, height)
// 顶部装饰条
ctx.setFillStyle('#00CED1')
ctx.fillRect(0, 0, width, 4)
// 标题区域
ctx.setFillStyle('#ffffff')
ctx.setFontSize(14)
ctx.fillText('📚 Soul创业派对', 20, 35)
// 章节标题
ctx.setFontSize(18)
ctx.setFillStyle('#ffffff')
const title = section?.title || '精彩内容'
const titleLines = this.wrapText(ctx, title, width - 40, 18)
let y = 70
titleLines.forEach(line => {
ctx.fillText(line, 20, y)
y += 26
})
// 分隔线
ctx.setStrokeStyle('rgba(255,255,255,0.1)')
ctx.beginPath()
ctx.moveTo(20, y + 10)
ctx.lineTo(width - 20, y + 10)
ctx.stroke()
// 内容摘要
ctx.setFontSize(12)
ctx.setFillStyle('rgba(255,255,255,0.8)')
y += 30
const summary = contentParagraphs.slice(0, 3).join(' ').slice(0, 150) + '...'
const summaryLines = this.wrapText(ctx, summary, width - 40, 12)
summaryLines.slice(0, 6).forEach(line => {
ctx.fillText(line, 20, y)
y += 20
})
// 底部区域背景
ctx.setFillStyle('rgba(0,206,209,0.1)')
ctx.fillRect(0, height - 120, width, 120)
// 小程序码占位(实际需要获取小程序码图片)
ctx.setFillStyle('#ffffff')
ctx.beginPath()
ctx.arc(width - 55, height - 60, 35, 0, Math.PI * 2)
ctx.fill()
ctx.setFillStyle('#00CED1')
ctx.setFontSize(10)
ctx.fillText('扫码阅读', width - 72, height - 58)
// 邀请信息
ctx.setFillStyle('#ffffff')
ctx.setFontSize(12)
ctx.fillText('长按识别 · 阅读全文', 20, height - 70)
ctx.setFillStyle('#FFD700')
ctx.setFontSize(11)
ctx.fillText(`邀请码: ${referralCode}`, 20, height - 50)
ctx.setFillStyle('rgba(255,255,255,0.6)')
ctx.setFontSize(10)
ctx.fillText('好友购买你获90%收益', 20, height - 32)
ctx.draw(true, () => {
wx.hideLoading()
this.setData({ isGeneratingPoster: false })
})
} catch (e) {
console.error('生成海报失败:', e)
wx.hideLoading()
wx.showToast({ title: '生成失败', icon: 'none' })
this.setData({ showPosterModal: false, isGeneratingPoster: false })
}
},
// 文字换行处理
wrapText(ctx, text, maxWidth, fontSize) {
const lines = []
let line = ''
for (let i = 0; i < text.length; i++) {
const testLine = line + text[i]
const metrics = ctx.measureText(testLine)
if (metrics.width > maxWidth && line) {
lines.push(line)
line = text[i]
} else {
line = testLine
}
}
if (line) lines.push(line)
return lines
},
// 关闭海报弹窗
closePosterModal() {
this.setData({ showPosterModal: false })
},
// 保存海报到相册
savePoster() {
wx.canvasToTempFilePath({
canvasId: 'posterCanvas',
success: (res) => {
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: () => {
wx.showToast({ title: '已保存到相册', icon: 'success' })
this.setData({ showPosterModal: false })
},
fail: (err) => {
if (err.errMsg.includes('auth deny')) {
wx.showModal({
title: '提示',
content: '需要相册权限才能保存海报',
confirmText: '去设置',
success: (res) => {
if (res.confirm) {
wx.openSetting()
}
}
})
} else {
wx.showToast({ title: '保存失败', icon: 'none' })
}
}
})
},
fail: () => {
wx.showToast({ title: '生成图片失败', icon: 'none' })
}
}, this)
},
// 阻止冒泡
stopPropagation() {}
})