
进度页面是运动健康App的数据汇总页。用户从首页点击运动记录或底部导航进度跳转到这里查看本周的运动数据和统计概览。这个页面的任务是把散落在各处的运动数据步数、卡路里、时长、次数汇总成直观的图表和数字让用户一眼看到我这周运动了多少。页面结构分为两部分上方的本周活动柱状图和下方的统计概览卡片。柱状图展示每天的趋势变化统计卡片展示累计总量。从趋势到总量信息从细节到宏观。完整效果柱状图的实现数据源和渲染Text(本周活动).fontSize(17).fontWeight(FontWeight.Bold).fontColor(T1) .width(100%).padding({ left: 16 }).margin({ bottom: 12 }) Row() { ForEach(WEEKLY_DATA, (day: ActivityRecord) { Column() { Column() {}.width(28).height(day.calories / 15).borderRadius(14) .linearGradient({ angle: 180, colors: [[A, 0], [#FF9F43, 1]] }) Text(day.calories.toString()).fontSize(10).fontColor(T2).margin({ top: 6 }) Text(day.date).fontSize(10).fontColor(T3) }.alignItems(HorizontalAlign.Center).layoutWeight(1) }) }.width(100%).height(120).padding({ left: 16, right: 16 }) .alignItems(VerticalAlign.Bottom).margin({ bottom: 20 })柱状图用ForEach渲染七天的数据每天是一个Column柱子卡路里数值日期。柱子高度的缩放系数.width(28).height(day.calories / 15).borderRadius(14)柱子宽度28px高度由day.calories / 15计算。和首页的柱状图对比属性首页进度页柱子宽度22px28px高度计算calories / 20calories / 15圆角11px宽度一半14px宽度一半区域高度100px120px进度页的柱子更宽28 vs 22、更高除以15 vs 除以20、区域更大120 vs 100。这是因为进度页是专门的数据展示页有更多空间给柱状图。首页的柱状图是预览进度页的柱状图是详情——同一个图表在不同页面的尺寸不同符合信息层级。除以15意味着最大卡路里值不能超过1800120×15否则柱子会溢出区域。首页除以20的最大上限是2000100×20。两个页面的上限不同但都没有做动态计算。底部对齐.alignItems(VerticalAlign.Bottom)Row的alignItems(VerticalAlign.Bottom)让所有柱子底部对齐——矮柱子在上面高的柱子在下面。这是柱状图的标准对齐方式底部代表零。柱子上方的数值Text(day.calories.toString()).fontSize(10).fontColor(T2).margin({ top: 6 })每个柱子上方显示卡路里数值10px灰色。margin({ top: 6 })在柱子和数值之间留6px间距。数值是固定的——直接显示WEEKLY_DATA中的calories值。统计概览卡片2×2 网格布局Text(统计概览).fontSize(17).fontWeight(FontWeight.Bold).fontColor(T1) .width(100%).padding({ left: 16 }).margin({ bottom: 12 }) Row({ space: 10 }) { this.SCard(总步数, 76,532, 本周, A) this.SCard(总消耗, 3,660, 千卡, #FF9F43) }.width(100%).padding({ left: 16, right: 16 }).margin({ bottom: 10 }) Row({ space: 10 }) { this.SCard(运动时长, 295, 分钟, #5DADE2) this.SCard(训练次数, 16, 次, #00B894) }.width(100%).padding({ left: 16, right: 16 })四个统计卡片分成两行每行两个。用两个Row实现2×2网格而不是用Grid或Flex-wrap。原因是ArkUI的Grid组件需要指定列数和行列间距对于简单的2×2布局来说太重了。两个Row更直观——每个Row放两个卡片space: 10控制卡片间距。SCard BuilderBuilder SCard(label: string, value: string, unit: string, color: string) { Column() { Text(value).fontSize(28).fontWeight(FontWeight.Bold).fontColor(color) Text(unit).fontSize(11).fontColor(T3).margin({ top: 4 }) Text(label).fontSize(12).fontColor(T2).margin({ top: 4 }) }.layoutWeight(1).padding(16).backgroundColor(#FFFFFF).borderRadius(16) .shadow({ radius: 4, color: rgba(0,0,0,0.03), offsetY: 1 }) }每个统计卡片由三行文字组成数值28px加粗彩色、单位11px灰色、标签12px灰色。数值最醒目单位和标签视觉层级较低。layoutWeight(1)让两个卡片均分Row的宽度。padding(16)给卡片内部留白避免文字紧贴边框。backgroundColor(#FFFFFF)白色背景borderRadius(16)圆角shadow轻微阴影和首页的训练卡片风格一致。四个统计指标的含义指标数值单位颜色含义总步数76,532本周红色(A)一周累计步数总消耗3,660千卡橙色(#FF9F43)一周累计卡路里消耗运动时长295分钟蓝色(#5DADE2)一周累计运动时间训练次数16次绿色(#00B894)一周训练次数四个颜色和首页的数据环一致红色步数橙色卡路里蓝色运动时间绿色训练次数。颜色体系在不同页面之间保持统一用户看到红色就联想到步数不管在哪个页面。数据的硬编码问题四个统计值76532、3660、295、16是硬编码的字符串不是从WEEKLY_DATA动态计算的。如果把WEEKLY_DATA七天的卡路里加起来和3660对不上。这意味着柱状图和统计卡片展示的是假数据——柱状图来自真实数据源统计卡片是静态写死的。实际项目中应该动态计算const totalCalories WEEKLY_DATA.reduce((sum, day) sum day.calories, 0) const totalSteps WEEKLY_DATA.reduce((sum, day) sum day.steps, 0)但原型阶段硬编码够用——页面布局和交互逻辑已经验证了数据对接是后续的工作。页面的数据流ProgressPage没有State变量——它不需要响应式渲染。数据来自WEEKLY_DATA导入的常量和硬编码的统计值。用户在这个页面只能看不能操作没有筛选、排序、编辑功能。这种纯展示页面的实现最简单——不需要状态管理不需要事件处理只需要把数据渲染成UI。但缺点是数据不实时——如果用户刚跑完步步数不会自动更新。实际项目中应该在onPageShow中刷新数据。和首页柱状图的复用首页和进度页都有柱状图代码几乎一样——都是ForEach渲染WEEKLY_DATA每天一个Column。区别在于尺寸和样式首页柱子更窄22px vs 28px区域更小100px vs 120px。这两个柱状图没有抽成公共组件——每个页面各自实现了一遍。如果以后要修改柱状图的样式比如加动画、改颜色需要改两个地方。更好的做法是抽成一个Builder WeeklyChart(height: number, barWidth: number)两个页面调用时传入不同参数。但原型阶段的重复是可以接受的——先验证布局再优化代码结构。过早抽象反而会增加理解成本。踩坑记录柱状图高度溢出。day.calories / 15的系数15是硬编码的。如果某天卡路里超过1800120×15柱子高度会超过区域高度和其他柱子重叠。首页用20作为系数上限是2000。两个页面的上限不同但都没有做动态计算或上限截断。2×2网格的间距不均。两个Row各自有space: 10但Row之间没有设置间距——第二行紧贴第一行。实际上有margin({ bottom: 10 })在第一个Row下方但第二个Row没有margin。如果卡片高度不一致比如数值长度不同导致文字换行两行之间可能出现不对齐。SCard的layoutWeight。两个SCard都用layoutWeight(1)均分宽度。如果以后要改成三个卡片一行需要把layoutWeight和Row的space配合调整。三个卡片时space需要减小否则间距太大。统计值的数字格式。76532显示为76,532——有千位分隔符。但这个分隔符是硬编码在字符串里的不是动态格式化的。实际项目中应该用数字格式化totalSteps.toLocaleString()。但鸿蒙的toLocaleString支持可能不完整需要测试。柱状图的触摸反馈。柱子没有绑定onClick——用户不能点击某个柱子查看当天的详细数据。如果要加交互需要在ForEach的Column上绑定onClick传入day参数跳转到当天的详情页。进度页面的核心价值是数据可视化——把一周的运动数据变成柱状图和统计卡片。柱状图展示趋势哪天运动多、哪天运动少统计卡片展示总量一共运动了多少。两个维度互补——趋势告诉用户哪天偷懒了总量告诉用户整体表现如何。颜色体系和首页保持一致用户不需要重新学习红色代表什么。