鸿蒙 6.0 羽毛球工具系列封面

系列第 1 篇。本文先讲工程底座:为什么一个看似简单的羽毛球工具,不应该只堆在一个页面里,而要从第一版就把入口、公共能力和业务页面拆开。

一、真实问题背景

羽毛球组局工具的功能并不只是一个费用计算器。它同时包含费用计算、对阵轮转、实时计分、排名统计、我的设置、主题、截图分享、语音播报等能力。如果这些逻辑全部写进 entry 模块,前期看起来快,后期会很快变成页面互相引用、状态刷新混乱、资源路径分散的局面。

这个项目选择用 HarmonyOS NEXT + ArkTS 做一个本地优先 App。当前工程的构建目标已经进入 API 20+ 区间:build-profile.json5compatibleSdkVersion6.0.0(20)targetSdkVersion6.1.0(23)。这意味着文章里谈到的不是旧模板项目,而是面向 HarmonyOS 6.0 之后应用形态的实战整理。

当前 App 首页截图

二、目标与边界

这篇文章只处理工程基线,不展开每一个业务细节。目标是回答三个问题:

1. App 为什么拆成 entry / common / features

2. API 20+ 工程里哪些配置决定了运行形态。

3. 后续文章如何基于这个工程继续讲响应式、多端、TTS、分享和跨设备路线。

边界也要说清楚:智能排阵、语音播报、手表端计分、跨设备数据流转会在后续文章展开。本文只关注工程底座,不把所有能力挤进一篇里。

三、工程分层

当前项目的核心结构是:

badmintonTools/
  entry/       # 应用壳、EntryAbility、页面路由壳、启动窗
  common/      # 模型、服务、存储、主题、断点系统、路由常量
  features/    # 首页、费用、对阵、计分、统计、我的页
  AppScope/    # 应用级图标、版本、bundle 信息
  doc/         # 需求、截图、宣发图、系列文章

entry 负责把系统入口接进来,包括 EntryAbilitymodule.json5main_pages.json、启动窗资源和主壳页面。common 放跨页面共享能力,例如 SessionStoreSettingsStoreFeeCalcServiceScoreSpeechServiceBreakpointSystemfeatures 放用户可见的业务页面,例如 features/src/main/ets/scoring/LiveScoringPage.ets

这套拆法的好处是:业务页面不直接关心 Ability 生命周期,服务层不依赖具体页面,入口层只调度页面和全局状态。后续接入 App Linking、备份恢复、手表控制端或平板展示端时,不必把核心逻辑从页面里再挖出来。

四、关键配置

项目根部的 build-profile.json5 决定 SDK 和产品配置,entry/build-profile.json5common/build-profile.json5features/build-profile.json5 分别声明 Stage 模式模块。

{
  "products": [
    {
      "name": "default",
      "targetSdkVersion": "6.1.0(23)",
      "compatibleSdkVersion": "6.0.0(20)",
      "runtimeOS": "HarmonyOS"
    }
  ]
}

entry/src/main/module.json5 则决定入口 Ability、设备类型、权限、深链和扩展能力。项目里声明了 phonetablet2in1,这为后续“手机底部 Tab、平板侧边栏、2in1 宽屏布局”打了基础。

{
  "module": {
    "name": "entry",
    "type": "entry",
    "deviceTypes": ["phone", "tablet", "2in1"],
    "mainElement": "EntryAbility"
  }
}

五、入口生命周期

entry/src/main/ets/entryability/EntryAbility.ets 做了几件关键事:初始化设置存储、恢复对局数据、恢复费用缓存、设置深浅色模式、初始化响应式断点系统,并在窗口创建后加载 pages/Index

SettingsStore.initPrefs(this.context);
SettingsStore.hydrateFromPrefs();
SessionStore.initPrefs(this.context);
SessionStore.hydrateFromPrefs();
FeeCalcService.initPrefs(this.context);
FeeCalcService.hydrateFromPrefs();
BreakpointSystem.init();

这段代码看起来普通,但它定义了应用启动后的数据顺序:先恢复本地持久化,再让页面读取 AppStorage 中的镜像状态。这样首页、计分页、排名页不需要各自到处读 Preferences,只要通过 @StorageLink 或服务层拿状态即可。

六、调试命令

本次工程基线验证使用 Hvigor 构建:

$env:DEVECO_SDK_HOME = 'D:\HuaweiDevelopFormalStudy\DevEco Studio\sdk'
$env:Path = 'D:\HuaweiDevelopFormalStudy\DevEco Studio\jbr\bin;D:\HuaweiDevelopFormalStudy\DevEco Studio\sdk\default\openharmony\toolchains;D:\HuaweiDevelopFormalStudy\DevEco Studio\tools\node;' + $env:Path
& 'D:\HuaweiDevelopFormalStudy\DevEco Studio\tools\hvigor\bin\hvigorw.bat' assembleHap --mode module -p product=default --no-daemon

验证时间:2026-06-28。当前构建结果为 BUILD SUCCESSFUL。这一步很重要,因为文章讲的是工程化,不是只停留在目录截图。

七、官方参考

HarmonyOS 工程配置、Stage 模型和 ArkTS 开发建议应以华为开发者官方文档为准。可以从 HarmonyOS 应用开发文档 进入,再按 SDK 版本核对对应 API 行为。

八、工程验收清单

  • build-profile.json5 明确 API 20+ 兼容线和目标 SDK。
  • entry / common / features 职责清楚,不把业务服务写进 Ability。
  • module.json5 声明多设备类型,为平板和 2in1 留出口。
  • 启动时先恢复 Preferences,再加载页面。
  • 当前修改通过 assembleHap 构建验证。

九、小结

一个小工具 App 如果想写成系列文章,第一篇不应该急着展示所有功能,而应该先把工程骨架说清楚。这个项目的价值在于:它既有真实业务,又有 HarmonyOS 系统能力接入点,后续可以自然展开响应式布局、本地持久化、截图分享、TTS 播报、App Linking、跨设备数据流转和手表端计分。

十、下一篇衔接

下一篇进入 ArkUI 响应式布局:同一个 Index.ets 如何在手机上显示底部 Tab,在平板和 2in1 上切换为侧边导航。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐