优化小程序推荐码处理逻辑,支持通过扫码场景解析推荐码和初始章节ID。新增获取用户邀请码的功能以便于分享。更新分享配置,确保分享时自动带上推荐码。调整部分页面逻辑以提升用户体验。
This commit is contained in:
@@ -77,5 +77,13 @@ Page({
|
||||
// 返回
|
||||
goBack() {
|
||||
wx.navigateBack()
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 关于作者',
|
||||
path: ref ? `/pages/about/about?ref=${ref}` : '/pages/about/about'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -119,5 +119,13 @@ Page({
|
||||
// 返回
|
||||
goBack() {
|
||||
wx.navigateBack()
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 收货地址',
|
||||
path: ref ? `/pages/addresses/addresses?ref=${ref}` : '/pages/addresses/addresses'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -197,5 +197,13 @@ Page({
|
||||
// 返回
|
||||
goBack() {
|
||||
wx.navigateBack()
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 编辑地址',
|
||||
path: ref ? `/pages/addresses/edit?ref=${ref}` : '/pages/addresses/edit'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -17,5 +17,13 @@ Page({
|
||||
|
||||
goBack() {
|
||||
wx.navigateBack()
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 用户协议',
|
||||
path: ref ? `/pages/agreement/agreement?ref=${ref}` : '/pages/agreement/agreement'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -257,5 +257,13 @@ Page({
|
||||
// 跳转到搜索页
|
||||
goToSearch() {
|
||||
wx.navigateTo({ url: '/pages/search/search' })
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 目录',
|
||||
path: ref ? `/pages/chapters/chapters?ref=${ref}` : '/pages/chapters/chapters'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -56,10 +56,9 @@ Page({
|
||||
navBarHeight: app.globalData.navBarHeight
|
||||
})
|
||||
|
||||
// 处理分享参数(推荐码绑定)
|
||||
if (options && options.ref) {
|
||||
console.log('[Index] 检测到推荐码:', options.ref)
|
||||
app.handleReferralCode({ query: options })
|
||||
// 处理分享参数与扫码 scene(推荐码绑定)
|
||||
if (options && (options.ref || options.scene)) {
|
||||
app.handleReferralCode(options)
|
||||
}
|
||||
|
||||
// 初始化数据
|
||||
@@ -211,5 +210,13 @@ Page({
|
||||
await this.initData()
|
||||
this.updateUserStatus()
|
||||
wx.stopPullDownRefresh()
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 真实商业故事',
|
||||
path: ref ? `/pages/index/index?ref=${ref}` : '/pages/index/index'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -891,5 +891,13 @@ Page({
|
||||
},
|
||||
|
||||
// 阻止事件冒泡
|
||||
preventBubble() {}
|
||||
preventBubble() {},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 找伙伴',
|
||||
path: ref ? `/pages/match/match?ref=${ref}` : '/pages/match/match'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -676,5 +676,13 @@ Page({
|
||||
},
|
||||
|
||||
// 阻止冒泡
|
||||
stopPropagation() {}
|
||||
stopPropagation() {},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 我的',
|
||||
path: ref ? `/pages/my/my?ref=${ref}` : '/pages/my/my'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -17,5 +17,13 @@ Page({
|
||||
|
||||
goBack() {
|
||||
wx.navigateBack()
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 隐私政策',
|
||||
path: ref ? `/pages/privacy/privacy?ref=${ref}` : '/pages/privacy/privacy'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -45,5 +45,13 @@ Page({
|
||||
wx.navigateTo({ url: `/pages/read/read?id=${id}` })
|
||||
},
|
||||
|
||||
goBack() { wx.navigateBack() }
|
||||
goBack() { wx.navigateBack() },
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 我的订单',
|
||||
path: ref ? `/pages/purchases/purchases?ref=${ref}` : '/pages/purchases/purchases'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -66,12 +66,18 @@ Page({
|
||||
isGeneratingPoster: false,
|
||||
|
||||
// 免费章节
|
||||
freeIds: ['preface', 'epilogue', '1.1', 'appendix-1', 'appendix-2', 'appendix-3']
|
||||
freeIds: ['preface', 'epilogue', '1.1', 'appendix-1', 'appendix-2', 'appendix-3'],
|
||||
|
||||
// 分享卡片图(canvas 生成后写入,供 onShareAppMessage 使用)
|
||||
shareImagePath: ''
|
||||
},
|
||||
|
||||
async onLoad(options) {
|
||||
const { id, ref } = options
|
||||
|
||||
// 扫码进入时 id 可能在 app.globalData.initialSectionId(scene 里 id=1.1 由 app 解析)
|
||||
let id = options.id || app.globalData.initialSectionId
|
||||
if (app.globalData.initialSectionId) delete app.globalData.initialSectionId
|
||||
const ref = options.ref
|
||||
|
||||
this.setData({
|
||||
statusBarHeight: app.globalData.statusBarHeight,
|
||||
navBarHeight: app.globalData.navBarHeight,
|
||||
@@ -268,10 +274,11 @@ Page({
|
||||
try {
|
||||
const res = await this.fetchChapterWithTimeout(id, 5000)
|
||||
if (res && res.content) {
|
||||
this.setData({ section: this.getSectionInfo(id) })
|
||||
this.setChapterContent(res)
|
||||
// 成功后缓存到本地
|
||||
wx.setStorageSync(cacheKey, res)
|
||||
console.log('[Read] 从API加载成功:', id)
|
||||
setTimeout(() => this.drawShareCard(), 600)
|
||||
return
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -282,10 +289,11 @@ Page({
|
||||
try {
|
||||
const cached = wx.getStorageSync(cacheKey)
|
||||
if (cached && cached.content) {
|
||||
this.setData({ section: this.getSectionInfo(id) })
|
||||
this.setChapterContent(cached)
|
||||
console.log('[Read] 从本地缓存加载成功:', id)
|
||||
// 后台静默刷新
|
||||
this.silentRefresh(id)
|
||||
setTimeout(() => this.drawShareCard(), 600)
|
||||
return
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -363,9 +371,11 @@ Page({
|
||||
try {
|
||||
const res = await this.fetchChapterWithTimeout(id, 8000)
|
||||
if (res && res.content) {
|
||||
this.setData({ section: this.getSectionInfo(id) })
|
||||
this.setChapterContent(res)
|
||||
wx.setStorageSync(`chapter_${id}`, res)
|
||||
console.log('[Read] 重试成功:', id, '第', currentRetry + 1, '次')
|
||||
setTimeout(() => this.drawShareCard(), 600)
|
||||
return
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -454,33 +464,91 @@ Page({
|
||||
})
|
||||
},
|
||||
|
||||
// 分享到微信 - 自动带分享人ID
|
||||
onShareAppMessage() {
|
||||
const { section, sectionId } = this.data
|
||||
const userInfo = app.globalData.userInfo
|
||||
const referralCode = userInfo?.referralCode || wx.getStorageSync('referralCode') || ''
|
||||
|
||||
// 分享标题优化
|
||||
const shareTitle = section?.title
|
||||
// 绘制分享卡片图(标题+正文摘要),生成后供 onShareAppMessage 使用
|
||||
drawShareCard() {
|
||||
const { section, sectionId, contentParagraphs } = this.data
|
||||
const title = section?.title || this.getSectionTitle(sectionId) || '精彩内容'
|
||||
const raw = (contentParagraphs && contentParagraphs.length)
|
||||
? contentParagraphs.slice(0, 4).join(' ').replace(/\s+/g, ' ').trim()
|
||||
: ''
|
||||
const excerpt = raw.length > 120 ? raw.slice(0, 120) + '...' : (raw || '来自派对房的真实商业故事')
|
||||
const ctx = wx.createCanvasContext('shareCardCanvas', this)
|
||||
const w = 500
|
||||
const h = 400
|
||||
// 白底
|
||||
ctx.setFillStyle('#ffffff')
|
||||
ctx.fillRect(0, 0, w, h)
|
||||
// 顶部:平台名
|
||||
ctx.setFillStyle('#333333')
|
||||
ctx.setFontSize(14)
|
||||
ctx.fillText('📚 Soul 创业派对 - 真实商业故事', 24, 36)
|
||||
// 深色内容区(模拟参考图效果)
|
||||
const boxX = 24
|
||||
const boxY = 52
|
||||
const boxW = w - 48
|
||||
const boxH = 300
|
||||
ctx.setFillStyle('#2c2c2e')
|
||||
ctx.fillRect(boxX, boxY, boxW, boxH)
|
||||
// 文章标题(白字)
|
||||
ctx.setFillStyle('#ffffff')
|
||||
ctx.setFontSize(15)
|
||||
const titleLines = this.wrapText(ctx, title.length > 50 ? title.slice(0, 50) + '...' : title, boxW - 32, 15)
|
||||
let y = boxY + 28
|
||||
titleLines.slice(0, 2).forEach(line => {
|
||||
ctx.fillText(line, boxX + 16, y)
|
||||
y += 22
|
||||
})
|
||||
y += 8
|
||||
// 正文摘要(浅灰)
|
||||
ctx.setFillStyle('rgba(255,255,255,0.88)')
|
||||
ctx.setFontSize(12)
|
||||
const excerptLines = this.wrapText(ctx, excerpt, boxW - 32, 12)
|
||||
excerptLines.slice(0, 8).forEach(line => {
|
||||
ctx.fillText(line, boxX + 16, y)
|
||||
y += 20
|
||||
})
|
||||
// 底部:小程序标识
|
||||
ctx.setFillStyle('#999999')
|
||||
ctx.setFontSize(11)
|
||||
ctx.fillText('小程序', 24, h - 16)
|
||||
ctx.draw(false, () => {
|
||||
wx.canvasToTempFilePath({
|
||||
canvasId: 'shareCardCanvas',
|
||||
fileType: 'png',
|
||||
success: (res) => {
|
||||
this.setData({ shareImagePath: res.tempFilePath })
|
||||
}
|
||||
}, this)
|
||||
})
|
||||
},
|
||||
|
||||
// 统一分享配置(底部「推荐给好友」与右下角分享按钮均走此配置,由 onShareAppMessage 使用)
|
||||
getShareConfig() {
|
||||
const { section, sectionId, shareImagePath } = this.data
|
||||
const ref = app.getMyReferralCode()
|
||||
const shareTitle = section?.title
|
||||
? `📚 ${section.title.length > 20 ? section.title.slice(0, 20) + '...' : section.title}`
|
||||
: '📚 Soul创业派对 - 真实商业故事'
|
||||
|
||||
const path = ref
|
||||
? `/pages/read/read?id=${sectionId}&ref=${ref}`
|
||||
: `/pages/read/read?id=${sectionId}`
|
||||
return {
|
||||
title: shareTitle,
|
||||
path: `/pages/read/read?id=${sectionId}${referralCode ? '&ref=' + referralCode : ''}`,
|
||||
imageUrl: '/assets/share-cover.png' // 可配置分享封面图
|
||||
path,
|
||||
imageUrl: shareImagePath || undefined
|
||||
}
|
||||
},
|
||||
|
||||
// 分享到朋友圈
|
||||
|
||||
onShareAppMessage() {
|
||||
return this.getShareConfig()
|
||||
},
|
||||
|
||||
onShareTimeline() {
|
||||
const { section, sectionId } = this.data
|
||||
const userInfo = app.globalData.userInfo
|
||||
const referralCode = userInfo?.referralCode || ''
|
||||
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: `${section?.title || 'Soul创业派对'} - 来自派对房的真实故事`,
|
||||
query: `id=${sectionId}${referralCode ? '&ref=' + referralCode : ''}`
|
||||
query: ref ? `id=${sectionId}&ref=${ref}` : `id=${sectionId}`
|
||||
}
|
||||
},
|
||||
|
||||
@@ -734,7 +802,8 @@ Page({
|
||||
|
||||
if (res.success && res.data?.payParams) {
|
||||
paymentData = res.data.payParams
|
||||
console.log('[Pay] 获取支付参数成功:', paymentData)
|
||||
paymentData._orderSn = res.data.orderSn
|
||||
console.log('[Pay] 获取支付参数成功, orderSn:', res.data.orderSn)
|
||||
} else {
|
||||
throw new Error(res.error || res.message || '创建订单失败')
|
||||
}
|
||||
@@ -767,11 +836,12 @@ Page({
|
||||
console.log('[Pay] 调起微信支付, paymentData:', paymentData)
|
||||
|
||||
try {
|
||||
const orderSn = paymentData._orderSn
|
||||
await this.callWechatPay(paymentData)
|
||||
|
||||
// 4. 【标准流程】支付成功后刷新权限并解锁内容
|
||||
// 4. 轮询订单状态确认已支付后刷新并解锁(不依赖 PayNotify 回调时机)
|
||||
console.log('[Pay] 微信支付成功!')
|
||||
await this.onPaymentSuccess()
|
||||
await this.onPaymentSuccess(orderSn)
|
||||
|
||||
} catch (payErr) {
|
||||
console.error('[Pay] 微信支付调起失败:', payErr)
|
||||
@@ -807,13 +877,34 @@ Page({
|
||||
}
|
||||
},
|
||||
|
||||
// 轮询订单状态,确认 paid 后刷新权限并解锁
|
||||
async pollOrderUntilPaid(orderSn) {
|
||||
const maxAttempts = 15
|
||||
const interval = 800
|
||||
for (let i = 0; i < maxAttempts; i++) {
|
||||
try {
|
||||
const r = await app.request(`/api/miniprogram/pay?orderSn=${encodeURIComponent(orderSn)}`, { method: 'GET', silent: true })
|
||||
if (r?.data?.status === 'paid') return true
|
||||
} catch (_) {}
|
||||
if (i < maxAttempts - 1) await this.sleep(interval)
|
||||
}
|
||||
return false
|
||||
},
|
||||
|
||||
// 【新增】支付成功后的标准处理流程
|
||||
async onPaymentSuccess() {
|
||||
async onPaymentSuccess(orderSn) {
|
||||
wx.showLoading({ title: '确认购买中...', mask: true })
|
||||
|
||||
try {
|
||||
// 1. 等待服务端处理支付回调(1-2秒)
|
||||
await this.sleep(2000)
|
||||
// 1. 轮询订单状态直到已支付(GET pay 会主动同步本地订单,不依赖 PayNotify)
|
||||
if (orderSn) {
|
||||
const paid = await this.pollOrderUntilPaid(orderSn)
|
||||
if (!paid) {
|
||||
console.warn('[Pay] 轮询超时,仍尝试刷新')
|
||||
}
|
||||
} else {
|
||||
await this.sleep(1500)
|
||||
}
|
||||
|
||||
// 2. 刷新用户购买状态
|
||||
await accessManager.refreshUserPurchaseStatus()
|
||||
@@ -936,134 +1027,115 @@ Page({
|
||||
wx.navigateTo({ url: '/pages/referral/referral' })
|
||||
},
|
||||
|
||||
// 生成海报
|
||||
// 生成海报(弹窗先展示,延迟再绘制,确保 canvas 已渲染)
|
||||
async generatePoster() {
|
||||
wx.showLoading({ title: '生成中...' })
|
||||
this.setData({ showPosterModal: true, isGeneratingPoster: true })
|
||||
|
||||
const { section, contentParagraphs, sectionId } = this.data
|
||||
const userInfo = app.globalData.userInfo
|
||||
const userId = userInfo?.id || ''
|
||||
const safeParagraphs = contentParagraphs || []
|
||||
|
||||
// 通过 GET 接口下载二维码图片,得到 tempFilePath 便于开发工具与真机统一用 drawImage 绘制
|
||||
let qrcodeTempPath = null
|
||||
try {
|
||||
const ctx = wx.createCanvasContext('posterCanvas', this)
|
||||
const { section, contentParagraphs, sectionId } = this.data
|
||||
const userInfo = app.globalData.userInfo
|
||||
const userId = userInfo?.id || ''
|
||||
|
||||
// 获取小程序码(带推荐人参数)
|
||||
let qrcodeImage = null
|
||||
try {
|
||||
const scene = userId ? `id=${sectionId}&ref=${userId.slice(0,10)}` : `id=${sectionId}`
|
||||
const qrRes = await app.request('/api/miniprogram/qrcode', {
|
||||
method: 'POST',
|
||||
data: { scene, page: 'pages/read/read', width: 280 }
|
||||
const scene = userId ? `id=${sectionId}&ref=${userId.slice(0, 10)}` : `id=${sectionId}`
|
||||
const baseUrl = app.globalData.baseUrl || ''
|
||||
const url = `${baseUrl}/api/miniprogram/qrcode/image?scene=${encodeURIComponent(scene)}&page=${encodeURIComponent('pages/read/read')}&width=280`
|
||||
qrcodeTempPath = await new Promise((resolve) => {
|
||||
wx.downloadFile({
|
||||
url,
|
||||
success: (res) => resolve(res.statusCode === 200 ? res.tempFilePath : null),
|
||||
fail: () => resolve(null)
|
||||
})
|
||||
if (qrRes.success && qrRes.image) {
|
||||
qrcodeImage = qrRes.image
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('[Poster] 获取小程序码失败,使用占位符')
|
||||
}
|
||||
|
||||
// 海报尺寸 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 - 100, width, 100)
|
||||
|
||||
// 左侧提示文字
|
||||
ctx.setFillStyle('#ffffff')
|
||||
ctx.setFontSize(13)
|
||||
ctx.fillText('长按识别小程序码', 20, height - 60)
|
||||
ctx.setFillStyle('rgba(255,255,255,0.6)')
|
||||
ctx.setFontSize(11)
|
||||
ctx.fillText('长按小程序码阅读全文', 20, height - 38)
|
||||
|
||||
// 绘制小程序码或占位符
|
||||
const drawQRCode = () => {
|
||||
return new Promise((resolve) => {
|
||||
if (qrcodeImage) {
|
||||
// 下载base64图片并绘制
|
||||
const fs = wx.getFileSystemManager()
|
||||
const filePath = `${wx.env.USER_DATA_PATH}/qrcode_${Date.now()}.png`
|
||||
const base64Data = qrcodeImage.replace(/^data:image\/\w+;base64,/, '')
|
||||
|
||||
fs.writeFile({
|
||||
filePath,
|
||||
data: base64Data,
|
||||
encoding: 'base64',
|
||||
success: () => {
|
||||
ctx.drawImage(filePath, width - 85, height - 85, 70, 70)
|
||||
resolve()
|
||||
},
|
||||
fail: () => {
|
||||
this.drawQRPlaceholder(ctx, width, height)
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.drawQRPlaceholder(ctx, width, height)
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
await drawQRCode()
|
||||
|
||||
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 })
|
||||
console.log('[Poster] 获取小程序码失败,使用占位符')
|
||||
}
|
||||
|
||||
const doDraw = () => {
|
||||
try {
|
||||
const ctx = wx.createCanvasContext('posterCanvas', this)
|
||||
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 || this.getSectionTitle(sectionId) || '精彩内容'
|
||||
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 = safeParagraphs.slice(0, 3).join(' ').replace(/\s+/g, ' ').trim().slice(0, 150)
|
||||
const summaryText = summary ? summary + (summary.length >= 150 ? '...' : '') : '来自派对房的真实商业故事'
|
||||
const summaryLines = this.wrapText(ctx, summaryText, 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 - 100, width, 100)
|
||||
|
||||
ctx.setFillStyle('#ffffff')
|
||||
ctx.setFontSize(13)
|
||||
ctx.fillText('长按识别小程序码', 20, height - 60)
|
||||
ctx.setFillStyle('rgba(255,255,255,0.6)')
|
||||
ctx.setFontSize(11)
|
||||
ctx.fillText('长按小程序码阅读全文', 20, height - 38)
|
||||
|
||||
const drawQRCode = () => {
|
||||
return new Promise((resolve) => {
|
||||
if (qrcodeTempPath) {
|
||||
ctx.drawImage(qrcodeTempPath, width - 85, height - 85, 70, 70)
|
||||
} else {
|
||||
this.drawQRPlaceholder(ctx, width, height)
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
|
||||
drawQRCode().then(() => {
|
||||
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 })
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(doDraw, 400)
|
||||
},
|
||||
|
||||
// 绘制小程序码占位符
|
||||
@@ -1101,11 +1173,20 @@ Page({
|
||||
this.setData({ showPosterModal: false })
|
||||
},
|
||||
|
||||
// 保存海报到相册
|
||||
// 保存海报到相册(与海报绘制尺寸一致,必须传 destWidth/destHeight 否则部分机型导出失败)
|
||||
savePoster() {
|
||||
const width = 300
|
||||
const height = 450
|
||||
wx.canvasToTempFilePath({
|
||||
canvasId: 'posterCanvas',
|
||||
destWidth: width,
|
||||
destHeight: height,
|
||||
fileType: 'png',
|
||||
success: (res) => {
|
||||
if (!res.tempFilePath) {
|
||||
wx.showToast({ title: '生成图片失败', icon: 'none' })
|
||||
return
|
||||
}
|
||||
wx.saveImageToPhotosAlbum({
|
||||
filePath: res.tempFilePath,
|
||||
success: () => {
|
||||
@@ -1113,25 +1194,25 @@ Page({
|
||||
this.setData({ showPosterModal: false })
|
||||
},
|
||||
fail: (err) => {
|
||||
if (err.errMsg.includes('auth deny')) {
|
||||
console.error('[savePoster] saveImageToPhotosAlbum fail:', err)
|
||||
if (err.errMsg && (err.errMsg.includes('auth deny') || err.errMsg.includes('authorize'))) {
|
||||
wx.showModal({
|
||||
title: '提示',
|
||||
content: '需要相册权限才能保存海报',
|
||||
confirmText: '去设置',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
wx.openSetting()
|
||||
}
|
||||
success: (sres) => {
|
||||
if (sres.confirm) wx.openSetting()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
wx.showToast({ title: '保存失败', icon: 'none' })
|
||||
wx.showToast({ title: err.errMsg || '保存失败', icon: 'none' })
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
fail: () => {
|
||||
wx.showToast({ title: '生成图片失败', icon: 'none' })
|
||||
fail: (err) => {
|
||||
console.error('[savePoster] canvasToTempFilePath fail:', err)
|
||||
wx.showToast({ title: err.errMsg || '生成图片失败', icon: 'none' })
|
||||
}
|
||||
}, this)
|
||||
},
|
||||
|
||||
@@ -297,4 +297,7 @@
|
||||
<button class="fab-share" open-type="share">
|
||||
<image class="fab-icon" src="/assets/icons/share.svg" mode="aspectFit"></image>
|
||||
</button>
|
||||
|
||||
<!-- 分享卡片用 canvas(离屏绘制,用于生成分享图) -->
|
||||
<canvas canvas-id="shareCardCanvas" class="share-card-canvas" style="width: 500px; height: 400px;"></canvas>
|
||||
</view>
|
||||
|
||||
@@ -912,6 +912,14 @@
|
||||
box-shadow: 0 16rpx 48rpx rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
/* 分享卡片 canvas:离屏绘制,不展示给用户 */
|
||||
.share-card-canvas {
|
||||
position: fixed;
|
||||
left: -600px;
|
||||
top: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.poster-actions {
|
||||
display: flex;
|
||||
gap: 24rpx;
|
||||
|
||||
@@ -796,14 +796,13 @@ Page({
|
||||
})
|
||||
},
|
||||
|
||||
// 分享 - 带推荐码
|
||||
// 分享 - 带自己的邀请码(与 app.getMyReferralCode 一致)
|
||||
onShareAppMessage() {
|
||||
console.log('[Referral] 分享给好友,推荐码:', this.data.referralCode)
|
||||
const app = getApp()
|
||||
const ref = app.getMyReferralCode() || this.data.referralCode
|
||||
return {
|
||||
title: 'Soul创业派对 - 来自派对房的真实商业故事',
|
||||
path: `/pages/index/index?ref=${this.data.referralCode}`
|
||||
// 不设置 imageUrl,使用小程序默认截图
|
||||
// 如需自定义图片,请将图片放在 /assets/ 目录并配置路径
|
||||
path: ref ? `/pages/index/index?ref=${ref}` : '/pages/index/index'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
157
miniprogram/pages/scan/scan.js
Normal file
157
miniprogram/pages/scan/scan.js
Normal file
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* Soul创业派对 - 扫码解析页
|
||||
* 扫描二维码/条形码,展示解析内容
|
||||
*/
|
||||
const app = getApp()
|
||||
|
||||
Page({
|
||||
data: {
|
||||
statusBarHeight: 44,
|
||||
// 最近一次解析结果
|
||||
lastResult: null,
|
||||
scanType: '',
|
||||
charSet: '',
|
||||
// 小程序码解析(路径、参数)
|
||||
parsedPath: null,
|
||||
parsedQuery: [],
|
||||
canNavigate: false,
|
||||
// 历史记录
|
||||
history: []
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.setData({
|
||||
statusBarHeight: app.globalData.statusBarHeight || 44
|
||||
})
|
||||
this.loadHistory()
|
||||
},
|
||||
|
||||
loadHistory() {
|
||||
try {
|
||||
const history = wx.getStorageSync('scanHistory') || []
|
||||
this.setData({ history })
|
||||
} catch (e) {
|
||||
console.log('加载扫码历史失败:', e)
|
||||
}
|
||||
},
|
||||
|
||||
saveToHistory(result, scanType, charSet) {
|
||||
const item = { result, scanType, charSet, time: new Date().toLocaleString() }
|
||||
let history = wx.getStorageSync('scanHistory') || []
|
||||
history = [item, ...history].slice(0, 10)
|
||||
wx.setStorageSync('scanHistory', history)
|
||||
this.setData({ history })
|
||||
},
|
||||
|
||||
// 解析小程序码内容:path?key=val 或 path
|
||||
parseMiniProgramCode(result) {
|
||||
if (!result || typeof result !== 'string') return { path: null, query: [], canNavigate: false }
|
||||
const idx = result.indexOf('?')
|
||||
let path = idx >= 0 ? result.slice(0, idx) : result
|
||||
const qs = idx >= 0 ? result.slice(idx + 1) : ''
|
||||
path = path.replace(/^\//, '').trim()
|
||||
const query = []
|
||||
if (qs) {
|
||||
qs.split('&').forEach(pair => {
|
||||
const eq = pair.indexOf('=')
|
||||
const k = eq >= 0 ? pair.slice(0, eq) : pair
|
||||
const v = eq >= 0 ? pair.slice(eq + 1) : ''
|
||||
try {
|
||||
if (k) query.push({ key: decodeURIComponent(k), value: decodeURIComponent(v) })
|
||||
} catch (_) {
|
||||
if (k) query.push({ key: k, value: v })
|
||||
}
|
||||
})
|
||||
}
|
||||
const isMiniProgramPath = /^pages\/[\w-]+\/[\w-]+$/.test(path)
|
||||
return { path: path || null, query, canNavigate: isMiniProgramPath }
|
||||
},
|
||||
|
||||
// 发起扫码(支持小程序码)
|
||||
doScan() {
|
||||
wx.scanCode({
|
||||
onlyFromCamera: false,
|
||||
scanType: ['qrCode', 'barCode'],
|
||||
success: (res) => {
|
||||
const { result, scanType, charSet } = res
|
||||
const parsed = this.parseMiniProgramCode(result)
|
||||
this.setData({
|
||||
lastResult: result,
|
||||
scanType: scanType || '未知',
|
||||
charSet: charSet || '',
|
||||
parsedPath: parsed.path,
|
||||
parsedQuery: parsed.query,
|
||||
canNavigate: parsed.canNavigate
|
||||
})
|
||||
this.saveToHistory(result, scanType, charSet)
|
||||
},
|
||||
fail: (err) => {
|
||||
if (err.errMsg && err.errMsg.includes('cancel')) {
|
||||
return
|
||||
}
|
||||
wx.showToast({ title: err.errMsg || '扫码失败', icon: 'none' })
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 复制内容
|
||||
copyResult() {
|
||||
const { lastResult } = this.data
|
||||
if (!lastResult) {
|
||||
wx.showToast({ title: '暂无解析内容', icon: 'none' })
|
||||
return
|
||||
}
|
||||
wx.setClipboardData({
|
||||
data: lastResult,
|
||||
success: () => wx.showToast({ title: '已复制', icon: 'success' })
|
||||
})
|
||||
},
|
||||
|
||||
// 清空当前结果
|
||||
clearResult() {
|
||||
this.setData({
|
||||
lastResult: null, scanType: '', charSet: '',
|
||||
parsedPath: null, parsedQuery: [], canNavigate: false
|
||||
})
|
||||
},
|
||||
|
||||
// 打开解析出的小程序页面
|
||||
openParsedPage() {
|
||||
const { parsedPath, parsedQuery } = this.data
|
||||
if (!parsedPath || !this.data.canNavigate) {
|
||||
wx.showToast({ title: '非本小程序页面', icon: 'none' })
|
||||
return
|
||||
}
|
||||
const queryStr = parsedQuery.length
|
||||
? '?' + parsedQuery.map(q => `${encodeURIComponent(q.key)}=${encodeURIComponent(q.value)}`).join('&')
|
||||
: ''
|
||||
const url = `/${parsedPath}${queryStr}`
|
||||
const tabPages = ['pages/index/index', 'pages/chapters/chapters', 'pages/match/match', 'pages/my/my']
|
||||
if (tabPages.includes(parsedPath)) {
|
||||
wx.switchTab({ url: `/${parsedPath}` })
|
||||
} else {
|
||||
wx.navigateTo({ url })
|
||||
}
|
||||
},
|
||||
|
||||
// 清空历史
|
||||
clearHistory() {
|
||||
wx.setStorageSync('scanHistory', [])
|
||||
this.setData({ history: [], lastResult: null, scanType: '', charSet: '' })
|
||||
wx.showToast({ title: '已清空', icon: 'success' })
|
||||
},
|
||||
|
||||
// 点击历史项复制
|
||||
onHistoryItemTap(e) {
|
||||
const result = e.currentTarget.dataset.result
|
||||
if (!result) return
|
||||
wx.setClipboardData({
|
||||
data: result,
|
||||
success: () => wx.showToast({ title: '已复制', icon: 'success' })
|
||||
})
|
||||
},
|
||||
|
||||
goBack() {
|
||||
wx.navigateBack()
|
||||
}
|
||||
})
|
||||
1
miniprogram/pages/scan/scan.json
Normal file
1
miniprogram/pages/scan/scan.json
Normal file
@@ -0,0 +1 @@
|
||||
{"usingComponents":{},"navigationStyle":"custom","navigationBarTitleText":"扫码解析"}
|
||||
81
miniprogram/pages/scan/scan.wxml
Normal file
81
miniprogram/pages/scan/scan.wxml
Normal file
@@ -0,0 +1,81 @@
|
||||
<!--pages/scan/scan.wxml-->
|
||||
<!--扫码解析页 - 扫描二维码/条形码展示解析内容-->
|
||||
<view class="page">
|
||||
<!-- 自定义导航栏 -->
|
||||
<view class="nav-bar" style="padding-top: {{statusBarHeight}}px;">
|
||||
<view class="nav-content">
|
||||
<view class="back-btn" bindtap="goBack">
|
||||
<text class="back-icon">←</text>
|
||||
</view>
|
||||
<text class="nav-title">扫码解析</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 主内容 -->
|
||||
<view class="main-content" style="padding-top: {{statusBarHeight + 56}}px;">
|
||||
<!-- 扫码按钮 -->
|
||||
<view class="scan-action">
|
||||
<view class="scan-btn" bindtap="doScan">
|
||||
<text class="scan-icon">📷</text>
|
||||
<text class="scan-text">扫描小程序码 / 二维码</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 解析结果 -->
|
||||
<view class="result-card" wx:if="{{lastResult}}">
|
||||
<view class="result-header">
|
||||
<text class="result-label">解析内容</text>
|
||||
<view class="result-actions">
|
||||
<view class="action-btn" bindtap="copyResult">复制</view>
|
||||
<view class="action-btn" wx:if="{{canNavigate}}" bindtap="openParsedPage">打开</view>
|
||||
<view class="action-btn secondary" bindtap="clearResult">清空</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 小程序码解析:路径 + 参数(仅当为 pages/ 路径时展示) -->
|
||||
<view class="parsed-section" wx:if="{{parsedPath && (parsedPath.indexOf('pages/') === 0 || parsedQuery.length > 0)}}">
|
||||
<view class="parsed-row">
|
||||
<text class="parsed-label">路径</text>
|
||||
<text class="parsed-value">{{parsedPath}}</text>
|
||||
</view>
|
||||
<view class="parsed-row" wx:for="{{parsedQuery}}" wx:key="key" wx:for-item="q">
|
||||
<text class="parsed-label">{{q.key}}</text>
|
||||
<text class="parsed-value">{{q.value}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="result-meta" wx:if="{{scanType}}">
|
||||
<text class="meta-item">类型: {{scanType}}</text>
|
||||
<text class="meta-item" wx:if="{{charSet}}">字符集: {{charSet}}</text>
|
||||
</view>
|
||||
<scroll-view class="result-content" scroll-y="{{true}}">
|
||||
<text class="result-text" selectable="{{true}}">{{lastResult}}</text>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 无结果提示 -->
|
||||
<view class="empty-tip" wx:else>
|
||||
<text class="empty-icon">📷</text>
|
||||
<text class="empty-text">点击上方按钮扫码</text>
|
||||
<text class="empty-desc">支持小程序码、二维码、条形码</text>
|
||||
</view>
|
||||
|
||||
<!-- 扫码历史 -->
|
||||
<view class="history-section" wx:if="{{history.length > 0}}">
|
||||
<view class="history-header">
|
||||
<text class="history-title">扫码历史</text>
|
||||
<view class="clear-history" bindtap="clearHistory">清空</view>
|
||||
</view>
|
||||
<view class="history-list">
|
||||
<view
|
||||
class="history-item"
|
||||
wx:for="{{history}}"
|
||||
wx:key="index"
|
||||
bindtap="onHistoryItemTap"
|
||||
data-result="{{item.result}}"
|
||||
>
|
||||
<text class="history-content">{{item.result}}</text>
|
||||
<text class="history-time">{{item.time}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
248
miniprogram/pages/scan/scan.wxss
Normal file
248
miniprogram/pages/scan/scan.wxss
Normal file
@@ -0,0 +1,248 @@
|
||||
/* 扫码解析页样式 */
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
background: linear-gradient(180deg, #0a0a0a 0%, #111111 100%);
|
||||
}
|
||||
|
||||
.nav-bar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
background: rgba(10, 10, 10, 0.95);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
}
|
||||
|
||||
.nav-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8rpx 24rpx;
|
||||
height: 88rpx;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 40rpx;
|
||||
color: #00CED1;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
flex: 1;
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
margin-right: 60rpx;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
/* 扫码按钮 */
|
||||
.scan-action {
|
||||
padding: 60rpx 0;
|
||||
}
|
||||
|
||||
.scan-btn {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, rgba(0, 206, 209, 0.2) 0%, rgba(32, 178, 170, 0.15) 100%);
|
||||
border: 2rpx solid rgba(0, 206, 209, 0.4);
|
||||
border-radius: 32rpx;
|
||||
padding: 80rpx 48rpx;
|
||||
}
|
||||
|
||||
.scan-icon {
|
||||
font-size: 80rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.scan-text {
|
||||
font-size: 32rpx;
|
||||
color: #00CED1;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 解析结果卡片 */
|
||||
.result-card {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border-radius: 24rpx;
|
||||
padding: 32rpx;
|
||||
margin-top: 32rpx;
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.result-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.result-label {
|
||||
font-size: 28rpx;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.result-actions {
|
||||
display: flex;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
font-size: 26rpx;
|
||||
color: #00CED1;
|
||||
padding: 8rpx 20rpx;
|
||||
}
|
||||
|
||||
.action-btn.secondary {
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
/* 小程序码解析:路径+参数 */
|
||||
.parsed-section {
|
||||
background: rgba(0, 206, 209, 0.08);
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
margin-bottom: 24rpx;
|
||||
border: 1rpx solid rgba(0, 206, 209, 0.2);
|
||||
}
|
||||
|
||||
.parsed-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.parsed-row:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.parsed-label {
|
||||
font-size: 24rpx;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
min-width: 120rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.parsed-value {
|
||||
font-size: 26rpx;
|
||||
color: #00CED1;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.result-meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.meta-item {
|
||||
font-size: 22rpx;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
|
||||
.result-content {
|
||||
max-height: 400rpx;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.result-text {
|
||||
font-size: 28rpx;
|
||||
color: #fff;
|
||||
line-height: 1.6;
|
||||
word-break: break-all;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/* 无结果提示 */
|
||||
.empty-tip {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 60rpx 0;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 80rpx;
|
||||
margin-bottom: 20rpx;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 30rpx;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.empty-desc {
|
||||
font-size: 24rpx;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
|
||||
/* 扫码历史 */
|
||||
.history-section {
|
||||
margin-top: 48rpx;
|
||||
}
|
||||
|
||||
.history-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.history-title {
|
||||
font-size: 28rpx;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
.clear-history {
|
||||
font-size: 26rpx;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.history-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.history-item {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.06);
|
||||
}
|
||||
|
||||
.history-content {
|
||||
font-size: 26rpx;
|
||||
color: #fff;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.history-time {
|
||||
font-size: 22rpx;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
margin-top: 8rpx;
|
||||
display: block;
|
||||
}
|
||||
@@ -105,5 +105,13 @@ Page({
|
||||
// 返回上一页
|
||||
goBack() {
|
||||
wx.navigateBack()
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 搜索',
|
||||
path: ref ? `/pages/search/search?ref=${ref}` : '/pages/search/search'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -493,5 +493,13 @@ Page({
|
||||
// 跳转到地址管理页
|
||||
goToAddresses() {
|
||||
wx.navigateTo({ url: '/pages/addresses/addresses' })
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 设置',
|
||||
path: ref ? `/pages/settings/settings?ref=${ref}` : '/pages/settings/settings'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -119,5 +119,13 @@ Page({
|
||||
wx.hideLoading()
|
||||
wx.showToast({ title: '网络异常,请重试', icon: 'none' })
|
||||
}
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 提现记录',
|
||||
path: ref ? `/pages/withdraw-records/withdraw-records?ref=${ref}` : '/pages/withdraw-records/withdraw-records'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user