鸿蒙原生应用实战(一):项目起航 — 从零搭建「纪念日管家」Stage模型应用

本文是「鸿蒙原生应用开发实战」系列第一篇,带你从零搭建一个完整的「纪念日管家」鸿蒙原生应用。这次我们将挑战日期计算、倒计时算法、多页面传参等全新场景。


一、项目背景与功能概览

1.1 为什么做纪念日管家?

在快节奏的现代生活中,我们常常被工作、学习等各种事务占据大部分精力,导致那些对我们个人和家庭有特殊意义的日子容易被遗忘。生日、结婚纪念日、恋爱纪念日、重要节日、体检日、证件到期日……这些看似简单的日期背后,承载着情感、健康、法律等多重价值。

纪念日管家正是为了解决这一痛点而诞生的鸿蒙原生应用。它不仅仅是一个简单的日期记录工具,更是一个智能的生活助手:

核心价值
  1. 情感连接:帮助用户维系重要的人际关系,不错过每一个值得庆祝的时刻
  2. 健康管理:定期提醒体检、复查等重要健康事项
  3. 事务规划:提前规划证件更新、保险续费等生活事务
  4. 记忆留存:记录生活中的美好瞬间,形成个人专属的时间轴
功能亮点
  • 智能首页:今日纪念日醒目提醒 + 未来30天事件预览,让重要日子一目了然
  • 灵活添加:支持名称、日期(月/日)、起始年份、7种分类(生日、纪念日、节日、健康、工作、证件、其他)、自定义提前提醒天数
  • 高效管理:全部列表支持按分类筛选 + 按日期排序 + 滑动删除,操作流畅便捷
  • 沉浸式详情:倒计时大数字视觉展示 + 第N年情感标注 + 实时备注编辑
  • 数据洞察:个人中心提供分类统计条形图,直观展示各类纪念日分布
技术优势

作为鸿蒙原生应用,纪念日管家充分利用了HarmonyOS的分布式能力,未来可轻松扩展到手表、平板等多设备协同,实现跨端提醒和数据同步。

1.2 技术栈详解

框架:HarmonyOS Stage 模型
语言:ArkTS (API 23)
SDK:compatibleSdkVersion 6.1.0(23), targetSdkVersion 6.1.1(24)
状态管理:AppStorage(单key: 'events')
导航:@ohos.router(含参数传递)
设备类型:Phone
技术选型解析
  1. Stage模型优势

    • 更好的进程管理:按需启动和销毁UIAbility,节省系统资源
    • 清晰的生命周期:便于状态管理和内存优化
    • 支持多实例:同一应用可打开多个窗口,适合纪念日对比查看
  2. ArkTS语言特性

    • 静态类型检查:提高代码健壮性,减少运行时错误
    • 声明式UI:简洁高效的界面开发方式
    • 生态完善:丰富的API和组件库支持
  3. 状态管理策略

    • 使用AppStorage全局状态管理,确保数据一致性
    • 单key设计简化了数据流,便于调试和维护
    • 支持本地持久化,数据安全可靠
  4. 导航系统

    • @ohos.router提供标准化的页面跳转能力
    • 支持参数传递,实现页面间数据共享
    • 路由栈管理清晰,用户体验流畅
扩展性考虑

当前版本专注于手机端体验,技术栈设计已为未来扩展预留了接口:

  • 可轻松适配平板的大屏布局
  • 支持手表端的轻量化提醒功能
  • 云端同步能力可基于HarmonyOS分布式数据管理实现

二、项目目录结构

MyApplication/
├── AppScope/
│   ├── app.json5
│   └── resources/
├── entry/
│   └── src/main/
│       ├── ets/
│       │   ├── entryability/
│       │   │   └── EntryAbility.ets      # 应用入口
│       │   ├── models/
│       │   │   └── EventData.ets         # 数据模型+分类+倒计时算法
│       │   └── pages/
│       │       ├── Index.ets             # 首页(今日+即将到来)
│       │       ├── AddEvent.ets          # 添加纪念日
│       │       ├── ListPage.ets          # 全部列表+分类筛选
│       │       ├── DetailPage.ets        # 详情页+倒计时+备注编辑
│       │       └── ProfilePage.ets       # 个人中心+分类统计
│       ├── module.json5
│       └── resources/base/profile/main_pages.json
├── build-profile.json5
└── hvigor/

三、Stage 模型与路由(含参数传递)

3.1 页面路由注册

{
  "src": [
    "pages/Index",
    "pages/AddEvent",
    "pages/ListPage",
    "pages/DetailPage",
    "pages/ProfilePage"
  ]
}

3.2 带参数的路由跳转

纪念日管家的一个独特之处在于 DetailPage 需要接收事件 ID:

// 列表页 → 详情页(携带参数)
router.pushUrl({
  url: 'pages/DetailPage',
  params: { eventId: ev.id }
});

// 详情页接收参数
aboutToAppear(): void {
  let p = router.getParams() as Record<string, Object>;
  let eventId = p['eventId'] as string;
  // 根据 eventId 查找事件数据...
}

参数传递的注意事项

  1. 参数通过 params 对象传递
  2. 接收方用 router.getParams() 获取
  3. 返回值类型为 Record<string, Object>,需要转型
  4. 使用 as string 确保类型安全

3.3 页面路由关系

Index(首页:今日+即将到来)
  ├─→ AddEvent(添加纪念日)
  ├─→ ListPage(全部列表+分类筛选)
  │    └─→ DetailPage(详情页,带 eventId 参数)
  └─→ ProfilePage(个人中心)

四、构建配置

// build-profile.json5
{
  app: {
    products: [{
      targetSdkVersion: "6.1.1(24)",
      compatibleSdkVersion: "6.1.0(23)",
      runtimeOS: "HarmonyOS",
      strictMode: { caseSensitiveCheck: true }
    }]
  }
}

五、踩坑记录

🕳️ 坑1:router.getParams() 的类型转换

问题router.getParams() 返回 Record<string, Object>,直接访问 p['eventId'] 类型为 Object,不能直接当字符串使用。

解决

let p = router.getParams() as Record<string, Object>;
let eventId = p['eventId'] as string;  // 显式转型

🕳️ 坑2:MM-DD 格式的日期比较

问题:纪念日只存 MM-DD(不含年份),但需要跨年比较(去年的节日在今天之前还是之后)。

解决:在 getCountdown 函数中分别计算今年和明年的日期:

let targetThisYear = new Date(thisYear, month - 1, day);
let diff = Math.ceil((targetThisYear.getTime() - now.getTime()) / 86400000);
if (diff >= 0) {
  // 今年还没过,用今年日期
} else {
  // 今年已过,算到明年
  let targetNext = new Date(thisYear + 1, month - 1, day);
  let nextDiff = Math.ceil(...);
}

六、下篇预告

本篇完成了「纪念日管家」的框架搭建和路由配置。下一篇将深入数据层设计,包括:

  • AnniversaryEvent 模型设计(MM-DD 日期格式的哲学)
  • 7种事件分类系统的设计
  • 倒计时算法(跨年计算 + 第N年标注)
  • 提前提醒天数机制

敬请期待!
在这里插入图片描述


如果你正在学习鸿蒙开发,欢迎关注本系列!

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐