// pages/stats/personal/personal.js import request from '../../../utils/request' Page({ data: { userInfo: null, loading: true, navbarHeight: 0, // 统计数据 stats: { total_games: 0, total_win: 0, total_loss: 0, win_rate: 0, net_profit: 0, max_win: 0, max_loss: 0, avg_profit: 0 }, // 时间范围 timeRange: 'all', // all/month/week timeRangeText: { all: '全部', month: '近30天', week: '近7天' }, // 趋势数据 trendData: [], // 游戏类型统计 gameTypeStats: [], // 最佳战绩 bestRecords: { max_win_session: null, max_loss_session: null, longest_win_streak: 0, longest_loss_streak: 0 } }, _isFirstLoad: true, // 标记是否首次加载 onLoad(options) { this._isFirstLoad = true // 计算导航栏高度 const windowInfo = wx.getWindowInfo() const menuButtonInfo = wx.getMenuButtonBoundingClientRect() const statusBarHeight = windowInfo.statusBarHeight const menuButtonTop = menuButtonInfo.top const navbarHeight = menuButtonInfo.bottom + (menuButtonTop - statusBarHeight) this.setData({ navbarHeight }) this.loadUserInfo() }, onShow() { // 只在非首次加载时刷新数据(避免onLoad和onShow重复加载) if (!this._isFirstLoad) { this.loadUserInfo() } this._isFirstLoad = false }, // 加载用户信息 loadUserInfo() { const app = getApp() const userInfo = app.getUserInfo() if (userInfo) { this.setData({ userInfo }) this.loadStats() this.loadTrendData() this.loadGameTypeStats() } else { // 未登录,显示提示 this.setData({ userInfo: null, loading: false }) } }, // 跳转登录 goToLogin() { wx.navigateTo({ url: '/pages/login/login' }) }, // 加载统计数据 async loadStats() { this.setData({ loading: true }) try { // 根据时间范围确定天数 let days = 0 // 0表示全部 if (this.data.timeRange === 'month') { days = 30 } else if (this.data.timeRange === 'week') { days = 7 } const stats = await request.get('/auth/profile', { days }) // 计算额外统计 const netProfit = (stats.total_win || 0) - (stats.total_loss || 0) const avgProfit = stats.total_games > 0 ? Math.round(netProfit / stats.total_games) : 0 this.setData({ stats: { total_games: stats.total_games || 0, total_win: stats.total_win || 0, total_loss: stats.total_loss || 0, win_rate: stats.win_rate || 0, net_profit: netProfit, max_win: stats.max_win || 0, max_loss: stats.max_loss || 0, avg_profit: avgProfit }, loading: false }) } catch (error) { console.error('加载统计失败:', error) this.setData({ loading: false }) wx.showToast({ title: '加载失败', icon: 'none' }) } }, // 加载趋势数据 async loadTrendData() { try { // 根据时间范围确定天数 let days = 30 if (this.data.timeRange === 'month') { days = 30 } else if (this.data.timeRange === 'week') { days = 7 } else if (this.data.timeRange === 'all') { days = 365 // 全部显示一年数据 } const data = await request.get('/stats/trend', { days }) console.log('=== 趋势数据调试 ===') console.log('API返回数据:', JSON.stringify(data)) console.log('数据长度:', data?.length) console.log('数据类型:', typeof data) if (!data || data.length === 0) { console.log('数据为空,设置trendData为[]') this.setData({ trendData: [] }) return } // 找出最大赢和最大输 const maxWin = Math.max(...data.map(item => item.profit > 0 ? item.profit : 0), 0) const maxLoss = Math.abs(Math.min(...data.map(item => item.profit < 0 ? item.profit : 0), 0)) const maxValue = Math.max(maxWin, maxLoss, 1) console.log('maxWin:', maxWin, 'maxLoss:', maxLoss, 'maxValue:', maxValue) // 格式化日期和计算百分比 const formattedData = data.map(item => { const date = new Date(item.date) const profit = item.profit || 0 // 计算相对于最大值的百分比 const heightPercent = (Math.abs(profit) / maxValue * 50).toFixed(2) console.log(`处理数据: date=${item.date}, profit=${profit}, heightPercent=${heightPercent}`) return { ...item, date: `${date.getMonth() + 1}/${date.getDate()}`, heightPercent: heightPercent } }) // 计算Y轴刻度 (上方正数,下方负数) const yAxisLabels = [ Math.round(maxValue), Math.round(maxValue * 0.5), 0, -Math.round(maxValue * 0.5), -Math.round(maxValue) ] console.log('formattedData:', JSON.stringify(formattedData)) console.log('yAxisLabels:', yAxisLabels) this.setData({ trendData: formattedData, maxValue: maxValue, yAxisLabels: yAxisLabels }) console.log('setData完成') } catch (error) { console.error('加载趋势失败:', error) this.setData({ trendData: [] }) } }, // 加载游戏类型统计 async loadGameTypeStats() { try { const data = await request.get('/stats/by-game-type') // 转换API数据格式为页面需要的格式 const formattedData = (data || []).map(item => ({ type: item.game_type, name: item.game_type_name, games: item.games, win_rate: item.win_rate, profit: item.total_profit })) this.setData({ gameTypeStats: formattedData }) } catch (error) { console.error('加载游戏类型统计失败:', error) } }, // 切换时间范围 onTimeRangeChange(e) { const timeRange = e.currentTarget.dataset.range console.log('=== 切换时间范围 ===', timeRange) this.setData({ timeRange }) this.loadStats() this.loadTrendData() }, // 查看战绩列表 viewRecords() { wx.navigateTo({ url: '/pages/record/list/list' }) }, // 分享战绩 shareStats() { wx.showModal({ title: '功能开发中', content: '战绩分享功能正在开发中', showCancel: false }) }, // 下拉刷新 onPullDownRefresh() { Promise.all([ this.loadStats(), this.loadTrendData(), this.loadGameTypeStats() ]).then(() => { wx.stopPullDownRefresh() }) } })