跟样式百分之百没关系,你参考一下这个代码里日期的数据
// pages/stats/stats.js
const eventBus = require('../../utils/event-bus.js');
Page({
data: {
loading: true,
dataType: 0,
dataTypes: ['步数', '饮水', '睡眠'],
years: ['2023', '2024', '2025'],
months: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
selectedYear: '2025',
selectedMonth: '06',
statsData: {
average: 0,
max: 0,
completion: 0
},
chartData: {
labels: [],
values: []
},
// 添加重绘标志
needRedraw: false
},
onLoad() {
// 初始化事件总线
this.initEventBus();
// 设置默认日期为当前年月
const now = new Date();
this.setData({
selectedYear: now.getFullYear().toString(),
selectedMonth: (now.getMonth() + 1).toString().padStart(2, '0')
}, () => {
this.loadStats();
});
},
// 初始化事件总线(关键修复)
initEventBus() {
this.dataUpdatedListener = () => {
console.log('收到数据更新事件,重新加载统计');
this.loadStats();
};
eventBus.on('healthDataUpdated', this.dataUpdatedListener);
},
onUnload() {
eventBus.off('healthDataUpdated', this.dataUpdatedListener);
},
onShow() {
// 页面显示时强制重绘
if (this.data.needRedraw) {
this.setData({ needRedraw: false }, () => {
setTimeout(() => this.drawChart(), 100);
});
}
},
// 加载统计数据(关键修复)
loadStats() {
const app = getApp();
const records = app.getAllRecords();
const filteredRecords = this.filterRecordsByMonth(records);
// 准备图表数据
const chartData = this.prepareChartData(filteredRecords);
// 计算统计数据
const statsData = this.calculateStats(filteredRecords);
this.setData({
statsData,
chartData,
loading: false,
needRedraw: true // 设置重绘标志
}, () => {
// 等待视图更新后绘制
setTimeout(() => {
this.drawChart();
}, 300);
});
},
// 修复日期筛选逻辑
filterRecordsByMonth(records) {
const { selectedYear, selectedMonth } = this.data;
return records.filter(record => {
const [year, month] = record.date.split('-');
const normalizedMonth = month.padStart(2, '0');
return year === selectedYear && normalizedMonth === selectedMonth;
}).sort((a, b) => new Date(a.date) - new Date(b.date));
},
// 准备图表数据
prepareChartData(records) {
const labels = [];
const values = [];
records.forEach(record => {
const day = record.date.split('-')[2];
labels.push(`${parseInt(day)}`);
// 直接映射类型字段
const typeMap = {
0: 'steps',
1: 'water',
2: 'sleep'
};
const typeKey = typeMap[this.data.dataType];
values.push(typeKey ? record[typeKey] || 0 : 0);
});
return { labels, values };
},
// 计算统计数据
calculateStats(records) {
if (!records || records.length === 0) {
return {
average: 0,
max: 0,
completion: 0
};
}
// 直接映射类型字段
const typeMap = {
0: 'steps',
1: 'water',
2: 'sleep'
};
const typeKey = typeMap[this.data.dataType];
const values = records.map(r => r[typeKey] || 0);
const sum = values.reduce((acc, val) => acc + val, 0);
const average = values.length > 0 ? (sum / values.length).toFixed(1) : 0;
const max = Math.max(...values);
const app = getApp();
const userInfo = app.globalData.userInfo;
let target = 0;
switch (this.data.dataType) {
case 0: target = userInfo.target_steps || 10000; break;
case 1: target = userInfo.target_water || 2.5; break;
case 2: target = userInfo.target_sleep || 8; break;
}
let completion = 0;
if (target > 0 && average > 0) {
completion = (average / target) * 100;
completion = Math.min(100, completion).toFixed(0);
}
return { average, max, completion };
},
// 切换数据类型
changeDataType(e) {
this.setData({
dataType: e.detail.value
}, () => {
this.loadStats();
});
},
// 切换年份
changeYear(e) {
this.setData({
selectedYear: this.data.years[e.detail.value]
}, () => {
this.loadStats();
});
},
// 切换月份
changeMonth(e) {
this.setData({
selectedMonth: this.data.months[e.detail.value]
}, () => {
this.loadStats();
});
},
// 关键修复:确保Canvas正确销毁和重绘
drawChart() {
// 销毁旧Canvas上下文
if (this.ctx) {
try {
this.ctx = null;
} catch (e) {
console.warn('Canvas上下文销毁异常', e);
}
}
// 创建新Canvas上下文
this.ctx = wx.createCanvasContext('chartCanvas');
const { labels, values } = this.data.chartData;
// 清除画布
this.ctx.clearRect(0, 0, 320, 200);
this.ctx.draw(true);
if (labels.length === 0) {
console.log('无数据,跳过绘图');
return;
}
const canvasWidth = 320;
const canvasHeight = 200;
const paddingLeft = 45;
const paddingTop = 25;
const paddingRight = 25;
const paddingBottom = 35;
const chartWidth = canvasWidth - paddingLeft - paddingRight;
const chartHeight = canvasHeight - paddingTop - paddingBottom;
// 绘制坐标轴
this.ctx.beginPath();
this.ctx.moveTo(paddingLeft, paddingTop);
this.ctx.lineTo(paddingLeft, paddingTop + chartHeight);
this.ctx.lineTo(paddingLeft + chartWidth, paddingTop + chartHeight);
this.ctx.strokeStyle = '#ddd';
this.ctx.stroke();
// 确定最大值
let maxValue = Math.max(...values, 1); // 确保最小值至少为1
// 根据数据类型调整最大值
if (this.data.dataType === 0) maxValue = Math.max(maxValue, 50000);
else if (this.data.dataType === 1) maxValue = Math.max(maxValue, 5);
else if (this.data.dataType === 2) maxValue = Math.max(maxValue, 12);
// 绘制数据点和折线
const pointRadius = 4;
const dataPoints = [];
for (let i = 0; i < values.length; i++) {
const x = paddingLeft + (i / (labels.length - 1)) * chartWidth;
const y = paddingTop + chartHeight - (values[i] / maxValue) * chartHeight;
dataPoints.push({ x, y });
this.ctx.beginPath();
this.ctx.arc(x, y, pointRadius, 0, Math.PI * 2);
this.ctx.fillStyle = '#2c9cf1';
this.ctx.fill();
this.ctx.font = '10px sans-serif';
this.ctx.fillStyle = '#666';
this.ctx.textAlign = 'center';
this.ctx.fillText(labels[i], x, paddingTop + chartHeight + 15);
}
// 绘制折线
this.ctx.beginPath();
this.ctx.moveTo(dataPoints[0].x, dataPoints[0].y);
for (let i = 1; i < dataPoints.length; i++) {
this.ctx.lineTo(dataPoints[i].x, dataPoints[i].y);
}
this.ctx.strokeStyle = '#2c9cf1';
this.ctx.lineWidth = 2;
this.ctx.stroke();
// 绘制值标签
for (let i = 0; i < values.length; i++) {
let displayValue;
switch (this.data.dataType) {
case 0: displayValue = `${values[i]}步`; break;
case 1: displayValue = `${values[i]}L`; break;
case 2: displayValue = `${values[i]}小时`; break;
default: displayValue = values[i].toString();
}
this.ctx.font = '10px sans-serif';
this.ctx.fillStyle = '#2c9cf1';
this.ctx.textAlign = 'center';
this.ctx.fillText(displayValue, dataPoints[i].x, dataPoints[i].y - 10);
}
// 绘制Y轴刻度
this.ctx.font = '10px sans-serif';
this.ctx.fillStyle = '#666';
this.ctx.textAlign = 'right';
this.ctx.textBaseline = 'middle';
for (let i = 0; i <= 3; i++) {
const value = (maxValue * (3 - i) / 3).toFixed(1);
const y = paddingTop + (chartHeight * i) / 3;
this.ctx.beginPath();
this.ctx.moveTo(paddingLeft - 5, y);
this.ctx.lineTo(paddingLeft, y);
this.ctx.strokeStyle = '#ddd';
this.ctx.stroke();
this.ctx.fillText(value, paddingLeft - 8, y);
}
// 确保绘制完成
this.ctx.draw(true);
}
});