663 lines
17 KiB
JavaScript
663 lines
17 KiB
JavaScript
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()
|
||
})
|
||
}
|
||
})
|