修复趋势图表加载与比例展示
This commit is contained in:
@@ -54,6 +54,73 @@ const formatDate = (date) => {
|
||||
/** Strip the time portion of a formatDate string → "YYYY-MM-DD". */
|
||||
const _dateOnly = (s) => (typeof s === 'string' && s.length >= 10) ? s.substring(0, 10) : ''
|
||||
|
||||
const _normalizeDuration = (value) => Math.max(0, Math.floor(Number(value) || 0))
|
||||
|
||||
const _formatTrendDuration = (seconds) => {
|
||||
const duration = _normalizeDuration(seconds)
|
||||
if (duration >= 3600) return `${Math.floor(duration / 60)}m`
|
||||
return formatTime(duration)
|
||||
}
|
||||
|
||||
/** Build daily or monthly duration totals from one training-record snapshot. */
|
||||
const getTrendData = (recordGroups, mode, now = new Date()) => {
|
||||
const dateTotals = {}
|
||||
const groups = recordGroups && typeof recordGroups === 'object' ? recordGroups : {}
|
||||
|
||||
Object.values(groups).forEach((records) => {
|
||||
if (!Array.isArray(records)) return
|
||||
records.forEach((record) => {
|
||||
const date = _dateOnly(record && record.date)
|
||||
if (!date) return
|
||||
dateTotals[date] = (dateTotals[date] || 0) + _normalizeDuration(record.duration)
|
||||
})
|
||||
})
|
||||
|
||||
const today = new Date(now)
|
||||
const weekdays = ['日', '一', '二', '三', '四', '五', '六']
|
||||
const pad = (n) => String(n).padStart(2, '0')
|
||||
|
||||
if (mode === 'month') {
|
||||
const monthTotals = {}
|
||||
Object.keys(dateTotals).forEach((date) => {
|
||||
const month = date.substring(0, 7)
|
||||
monthTotals[month] = (monthTotals[month] || 0) + dateTotals[date]
|
||||
})
|
||||
return Array.from({ length: 6 }, (_, index) => {
|
||||
const offset = 5 - index
|
||||
const date = new Date(today.getFullYear(), today.getMonth() - offset, 1)
|
||||
const monthKey = `${date.getFullYear()}-${pad(date.getMonth() + 1)}`
|
||||
const value = monthTotals[monthKey] || 0
|
||||
return {
|
||||
label: `${date.getMonth() + 1}月`,
|
||||
value,
|
||||
valueText: value > 0 ? _formatTrendDuration(value) : '',
|
||||
highlight: offset === 0
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return Array.from({ length: 7 }, (_, index) => {
|
||||
const offset = 6 - index
|
||||
const date = new Date(today)
|
||||
date.setDate(date.getDate() - offset)
|
||||
const dateKey = `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`
|
||||
const value = dateTotals[dateKey] || 0
|
||||
return {
|
||||
label: offset === 0 ? '今天' : weekdays[date.getDay()],
|
||||
value,
|
||||
valueText: value > 0 ? _formatTrendDuration(value) : '',
|
||||
highlight: offset === 0
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getBarPercent = (value, max) => {
|
||||
const amount = _normalizeDuration(value)
|
||||
const maximum = _normalizeDuration(max)
|
||||
return maximum > 0 ? amount / maximum * 100 : 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a local file path (typically `wxfile://...` from chooseAvatar) to a
|
||||
* base64 data URI. Used to make temporary file URLs survive the WeChat
|
||||
@@ -101,5 +168,7 @@ module.exports = {
|
||||
getMonthCalendar,
|
||||
formatDate,
|
||||
dateOnly: _dateOnly,
|
||||
getTrendData,
|
||||
getBarPercent,
|
||||
fileToDataURI
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user