const api = require('../../utils/api'); const util = require('../../utils/util'); const app = getApp(); Page({ data: { defaultAvatar: '/images/default-avatar.svg', me: { id: '', idShort: '', nickname: '未登录', avatar: '', phone: '' }, vip: { levelText: '', expireText: '' }, balances: { grass: 0, commission: '0.00' }, counts: { orders: 0, team: 0, performance: 0 }, isLoggedIn: false, isDistributor: false, referralCode: '', statusBarHeight: 20, totalUnread: 0, // Modal States showPromoterModal: false, showPromoterSuccess: false, // 注册奖励 showRegistrationReward: false, registrationRewardAmount: 0, claiming: false, auditStatus: 0, // GF100 弹窗 showGf100Popup: false, gf100ImageUrl: '' }, onShow() { this.setData({ statusBarHeight: wx.getSystemInfoSync().statusBarHeight, auditStatus: app.globalData.auditStatus }); wx.hideTabBar({ animation: false }); this.loadAll(); }, async loadAll() { const isLoggedIn = app.globalData.isLoggedIn || !!wx.getStorageSync('auth_token'); this.setData({ isLoggedIn }); wx.showNavigationBarLoading(); try { if (isLoggedIn) { await Promise.all([ this.loadMe(), this.loadBalance(), this.loadCommission(), this.loadCounts(), this.loadUnreadCount() ]); this.checkRegistrationReward(); this.checkGf100Popup(); } else { this.setData({ me: { nickname: '未登录', avatar: this.data.defaultAvatar }, balances: { grass: 0, commission: '0.00' }, counts: { orders: 0, team: 0, performance: 0 }, totalUnread: 0 }); } } catch (err) { console.error('Load profile failed', err); } finally { wx.hideNavigationBarLoading(); } }, /** * 检查是否需要登录 * @returns {boolean} 是否已登录 */ requireLogin() { const isLoggedIn = app.globalData.isLoggedIn || !!wx.getStorageSync('auth_token'); if (!isLoggedIn) { wx.showModal({ title: '提示', content: '请先登录后再操作', confirmText: '去登录', success: (res) => { if (res.confirm) { wx.navigateTo({ url: '/pages/login/login' }); } } }); return false; } return true; }, async loadMe() { try { // Use direct request with cache busting to ensure fresh data const res = await api.request('/auth/me', { data: { _t: Date.now() } }); // Correctly unwrap the data object from the response const user = (res && res.data) ? res.data : {}; const id = user.id || ''; const idShort = id ? String(id).substring(0, 8).toUpperCase() : ''; const nickname = user.nickname || user.name || '微信用户'; // 处理头像:如果是默认头像则不处理,否则拼接完整路径 let avatar = user.avatar || user.avatar_url; if (avatar) { avatar = util.getFullImageUrl(avatar); } else { avatar = this.data.defaultAvatar; } const phone = user.phone || user.mobile || ''; // Determine Display Role const distributorRole = user.distributorRole || user.role; let roleText = ''; let roleClass = ''; const roleMap = { 'soulmate': { text: '心伴会员', class: 'vip-soulmate' }, 'guardian': { text: '守护会员', class: 'vip-guardian' }, 'companion': { text: '陪伴会员', class: 'vip-companion' }, 'listener': { text: '倾听会员', class: 'vip-listener' }, 'partner': { text: '城市合伙人', class: 'vip-partner' } }; if (user.isDistributor && roleMap[distributorRole]) { const info = roleMap[distributorRole]; roleText = info.text; roleClass = info.class; } else { // Fallback to VIP const vipLevel = Number(user.vip_level || 0); if (vipLevel > 0) { roleText = vipLevel >= 2 ? 'SVIP' : 'VIP'; roleClass = 'vip-normal'; } } this.setData({ me: { id, idShort, nickname, avatar, phone }, vip: { levelText: roleText || '', levelClass: roleClass }, isDistributor: !!user.isDistributor }); // CRITICAL: Update global data and local storage to ensure avatar consistency across pages if (app && app.setUserInfo) { app.setUserInfo(user); } else { // Fallback if app.setUserInfo is not available app.globalData.userInfo = user; app.globalData.userId = user.id; wx.setStorageSync('user_info', user); } } catch (e) { console.error('loadMe error', e); } }, async loadBalance() { try { const res = await api.user.getBalance(); const data = (res && res.data) ? res.data : res; const balance = data.flower_balance || data.balance || 0; this.setData({ 'balances.grass': Number(balance) }); } catch (e) { console.error('loadBalance error', e); } }, async loadCommission() { try { const res = await api.commission.getStats(); const data = (res && res.data) ? res.data : res; const commission = data.commissionBalance || data.commission_balance || 0; // Use individualPerformance for "Performance Data" card as per documentation const performance = data.individualPerformance || data.individual_performance || data.totalContribution || data.total_contribution || 0; this.setData({ 'balances.commission': Number(commission).toFixed(2), 'counts.performance': this.formatAmount(performance) }); } catch (e) { console.error('loadCommission error', e); } }, /** * 格式化金额,超过一万显示为“x.x万” * @param {number|string} val */ formatAmount(val) { const num = Number(val || 0); if (num >= 10000) { return (num / 10000).toFixed(1) + '万'; } return num.toFixed(2); }, async loadCounts() { try { // 1. Fetch self orders (all statuses) const selfOrdersRes = await api.payment.getOrders({ page: 1, pageSize: 1 }); const selfCount = (selfOrdersRes.data && selfOrdersRes.data.total) ? selfOrdersRes.data.total : 0; // 2. Fetch promotion orders (records) - usually pageSize=1 is enough to get total // Note: check backend response structure for total count const promoRes = await api.commission.getRecords({ page: 1, pageSize: 1 }); const promoCount = (promoRes.data && promoRes.data.total) ? promoRes.data.total : 0; // 3. Fetch team members count const teamRes = await api.commission.getReferrals({ page: 1, pageSize: 1 }); const teamCount = (teamRes.data && teamRes.data.total) ? teamRes.data.total : 0; this.setData({ 'counts.orders': selfCount + promoCount, 'counts.team': teamCount }); } catch (err) { console.error('loadCounts failed', err); // Keep existing data or set to 0 on error // this.setData({ 'counts.orders': 0, 'counts.team': 0 }); } }, async loadUnreadCount() { if (!this.data.isLoggedIn) { this.setData({ totalUnread: 0 }); return; } try { const [convRes, proactiveRes] = await Promise.all([ api.chat.getConversations(), api.proactiveMessage.getPending ? api.proactiveMessage.getPending() : Promise.resolve({ success: true, data: [] }) ]); let totalUnread = 0; if (convRes.success && convRes.data) { totalUnread = convRes.data.reduce((sum, conv) => sum + (conv.unread_count || 0), 0); } if (proactiveRes.success && proactiveRes.data && Array.isArray(proactiveRes.data)) { totalUnread += proactiveRes.data.length; } this.setData({ totalUnread }); } catch (err) { console.log('获取未读消息数失败', err); this.setData({ totalUnread: 0 }); } }, goSettings() { if (this.requireLogin()) { wx.navigateTo({ url: '/pages/settings/settings' }); } }, goEdit() { if (this.requireLogin()) { wx.navigateTo({ url: '/pages/edit-profile/edit-profile' }); } }, goRecharge() { if (this.requireLogin()) { wx.navigateTo({ url: '/pages/recharge/recharge' }); } }, goOrders() { if (this.requireLogin()) { wx.navigateTo({ url: '/pages/orders/orders' }); } }, goTeam() { if (this.requireLogin()) { wx.navigateTo({ url: '/pages/team/team' }); } }, goGiftShop() { if (this.requireLogin()) { wx.navigateTo({ url: '/pages/gift-shop/gift-shop' }); } }, goBackpack() { if (this.requireLogin()) { wx.navigateTo({ url: '/pages/backpack/backpack' }); } }, goMyActivities() { if (this.requireLogin()) { wx.navigateTo({ url: '/pages/my-activities/my-activities' }); } }, goWithdraw() { if (this.requireLogin()) { wx.navigateTo({ url: '/pages/withdraw/withdraw' }); } }, goCommission() { if (this.requireLogin()) { wx.navigateTo({ url: '/pages/commission/commission' }); } }, goPerformance() { if (this.requireLogin()) { wx.navigateTo({ url: '/pages/performance/performance' }); } }, goCooperation() { if (this.requireLogin()) { wx.navigateTo({ url: '/subpackages/cooperation/pages/cooperation/cooperation' }); } }, goSupport() { if (this.requireLogin()) { wx.navigateTo({ url: '/pages/support/support' }); } }, goPromote() { if (this.requireLogin()) { wx.navigateTo({ url: '/pages/promote/promote' }); } }, onAvatarError() { this.setData({ 'me.avatar': this.data.defaultAvatar }); }, async handleLogout() { wx.showModal({ title: '提示', content: '确定要退出登录吗?', success: async (res) => { if (res.confirm) { try { await api.auth.logout(); } catch (e) { console.error('logout api error', e); } wx.removeStorageSync('auth_token'); wx.removeStorageSync('user_info'); app.globalData.isLoggedIn = false; app.globalData.userInfo = null; this.loadAll(); wx.showToast({ title: '已退出登录', icon: 'success' }); } } }); }, /** * 检查注册奖励领取资格 */ async checkRegistrationReward() { try { if (!api.lovePoints || typeof api.lovePoints.checkRegistrationReward !== 'function') { return; } // 检查注册奖励领取资格 - 增加静默处理,避免 404 时控制台报错 const res = await api.lovePoints.checkRegistrationReward(); if (res && res.success && res.data && res.data.eligible) { this.setData({ showRegistrationReward: true, registrationRewardAmount: res.data.amount || 100 }); } } catch (err) { // 生产环境可能未部署此接口,静默处理 if (err.code !== 404) { console.warn('[profile] 检查注册奖励静默失败:', err.message || '接口可能未部署'); } } }, /** * 领取注册奖励 */ async onClaimReward() { if (this.data.claiming) return; if (!api.lovePoints || typeof api.lovePoints.claimRegistrationReward !== 'function') { wx.showToast({ title: '功能暂不可用', icon: 'none' }); return; } this.setData({ claiming: true }); wx.showLoading({ title: '领取中...' }); try { const res = await api.lovePoints.claimRegistrationReward(); wx.hideLoading(); if (res.success) { wx.showToast({ title: '领取成功', icon: 'success', duration: 2000 }); this.setData({ showRegistrationReward: false }); // 如果后端返回了免费畅聊时间,可以做提示 if (res.data && res.data.free_chat_time) { console.log('[profile] 获得免费畅聊时间:', res.data.free_chat_time); setTimeout(() => { wx.showModal({ title: '额外奖励', content: '恭喜获得 60 分钟免费畅聊时间,现在就去和 AI 角色聊天吧!', confirmText: '去聊天', success: (modalRes) => { if (modalRes.confirm) { wx.switchTab({ url: '/pages/index/index' }); } } }); }, 2000); } // 刷新余额 this.loadBalance(); } else { wx.showToast({ title: res.message || '领取失败', icon: 'none' }); } } catch (err) { wx.hideLoading(); console.error('[profile] 领取注册奖励失败:', err); wx.showToast({ title: '网络错误,请重试', icon: 'none' }); } finally { this.setData({ claiming: false }); } }, /** * 关闭注册奖励弹窗 */ closeRewardPopup() { this.setData({ showRegistrationReward: false }); }, /** * 检查 GF100 弹窗状态 */ async checkGf100Popup() { if (!this.data.isLoggedIn) return; try { const res = await api.lovePoints.checkGf100Status(); console.log('[profile] GF100 检查结果:', res); if (res.success && res.data && res.data.showPopup) { const imageUrl = res.data.imageUrl; this.setData({ showGf100Popup: true, gf100ImageUrl: imageUrl ? util.getFullImageUrl(imageUrl) : '/images/gf100.png' }); } } catch (err) { console.error('[profile] 检查 GF100 弹窗失败:', err); } }, /** * 领取 GF100 奖励 */ async onClaimGf100() { if (this.data.claiming) return; this.setData({ claiming: true }); wx.showLoading({ title: '领取中...', mask: true }); try { const res = await api.lovePoints.claimGf100(); wx.hideLoading(); if (res.success) { wx.showToast({ title: '领取成功', icon: 'success', duration: 2000 }); this.setData({ showGf100Popup: false }); // 弹出获得 60 分钟免费畅聊的提示 setTimeout(() => { wx.showModal({ title: '领取成功', content: '恭喜获得 100 爱心 + 60 分钟免费畅聊时间!', confirmText: '去聊天', success: (modalRes) => { if (modalRes.confirm) { wx.switchTab({ url: '/pages/chat/chat' }) } } }); }, 500); // 刷新余额 this.loadBalance(); } else { wx.showToast({ title: res.message || '领取失败', icon: 'none' }); } } catch (err) { wx.hideLoading(); console.error('[profile] 领取 GF100 失败:', err); wx.showToast({ title: '网络错误,请重试', icon: 'none' }); } finally { this.setData({ claiming: false }); } }, /** * 关闭 GF100 弹窗 */ closeGf100Popup() { this.setData({ showGf100Popup: false }); }, preventBubble() { }, preventTouchMove() { }, async onLoad() { await this.loadReferralCode() }, async loadReferralCode() { if (!this.data.isLoggedIn) return try { const res = await api.commission.getStats() if (res.success && res.data) { this.setData({ referralCode: res.data.referralCode || '' }) } } catch (err) { console.error('加载推荐码失败:', err) } }, onShareAppMessage() { const { referralCode, isDistributor } = this.data const referralCodeParam = referralCode ? `?referralCode=${referralCode}` : '' this.recordShareReward() return { title: isDistributor ? `我的推荐码:${referralCode},注册即可享受优惠!` : '欢迎来到心伴俱乐部 - 随时可聊 一直陪伴', path: `/pages/index/index${referralCodeParam}`, imageUrl: isDistributor ? '/images/share-commission.png' : '/images/icon-heart-new.png' } }, onShareTimeline() { const { referralCode, isDistributor } = this.data const query = referralCode ? `referralCode=${referralCode}` : '' this.recordShareReward() return { title: isDistributor ? `推荐码:${referralCode},注册即可享受优惠!` : '心伴俱乐部 - 随时可聊 一直陪伴', query: query, imageUrl: isDistributor ? '/images/share-commission.png' : '/images/icon-heart-new.png' } }, /** * 静默记录分享奖励(分享人A获得+100爱心值) */ async recordShareReward() { try { const res = await api.lovePoints.share() console.log('[profile] 分享爱心值奖励:', res) } catch (err) { console.error('[profile] 记录分享奖励失败:', err) } }, // Tab Bar Switching switchTab(e) { const path = e.currentTarget.dataset.path; const app = getApp(); if (path === '/pages/chat/chat') { if (!app.globalData.isLoggedIn && !wx.getStorageSync('auth_token')) { wx.navigateTo({ url: '/pages/login/login?redirect=' + encodeURIComponent(path) }); return; } } wx.switchTab({ url: path }); } });