667 lines
18 KiB
JavaScript
667 lines
18 KiB
JavaScript
// 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' })
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
})
|