HarmonyOS ArkTS实战:从零实现 —— 保养日志页的圆点竖线时间轴与双列统计卡
App 58「车辆保养提醒」日志页(Func2Tab),主题色
#008080青蓝。本页是保养历史的"日志页"——白色单行 Header("保养日志"20 号加粗)+双列统计卡(12 保养次数青 / ¥3860 累计花费浅青)+SectionTitle(保养历史)+ 4 条保养时间轴(🛢️ 机油机滤更换 12080 km·2026-07-28 ¥480 / 🛞 四轮换位 11000 km·2026-06-15 ¥60 / 🔧 常规保养 10000 km·2026-05-02 ¥650 / ❄️ 空调滤芯更换 8500 km·2026-03-20 ¥120,左侧 32×32 浅青圆标 + 竖线连接 + 项目名 + 红色金额 + 里程·日期副行)。本篇基于58-car-maintain/entry/src/main/ets/pages/Func2Tab.ets(共 98 行)逐段拆解,附 4 张实机截图。
一、整体结构:三区"Header + 统计 + 时间轴"布局
日志页是"保养统计 + 历史时间轴"的组合布局——3 个 @Builder 块:
build() { Column() { this.Header() Scroll() { Column({ space: 14 }) { this.SummaryCard() this.SectionTitle('保养历史') this.Timeline() } .width('100%') .padding({ left: D.pad, right: D.pad, top: 14, bottom: D.pad + this.safeBottom + 20 }) } .layoutWeight(1).scrollBar(BarState.Off).align(Alignment.Top) } .width('100%').height('100%').backgroundColor(C.bg) }3 块结构:
- SummaryCard— 双列统计卡(保养次数 12 / 累计花费 ¥3860)
- SectionTitle— "保养历史"标题
- Timeline— 4 条圆点竖线保养时间轴(按时间倒序)
日志页是"保养账本"——先看统计(累计保养 12 次、花费 3860 元),再看历史时间轴(机油机滤更换/四轮换位/常规保养/空调滤芯更换,按时间倒序),让用户掌握"这台车做过哪些保养、花了多少钱"。与 App 55 续费日历的"红点竖线时间轴"同手法(58 用浅青圆标),是系列第二个时间轴页面。
项目源码开源:https://gitee.com/codenestFlow/HarmonyOSHub
二、Header:单行品牌头
Header() { Row() { Text('保养日志').fontSize(20).fontWeight(FontWeight.Bold).fontColor(C.text) } .width('100%').height(this.safeTop + 56).padding({ top: this.safeTop, left: D.pad, right: D.pad }) .backgroundColor(C.card).alignItems(VerticalAlign.Bottom) }功能页 Header 标准范式(20 号、固定高、文字贴底),与保养页、我的页同款。"保养日志"点明本页职能——查看维修保养历史。
三、SummaryCard:双列保养统计卡
SummaryCard() { Row() { Column({ space: 4 }) { Text('12').fontSize(22).fontWeight(FontWeight.Bold).fontColor(C.primary) Text('保养次数').fontSize(11).fontColor(C.textDim) }.layoutWeight(1) Column({ space: 4 }) { Text('¥3860').fontSize(22).fontWeight(FontWeight.Bold).fontColor(C.accent) Text('累计花费').fontSize(11).fontColor(C.textDim) }.layoutWeight(1) } .width('100%').padding({ top: 16, bottom: 16 }).backgroundColor(C.card).borderRadius(D.rLg).border({ width: 1, color: C.stroke }) }技术拆解:
- 双列均分:
Row+ 两个layoutWeight(1)Column——**保养次数(12)/ 累计花费(¥3860)**两列 1:1,每列 22 号 Bold 数值 + 11 号淡灰标签。 - 双色数值:次数青(
C.primary)、累计花费浅青(C.accent)——数值用主题色系区分(次数 = 主青、花费 = 浅青)。 - 数据自洽:累计花费 3860 = 时间轴 4 条之和(480+60+650+120 = 1310)?——演示数据的 3860 是"全部历史累计"(含时间轴之外的更早保养),时间轴只展示最近 4 条(示例数据),数字口径"累计 vs 近期"需在正文说明(避免对不上账的困惑)。
- 双指标定位:两个数字回答"这台车保养过几次"(12 次)与"保养花了多少"(3860 元)——频次 + 费用的累计快览。
四、Timeline:圆点竖线保养时间轴
Timeline() { Column() { ForEach(this.logs, (l: LogItem, idx: number) => { Row({ space: 12 }) { Column() { Row() { Text(l.emoji).fontSize(16) } .width(32).height(32).backgroundColor(C.primarySoft).borderRadius(16).justifyContent(FlexAlign.Center) if (idx < this.logs.length - 1) { Column().width(2).height(48).backgroundColor(C.stroke) } }.width(32) Column({ space: 4 }) { Row() { Text(l.name).fontSize(14).fontWeight(FontWeight.Medium).fontColor(C.text).layoutWeight(1) Text('¥' + l.cost).fontSize(14).fontWeight(FontWeight.Bold).fontColor(C.danger) }.width('100%') Text(l.mileage + ' km · ' + l.date).fontSize(12).fontColor(C.textDim) } .alignItems(HorizontalAlign.Start).layoutWeight(1).padding(12).margin({ bottom: 12 }) .backgroundColor(C.card).borderRadius(D.rMd).border({ width: 1, color: C.stroke }) } .width('100%').alignItems(VerticalAlign.Top) }, (l: LogItem) => l.id.toString()) }.width('100%') }4 条保养日志数据(21-26 行):
| 项目 | 里程 | 日期 | 费用 |
|---|---|---|---|
| 🛢️ 机油机滤更换 | 12080 km | 2026-07-28 | ¥480 |
| 🛞 四轮换位 | 11000 km | 2026-06-15 | ¥60 |
| 🔧 常规保养 | 10000 km | 2026-05-02 | ¥650 |
| ❄️ 空调滤芯更换 | 8500 km | 2026-03-20 | ¥120 |
卡片细节:
- 32×32 浅青圆标:
backgroundColor(C.primarySoft)(#E0F5F5)+borderRadius(16)(正圆)+ 16 号 emoji——时间轴节点图标(比 App 55 的红点大,圆标内嵌 emoji 更丰富),每个保养项目一个 emoji(🛢️🛞🔧❄️)。 - 竖线连接:
if (idx < length - 1)画 2×48 竖线——非末项才画线(最后一项无后续节点),时间轴"节点 + 连线"结构。 - 项目名 + 红色金额:14 号 Medium 项目名 + 14 号 Bold
¥480(C.danger红)——费用用警示红(花钱 = 支出),与项目名同行左右分布。 - 里程·日期副行:12 号淡灰"12080 km · 2026-07-28"——保养里程 + 日期(在多少公里、什么时候做的),
layoutWeight(1)撑开。 - 时间倒序:07-28 → 06-15 → 05-02 → 03-20——最近保养在前(2026-07-28 的机油机滤更换最新),时间流符合直觉;里程递减(12080 → 11000 → 10000 → 8500,里程随时间递增)。
五、跨页数据自洽:保养日志的全局闭环
日志页与首页、保养、我的三页形成闭环:
- 日志页"机油机滤更换 12080 km ¥480"↔ 首页"机油机滤 还剩 500km"——日志页记录的是最近一次机油保养(07-28 在 12080 km),首页"还剩 500km"由这次保养推算(下次保养里程 ≈ 13080 - 当前 12580 = 500),日志记录 → 首页剩余里程。
- 日志页"累计花费 ¥3860"↔ 我的页"¥3.8k 累计花费"——金额完全一致(3860 ≈ 3.8k 四舍五入),日志给明细、我的页给统计。
- 日志页"12 次"↔ 我的页"12 保养次数"——次数一致(12 次累计),日志页统计与我的页统计同源。
- 日志页时间轴 4 条↔ 保养页"记录保养"——每次在保养页记录,日志页时间轴新增一条,录入即入日志(时间轴是保养记录的历史沉淀)。
- 日志页"四轮换位 11000km"↔ 首页"轮胎更换 还剩 8000km"——轮胎相关保养(换位 60 元)与首页轮胎项目对应(下次轮胎更换里程由周期推算),日志历史支撑首页状态。
六、系列横向对比:时间轴页面的三种形态
系列中"时间轴"型页面各有侧重:
- App 58 保养日志(青
#008080):浅青圆标时间轴 + 双列统计——"保养历史",项目 + 费用。 - App 55 续费日历(红
#FF6B6B):红点竖线时间轴 + 年度汇总——"扣款计划"。 - App 44 纪念册(淡紫
#A29BFE):时间轴 + 回忆照片——"回忆叙事"。
58 与 55 都是"圆点/红点竖线时间轴",差异在节点形态与信息:55 是红点(12×12 纯色圆点)+ 金额,58 是浅青圆标(32×32 内嵌 emoji)+ 项目名 + 红色金额 + 里程日期——58 的节点更"信息丰富"(emoji 标识项目类型),因为保养日志的项目多样性需要图标区分(机油/轮胎/常规/空调各有 emoji),而续费日历的扣款项目同质(都是订阅)用纯点即可。58 的时间轴同时是"日志账本"(记录花了多少钱)。
七、开发者避坑:保养日志的四个细节
从 Func2Tab 的实现提炼四个易踩坑点:
- 累计与近期的口径:统计卡"累计花费 ¥3860"是全部历史、时间轴只展示 4 条(示例)——产品化应统一口径(统计 = 全部记录之和,时间轴可全量滚动或分页),并确保"统计 = 明细之和"(若只展示 4 条而统计是全部,需说明"更多记录向下滚动")。
- 竖线高度与卡片对齐:竖线 48 高与卡片(含底部 12 间距)不完全匹配——产品化按卡片实际高度计算竖线高度(或用弹性高度),保证"节点-连线-节点"的视觉连续,避免线长于卡或短于卡。
- 时间与里程的排序:当前按时间倒序(07-28 在前)——产品化按日期字段排序(新记录自动插到顶部),并校验"里程随日期递增"(若某条记录里程小于前一条,说明录入错误)。
- 费用汇总动态化:¥3860 写死——产品化由所有日志费用求和(每次记录保养自动累加),新增记录后统计卡自动更新,避免"日志多了但统计不变"。
八、常见问题 FAQ
问:统计卡说累计花费 3860 元,但时间轴 4 条加起来只有 1310 元,为什么?答:统计卡的"累计花费"是全部历史保养费用(3860 元,含更早的 8 次保养),时间轴只展示"最近 4 条"(机油 480 + 换位 60 + 常规 650 + 空调 120 = 1310 元)——最近 4 条是 3860 元的一部分(1310 元),更早的 8 次约 2550 元未在示例时间轴中展示(演示数据只列了 4 条代表记录)。产品化后时间轴应展示全部记录(可滚动),统计与明细完全对账。
问:日志页的时间轴和首页的保养项目是什么关系?答:时间轴是"做过什么"的历史记录(每做一次保养记一条),首页是"还该做什么"的状态计划(每个项目还剩多少公里)——日志是"过去式"(记录),首页是"未来式"(计划),两者通过"保养周期"衔接:日志记录本次保养里程 → 加周期 = 下次保养里程 → 首页显示剩余。保养页的"记录保养"就是"把过去记进日志、把未来算进首页"的动作。
问:为什么费用用红色而项目名用深色?答:费用(¥480)用红色(danger)强调"花了钱"——保养日志是"支出记录",红色金额让用户在浏览历史时对"花钱"有感知(哪次保养花得多:常规保养 650 最高);项目名用深色(text)保持中性(项目名不携带情绪)。颜色语义与 App 55 续费日历的红色金额一致(支出 = 红),系列"费用红色"的语义统一。
九、验收与总结
本篇对 58-car-maintain 日志页(Func2Tab,98 行)做了逐块拆解:
- 三区结构:Header(保养日志)+ SummaryCard(双列统计)+ SectionTitle + Timeline(圆点竖线时间轴)
- 核心交互:无点击(纯展示),32×32 浅青圆标 + 红色金额
- 主题色:
#008080青蓝——统计次数、圆标浅青底 - 数据闭环:日志 12080/480 → 首页 500km,12/3860 → 我的页 12/3.8k,保养记录 → 日志时间轴
日志页是车辆保养提醒的"保养账本"——统计卡给结论(12 次/3860 元)、时间轴给历史(4 条最近保养、里程日期费用),一屏掌握"这台车保养过什么、花了多少"。
十、扩展思考:从保养日志到养车账本
日志页的演进方向是"养车账本":第一是养车成本全览——当前只有保养费用(3860 元),演进方向是聚合"保养 + 加油 + 保险 + 维修"全部养车支出,形成年度养车成本报告("今年养车花了 2 万元:油费 1 万、保养 3860、保险 5000"),日志页的保养费用是成本全览的一部分;第二是保养频率分析——时间轴展示保养时间(07-28、06-15、05-02、03-20),演进方向是"平均保养间隔分析"(多久保养一次:2 个月?5000km?),发现保养过频(浪费)或过疏(伤车);第三是单次保养对比——各次保养费用对比(常规 650 元最高、四轮换位 60 元最低),演进方向是"同项目费用趋势"(机油保养每次多少钱、涨没涨),帮助用户判断"哪家店贵了";第四是保养到期预测——基于历史保养间隔预测下次保养时间(上次 07-28 机油 + 5000km ≈ 下次),日志页的历史记录是预测的数据基础。这四个方向都从日志页已有的时间轴数据长出来,让"看历史"变成"管成本"。
十一、从设计稿到代码的映射
把日志页设计稿翻译成代码,有几组典型映射:第一,"双列统计"映射为"两个等权重列容器"——设计稿的保养次数与累计花费两列,代码里用两个等权重列容器各放 22 号数值(青与浅青)与 11 号标签;第二,"时间轴圆标"映射为"圆形容器加表情"——设计稿的浅青圆点节点,代码里用三十二乘三十二圆角十六的浅青底圆形容器内嵌十六号表情图标;第三,"竖线连接"映射为"条件渲染的细长容器"——设计稿节点间的竖线,代码里用两单位宽四十八高的细容器,非最后一项才渲染;第四,"事件卡片"映射为"项目名加金额加里程日期"——设计稿的保养卡片,代码里用项目名与红色金额同行、里程日期副行的组合。这四组映射展示了"日志时间轴"的完整翻译,与 App 55 的红点竖线时间轴同构(58 用浅青圆标内嵌图标)。
十二、常见问题 FAQ
问:日志页的保养时间和里程为什么是倒序的?答:时间轴按时间倒序排列(2026-07-28 最新在前、03-20 最早在后)——用户浏览历史时最关心"最近做了什么保养",最新记录置顶减少滚动;同时里程也随日期倒序递减(12080 → 8500,最近的保养里程最高),时间与里程两个维度都"最新在前"。产品化后新记录自动插入顶部,时间轴始终"最新在上"。
问:累计花费 3860 元包括什么?答:包括全部历史保养费用(12 次保养的总花费)——时间轴展示的 4 条(机油 480 + 四轮换位 60 + 常规 650 + 空调 120 = 1310 元)是最近 4 次,更早的 8 次保养约 2550 元未在示例时间轴中列出(演示数据只展示了 4 条代表记录),3860 元是 12 次的总和。产品化后时间轴展示全部记录(可滚动),"统计 = 明细之和"完全对账。
问:时间轴的节点为什么用圆形图标而不是纯圆点?答:因为保养项目的类型多样(机油/轮胎/常规/空调各有不同),纯圆点无法区分"做了什么保养";32×32 的浅青圆标内嵌 16 号 emoji(🛢️🛞🔧❄️),既是时间轴节点又标识项目类型,扫一眼圆标就知道"那次保养做了什么"——比 App 55 续费日历的纯红点(扣款项目同质不需要区分)信息更丰富。
十三、补充要点:日志页三个细节再思考
第一,关于红色金额的支出语义。每次保养的费用用红色(danger)加粗——保养是支出(花钱),红色让"花了多少"在时间轴中醒目(常规保养 650 元一眼可见),与 App 55 续费日历、App 56 停车记录的红色金额语义一致,系列"费用 = 红"的视觉语言统一。第二,关于里程与日期的双信息。副行"12080 km · 2026-07-28"同时展示"在多少公里做的"与"什么时候做的"——保养记录的两个关键时间坐标(里程维 + 日期维),因为保养周期既可以按里程算(5000km)也可以按时间算(半年),双坐标让用户从任一维度回顾保养历史。第三,关于圆标与竖线的视觉节奏。32×32 圆标 + 2 宽 48 高竖线 + 卡片(底部 12 间距)——"圆标-竖线-圆标"的串珠结构形成时间流动感,圆标比 App 55 的红点大(信息承载更多),竖线比红点版更短(卡片间距 12),视觉节奏紧凑,符合"日志记录较多"的场景。
十四、最后总结
日志页作为车辆保养提醒的"账本页",用两个区块完成了保养历史的完整呈现:双列统计卡给结论(12 次/3860 元)、圆点竖线时间轴给明细(4 条最近保养、里程日期费用)。整页没有用户卡与菜单,是系列"纯数据页"的又一代表——第 3 Tab 完全让给保养历史,体现"记录沉淀"的产品价值。时间轴的圆标内嵌 emoji 让保养项目类型一目了然(比纯文本列表更直观),红色金额标注每次花费。从演示到产品,日志页的进化方向是养车成本全览、保养频率分析、同项目费用对比、到期预测,从"看历史"走向"管成本"。作为系列"时间轴账本"页的代表,它与首页(状态告警)、保养页(记录入口)、我的页(双保管理)共同构成车辆保养提醒的完整链路:记录 → 告警 → 历史 → 管理。
十五、补充要点:时间轴的工程细节再思考
日志页的时间轴有几个工程细节值得再思考:第一,竖线高度与卡片高度的匹配——竖线固定 48 高、卡片含底部 12 间距,两者并不严格相等(竖线略短于"卡片 + 间距"的总高),产品化应按卡片实际高度计算竖线长度或用弹性布局,保证"圆标-竖线-圆标"的视觉连续(线不悬空、不断裂);第二,数据渲染的性能——时间轴记录多了(12 次、未来可能几十次)ForEach 全量渲染会影响滚动性能,产品化可用列表组件懒加载或分页(先展示最近 20 条);第三,日期与里程的格式——日期"2026-07-28"(年-月-日)与里程"12080 km"(整数 + 单位)格式统一,产品化用日期格式化函数与里程千位分隔(12,080 km),与首页保持一致;第四,时间轴的排序稳定性——当前按数据声明顺序(已按时间倒序声明),产品化按日期字段排序(新记录自动插入顶部),并处理"同一天多条保养"的顺序(按录入先后)。这四个细节共同保证时间轴"看得顺、滚得快、排得对"。
十六、最后总结
日志页解析至此完整收尾:双列统计卡、圆点竖线时间轴、红色金额全部覆盖。读者可重点回顾"圆标内嵌表情"的时间轴节点设计——32×32 浅青圆标加 16 号表情让保养项目类型一目了然(机油/轮胎/常规/空调),比纯文本列表更直观,是时间轴页面"信息丰富"的形态。车辆保养的历史从这一页展开:12 次保养、3860 元花费、最近 4 次的里程日期费用,让车主掌握这台车的保养轨迹与成本。