feat(records): 训练趋势图表 + 列表时长改 MM:SS
- 新增 trend-chart 柱状图组件(CSS,近7天/近6月切换) - records 页加训练趋势卡片(统计卡片后) - 训练记录列表时长从秒数改为 MM:SS 显示 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,8 @@ Page({
|
||||
monthRecords: [],
|
||||
historyList: [],
|
||||
listMode: 'month',
|
||||
trendMode: 'week',
|
||||
trendData: [],
|
||||
showDayDetail: false,
|
||||
dayDetail: {},
|
||||
icons: iconsMod.build()
|
||||
@@ -52,7 +54,7 @@ Page({
|
||||
storage.validateStreak()
|
||||
const stats = storage.getTotalStats()
|
||||
const monthKey = `${this.data.currentYear}-${String(this.data.currentMonth).padStart(2, '0')}`
|
||||
const records = storage.getRecordsByMonth(monthKey)
|
||||
const records = (storage.getRecordsByMonth(monthKey) || []).map(r => ({ ...r, durationText: util.formatTime(r.duration) }))
|
||||
|
||||
// Each month is already sorted newest-first in storage. To get top 30 most recent,
|
||||
// walk months in reverse chrono order and concat — O(months*30) instead of O(n log n).
|
||||
@@ -61,7 +63,7 @@ Page({
|
||||
const historyList = []
|
||||
for (const mk of monthKeys) {
|
||||
for (const r of byMonth[mk]) {
|
||||
historyList.push(r)
|
||||
historyList.push({ ...r, durationText: util.formatTime(r.duration) })
|
||||
if (historyList.length >= 30) break
|
||||
}
|
||||
if (historyList.length >= 30) break
|
||||
@@ -80,6 +82,7 @@ Page({
|
||||
historyList,
|
||||
listMode: this.data.listMode || 'month',
|
||||
displayList: (this.data.listMode || 'month') === 'month' ? records : historyList,
|
||||
trendData: this._computeTrend(this.data.trendMode || 'week'),
|
||||
loading: false
|
||||
})
|
||||
},
|
||||
@@ -115,6 +118,61 @@ Page({
|
||||
this.refresh()
|
||||
},
|
||||
|
||||
onToggleTrendMode(e) {
|
||||
const mode = e.currentTarget.dataset.mode
|
||||
if (!mode || mode === this.data.trendMode) return
|
||||
this.setData({ trendMode: mode, trendData: this._computeTrend(mode) })
|
||||
},
|
||||
|
||||
/**
|
||||
* 训练趋势数据:
|
||||
* week - 近 7 天每天的训练时长(秒)
|
||||
* month - 近 6 个月每月的训练时长(秒)
|
||||
* 返回 [{ label, value, valueText, highlight }] 供 trend-chart 渲染。
|
||||
*/
|
||||
_computeTrend(mode) {
|
||||
const allRecords = Object.values(storage.getRecords()).flat()
|
||||
const today = new Date()
|
||||
const weekdays = ['日', '一', '二', '三', '四', '五', '六']
|
||||
const pad = (n) => String(n).padStart(2, '0')
|
||||
|
||||
if (mode === 'month') {
|
||||
const data = []
|
||||
for (let i = 5; i >= 0; i--) {
|
||||
const d = new Date(today.getFullYear(), today.getMonth() - i, 1)
|
||||
const monthKey = `${d.getFullYear()}-${pad(d.getMonth() + 1)}`
|
||||
const monthRecords = storage.getRecordsByMonth(monthKey) || []
|
||||
const total = monthRecords.reduce((s, r) => s + (Number(r.duration) || 0), 0)
|
||||
data.push({
|
||||
label: `${d.getMonth() + 1}月`,
|
||||
value: total,
|
||||
valueText: total > 0 ? util.formatDuration(total) : '',
|
||||
highlight: i === 0
|
||||
})
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// default: week (近 7 天)
|
||||
const data = []
|
||||
for (let i = 6; i >= 0; i--) {
|
||||
const d = new Date(today)
|
||||
d.setDate(d.getDate() - i)
|
||||
const dateStr = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`
|
||||
const total = allRecords
|
||||
.filter((r) => util.dateOnly(r.date) === dateStr)
|
||||
.reduce((s, r) => s + (Number(r.duration) || 0), 0)
|
||||
const isToday = i === 0
|
||||
data.push({
|
||||
label: isToday ? '今天' : weekdays[d.getDay()],
|
||||
value: total,
|
||||
valueText: total > 0 ? util.formatDuration(total) : '',
|
||||
highlight: isToday
|
||||
})
|
||||
}
|
||||
return data
|
||||
},
|
||||
|
||||
onDayTap(e) {
|
||||
const { year, month, day } = e.detail
|
||||
const dateStr = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`
|
||||
|
||||
Reference in New Issue
Block a user