鸿蒙原生应用实战五塔罗牌App开发 — 数据模型、构建配置与工程优化前言经过前四篇的逐步开发我们已经完成了塔罗牌 App 的所有功能页面。本篇作为收官之作将聚焦于那些看不见但至关重要的部分TarotData 全量数据模型78 张塔罗牌的数据结构设计与内容填充资源文件管理string / float / color 资源的定义与引用构建配置解析build-profile / hvigor / module.json5 配置详解API 版本适配compatibleSdkVersion 与 targetSdkVersion 的策略ArkTS 严格模式规则常见编译错误及解决方案工程构建与发布从代码到 HAP 包的完整流程一、TarotData 数据模型深度解析1.1 数据结构设计塔罗牌分为两大类大阿卡纳Major Arcana22 张编号 0-XXI代表重大人生课题小阿卡纳Minor Arcana56 张分四花色 × 14 张代表日常事务exportinterfaceTarotCard{id:number;// 唯一标识0-77name:string;// 中文名称如愚者魔术师englishName:string;// 英文名称如The FoolThe Magicianarcana:string;// 分类大阿卡纳 或 小阿卡纳number:string;// 编号如0、I、权杖一keywords:string;// 关键词如开始、冒险、天真meaningUp:string;// 正位含义meaningDown:string;// 逆位含义description:string;// 牌面描述color:string;// 显示颜色十六进制isFavorite:boolean;// 收藏状态未使用保留字段}1.2 大阿卡纳数据示例以下是部分大阿卡纳牌的数据共 22 张编号 0-XXIexportconstTAROT_CARDS:TarotCard[][{id:0,name:愚者,englishName:The Fool,arcana:大阿卡纳,number:0,keywords:开始、冒险、天真、无限可能,meaningUp:愚者正位象征着全新的开始、天真的冒险精神和对未知的期待。这张牌鼓励你放下过去的包袱勇敢地踏上新的旅程。它代表着一个充满可能性的新阶段提醒你保持开放的心态和对世界的好奇心。,meaningDown:愚者逆位暗示着鲁莽、不负责任的决策或对后果的忽视。你可能在逃避责任或者在某个重要决定上过于草率。这张牌提醒你需要三思而后行避免因冲动而后悔。,description:愚者站在悬崖边缘背上背着一个行囊手中握着一朵白玫瑰仰望天空。他即将迈出脚步却完全不在意前方的危险。身边的小狗在吠叫试图提醒他注意。画面中明亮的黄色背景象征着新的开始和无限的可能性。,color:#F5E642,isFavorite:false},{id:1,name:魔术师,englishName:The Magician,arcana:大阿卡纳,number:I,keywords:创造力、技能、资源、显化,meaningUp:魔术师正位代表着你有能力将想法转化为现实。你拥有所需的一切资源和技能只需要善加运用。这张牌鼓励你相信自己的能力主动采取行动去创造你想要的现实。,meaningDown:魔术师逆位暗示着才能被浪费、操控他人或缺乏方向。你可能没有充分利用自己的天赋或者正在用不正当的手段达到目的。需要重新审视自己的动机和方法。,description:魔术师站在桌前一只手举向天空接收能量另一只手指向大地象征着如上如下的宇宙法则。桌上摆放着四大元素的象征物——圣杯、宝剑、星币和权杖。他头上有无限符号代表着无限的潜力。,color:#E8B832,isFavorite:false},// ... 共 78 张牌];1.3 数据填充的工程化思考为 78 张牌填写完整的中英文含义是一项大工程。在实际项目中我有几点建议结构化优先先确定接口字段再填充数据分批填充按大阿卡纳22 张→ 权杖组14 张→ 圣杯组14 张→ 宝剑组14 张→ 星币组14 张分批完成释义长度控制正逆位释义各保持在 100-150 字之间过长会影响阅读体验颜色编码为每张牌分配一个辨识色增加视觉层次感二、资源文件管理2.1 字符串资源// resources/base/element/string.json{string:[{name:title_home,value:命运之轮},{name:title_cards,value:全部牌义},{name:title_spread,value:牌阵解读},{name:title_favorites,value:我的收藏},{name:today_card,value:今日塔罗},{name:module_desc,value:塔罗牌占卜应用},{name:EntryAbility_desc,value:塔罗牌主入口},{name:EntryAbility_label,value:命运之轮}]}2.2 浮点尺寸资源// resources/base/element/float.json{float:[{name:app_title_size,value:28fp},{name:app_subtitle_size,value:22fp},{name:app_body_size,value:16fp},{name:app_small_size,value:14fp},{name:app_caption_size,value:12fp},{name:app_card_radius,value:16vp},{name:app_button_radius,value:24vp}]}2.3 颜色资源// resources/base/element/color.json{color:[{name:start_window_background,value:#1A0A2E},{name:primary_text,value:#FFFFFF},{name:secondary_text,value:#B8A8D0}]}为什么使用$r()引用资源支持多语言适配国际化支持多设备适配不同 dpi 自动缩放编译时校验避免硬编码错误三、构建配置解析3.1 项目级 build-profile.json5{ app: { signingConfigs: [], products: [ { name: default, signingConfig: default, targetSdkVersion: 6.1.1(24), // 目标 SDK compatibleSdkVersion: 6.1.0(23), // 兼容最低版本 runtimeOS: HarmonyOS, buildOption: { strictMode: { caseSensitiveCheck: true, // 大小写检查 useNormalizedOHMUrl: true // 归一化 OHM URL } } } ], buildModeSet: [ { name: debug }, { name: release } ] } }API 版本策略解读参数值含义compatibleSdkVersion23最低支持 API 23 的设备targetSdkVersion24最高使用 API 24 的特性runtimeOSHarmonyOS仅运行在 HarmonyOS 上3.2 模块级 build-profile.json5{ apiType: stageMode, // Stage 模型 buildOption: { resOptions: { copyCodeResource: { enable: false // 不复制代码资源 } } }, buildOptionSet: [ { name: release, arkOptions: { obfuscation: { // 代码混淆配置 ruleOptions: { enable: false, // 可开启以减小包体 files: [./obfuscation-rules.txt] } } } } ] }3.3 AppScope/app.json5 — 全局应用配置{ app: { bundleName: com.example.myapplication, // 包名全局唯一 vendor: example, versionCode: 1000000, // 内部版本号 versionName: 1.0.0, // 对外版本名 icon: $media:layered_image, label: $string:app_name // 应用名称仅在 AppScope 定义一次 } }注意app_name只需在AppScope的string.json中定义一次不可在entry模块中重复定义否则编译会报冲突。3.4 module.json5 — 模块配置{ module: { name: entry, type: entry, // entry 类型可独立运行 mainElement: EntryAbility, deviceTypes: [phone], deliveryWithInstall: true, installationFree: false, pages: $profile:main_pages, // 路由配置引用 abilities: [ { name: EntryAbility, srcEntry: ./ets/entryability/EntryAbility.ets, exported: true, skills: [ { entities: [entity.system.home], actions: [ohos.want.action.home] } ] } ] } }关键字段解释type: entry可独立安装运行的应用入口模块skills声明 Ability 的能力entity.system.homeohos.want.action.home表明这是桌面入口pages引用main_pages.json中注册的所有页面路由四、ArkTS 严格模式规则详解在开发过程中严格模式arkts-no-untyped-obj-literals等是误报最多的配置。以下是完整的规则及应对方案4.1 规则清单规则含义触发场景arkts-no-untyped-obj-literals对象字面量必须显式类型const obj {a:1, b:2}arkts-no-noninferrable-arr-literals数组字面量必须可推断类型const arr [{a:1, b:2}]arkts-no-nullable-array不允许可空数组类型arr?: string[]arkts-no-any不允许 any 类型let x: anyarkts-no-eval不允许 evaleval(code)4.2 实战解决方案方案一提取为具名变量// ❌ 错误字面量数组无法推断// ForEach(this.drawnCards, (item: NumberedCard) { ... })// ✅ 正确显式声明后使用constpositions[过去,现在,未来];方案二对象赋值使用类型断言// ❌ 可能的不严格写法constcard{id:0,name:愚者};// ✅ 显式声明类型constcard:TarotCard{id:0,name:愚者,englishName:,arcana:,// 全部字段number:,keywords:,meaningUp:,meaningDown:,description:,color:#FFF,isFavorite:false};方案三Component 属性必须初始化Componentstruct MyComponent{// ✅ 所有属性必须赋默认值name:string;count:number0;items:string[][];callback?:()void;// 可选属性用 ?}4.3 编译错误排查技巧当 DevEco Studio 报编译错误时按以下步骤排查看错误码arkts-no-xxx的格式直接表明违反的规则定位行号大多数错误会精确到行检查字面量70% 的错误是对象/数组字面量缺少类型声明检查类型组件属性、函数参数是否都有明确类型五、构建与发布流程5.1 本地构建命令# 使用 DevEco Studio 内置的 hvigor 构建D:\DevEco Studio\tools\node\node.exe\D:\DevEco Studio\tools\hvigor\bin\hvigorw.js\--modemodule\-pmoduleentrydefault\-pproductdefault\-prequiredDeviceTypephone\assembleHap\--analyzenormal\--parallel\--incremental\--daemon参数解读参数含义--mode module模块级构建-p moduleentrydefault构建 entry 模块的 default 产品assembleHap打包为 HAP 文件--parallel并行构建加速--incremental增量编译--daemon守护进程模式5.2 构建产物构建完成后HAP 包位于entry/build/default/outputs/default/entry-default-unsigned.hap5.3 签名与发布在 DevEco Studio 中配置签名证书.p12.cer.p7b使用build→Build HAP(s)生成已签名的 HAP上传至华为应用市场 AppGallery Connect六、项目经验总结6.1 架构回顾经过五篇文章的开发我们的塔罗牌 App 形成了清晰的架构分层┌─────────────────────────┐ │ UI 层 (pages/) │ ← 5 个页面 ├─────────────────────────┤ │ 模型层 (model/) │ ← TarotData 数据 管理器 ├─────────────────────────┤ │ 能力层 (ability/) │ ← EntryAbility 入口 ├─────────────────────────┤ │ 配置层 (config/) │ ← build / module / resources └─────────────────────────┘6.2 关键技术决策决策选择理由开发模型Stage 模型官方推荐适合复杂应用开发语言ArkTS类型安全编译期校验状态管理静态类管理器轻量、无第三方依赖主题切换订阅发布模式解耦、可扩展路由导入ohos.routerAPI 23 兼容性6.3 后续可扩展方向数据持久化Preferences 存储收藏数据网络请求对接塔罗牌 API 获取每日运势动画效果抽牌翻转动画、卡片入场动画自定义牌阵用户自由选择牌数和位置多语言支持英文版、日文版国际化Widget 服务卡片桌面显示今日塔罗结语五篇文章从环境搭建到发布上线我们完整地走了一遍鸿蒙原生应用的开发流程。这个塔罗牌 App 虽小但五脏俱全——路由导航、列表渲染、组件化、状态管理、主题切换、构建配置覆盖了日常开发中的大多数场景。鸿蒙生态正在快速发展现在入局正当时。希望这个系列能成为你鸿蒙开发路上的实战参考。如果你有任何问题或想法欢迎在评论区交流讨论项目代码: 基于 HarmonyOS API 23 Stage 模型 ArkTS源码位置:entry/src/main/ets/构建工具: DevEco Studio hvigor全文完附录本系列目录篇号标题核心内容第一篇环境搭建与首页开发项目初始化、Stage 模型、Index 首页第二篇牌义列表与路由导航CardListPage、CardDetailPage、路由传参第三篇牌阵解读与交互设计SpreadPage、随机算法、正逆位判定第四篇收藏功能与主题切换FavoriteManager、ThemeManager、FavPage第五篇数据模型与工程优化TarotData、构建配置、严格模式、发布流程
鸿蒙原生应用实战(五):塔罗牌App开发 — 数据模型、构建配置与工程优化
发布时间:2026/6/15 6:47:54
鸿蒙原生应用实战五塔罗牌App开发 — 数据模型、构建配置与工程优化前言经过前四篇的逐步开发我们已经完成了塔罗牌 App 的所有功能页面。本篇作为收官之作将聚焦于那些看不见但至关重要的部分TarotData 全量数据模型78 张塔罗牌的数据结构设计与内容填充资源文件管理string / float / color 资源的定义与引用构建配置解析build-profile / hvigor / module.json5 配置详解API 版本适配compatibleSdkVersion 与 targetSdkVersion 的策略ArkTS 严格模式规则常见编译错误及解决方案工程构建与发布从代码到 HAP 包的完整流程一、TarotData 数据模型深度解析1.1 数据结构设计塔罗牌分为两大类大阿卡纳Major Arcana22 张编号 0-XXI代表重大人生课题小阿卡纳Minor Arcana56 张分四花色 × 14 张代表日常事务exportinterfaceTarotCard{id:number;// 唯一标识0-77name:string;// 中文名称如愚者魔术师englishName:string;// 英文名称如The FoolThe Magicianarcana:string;// 分类大阿卡纳 或 小阿卡纳number:string;// 编号如0、I、权杖一keywords:string;// 关键词如开始、冒险、天真meaningUp:string;// 正位含义meaningDown:string;// 逆位含义description:string;// 牌面描述color:string;// 显示颜色十六进制isFavorite:boolean;// 收藏状态未使用保留字段}1.2 大阿卡纳数据示例以下是部分大阿卡纳牌的数据共 22 张编号 0-XXIexportconstTAROT_CARDS:TarotCard[][{id:0,name:愚者,englishName:The Fool,arcana:大阿卡纳,number:0,keywords:开始、冒险、天真、无限可能,meaningUp:愚者正位象征着全新的开始、天真的冒险精神和对未知的期待。这张牌鼓励你放下过去的包袱勇敢地踏上新的旅程。它代表着一个充满可能性的新阶段提醒你保持开放的心态和对世界的好奇心。,meaningDown:愚者逆位暗示着鲁莽、不负责任的决策或对后果的忽视。你可能在逃避责任或者在某个重要决定上过于草率。这张牌提醒你需要三思而后行避免因冲动而后悔。,description:愚者站在悬崖边缘背上背着一个行囊手中握着一朵白玫瑰仰望天空。他即将迈出脚步却完全不在意前方的危险。身边的小狗在吠叫试图提醒他注意。画面中明亮的黄色背景象征着新的开始和无限的可能性。,color:#F5E642,isFavorite:false},{id:1,name:魔术师,englishName:The Magician,arcana:大阿卡纳,number:I,keywords:创造力、技能、资源、显化,meaningUp:魔术师正位代表着你有能力将想法转化为现实。你拥有所需的一切资源和技能只需要善加运用。这张牌鼓励你相信自己的能力主动采取行动去创造你想要的现实。,meaningDown:魔术师逆位暗示着才能被浪费、操控他人或缺乏方向。你可能没有充分利用自己的天赋或者正在用不正当的手段达到目的。需要重新审视自己的动机和方法。,description:魔术师站在桌前一只手举向天空接收能量另一只手指向大地象征着如上如下的宇宙法则。桌上摆放着四大元素的象征物——圣杯、宝剑、星币和权杖。他头上有无限符号代表着无限的潜力。,color:#E8B832,isFavorite:false},// ... 共 78 张牌];1.3 数据填充的工程化思考为 78 张牌填写完整的中英文含义是一项大工程。在实际项目中我有几点建议结构化优先先确定接口字段再填充数据分批填充按大阿卡纳22 张→ 权杖组14 张→ 圣杯组14 张→ 宝剑组14 张→ 星币组14 张分批完成释义长度控制正逆位释义各保持在 100-150 字之间过长会影响阅读体验颜色编码为每张牌分配一个辨识色增加视觉层次感二、资源文件管理2.1 字符串资源// resources/base/element/string.json{string:[{name:title_home,value:命运之轮},{name:title_cards,value:全部牌义},{name:title_spread,value:牌阵解读},{name:title_favorites,value:我的收藏},{name:today_card,value:今日塔罗},{name:module_desc,value:塔罗牌占卜应用},{name:EntryAbility_desc,value:塔罗牌主入口},{name:EntryAbility_label,value:命运之轮}]}2.2 浮点尺寸资源// resources/base/element/float.json{float:[{name:app_title_size,value:28fp},{name:app_subtitle_size,value:22fp},{name:app_body_size,value:16fp},{name:app_small_size,value:14fp},{name:app_caption_size,value:12fp},{name:app_card_radius,value:16vp},{name:app_button_radius,value:24vp}]}2.3 颜色资源// resources/base/element/color.json{color:[{name:start_window_background,value:#1A0A2E},{name:primary_text,value:#FFFFFF},{name:secondary_text,value:#B8A8D0}]}为什么使用$r()引用资源支持多语言适配国际化支持多设备适配不同 dpi 自动缩放编译时校验避免硬编码错误三、构建配置解析3.1 项目级 build-profile.json5{ app: { signingConfigs: [], products: [ { name: default, signingConfig: default, targetSdkVersion: 6.1.1(24), // 目标 SDK compatibleSdkVersion: 6.1.0(23), // 兼容最低版本 runtimeOS: HarmonyOS, buildOption: { strictMode: { caseSensitiveCheck: true, // 大小写检查 useNormalizedOHMUrl: true // 归一化 OHM URL } } } ], buildModeSet: [ { name: debug }, { name: release } ] } }API 版本策略解读参数值含义compatibleSdkVersion23最低支持 API 23 的设备targetSdkVersion24最高使用 API 24 的特性runtimeOSHarmonyOS仅运行在 HarmonyOS 上3.2 模块级 build-profile.json5{ apiType: stageMode, // Stage 模型 buildOption: { resOptions: { copyCodeResource: { enable: false // 不复制代码资源 } } }, buildOptionSet: [ { name: release, arkOptions: { obfuscation: { // 代码混淆配置 ruleOptions: { enable: false, // 可开启以减小包体 files: [./obfuscation-rules.txt] } } } } ] }3.3 AppScope/app.json5 — 全局应用配置{ app: { bundleName: com.example.myapplication, // 包名全局唯一 vendor: example, versionCode: 1000000, // 内部版本号 versionName: 1.0.0, // 对外版本名 icon: $media:layered_image, label: $string:app_name // 应用名称仅在 AppScope 定义一次 } }注意app_name只需在AppScope的string.json中定义一次不可在entry模块中重复定义否则编译会报冲突。3.4 module.json5 — 模块配置{ module: { name: entry, type: entry, // entry 类型可独立运行 mainElement: EntryAbility, deviceTypes: [phone], deliveryWithInstall: true, installationFree: false, pages: $profile:main_pages, // 路由配置引用 abilities: [ { name: EntryAbility, srcEntry: ./ets/entryability/EntryAbility.ets, exported: true, skills: [ { entities: [entity.system.home], actions: [ohos.want.action.home] } ] } ] } }关键字段解释type: entry可独立安装运行的应用入口模块skills声明 Ability 的能力entity.system.homeohos.want.action.home表明这是桌面入口pages引用main_pages.json中注册的所有页面路由四、ArkTS 严格模式规则详解在开发过程中严格模式arkts-no-untyped-obj-literals等是误报最多的配置。以下是完整的规则及应对方案4.1 规则清单规则含义触发场景arkts-no-untyped-obj-literals对象字面量必须显式类型const obj {a:1, b:2}arkts-no-noninferrable-arr-literals数组字面量必须可推断类型const arr [{a:1, b:2}]arkts-no-nullable-array不允许可空数组类型arr?: string[]arkts-no-any不允许 any 类型let x: anyarkts-no-eval不允许 evaleval(code)4.2 实战解决方案方案一提取为具名变量// ❌ 错误字面量数组无法推断// ForEach(this.drawnCards, (item: NumberedCard) { ... })// ✅ 正确显式声明后使用constpositions[过去,现在,未来];方案二对象赋值使用类型断言// ❌ 可能的不严格写法constcard{id:0,name:愚者};// ✅ 显式声明类型constcard:TarotCard{id:0,name:愚者,englishName:,arcana:,// 全部字段number:,keywords:,meaningUp:,meaningDown:,description:,color:#FFF,isFavorite:false};方案三Component 属性必须初始化Componentstruct MyComponent{// ✅ 所有属性必须赋默认值name:string;count:number0;items:string[][];callback?:()void;// 可选属性用 ?}4.3 编译错误排查技巧当 DevEco Studio 报编译错误时按以下步骤排查看错误码arkts-no-xxx的格式直接表明违反的规则定位行号大多数错误会精确到行检查字面量70% 的错误是对象/数组字面量缺少类型声明检查类型组件属性、函数参数是否都有明确类型五、构建与发布流程5.1 本地构建命令# 使用 DevEco Studio 内置的 hvigor 构建D:\DevEco Studio\tools\node\node.exe\D:\DevEco Studio\tools\hvigor\bin\hvigorw.js\--modemodule\-pmoduleentrydefault\-pproductdefault\-prequiredDeviceTypephone\assembleHap\--analyzenormal\--parallel\--incremental\--daemon参数解读参数含义--mode module模块级构建-p moduleentrydefault构建 entry 模块的 default 产品assembleHap打包为 HAP 文件--parallel并行构建加速--incremental增量编译--daemon守护进程模式5.2 构建产物构建完成后HAP 包位于entry/build/default/outputs/default/entry-default-unsigned.hap5.3 签名与发布在 DevEco Studio 中配置签名证书.p12.cer.p7b使用build→Build HAP(s)生成已签名的 HAP上传至华为应用市场 AppGallery Connect六、项目经验总结6.1 架构回顾经过五篇文章的开发我们的塔罗牌 App 形成了清晰的架构分层┌─────────────────────────┐ │ UI 层 (pages/) │ ← 5 个页面 ├─────────────────────────┤ │ 模型层 (model/) │ ← TarotData 数据 管理器 ├─────────────────────────┤ │ 能力层 (ability/) │ ← EntryAbility 入口 ├─────────────────────────┤ │ 配置层 (config/) │ ← build / module / resources └─────────────────────────┘6.2 关键技术决策决策选择理由开发模型Stage 模型官方推荐适合复杂应用开发语言ArkTS类型安全编译期校验状态管理静态类管理器轻量、无第三方依赖主题切换订阅发布模式解耦、可扩展路由导入ohos.routerAPI 23 兼容性6.3 后续可扩展方向数据持久化Preferences 存储收藏数据网络请求对接塔罗牌 API 获取每日运势动画效果抽牌翻转动画、卡片入场动画自定义牌阵用户自由选择牌数和位置多语言支持英文版、日文版国际化Widget 服务卡片桌面显示今日塔罗结语五篇文章从环境搭建到发布上线我们完整地走了一遍鸿蒙原生应用的开发流程。这个塔罗牌 App 虽小但五脏俱全——路由导航、列表渲染、组件化、状态管理、主题切换、构建配置覆盖了日常开发中的大多数场景。鸿蒙生态正在快速发展现在入局正当时。希望这个系列能成为你鸿蒙开发路上的实战参考。如果你有任何问题或想法欢迎在评论区交流讨论项目代码: 基于 HarmonyOS API 23 Stage 模型 ArkTS源码位置:entry/src/main/ets/构建工具: DevEco Studio hvigor全文完附录本系列目录篇号标题核心内容第一篇环境搭建与首页开发项目初始化、Stage 模型、Index 首页第二篇牌义列表与路由导航CardListPage、CardDetailPage、路由传参第三篇牌阵解读与交互设计SpreadPage、随机算法、正逆位判定第四篇收藏功能与主题切换FavoriteManager、ThemeManager、FavPage第五篇数据模型与工程优化TarotData、构建配置、严格模式、发布流程