const request = require('../utils/request') Page({ data: { // 当前时间类型:year, month, quarter currentTimeType: 'year', // 当前周期文本 currentPeriodText: '2023年', // 当前时间 currentDate: { year: 2023, month: 1, quarter: 1 }, selectedMonth: '', selectedMonthText: '', summary: { income: '0.00', expense: '0.00', balance: '0.00' }, activeType: 'expense', categoryStats: [], monthRecords: [] }, onShow() { // 初始化当前月份 const today = new Date(); const year = today.getFullYear(); const month = String(today.getMonth() + 1).padStart(2, '0'); const selectedMonth = `${year}-${month}`; this.setData({ selectedMonth, selectedMonthText: `${year}年${month}月`, currentPeriodText:`${year}年`, currentDate: { year, month } }); this.updateStatistics(); }, // 上一个周期 prevPeriod() { const { currentDate, currentTimeType } = this.data; const newDate = { ...currentDate }; switch (currentTimeType) { case 'year': newDate.year--; break; case 'month': newDate.month--; if (newDate.month < 1) { newDate.month = 12; newDate.year--; } break; case 'quarter': newDate.quarter--; if (newDate.quarter < 1) { newDate.quarter = 4; newDate.year--; } break; } this.setData({ currentDate: newDate }, () => { this.updatePeriodDisplay(); // 实际应用中这里应该根据新日期请求数据 }); }, // 下一个周期 nextPeriod() { const { currentDate, currentTimeType } = this.data; const newDate = { ...currentDate }; switch (currentTimeType) { case 'year': newDate.year++; break; case 'month': newDate.month++; if (newDate.month > 12) { newDate.month = 1; newDate.year++; } break; case 'quarter': newDate.quarter++; if (newDate.quarter > 4) { newDate.quarter = 1; newDate.year++; } break; } this.setData({ currentDate: newDate }, () => { this.updatePeriodDisplay(); // 实际应用中这里应该根据新日期请求数据 }); }, // 切换时间类型 changeTimeType(e) { const type = e.currentTarget.dataset.type; if (this.data.currentTimeType === type) return; this.setData({ currentTimeType: type }, () => { this.updatePeriodDisplay(); }); }, // 更新时间周期显示 updatePeriodDisplay() { const { year, month, quarter } = this.data.currentDate; let text = ''; switch (this.data.currentTimeType) { case 'year': text = `${year}年`; break; case 'month': text = `${year}年${month}月`; break; case 'quarter': text = `${year}年第${quarter}季度`; break; } this.setData({ currentPeriodText: text }); }, onMonthChange(e) { const selectedMonth = e.detail.value; const [year, month] = selectedMonth.split('-'); this.setData({ selectedMonth, selectedMonthText: `${year}年${month}月` }); this.updateStatistics(); }, setActiveType(e) { const type = e.currentTarget.dataset.type; this.setData({ activeType: type }, () => { this.calculateCategoryStats(); }); }, async updateStatistics() { // 筛选当月记录 const res = await request.get('/app-api/book/inout/allList') let monthRecords=[] if(res.code==0){ monthRecords=res.data } // 计算收支汇总 let income = 0; let expense = 0; const res1 = await request.get('/app-api/book/inout/myList-tol',{type:"in"}) console.log('获取数据成功:', res1) if(res1.code==0){ income=res1.data } const res2 = await request.get('/app-api/book/inout/myList-tol',{type:"out"}) console.log('获取数据成功:', res2) if(res2.code==0){ expense=res2.data } const balance = income - expense; this.setData({ monthRecords, summary: { income: income.toFixed(2), expense: expense.toFixed(2), balance: balance.toFixed(2) } }, () => { this.calculateCategoryStats(); }); }, async calculateCategoryStats() { const { monthRecords, activeType } = this.data; // 按分类汇总 const categoryMap = {}; const res3 = await request.get('/app-api/book/classification/group-one',{type:activeType=='expense'?"out":"in"}) console.log('获取数据成功:', res3) if(res3.code==0){ res3.data.forEach(record => { categoryMap[record.id] = { categoryId: record.id, categoryName: record.classificationName, amount: record.money, count: record.num, }; }); } // 转换为数组并排序 let categoryStats = Object.values(categoryMap); categoryStats.sort((a, b) => b.amount - a.amount); // 计算百分比 const total = activeType === 'income' ? parseFloat(this.data.summary.income) : parseFloat(this.data.summary.expense); if (total > 0) { categoryStats.forEach(item => { item.percentage = Math.round((item.amount / total) * 100); item.amount = item.amount.toFixed(2); }); } // 分配颜色 const colors = ['#F44336', '#E91E63', '#9C27B0', '#673AB7', '#3F51B5', '#2196F3', '#03A9F4', '#00BCD4', '#009688', '#4CAF50', '#8BC34A', '#CDDC39']; categoryStats.forEach((item, index) => { item.color = colors[index % colors.length]; }); this.setData({ categoryStats }); this.drawPieChart(); }, drawPieChart() { const { categoryStats } = this.data; console.log("drawPieChart:",categoryStats) if (categoryStats.length === 0) { // return; } const ctx = wx.createCanvasContext('pieChart', this); const centerX = 120; // 饼图中心X坐标 const centerY = 120; // 饼图中心Y坐标 const radius = 90; // 饼图半径 let startAngle = 0; categoryStats.forEach(item => { const percentage = parseFloat(item.percentage); const endAngle = startAngle + 2 * Math.PI * (percentage / 100); // 绘制扇形 ctx.beginPath(); ctx.setFillStyle(item.color); ctx.moveTo(centerX, centerY); ctx.arc(centerX, centerY, radius, startAngle, endAngle, false); ctx.closePath(); ctx.fill(); // 计算文本位置 const midAngle = startAngle + (endAngle - startAngle) / 2; const textRadius = radius * 0.6; // 文本距离中心的距离 const textX = centerX + Math.cos(midAngle) * textRadius; const textY = centerY + Math.sin(midAngle) * textRadius; // 绘制百分比文本 ctx.setFontSize(14); ctx.setFillStyle('#333'); ctx.setTextAlign('center'); ctx.setTextBaseline('middle'); ctx.fillText(`${percentage}%`, textX, textY); startAngle = endAngle; }); // 绘制中心空白区域 ctx.beginPath(); ctx.setFillStyle('#ffffff'); ctx.arc(centerX, centerY, radius * 0.4, 0, 2 * Math.PI, false); ctx.fill(); // 绘制中心文本 const total = this.data.activeType === 'income' ? this.data.summary.income : this.data.summary.expense; ctx.setFontSize(16); ctx.setFillStyle('#333'); ctx.setTextAlign('center'); ctx.setTextBaseline('middle'); // ctx.fillText(`总计`, centerX, centerY - 10); ctx.setFontSize(18); ctx.setFillStyle(this.data.activeType === 'income' ? '#4CAF50' : '#f44336'); // ctx.fillText(`¥${total}`, centerX, centerY + 15); ctx.draw(); }, formatDate(dateStr) { const date = new Date(dateStr); const month = date.getMonth() + 1; const day = date.getDate(); return `${month}月${day}日`; } })