// pages/commission/commission.js - 佣金明细页面 // 对接后端API const api = require('../../utils/api') const errorHandler = require('../../utils/errorHandler') // 缓存配置 const CACHE_CONFIG = { STATS_KEY: 'commission_stats_cache', RECORDS_KEY: 'commission_records_cache', EXPIRE_TIME: 5 * 60 * 1000 // 5分钟有效期 } Page({ data: { statusBarHeight: 44, navBarHeight: 44, totalNavHeight: 88, navHeight: 96, // Keep for compatibility if used elsewhere loading: false, currentTab: 'all', // 佣金统计 isDistributor: false, referralCode: '', cardType: '', commissionBalance: '0.00', totalCommission: '0.00', pendingAmount: '0.00', // Confirmed field for display totalWithdrawn: '0.00', totalReferrals: 0, totalContribution: '0.00', // 佣金比例 rechargeRate: 10, vipRate: 15, cardRate: 20, // 兼容旧字段 totalEarnings: '0.00', availableBalance: '0.00', withdrawnAmount: '0.00', // 记录列表 allList: [], commissionList: [], page: 1, hasMore: true, // 缓存状态 cacheExpired: false, lastUpdateTime: '', defaultAvatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=500&auto=format&fit=crop&q=60', cardTitle: '守护会员', pickerDate: '', // YYYY-MM pickerDateDisplay: '' // YYYY年MM月 }, onLoad() { // Init Date const now = new Date(); const year = now.getFullYear(); const month = String(now.getMonth() + 1).padStart(2, '0'); this.setData({ pickerDate: `${year}-${month}`, pickerDateDisplay: `${year}年${month}月` }); const systemInfo = wx.getSystemInfoSync() const statusBarHeight = systemInfo.statusBarHeight || 44 const navHeight = statusBarHeight + 48 this.setData({ statusBarHeight, navHeight }) // 先尝试加载缓存(快速显示) this.loadFromCache() // 然后加载最新数据(确保数据准确) this.loadCommissionStats() this.loadCommissionRecords() }, /** * 页面显示时刷新数据 */ onShow() { // 每次显示页面时,强制刷新用户信息 // 确保从其他页面返回时数据是最新的 this.loadCommissionStats() }, /** * 从缓存加载数据 */ loadFromCache() { try { // 加载统计数据缓存 const statsCache = wx.getStorageSync(CACHE_CONFIG.STATS_KEY) if (statsCache && this.isCacheValid(statsCache.timestamp)) { const cachedData = statsCache.data || {} // 强制修正缓存中的错误规定值 if (cachedData.pendingAmount === '210.00' || cachedData.pendingAmount === 210) { cachedData.pendingAmount = '0.00' } this.setData({ ...cachedData, cacheExpired: false, lastUpdateTime: this.formatCacheTime(statsCache.timestamp) }) } else { this.setData({ cacheExpired: true }) } // 加载记录列表缓存 const recordsCache = wx.getStorageSync(CACHE_CONFIG.RECORDS_KEY) if (recordsCache && this.isCacheValid(recordsCache.timestamp)) { this.setData({ allList: recordsCache.data, commissionList: recordsCache.data }) } } catch (error) { console.error('加载缓存失败:', error) } }, /** * 检查缓存是否有效 */ isCacheValid(timestamp) { if (!timestamp) return false const now = Date.now() return (now - timestamp) < CACHE_CONFIG.EXPIRE_TIME }, /** * 格式化缓存时间 */ formatCacheTime(timestamp) { const date = new Date(timestamp) const hour = String(date.getHours()).padStart(2, '0') const minute = String(date.getMinutes()).padStart(2, '0') return `${hour}:${minute}` }, /** * 保存统计数据到缓存 */ saveStatsToCache(data) { try { wx.setStorageSync(CACHE_CONFIG.STATS_KEY, { data, timestamp: Date.now() }) } catch (error) { console.error('保存统计缓存失败:', error) } }, /** * 保存记录列表到缓存 */ saveRecordsToCache(records) { try { wx.setStorageSync(CACHE_CONFIG.RECORDS_KEY, { data: records, timestamp: Date.now() }) } catch (error) { console.error('保存记录缓存失败:', error) } }, /** * 清除缓存 */ clearCache() { try { wx.removeStorageSync(CACHE_CONFIG.STATS_KEY) wx.removeStorageSync(CACHE_CONFIG.RECORDS_KEY) this.setData({ cacheExpired: true, lastUpdateTime: '' }) wx.showToast({ title: '缓存已清除', icon: 'success' }) } catch (error) { console.error('清除缓存失败:', error) } }, /** * 下拉刷新 */ onPullDownRefresh() { // 清除缓存,强制刷新 this.clearCache() Promise.all([ this.loadCommissionStats(), this.loadCommissionRecords() ]).then(() => { wx.stopPullDownRefresh() wx.showToast({ title: '刷新成功', icon: 'success' }) }) }, /** * 上拉加载更多 */ onReachBottom() { if (this.data.hasMore && !this.data.loading) { this.loadMoreRecords() } }, /** * 加载佣金统计 */ async loadCommissionStats() { try { const res = await api.commission.getStats() if (res.success && res.data) { const data = res.data const statsData = { isDistributor: data.isDistributor || false, referralCode: data.referralCode || '', cardType: data.cardType || '', commissionBalance: Number(data.commissionBalance || 0).toFixed(2), totalCommission: Number(data.totalCommission || 0).toLocaleString('zh-CN', { minimumFractionDigits: 2 }), pendingAmount: Number(data.pendingWithdrawal || data.pendingAmount || 0).toFixed(2), totalWithdrawn: Number(data.totalWithdrawn || 0).toLocaleString('zh-CN', { minimumFractionDigits: 2 }), totalReferrals: data.totalReferrals || 0, totalContribution: Number(data.totalContribution || data.total_contribution || 0).toLocaleString('zh-CN', { minimumFractionDigits: 2 }), pendingWithdrawal: Number(data.pendingWithdrawal || 0).toFixed(2), rechargeRate: data.rechargeRate || 10, vipRate: data.vipRate || 15, cardRate: data.cardRate || 20, // 兼容旧字段 totalEarnings: Number(data.totalCommission || data.total_earnings || 0).toLocaleString('zh-CN', { minimumFractionDigits: 2 }), availableBalance: Number(data.commissionBalance || data.available_balance || 0).toFixed(2), withdrawnAmount: Number(data.totalWithdrawn || data.withdrawn_amount || 0).toLocaleString('zh-CN', { minimumFractionDigits: 2 }) } this.setData({ ...statsData, cardTitle: this.getCardTitle(statsData.cardType), cacheExpired: false, lastUpdateTime: this.formatCacheTime(Date.now()) }) // 保存到缓存 this.saveStatsToCache(statsData) // 如果不是分销商,显示引导提示 if (!data.isDistributor) { this.showBecomeDistributorTip() } } } catch (err) { console.log('获取佣金统计失败', err) // 如果有缓存,显示缓存失效提示 if (!this.data.cacheExpired) { wx.showToast({ title: '数据加载失败,显示缓存数据', icon: 'none', duration: 2000 }) } } }, /** * 显示成为分销商提示 */ showBecomeDistributorTip() { wx.showModal({ title: '成为分销商', content: '购买身份卡即可成为分销商,推荐好友赚佣金!', confirmText: '了解详情', cancelText: '暂不需要', success: (res) => { if (res.confirm) { // 跳转到推广页面查看详情 wx.navigateTo({ url: '/pages/promote/promote' }) } } }) }, /** * 加载佣金记录 */ async loadCommissionRecords() { this.setData({ loading: true, page: 1 }) try { const res = await api.commission.getRecords({ page: 1, limit: 20 }) if (res.success && res.data) { const records = (res.data.list || res.data || []).map(record => this.transformRecord(record)) this.setData({ allList: records, commissionList: records, hasMore: records.length >= 20, loading: false }) // 保存到缓存 this.saveRecordsToCache(records) } else { this.setData({ allList: [], commissionList: [], loading: false }) } } catch (err) { console.error('加载佣金记录失败', err) this.setData({ loading: false }) // 如果有缓存,显示缓存失效提示 if (this.data.allList.length > 0) { wx.showToast({ title: '数据加载失败,显示缓存数据', icon: 'none', duration: 2000 }) } } }, /** * 加载更多记录 */ async loadMoreRecords() { const nextPage = this.data.page + 1 this.setData({ loading: true }) try { const res = await api.commission.getRecords({ page: nextPage, limit: 20 }) if (res.success && res.data) { const newRecords = (res.data.list || res.data || []).map(record => this.transformRecord(record)) const allList = [...this.data.allList, ...newRecords] this.setData({ allList, page: nextPage, hasMore: newRecords.length >= 20, loading: false }) // 更新当前筛选列表 this.filterRecords(this.data.currentTab) } else { this.setData({ hasMore: false, loading: false }) } } catch (err) { console.error('加载更多记录失败', err) this.setData({ loading: false }) } }, /** * 转换记录数据格式 */ transformRecord(record) { let titleText = record.fromUserName || record.userName || '用户'; let descText = 'VIP月卡'; if (record.amount > 100) descText = 'SVIP年卡'; if (record.fromUserLevel) { descText = this.getUserLevelText(record.fromUserLevel); } else if (record.orderType === 'vip' || record.orderType === 'svip') { descText = record.orderType.toUpperCase() === 'SVIP' ? 'SVIP会员' : 'VIP会员'; } else if (record.orderType === 'identity_card') { descText = '身份会员'; } else if (record.orderType === 'companion_chat') { descText = '陪伴聊天'; } const dateObj = new Date(record.created_at || record.createdAt); const mm = String(dateObj.getMonth() + 1).padStart(2, '0'); const dd = String(dateObj.getDate()).padStart(2, '0'); const hh = String(dateObj.getHours()).padStart(2, '0'); const min = String(dateObj.getMinutes()).padStart(2, '0'); const fmtTime = `${mm}-${dd} ${hh}:${min}`; return { id: record.id, type: record.type, title: titleText, desc: descText, amount: record.commissionAmount ? record.commissionAmount.toFixed(0) : (record.amount ? Number(record.amount).toFixed(0) : '0'), status: record.status || 'settled', statusText: record.status === 'pending' ? '待结算' : '已结算', time: this.formatTime(record.created_at || record.createdAt), orderNo: record.orderId ? `ORD${record.orderId.substring(0, 12)}` : 'ORD2024012401', userAvatar: record.userAvatar || record.fromUserAvatar || record.avatar || '', listTitle: titleText, fmtTime: fmtTime, } }, getUserLevelText(level) { const levelMap = { 'vip': 'VIP会员', 'svip': 'SVIP会员', 'guardian': '守护会员', 'companion': '陪伴会员', 'partner': '城市合伙人', '1': '普通用户', '2': 'VIP会员', '3': 'SVIP会员', '4': '守护会员', '5': '陪伴会员', '6': '城市合伙人' }; return levelMap[level] || levelMap['1']; }, getCardTitle(type) { const map = { 'guardian_card': '守护会员', 'companion_card': '陪伴会员', 'identity_card': '身份会员', 'vip': 'VIP会员', 'partner': '城市合伙人' }; return map[type] || '守护会员'; }, goToTeam() { wx.navigateTo({ url: '/pages/team/team', }); }, /** * 格式化时间 */ formatTime(dateStr) { if (!dateStr) return '' const date = new Date(dateStr) const year = date.getFullYear() const month = String(date.getMonth() + 1).padStart(2, '0') const day = String(date.getDate()).padStart(2, '0') const hour = String(date.getHours()).padStart(2, '0') const minute = String(date.getMinutes()).padStart(2, '0') return `${year}-${month}-${day} ${hour}:${minute}` }, onBack() { wx.navigateBack() }, onTabChange(e) { const tab = e.currentTarget.dataset.tab this.setData({ currentTab: tab }) this.filterRecords(tab) }, /** * 筛选记录 */ filterRecords(tab) { let list = [] if (tab === 'all') { list = this.data.allList } else if (tab === 'settled') { list = this.data.allList.filter(item => item.status === 'settled') } else if (tab === 'pending') { list = this.data.allList.filter(item => item.status === 'pending') } this.setData({ commissionList: list }) }, onDateChange(e) { const val = e.detail.value; // YYYY-MM const [y, m] = val.split('-'); this.setData({ pickerDate: val, pickerDateDisplay: `${y}年${m}月` }); // TODO: Call API to reload records with date filter if needed this.loadCommissionRecords(); // Reload with new date }, /** * 跳转到提现页面 */ onWithdraw() { wx.navigateTo({ url: '/pages/withdraw/withdraw' }) }, /** * 跳转到推广页面 */ onPromote() { wx.navigateTo({ url: '/pages/promote/promote' }) }, /** * 跳转到推荐用户列表 */ async goToReferrals() { // 显示加载提示 wx.showLoading({ title: '加载中...', mask: true }) try { // 强制刷新用户信息,确保使用最新数据 const res = await api.commission.getStats() if (res.success && res.data) { const isDistributor = res.data.isDistributor || false // 更新本地状态 this.setData({ isDistributor }) wx.hideLoading() // 检查是否是分销商 if (!isDistributor) { wx.showModal({ title: '成为分销商', content: '购买身份卡即可成为分销商,推荐好友赚佣金!', confirmText: '了解详情', cancelText: '取消', success: (modalRes) => { if (modalRes.confirm) { wx.navigateTo({ url: '/pages/promote/promote' }) } } }) return } // 跳转到推荐用户列表 wx.navigateTo({ url: '/pages/referrals/referrals' }) } else { wx.hideLoading() wx.showToast({ title: '获取用户信息失败', icon: 'none' }) } } catch (error) { wx.hideLoading() console.error('获取用户信息失败:', error) wx.showToast({ title: '网络错误,请重试', icon: 'none' }) } }, /** * 跳转到提现记录 */ goToWithdrawRecords() { wx.navigateTo({ url: '/pages/withdraw-records/withdraw-records' }) }, /** * 微信分享推荐码 */ onShareAppMessage() { const { referralCode, isDistributor } = this.data if (!isDistributor || !referralCode) { return { title: '心伴AI - 情感陪伴聊天机器人', path: '/pages/index/index', imageUrl: '/images/share-cover.jpg' } } return { title: `我的推荐码:${referralCode},注册即可享受优惠!`, path: `/pages/index/index?referralCode=${referralCode}`, imageUrl: '/images/share-commission.png' } }, /** * 分享到朋友圈 */ onShareTimeline() { const { referralCode, isDistributor } = this.data if (!isDistributor || !referralCode) { return { title: '心伴AI - 情感陪伴聊天机器人', imageUrl: '/images/share-cover.jpg' } } return { title: `我的推荐码:${referralCode},注册即可享受优惠!`, query: `referralCode=${referralCode}`, imageUrl: '/images/share-commission.png' } }, /** * 复制推荐码 */ copyReferralCode() { const { referralCode } = this.data if (!referralCode) { wx.showToast({ title: '暂无推荐码', icon: 'none' }) return } wx.setClipboardData({ data: referralCode, success: () => { wx.showToast({ title: '已复制推荐码', icon: 'success' }) } }) }, /** * 绑定推荐码 */ bindReferralCode() { wx.showModal({ title: '绑定推荐码', editable: true, placeholderText: '请输入推荐码', success: async (res) => { if (res.confirm && res.content) { try { wx.showLoading({ title: '绑定中...' }) const result = await api.commission.bindReferral(res.content.trim()) wx.hideLoading() if (result.success) { wx.showToast({ title: '绑定成功', icon: 'success' }) this.loadCommissionStats() } else { wx.showToast({ title: result.message || '绑定失败', icon: 'none' }) } } catch (err) { wx.hideLoading() wx.showToast({ title: err.message || '绑定失败', icon: 'none' }) } } } }) } })