食材保鲜手册·ArkTS·鸿蒙:从车辆保养到食材保鲜的项目重构与数据建模迁移
本文基于 HarmonyOS Next API 24+ 与 ArkTS 2.x,记录「食材保鲜手册」应用从「车辆保养手册」整体重构的工程过程。我们将从项目定位迁移、数据建模对照、双数据集拆分、字段语义重命名、保鲜常识的领域知识注入五个维度,讲透一个鸿蒙 ArkTS 工具型应用如何在不改动整体 UI 骨架的前提下完成领域迁移,以及迁移过程中暴露的 ArkTS 类型系统、常量数据建模、接口字段语义的工程取舍。


一、项目重构的起点:领域迁移而非 UI 重写
1.1 重构决策的边界
「食材保鲜手册」并非从零创建的新项目,而是基于已有「车辆保养手册」代码骨架做领域迁移。这个决策的关键边界是:
| 维度 | 是否迁移 | 理由 |
|---|---|---|
| UI 骨架(双 Tab + 分类筛选 + 卡片列表 + 双进度条) | 保留 | 信息列表型工具应用的通用形态,与领域无关 |
| 数据接口字段名 | 重命名 | 字段语义与领域强绑定(里程→冷藏天数) |
| 静态数据集 | 全替换 | 项目名变了,数据内容必须跟随 |
| 分类色锚点 | 重选 | 车辆分类(发动机/底盘)与食材分类(冷藏/冷冻)色感不同 |
| 色板主色 | 调整 | 车辆是工业蓝科技感,食材是厨房暖色自然感 |
| 字符串资源 | 全替换 | 用户可见文案必须贴近食材场景 |
这个边界划定的核心认知是:UI 骨架是领域无关的,数据与色彩是领域相关的。ArkUI 的声明式 UI 把"骨架"与"内容"分离得足够干净——ForEach 渲染的数据集与 @Builder 渲染的卡片结构是解耦的,换数据集不动卡片结构、换卡片结构不动数据集。这种解耦让领域迁移的成本控制在"重命名 + 数据替换"的范围内,不必重写 UI。
1.2 鸿蒙应用项目结构的不变性
重构前后,项目目录结构完全不变:
doubleinfo/
AppScope/
app.json5 # 应用级配置(bundleName、版本)
resources/base/element/
string.json # 应用名等全局字符串
entry/
src/main/
ets/
entryability/EntryAbility.ets # UIAbility 入口
pages/Index.ets # 唯一页面(应用主体)
resources/base/element/
color.json # 色板
string.json # 页面级字符串
鸿蒙应用的项目结构是硬约束——AppScope 管 bundle 级资源,entry 管 module 级资源,ets 存放 ArkTS 源码,entryability 是 UIAbility 入口,pages 是页面。这个结构不随领域变化,所以领域迁移完全集中在 Index.ets、color.json、string.json 三个文件上。
EntryAbility.ets 在迁移中一个字都不改——它只负责 windowStage.loadContent('pages/Index', ...) 加载首页,与领域无关。这是鸿蒙 Ability 模型的解耦红利:UIAbility 是 UI 的承载壳,壳与内容分离。
1.3 bundleName 与应用名的迁移
AppScope/app.json5 里 bundleName: "com.doubleapp.infoapp" 在迁移后保持不变——bundleName 是应用在鸿蒙应用市场的唯一标识,改了就等于新应用,老用户的安装记录会断。所以领域迁移不动 bundleName,是工程惯用法。
但应用名(用户可见的图标下方文字)必须迁移。app.json5 的 "label": "$string:app_name" 引用字符串资源,AppScope/resources/base/element/string.json 里:
{
"string": [
{ "name": "app_name", "value": "食材保鲜手册" }
]
}
从"车辆保养手册"改为"食材保鲜手册"——用户安装后在桌面看到的图标文字就跟着变了。$string:app_name 这种资源引用让应用名的迁移成本是"改一个 JSON 条目",而不是"改 N 处硬编码"。
二、数据建模的对照迁移
2.1 接口字段语义的整体重命名
「车辆保养手册」的核心数据接口:
interface MaintenanceItem {
name: string // 项目名(如"机油")
category: string // 分类(如"发动机")
intervalKm: number // 里程间隔(公里)
intervalMonth: number // 时间间隔(月)
note: string // 备注
}
interface PartItem {
name: string
category: string
replaceKm: number // 更换里程
replaceMonth: number // 更换月数
replaceTip: string // 更换提示
}
「食材保鲜手册」迁移后:
interface MaintenanceItem {
name: string // 食材名(如"绿叶蔬菜")
category: string // 分类(如"冷藏")
fridgeDays: number // 冷藏天数
freezerDays: number // 冷冻天数
note: string // 备注(保鲜建议)
}
interface PartItem {
name: string
category: string
pantryDays: number // 常温天数
dryDays: number // 干燥天数
replaceTip: string // 保存提示
}
字段语义对照:
| 旧字段 | 新字段 | 语义迁移 |
|---|---|---|
intervalKm |
fridgeDays |
公里 → 冷藏天数 |
intervalMonth |
freezerDays |
月 → 冷冻天数 |
replaceKm |
pantryDays |
公里 → 常温天数 |
replaceMonth |
dryDays |
月 → 干燥天数 |
replaceTip |
replaceTip |
字段名保留,语义从"更换提示"变"保存提示" |
note |
note |
字段名保留,语义从"保养备注"变"保鲜建议" |
注意 replaceTip 和 note 字段名保留但语义变化——这是有意的工程取舍。改字段名要同步改所有引用点(卡片渲染、过滤逻辑),成本高;语义变化只改数据内容,不动代码结构。如果字段名表达的是"抽象的提示/备注"而非"具体的更换/保养",就保留字段名只换语义。
ArkTS 的接口是结构化类型——字段名是编译期约束,改字段名要同步改所有 .field 访问点。本项目里 intervalKm 改成 fridgeDays 涉及的引用点有:数据集定义、getFilteredMaintenance 过滤逻辑、getMaxDays 统计逻辑、MaintenanceCard 渲染逻辑、getBarWidth 调用——共 5 处。两个字段都改就要同步改 10 处,加上 PartItem 的两个字段共 20 处。这种"牵一发动全身"的字段重命名是迁移中最容易出错的部分。
2.2 双数据集的拆分逻辑
应用有两个数据集——MAINTENANCE_DATA 和 PARTS_DATA,分别对应两个 Tab:
| Tab | 数据集 | 接口 | 领域语义(迁移后) |
|---|---|---|---|
| 保鲜周期 | MAINTENANCE_DATA |
MaintenanceItem |
冷藏/冷冻的可控保鲜周期 |
| 常温保存 | PARTS_DATA |
PartItem |
常温/干燥的非控保存时长 |
迁移前这个拆分对应"按里程保养"与"按时间更换"——车辆保养的两种触发维度。迁移后对应"控温保鲜"与"常温保存"——食材保鲜的两种环境策略。语义迁移后这个拆分依然合理:
- 保鲜周期:需要冷藏或冷冻的食材,保鲜时长受温度控制,用户能通过调整存放环境延长保鲜
- 常温保存:不需要冷藏的食材,保存时长由食材本身的含水量、含糖量、含盐量决定,用户只能"避光防潮"不能"控温延长"
这个拆分的领域契合度比车辆保养还好——车辆保养的"里程 vs 时间"是双触发条件(哪个先到按哪个),而食材保鲜的"控温 vs 常温"是双环境策略(不同食材用不同策略),语义更清晰。
2.3 数据集的领域知识注入
迁移不只是字段重命名,还要把食材保鲜的领域知识注入数据内容。这是迁移工程里工作量最大的部分——20 个冷藏食材 + 20 个常温食材,每个都要查保鲜常识填进去。
MAINTENANCE_DATA 节选:
const MAINTENANCE_DATA: MaintenanceItem[] = [
{ name: '绿叶蔬菜(生菜、菠菜)', category: '冷藏', fridgeDays: 5, freezerDays: 180,
note: '清洗后沥干,密封冷藏可延长至一周' },
{ name: '新鲜鸡蛋', category: '冷藏', fridgeDays: 35, freezerDays: 0,
note: '冷藏时大头朝上放置更耐存' },
{ name: '巴氏鲜牛奶', category: '冷藏', fridgeDays: 7, freezerDays: 90,
note: '开封后建议三天内喝完' },
{ name: '豆腐(盒装)', category: '冷藏', fridgeDays: 7, freezerDays: 60,
note: '冷冻后变为冻豆腐,风味独特' },
// ...
]
每条数据承载 5 个领域信息:
- 食材名:常见家庭食材,覆盖蔬果、肉蛋、乳制品、豆制品、主食剩菜等
- 分类:冷藏/冷冻/常温/蔬果——与分类筛选器的 5 个 chip 对齐
- fridgeDays:冷藏室(4°C 左右)的保鲜天数
- freezerDays:冷冻室(-18°C 左右)的保鲜天数,0 表示不耐冷冻
- note:保鲜小贴士,承载领域专家知识(如"苹果释放乙烯,需与其他水果分开")
freezerDays: 0 是个特殊的领域信号——表示该食材不耐冷冻,冷冻会破坏质地(如鸡蛋冷冻后蛋白变稀水状、开封酱料冷冻后油水分离)。这个 0 值在 UI 层触发"不耐冷冻"警示标签,是数据驱动 UI 的典型体现。
PARTS_DATA 节选:
const PARTS_DATA: PartItem[] = [
{ name: '蜂蜜', category: '常温', pantryDays: 1095, dryDays: 1095,
replaceTip: '可长期常温保存,结晶属正常现象' },
{ name: '白糖 / 食盐', category: '常温', pantryDays: 1095, dryDays: 1095,
replaceTip: '理论上可永久保存,需防潮' },
{ name: '罐头(未开封)', category: '常温', pantryDays: 730, dryDays: 730,
replaceTip: '鼓罐、漏液立即弃用' },
// ...
]
pantryDays: 1095(3 年)是个超长保鲜值——蜂蜜、白糖、食盐这类高糖高盐食材理论上可永久保存,但 UI 上要有个数值上限用于进度条渲染,所以取 1095 天(3 年)作为"长期"的具象化表达。
这个 1095 在 PartCard 渲染时影响进度条长度计算:
.width(this.getBarWidth(item.pantryDays, 1095))
getBarWidth(value, 1095) 把食材的 pantryDays 转成相对 1095 的百分比——蜂蜜 1095 天对应 100% 进度条,白糖 1095 天对应 100%,大米 365 天对应 33%。这个 max 值的选择直接影响视觉对比:
| max 值 | 蜂蜜 1095d | 大米 365d | 食盐 1095d | 视觉效果 |
|---|---|---|---|---|
| 365 | 100%(截断) | 100% | 100%(截断) | 都满条,看不出差异 |
| 730 | 100%(截断) | 50% | 100%(截断) | 蜂蜜食盐满,大米半 |
| 1095 | 100% | 33% | 100% | 蜂蜜食盐满,大米三分之一 |
取 1095 让"超长保存"的食材(蜂蜜、白糖、食盐、罐头、料酒)都是满条,“中等保存”(大米、面粉、干货)是三分之一到半条,“短期常温”(饼干、坚果)是短条。这个视觉对比符合用户对"哪些能久存"的认知直觉。
2.4 数据集大小的工程取舍
迁移时数据集大小(每集 20 条)是有意的工程取舍:
| 数据量 | 视觉效果 | 工程代价 |
|---|---|---|
| 10 条 | 列表太短,一屏就看完,进度条对比不明显 | 数据采集少 |
| 20 条 | 滚动 2-3 屏,分类筛选后约 5-10 条,对比充分 | 数据采集中等 |
| 50 条 | 滚动 5-7 屏,分类筛选后仍 10+ 条,信息过载 | 数据采集多 |
20 条是"信息密度适中 + 横向对比充分"的甜点。每张卡片高度约 140vp,20 条总高 2800vp,在 360vp 窄屏上滚动约 8 屏——但实际上分类筛选后通常只剩 5-8 条,1-2 屏就看完了,滚动压力不大。
ArkTS 的静态数据集用 const + 数组字面量定义,编译后是单例常量,没有运行时开销。20 条 × 5 字段 = 100 个字段值的常量数据,内存占用 KB 级,对鸿蒙应用毫无压力。
三、ArkTS 类型系统在迁移中的约束
3.1 interface 的结构化类型校验
ArkTS 的 interface 是结构化类型——数据字面量必须严格匹配接口定义的字段名和类型,多一个字段、少一个字段、类型不符都会编译失败。
迁移时 MaintenanceItem 从 4 个字段变 4 个字段(intervalKm → fridgeDays、intervalMonth → freezerDays),数据集 20 条每条都要同步改字段名。如果漏改一条——例如第 15 条还保留 intervalKm: 5000——ArkTS 编译器会报错:
error: Object literal must correspond to a known interface type.
这种严格校验是 ArkTS 相对 JavaScript 的核心增益——JS 里接口是鸭子类型,漏改字段名运行时才暴露为 undefined,调试成本高;ArkTS 编译期就卡住,迁移正确性有保障。
3.2 Record<string, string> 的分类色映射
const CATEGORY_COLORS: Record<string, string> = {
'冷藏': '#3D8FA8',
'冷冻': '#6FAEDB',
'常温': '#D4A04C',
'蔬果': '#6FAE3C'
}
Record<string, string> 是 ArkTS 的索引签名类型——键是 string、值是 string 的映射表。迁移时分类从"发动机/底盘/电气/车身"改为"冷藏/冷冻/常温/蔬果",键名全换。
注意分类名与数据集的 category 字段必须严格一致——如果数据集里某条的 category: '冷藏' 但 CATEGORY_COLORS 里键是 '冷藏 '(多一个空格),运行时 CATEGORY_COLORS[item.category] 返回 undefined,色条渲染会失败(ArkUI 的 .backgroundColor(undefined) 会用默认色)。
迁移时这种"键名一致性"靠人工核对——ArkTS 的 Record 类型不会校验键名是否存在于某个集合,因为键是开放 string。如果想编译期校验,可以改成枚举:
enum Category { Fridge, Freezer, Pantry, Vegetable }
const CATEGORY_COLORS: Record<Category, string> = { ... }
但本项目没用枚举,理由是:
- 数据字面量要用字符串分类名:
category: '冷藏'比category: Category.Fridge更贴近领域语义(中文分类名直接可读) - 分类筛选 chip 列也要用字符串:
private categories: string[] = ['全部', '冷藏', '冷冻', '常温', '蔬果'],枚举要拆成字符串数组反而绕 - 自由度:未来加新分类(如"熟食")只改数据集和映射表,不动枚举定义
这是"类型严格性 vs 领域可读性"的取舍——本项目选可读性,代价是键名一致性靠人工保证。
3.3 private 方法的类型标注
private getFilteredMaintenance(): MaintenanceItem[] {
if (this.activeCategory === '全部') {
return MAINTENANCE_DATA
}
return MAINTENANCE_DATA.filter((item: MaintenanceItem) => item.category === this.activeCategory)
}
迁移时这类过滤方法的逻辑完全不动——item.category === this.activeCategory 的语义是"分类等于选中分类",与领域无关(车辆保养也按分类过滤、食材保鲜也按分类过滤)。只改返回类型 MaintenanceItem[](接口名没变所以不用改)和内部数据集引用(MAINTENANCE_DATA 名没变所以不用改)。
ArkTS 的 private 方法在 struct 内部可见,迁移时这种"领域无关的通用逻辑"是迁移成本最低的部分——零改动。这也印证了"UI 骨架与数据解耦"的设计价值:解耦越彻底,迁移成本越低。
3.4 @State 与 @Builder 的迁移影响
@State currentTab: number = 0
@State activeCategory: string = '全部'
两个 @State 在迁移中零改动——currentTab(当前 Tab 索引)和 activeCategory(当前选中分类)都是 UI 交互状态,与领域无关。鸿蒙的 @State 是响应式状态装饰器,值变化时自动触发依赖该状态的 UI 重新渲染。迁移不动 @State 意味着响应式行为不变——点击 Tab 切换、点击分类筛选的反应逻辑完全复用。
@Builder 方法(MaintenanceCard、PartCard、LegendDot)在迁移中要改内部渲染的字段引用(item.intervalKm → item.fridgeDays),但 Builder 的结构骨架(Row + Column 的布局)不动。@Builder 是 ArkUI 的 UI 复用单元,相当于"渲染函数"——参数传入数据,内部渲染 UI。骨架稳定 + 数据字段重命名,是 Builder 在迁移中的典型工作模式。
四、保鲜常识的领域知识注入细节
4.1 冷藏天数的领域依据
每条数据的 fridgeDays 不是拍脑袋填的,而是依据食材保鲜常识:
| 食材 | fridgeDays | 依据 |
|---|---|---|
| 绿叶蔬菜 | 5 | 叶片薄含水量高,5 天后黄化 |
| 西兰花 | 7 | 花球结构较密,一周仍脆 |
| 番茄 | 7 | 未熟常温催熟,熟后 7 天风味最佳 |
| 鸡蛋 | 35 | 大头朝上摆放,气室稳定,5 周仍新鲜 |
| 鲜牛奶 | 7 | 巴氏杀菌后冷藏 7 天,开封后 3 天最佳 |
| 新鲜鱼类 | 2 | 蛋白质易分解,铺冰冷藏 2 天是极限 |
| 豆腐 | 7 | 盒装未开封 7 天,开封后浸泡清水延长 |
| 草莓 | 5 | 浆果类易霉,5 天后霉斑出现 |
这些数值是迁移时查保鲜常识资料填的——不是写代码的工程任务,是查资料的领域任务。迁移工程的工作量分配往往是"代码改动 30% + 数据采集 70%",因为数据才是领域迁移的本质内容。
4.2 冷冻天数与不耐冷冻的领域信号
freezerDays 的领域逻辑比 fridgeDays 复杂——不是所有食材都能冷冻:
| 食材 | freezerDays | 冷冻行为 |
|---|---|---|
| 西兰花 | 365 | 焯水后冷冻可一年 |
| 鸡蛋 | 0 | 不耐冷冻(蛋白变稀水状) |
| 鲜牛奶 | 90 | 可冷冻但解冻后水油分离 |
| 豆腐 | 60 | 冷冻成冻豆腐,风味独特(不算"坏") |
| 酱料(开封) | 0 | 不耐冷冻(油水分离) |
| 果汁(鲜榨) | 90 | 可冷冻但维 C 流失 |
freezerDays: 0 不是"冷冻 0 天"的字面意义,而是"不建议冷冻"的领域信号。这个 0 值在 UI 层触发两个行为:
getMaxDays统计最长天数时,0 不影响 Math.max 的结果(除非全是 0)MaintenanceCard渲染时,item.freezerDays === 0走"不耐冷冻"警示标签分支,不显示冷冻天数数值
这是数据驱动 UI 的典型体现——同一个字段(freezerDays)的值(0 vs 非 0)决定 UI 的不同渲染分支,UI 不需要额外的"是否耐冷冻"布尔字段,0 值就承载了这个语义。
4.3 保鲜贴士的领域知识浓缩
note 字段是保鲜小贴士,每条 10-20 字浓缩一条保鲜常识:
- “清洗后沥干,密封冷藏可延长至一周” — 流程性建议
- “冷藏时大头朝上放置更耐存” — 摆放方式建议
- “苹果释放乙烯,需与其他水果分开” — 化学相互作用警告
- “分装冷冻避免反复解冻” — 操作方式建议
- “冷藏超三天口感下降,建议分装冷冻” — 阈值警告
这些贴士是迁移时从保鲜常识资料里提炼的"一句话精华"——不能太长(卡片备注区空间有限),不能太短(要传达可操作的建议),不能太抽象(要具体到"大头朝上"这种可执行动作)。每条贴士的写作成本比填数值高,因为要"浓缩 + 可执行"。
4.4 常温保存提示的领域侧重
PARTS_DATA 的 replaceTip 字段语义从"更换提示"迁移为"保存提示",内容侧重也不同:
- 车辆保养的 replaceTip 侧重"何时该换"(如"3 万公里必换")
- 食材保鲜的 replaceTip 侧重"如何存放"(如"密封防潮可保存一年以上")
这个语义迁移让 replaceTip 的内容模式从"时间触发"变成"操作建议"——更贴近食材保鲜的"主动操作"语境(用户主动密封防潮),而非车辆保养的"被动更换"语境(里程到了必须换)。
五、迁移工程的验证闭环
5.1 编译期验证
迁移后第一步是 ArkTS 编译:
hvigorw assembleHap
编译期会校验:
- 接口字段名一致性(数据字面量 vs 接口定义)
- 字段访问点一致性(
.fridgeDaysvs 接口定义的fridgeDays) - 类型一致性(
numbervsstring不混用)
迁移时最容易遗漏的是"某条数据还保留旧字段名"——编译器会报"Object literal must correspond to a known interface type",逐条核对即可定位。
5.2 资源引用的验证
迁移后 Index.ets 里所有 $r('app.color.xxx') 和 $r('app.string.xxx') 的引用,对应的资源条目必须在 color.json 或 string.json 里存在。鸿蒙的资源系统在编译期校验资源名——如果引用了不存在的资源名,编译失败报"resource not found"。
迁移时如果只改了 Index.ets 而忘了同步 color.json(例如新加了一个颜色引用),编译期会卡住。这个校验是鸿蒙资源系统的安全网。
5.3 运行期验证
编译通过后是真机运行验证:
- 双 Tab 切换是否正常(保鲜周期 vs 常温保存)
- 分类筛选是否正常(全部 / 冷藏 / 冷冻 / 常温 / 蔬果)
- 卡片渲染是否正常(字段值正确显示)
- 进度条长度是否合理(基于新的 max 值)
- "不耐冷冻"警示是否在 freezerDays=0 的食材卡片显示
运行期验证靠人工浏览——这种没有单元测试的工具型应用,迁移后的烟雾测试靠"每个 Tab × 每个分类 × 每张卡片"的网格化核对。20+20 条数据 × 5 个分类 × 2 个 Tab = 200 个核对点,实际不需要全核对,抽查每个分类的几条即可。
六、迁移工程的工程哲学
6.1 领域无关 vs 领域相关的边界
迁移工程的核心认知是"领域无关 vs 领域相关"的边界划分:
| 层次 | 领域无关 | 领域相关 |
|---|---|---|
| UI 骨架 | Tab 栏、分类筛选、卡片列表、进度条 | 无 |
| 色彩 | 无 | 主色、分类色、强调色 |
| 数据 | 无 | 数据集内容、字段语义 |
| 字符串 | 无 | 用户可见文案 |
| 交互逻辑 | Tab 切换、分类筛选过滤、进度条计算 | 无 |
| 渲染逻辑 | 卡片布局骨架 | 字段值显示、警示分支 |
这个边界划分让迁移的"改动面"集中——领域相关的部分全改,领域无关的部分不动。ArkUI 的声明式 UI 让这个边界格外清晰:build() 方法里的 UI 骨架是领域无关的"形",ForEach 渲染的数据和 @Builder 内的字段访问是领域相关的"内容"。
6.2 数据驱动 UI 的迁移红利
迁移能控制在"重命名 + 数据替换"范围内的根本原因是应用采用了"数据驱动 UI"的架构:
- UI 骨架(
build()+@Builder)是"渲染引擎",渲染什么取决于数据 - 数据集(
MAINTENANCE_DATA+PARTS_DATA)是"内容仓库",换内容不动引擎
这种架构让迁移成本 = 数据采集成本 + 字段重命名成本,而不是 UI 重写成本。如果应用是"硬编码 UI"(每条数据写一个独立的 Column() { Text('机油') ... }),迁移就要逐条重写 UI,成本天文数字。
数据驱动 UI 是鸿蒙 ArkUI 倡导的设计范式——ForEach + 数据集 + @Builder 的三件套是这个范式的标准实现。迁移工程的顺畅度是验证这个范式是否贯彻的试金石。
6.3 字段语义 vs 字段名的分离
迁移时 replaceTip 和 note 字段名保留但语义变化,体现的是"字段名表达抽象语义、字段值表达具体语义"的工程惯用法:
replaceTip字段名表达"替换/保存的提示"这个抽象语义- 字段值从"3 万公里必换"变"密封防潮可保存一年"是具体语义变化
如果字段名表达的是具体语义(如 replaceKmTip “更换里程提示”),迁移到食材保鲜就要改字段名(如 pantryTip “常温保存提示”),改动面扩大。
所以接口字段命名的最佳实践是"抽象到领域无关的层次"——note、tip、category、name 这类字段名在任何领域都通用,迁移时不用改字段名只改内容。这是接口设计的"领域无关命名"原则。
七、本篇小结
本章从项目重构的起点讲到迁移工程的验证闭环,完整覆盖了「食材保鲜手册」从「车辆保养手册」整体迁移的工程过程。关键点归纳:
- 领域迁移而非 UI 重写:UI 骨架领域无关,数据色彩领域相关,边界划分让迁移成本可控
- 字段语义重命名:
intervalKm→fridgeDays、replaceKm→pantryDays,字段名跟随领域语义 - 双数据集拆分对齐:保鲜周期 vs 常温保存,对应车辆保养的里程 vs 时间,语义迁移更清晰
- 领域知识注入:每条数据的保鲜天数和贴士浓缩保鲜常识,是迁移工程的主要工作量
- ArkTS 类型系统保障:interface 结构化校验、资源引用编译期校验,让迁移正确性有编译期保障
- 数据驱动 UI 的迁移红利:ForEach + 数据集 + @Builder 三件套让迁移成本 = 数据采集 + 字段重命名
八、附录:本篇涉及的迁移映射表
8.1 接口字段迁移
| 旧字段(车辆) | 新字段(食材) | 类型 | 语义 |
|---|---|---|---|
intervalKm |
fridgeDays |
number | 公里 → 冷藏天数 |
intervalMonth |
freezerDays |
number | 月 → 冷冻天数 |
replaceKm |
pantryDays |
number | 公里 → 常温天数 |
replaceMonth |
dryDays |
number | 月 → 干燥天数 |
replaceTip |
replaceTip |
string | 字段名保留,语义迁移 |
note |
note |
string | 字段名保留,语义迁移 |
8.2 分类迁移
| 旧分类(车辆) | 新分类(食材) | 旧色 | 新色 |
|---|---|---|---|
| 发动机 | 冷藏 | #1F6FEB |
#3D8FA8 |
| 底盘 | 冷冻 | #FF8C1A |
#6FAEDB |
| 电气 | 常温 | #16A34A |
#D4A04C |
| 车身 | 蔬果 | #9333EA |
#6FAE3C |
8.3 字符串资源迁移
| 旧值(车辆) | 新值(食材) | 资源名 |
|---|---|---|
| 车辆保养手册 | 食材保鲜手册 | app_name |
至此完整覆盖了「食材保鲜手册」从「车辆保养手册」整体重构的工程过程。下篇将从 ArkUI 双 Tab 与保鲜周期可视化的布局实现继续展开。
更多推荐

所有评论(0)