const api = require('../../utils/api') const auth = require('../../utils/auth') const config = require('../../config/index') Page({ data: { invitationCode: '', referralCode: '', // 推荐码(佣金系统) shareUrl: '', stats: { total_invites: 0, completed_invites: 0 }, // 佣金统计 commissionStats: { totalReferrals: 0, commissionBalance: 0, totalEarned: 0 }, lovePoints: 0, shareCount: 0, maxShareCount: 3, loading: false, isDistributor: false, // 是否是分销商 // 海报相关 posterTemplates: [], currentPosterIndex: 0, generatingPoster: false, shareConfig: null }, async onLoad() { // 统一登录验证 const isValid = await auth.ensureLogin({ pageName: 'invite', redirectUrl: '/pages/invite/invite' }) if (!isValid) return // 验证通过后,稍作延迟确保token稳定 await new Promise(resolve => setTimeout(resolve, 50)) // 加载数据 this.loadData() }, onShow() { // 每次显示页面时刷新数据(已登录的情况下) const app = getApp() if (app.globalData.isLoggedIn) { this.loadData() } }, /** * 加载所有数据 */ async loadData() { if (this.data.loading) return this.setData({ loading: true }) try { await Promise.all([ this.loadInvitationCode(), this.loadCommissionStats(), // 加载佣金统计 this.getLovePoints(), this.getTodayShareCount(), this.loadPosterTemplates(), this.loadShareConfig() ]) } catch (error) { console.error('加载数据失败:', error) } finally { this.setData({ loading: false }) } }, /** * 获取邀请码 */ async loadInvitationCode() { try { const res = await api.lovePoints.getInvitationCode() if (res.success) { this.setData({ invitationCode: res.data.invitation_code, shareUrl: res.data.share_url, stats: res.data.stats }) } } catch (error) { console.error('获取邀请码失败:', error) // 401错误由API层统一处理,这里只处理其他错误 if (error.code !== 401) { wx.showToast({ title: error.message || '获取邀请码失败', icon: 'none' }) } } }, /** * 加载佣金统计数据 */ async loadCommissionStats() { try { const res = await api.commission.getStats() if (res.success && res.data) { this.setData({ referralCode: res.data.referralCode || '', isDistributor: res.data.isDistributor || false, commissionStats: { totalReferrals: res.data.totalReferrals || 0, commissionBalance: res.data.commissionBalance || 0, totalEarned: res.data.totalEarned || 0 } }) } } catch (error) { console.error('获取佣金统计失败:', error) // 不显示错误提示,静默失败 } }, /** * 获取爱心值余额(使用后端新接口) */ getLovePoints() { return new Promise((resolve, reject) => { const token = wx.getStorageSync('auth_token') if (!token) { resolve() return } wx.request({ url: `${config.API_BASE_URL}/love-points/balance`, method: 'GET', header: { 'Authorization': `Bearer ${token}` }, success: (res) => { console.log('爱心值余额API响应:', res.data) if (res.data.success) { this.setData({ lovePoints: res.data.data.love_points }) resolve(res.data.data) } else { reject(new Error(res.data.error)) } }, fail: reject }) }) }, /** * 获取今日分享次数(使用后端新接口) */ getTodayShareCount() { return new Promise((resolve, reject) => { const token = wx.getStorageSync('auth_token') if (!token) { resolve() return } wx.request({ url: `${config.API_BASE_URL}/love-points/share-count`, method: 'GET', header: { 'Authorization': `Bearer ${token}` }, success: (res) => { console.log('分享次数API响应:', res.data) if (res.data.success) { this.setData({ shareCount: res.data.data.count, maxShareCount: res.data.data.max }) resolve(res.data.data) } else { reject(new Error(res.data.error)) } }, fail: reject }) }) }, /** * 复制邀请码 */ copyInviteCode() { const { isDistributor, referralCode, invitationCode } = this.data; // 如果是分销商且有推荐码,优先复制推荐码 const codeToCopy = (isDistributor && referralCode) ? referralCode : invitationCode; if (!codeToCopy) { wx.showToast({ title: '邀请码加载中...', icon: 'none' }) return } wx.setClipboardData({ data: codeToCopy, success: () => { wx.showToast({ title: '邀请码已复制', icon: 'success' }) } }) }, /** * 查看佣金中心 */ goToCommission() { wx.navigateTo({ url: '/pages/commission/commission' }) }, /** * 点击分享按钮 */ onShareTap() { console.log('用户点击了分享按钮') // 检查登录状态 const token = wx.getStorageSync('auth_token') if (!token) { wx.showModal({ title: '提示', content: '请先登录', confirmText: '去登录', success: (res) => { if (res.confirm) { wx.navigateTo({ url: '/pages/login/login' }) } } }) return } // 检查是否达到上限 if (this.data.shareCount >= this.data.maxShareCount) { wx.showToast({ title: '今日分享次数已达上限', icon: 'none', duration: 2000 }) return } // 立即记录分享 this.recordShare() }, /** * 记录分享并获得爱心值(使用后端新接口) */ recordShare() { const token = wx.getStorageSync('auth_token') if (!token) return wx.showLoading({ title: '处理中...', mask: true }) wx.request({ url: `${config.API_BASE_URL}/love-points/share`, method: 'POST', header: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, success: (res) => { wx.hideLoading() console.log('分享奖励API响应:', res.data) if (res.data.success) { const newShareCount = this.data.shareCount + 1 const newLovePoints = this.data.lovePoints + res.data.data.earned this.setData({ shareCount: newShareCount, lovePoints: newLovePoints }) wx.showToast({ title: `+${res.data.data.earned} 爱心值`, icon: 'success', duration: 2000 }) const app = getApp() if (app.globalData) { app.globalData.lovePoints = newLovePoints } this.triggerPageRefresh() } else { wx.showToast({ title: res.data.error || '分享失败', icon: 'none', duration: 2000 }) } }, fail: (error) => { wx.hideLoading() console.error('分享奖励API调用失败:', error) wx.showToast({ title: '网络错误,请稍后重试', icon: 'none', duration: 2000 }) } }) }, /** * 静默记录分享奖励(用于 onShareAppMessage/onShareTimeline) * 不显示 loading 和 Toast,后台静默调用 * 分享人A获得+100爱心值 */ async recordShareReward() { try { const token = wx.getStorageSync('auth_token') if (!token) return const res = await new Promise((resolve, reject) => { wx.request({ url: `${config.API_BASE_URL}/love-points/share`, method: 'POST', header: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, success: resolve, fail: reject }) }) if (res.data && res.data.success && res.data.data) { const newShareCount = this.data.shareCount + 1 const newLovePoints = this.data.lovePoints + (res.data.data.earned || 0) this.setData({ shareCount: newShareCount, lovePoints: newLovePoints }) console.log('[invite] 分享爱心值奖励:', res.data.data.earned) } } catch (err) { console.error('[invite] 记录分享奖励失败:', err) } }, /** * 触发其他页面刷新 */ triggerPageRefresh() { const pages = getCurrentPages() if (pages.length > 1) { const prevPage = pages[pages.length - 2] // 如果上一个页面有刷新方法,调用它 if (prevPage.onLovePointsUpdate) { prevPage.onLovePointsUpdate() } if (prevPage.loadData) { prevPage.loadData() } } }, /** * 微信分享配置 * 用户点击分享按钮时触发,返回分享信息 * 同时记录爱心值奖励(分享人A获得+100) */ onShareAppMessage() { const userId = wx.getStorageSync('user_id') || '' const { referralCode, isDistributor, shareConfig } = this.data const inviterParam = userId ? `?inviter=${userId}` : '' const referralParam = referralCode ? `?referralCode=${referralCode}` : '' // 记录爱心值奖励(分享人A获得+100) this.recordShareReward() if (shareConfig && (userId || (isDistributor && referralCode))) { return { title: shareConfig.title, desc: shareConfig.desc || '', path: `${shareConfig.path || '/pages/index/index'}${isDistributor && referralCode ? referralParam : inviterParam}`, imageUrl: shareConfig.imageUrl } } if (isDistributor && referralCode) { return { title: `我的推荐码:${referralCode},注册即可享受优惠!`, path: `/pages/index/index?referralCode=${referralCode}`, imageUrl: shareConfig?.imageUrl || '/images/share-cover.jpg' } } if (userId) { return { title: '邀请你一起来玩AI陪伴,超多有趣角色等你来聊~', path: `/pages/index/index?inviter=${userId}`, imageUrl: shareConfig?.imageUrl || '/images/share-cover.jpg' } } return { title: 'AI情感陪伴,随时可聊 一直陪伴', path: '/pages/index/index', imageUrl: shareConfig?.imageUrl || '/images/share-cover.jpg' } }, /** * 分享到朋友圈 */ onShareTimeline() { const { referralCode, isDistributor, shareConfig } = this.data const userId = wx.getStorageSync('user_id') || '' this.recordShareReward() if (shareConfig && (userId || (isDistributor && referralCode))) { return { title: shareConfig.title, query: isDistributor && referralCode ? `referralCode=${referralCode}` : (userId ? `inviter=${userId}` : ''), imageUrl: shareConfig.imageUrl } } if (isDistributor && referralCode) { return { title: `推荐码:${referralCode},注册即可享受优惠!`, query: `referralCode=${referralCode}`, imageUrl: shareConfig?.imageUrl || '/images/share-cover.jpg' } } if (userId) { return { title: '邀请你一起来玩AI陪伴~', query: `inviter=${userId}`, imageUrl: shareConfig?.imageUrl || '/images/share-cover.jpg' } } return { title: 'AI情感陪伴', query: '', imageUrl: shareConfig?.imageUrl || '/images/share-cover.jpg' } }, /** * 加载海报模板 * 调用后端API获取海报图片 */ async loadPosterTemplates() { try { const res = await api.pageAssets.getAssets('poster_templates') if (res.success && res.data && res.data.length > 0) { const posterTemplates = res.data.map(item => ({ id: item.id, imageUrl: this.processImageUrl(item.asset_url || item.imageUrl || item.url) })) this.setData({ posterTemplates, currentPosterIndex: 0 }) console.log(`加载了 ${posterTemplates.length} 个海报模板`) } else { this.setDefaultPosterTemplates() } } catch (error) { console.error('加载海报模板失败:', error) this.setDefaultPosterTemplates() } }, /** * 设置默认海报模板(降级方案 - 使用CDN URL) */ setDefaultPosterTemplates() { const cdnBase = 'https://ai-c.maimanji.com/images' this.setData({ posterTemplates: [ { id: 1, imageUrl: `${cdnBase}/service-banner-1.png` }, { id: 2, imageUrl: `${cdnBase}/service-banner-2.png` } ], currentPosterIndex: 0 }) console.log('使用默认海报模板配置') }, /** * 加载分享配置 */ async loadShareConfig() { try { const res = await api.promotion.getShareConfig('invite') if (res.success && res.data) { const util = require('../../utils/util') const shareConfig = { ...res.data, imageUrl: res.data.imageUrl ? util.getFullImageUrl(res.data.imageUrl) : '' } this.setData({ shareConfig }) } } catch (error) { console.error('加载分享配置失败', error) } }, /** * 切换海报 */ onPosterChange(e) { this.setData({ currentPosterIndex: e.detail.current }) }, /** * 生成并保存海报 */ async generatePoster() { if (this.data.generatingPoster) return this.setData({ generatingPoster: true }) wx.showLoading({ title: '生成中...' }) try { const template = this.data.posterTemplates[this.data.currentPosterIndex] const userInfo = wx.getStorageSync('user_info') || {} const nickname = userInfo.nickname || '神秘用户' const query = wx.createSelectorQuery() query.select('#posterCanvas') .fields({ node: true, size: true }) .exec(async (res) => { if (!res[0]) { throw new Error('Canvas not found') } const canvas = res[0].node const ctx = canvas.getContext('2d') const dpr = wx.getSystemInfoSync().pixelRatio canvas.width = res[0].width * dpr canvas.height = res[0].height * dpr ctx.scale(dpr, dpr) const width = 300 const height = 533 // 绘制背景 const bgImage = canvas.createImage() bgImage.src = template.imageUrl await new Promise((resolve) => { bgImage.onload = resolve bgImage.onerror = (e) => { console.error('BG Error', e); resolve() } }) ctx.drawImage(bgImage, 0, 0, width, height) // 绘制二维码背景 ctx.fillStyle = '#FFFFFF' ctx.fillRect(20, height - 120, 100, 100) // 模拟二维码 ctx.fillStyle = '#000000' ctx.fillRect(25, height - 115, 90, 90) // 绘制文字 ctx.fillStyle = '#FFFFFF' ctx.font = 'bold 18px sans-serif' ctx.fillText(nickname, 130, height - 80) ctx.font = '14px sans-serif' ctx.fillText('邀请你体验AI心伴', 130, height - 55) wx.canvasToTempFilePath({ canvas, success: (fileRes) => { wx.saveImageToPhotosAlbum({ filePath: fileRes.tempFilePath, success: () => { wx.hideLoading() wx.showToast({ title: '已保存到相册', icon: 'success' }) this.setData({ generatingPoster: false }) }, fail: (err) => { console.error('保存失败', err) wx.hideLoading() if (err.errMsg.includes('auth')) { wx.showModal({ title: '提示', content: '需要保存图片到相册的权限,是否去设置?', success: (mRes) => { if (mRes.confirm) wx.openSetting() } }) } else { wx.showToast({ title: '保存失败', icon: 'none' }) } this.setData({ generatingPoster: false }) } }) }, fail: (err) => { console.error('导出图片失败', err) wx.hideLoading() this.setData({ generatingPoster: false }) } }) }) } catch (error) { console.error('流程错误:', error) wx.hideLoading() this.setData({ generatingPoster: false }) } }, /** * 查看爱心值明细 */ viewTransactions() { wx.navigateTo({ url: '/pages/love-transactions/love-transactions' }) }, /** * 下拉刷新 */ onPullDownRefresh() { this.loadData().then(() => { wx.stopPullDownRefresh() }) } })