feat(records): 训练趋势图表 + 列表时长改 MM:SS

- 新增 trend-chart 柱状图组件(CSS,近7天/近6月切换)
- records 页加训练趋势卡片(统计卡片后)
- 训练记录列表时长从秒数改为 MM:SS 显示

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-07-28 11:19:07 +08:00
parent faa49cff1c
commit 75bad477b1
8 changed files with 233 additions and 3 deletions
+48
View File
@@ -0,0 +1,48 @@
/**
* Trend bar chart - pure CSS (no canvas), matches the calendar-heatmap's
* rendering approach for consistency.
*
* chartData: [{ label, value, valueText, highlight }]
* - label: bottom caption (e.g. "一" / "7月")
* - value: numeric magnitude (seconds); drives bar height
* - valueText: formatted string shown above the bar (e.g. "1分30秒")
* - highlight: truthy -> theme glow + bold label (today / this month)
*
* Bar height is value/max*100%, with an 8% floor for any non-zero value so
* short sessions stay visible. Zero values render a faint stub.
*/
Component({
properties: {
chartData: { type: Array, value: [] }
},
data: {
bars: []
},
observers: {
'chartData'(chartData) {
this._compute(chartData)
}
},
lifetimes: {
ready() {
this._compute(this.properties.chartData)
}
},
methods: {
_compute(chartData) {
const arr = Array.isArray(chartData) ? chartData : []
const max = arr.reduce((m, d) => Math.max(m, Number(d && d.value) || 0), 0)
const bars = arr.map((d) => {
const v = Number(d && d.value) || 0
return {
label: (d && d.label) || '',
value: v,
valueText: (d && d.valueText) || '',
highlight: !!(d && d.highlight),
percent: max > 0 ? Math.max((v / max) * 100, v > 0 ? 8 : 0) : 0
}
})
this.setData({ bars })
}
}
})
+4
View File
@@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}
+12
View File
@@ -0,0 +1,12 @@
<view class="trend-chart">
<view class="trend-bars">
<view class="trend-bar-col" wx:for="{{bars}}" wx:key="label">
<view class="trend-bar {{item.value === 0 ? 'zero' : ''}} {{item.highlight ? 'highlight' : ''}}" style="height: {{item.percent}}%;">
<text class="trend-bar-value" wx:if="{{item.value > 0}}">{{item.valueText}}</text>
</view>
</view>
</view>
<view class="trend-labels">
<text class="trend-bar-label {{item.highlight ? 'highlight' : ''}}" wx:for="{{bars}}" wx:key="label">{{item.label}}</text>
</view>
</view>
+68
View File
@@ -0,0 +1,68 @@
.trend-chart {
/* top room so the value labels above tall bars aren't clipped */
padding-top: 32rpx;
}
.trend-bars {
display: flex;
align-items: flex-end;
height: 220rpx;
gap: 14rpx;
}
.trend-bar-col {
flex: 1;
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-end;
}
.trend-bar {
width: 100%;
position: relative;
border-radius: 8rpx 8rpx 0 0;
background: linear-gradient(180deg, var(--primary), var(--primary-light));
min-height: 6rpx;
transition: height 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.trend-bar.zero {
background: var(--border);
min-height: 4rpx;
}
.trend-bar.highlight {
box-shadow: 0 0 14rpx rgba(var(--primary-rgb), 0.5);
}
/* value caption floats above the bar so it never eats into bar height */
.trend-bar-value {
position: absolute;
top: -28rpx;
left: 0;
right: 0;
text-align: center;
font-size: 18rpx;
color: var(--text-secondary);
line-height: 1;
white-space: nowrap;
}
.trend-labels {
display: flex;
margin-top: 12rpx;
gap: 14rpx;
}
.trend-bar-label {
flex: 1;
text-align: center;
font-size: 20rpx;
color: var(--text-secondary);
}
.trend-bar-label.highlight {
color: var(--primary);
font-weight: 600;
}