Harmony鸿蒙6.0实战开发项目–鸿蒙记账本(登录、注册、记账、图表)

本项目是一个基于 HarmonyOS ArkTS + ArkUI 开发的鸿蒙记账本,项目名为 HarmonyAccount。功能覆盖登录、注册、收入支出记录、账单列表、年度统计和经济图表,适合用来练习 HarmonyOS 应用中的页面组织、路由跳转、本地存储、RDB 数据库和自定义图表。

功能如下:

  • 用户登录或注册
  • 新增收入、支出
  • 首页展示本月统计
  • 账单页展示明细
  • 图表页展示趋势和结构
  • 本地数据库保存账单

一、系统架构总览

项目采用 HarmonyOS Stage 模型开发,整体可以拆成四层:

层级 主要文件 职责
页面层 AuthPage.etsIndex.etsaddBalance.etsBillInfoPage.etsChartPage.ets 页面结构、路由跳转、用户交互
组件层 BalanceList.etsHarmonyCharts.ets 账单列表、统计图表等复用 UI
数据层 AuthStore.etsbalanceTypes.etsBillingInfo.ets 登录状态、分类配置、账单模型
公共能力层 DBManager.etsBillingInfoUtils.etsStringUtils.ts 数据库存取、账单计算、格式处理

核心数据流如下:

页面操作
  -> 更新 ArkUI 状态
  -> 调用 AuthStore / DBManager
  -> 写入 Preferences 或 RDB
  -> 页面重新读取数据
  -> @State / @Link 驱动 UI 刷新

项目中主要用了两类本地存储:

存储方式 用途
preferences 保存本地账户和登录状态
relationalStore 保存收入、支出、分类和时间戳

二、运行截图

1. 登录页

登录页包含账号、密码和注册入口。

登录页

2. 注册页

注册页包含用户名、账号、密码和确认密码。提交时完成基础校验。

注册页

3. 首页总览

首页展示本月结余、收入、支出和支出率,下方展示最近账单。

首页总览

4. 首页账单

首页只展示最近几条账单,完整明细放到账单页,避免首页信息过密。

首页账单

5. 记账页

记账页支持收入和支出切换,用户选择分类后输入金额、备注和日期。

记账页

6. 月度账单

账单页按照日期分组,展示当前月份的收入和支出明细。

月度账单

7. 经济图表

图表页展示近 6 个月结余趋势,以及本月收入、支出和消费结构。

经济图表

8. 年度统计

年度统计页按月份展示收入、支出和结余。

年度统计

9. 我的页面

我的页面展示账号信息、账单数、本月收入、本月支出,并提供退出登录。

我的页面


三、系统详细介绍

1. 登录与注册

登录注册页面位于 AuthPage.ets,账户逻辑封装在 AuthStore.ets

AuthStore 使用 preferences 保存本地用户信息和当前登录状态。这里没有接入服务端,适合作为本地登录注册流程的练习版本。

核心数据结构:

export interface AccountProfile {
  username: string;
  account: string;
  password: string;
}

export interface AuthResult {
  success: boolean;
  message: string;
  profile?: AccountProfile;
}

登录注册主要处理四件事:

  • 注册时校验用户名、账号和密码
  • 登录时校验账号和密码
  • 登录成功后保存当前用户
  • 退出登录时清理会话状态

注册成功后写入本地存储:

const user: AccountProfile = { username, account, password };
const prefs: preferences.Preferences = await AuthStore.getPrefs(context);
await prefs.put(AuthStore.USER_KEY, JSON.stringify(user));
await prefs.put(AuthStore.SESSION_KEY, user.username);
await prefs.flush();

登录成功后使用 router.replaceUrl() 进入首页,避免用户返回到登录页。


2. 首页总览

首页位于 Index.ets,是 App 的主界面。

首页主要展示:

  • 本月结余
  • 本月收入
  • 本月支出
  • 支出率
  • 最近账单
  • 底部导航

账单数据通过 DBManager.getInstance().getAllBillingInfo() 获取,读取后再根据当前月份过滤。

月度过滤采用 [月初, 下月初)

private getSelectedMonthBills(): BillingInfo[] {
  const start: number = this.getMonthStart(0).getTime();
  const end: number = this.getMonthStart(1).getTime();
  return this.currentBillingInfo.filter((item: BillingInfo) =>
    item.timestamp >= start && item.timestamp < end
  );
}

这种写法比直接比较月份更稳定,也能避免把下个月第一天的数据算进来。


3. 记账录入

记账页位于 addBalance.ets

用户新增账单的流程:

  1. 选择支出或收入
  2. 选择账单分类
  3. 输入金额
  4. 填写备注
  5. 选择日期
  6. 保存账单

保存时组装 BillingInfo,再写入 RDB:

DBManager.getInstance().addBillingInfo({
  type: {
    icon: this.activeType,
    name: this.selectedTypeName
  },
  amount: parseFloat(this.balanceAmount),
  direction: this.activeTab == 0 ? BillingDirection.OUT : BillingDirection.IN,
  timestamp: this.getRecordTimestamp(),
  remark: this.remark
})

这里的 timestamp 会保留当前时分秒,避免当天账单被保存成 00:00:00 后在列表中过滤异常。


4. 账单列表

账单列表封装在 BalanceList.ets

列表会先过滤当前月份,再按时间倒序排列:

private getSelectedMonthBills(): BillingInfo[] {
  const start: number = this.getMonthStart(0).getTime();
  const end: number = this.getMonthStart(1).getTime();
  return this.currentBillingInfo
    .filter((item: BillingInfo) => item.timestamp >= start && item.timestamp < end)
    .sort((a: BillingInfo, b: BillingInfo) => b.timestamp - a.timestamp);
}

为了让账单更容易浏览,组件会把账单按日期分组:

interface DayBillGroup {
  label: string;
  bills: BillingInfo[];
}

最终展示时只渲染有数据的日期,不显示空分组。


5. 经济图表

图表组件位于 HarmonyCharts.ets

目前包含三块内容:

图表 说明
本月概览 展示收入、支出、结余
收支趋势 展示近 6 个月结余折线
消费结构 展示本月支出分类占比

近 6 个月趋势数据由账单计算得到:

private getTrendPoints(): TrendPoint[] {
  const points: TrendPoint[] = [];
  for (let i = 5; i >= 0; i--) {
    const bills: BillingInfo[] = this.getMonthBills(i);
    const income: number = this.sumByDirection(bills, BillingDirection.IN);
    const expense: number = this.sumByDirection(bills, BillingDirection.OUT);
    points.push({
      month: this.getMonthLabel(i),
      income,
      expense,
      balance: income - expense
    });
  }
  return points;
}

趋势图使用 ArkUI 的 LineCircleStack 等组件绘制,没有额外引入第三方图表库。为了避免点线错位,折线、圆点和月份标签使用同一套横向坐标。

消费结构会统计本月支出分类,并按金额从高到低排序。这样能直接看出钱主要花在哪些分类上。


6. 本地数据库

数据库逻辑封装在 DBManager.ets,底层使用 HarmonyOS relationalStore

新增账单时写入表字段:

let bucket: relationalStore.ValuesBucket = {
  'TYPE': JSON.stringify(data.type),
  'AMOUNT': data.amount,
  'DIRECTION': data.direction,
  'TIMESTAMP': data.timestamp,
  'IMAGE': data.image ?? '',
  'REMARK': data.remark ?? ''
};

账单表结构:

字段 类型 说明
ID INTEGER 自增主键
TYPE TEXT 分类信息,JSON 字符串
AMOUNT REAL 金额
DIRECTION INTEGER 收入或支出
TIMESTAMP BIG INT 账单时间
REMARK TEXT 备注
IMAGE TEXT 图片字段,预留

核心账单模型:

export enum BillingDirection {
  IN,
  OUT
}

export interface BillingInfo {
  id?: number;
  type: BillingType;
  amount: number;
  direction: BillingDirection;
  timestamp: number;
  remark?: string;
  image?: string;
}

四、核心模型说明

项目内部没有网络接口,页面和组件之间主要通过本地数据模型传递信息。

模型 类型 说明
AccountProfile interface 本地账户信息
AuthResult interface 登录注册结果
BillingInfo interface 单条账单
BillingDirection enum 收入或支出
BillingType interface 分类图标和名称
DayBillGroup interface 日期分组后的账单
CategoryMetric interface 消费结构统计项
TrendPoint interface 趋势图点位数据

这些模型把页面展示和业务数据拆开,后续如果接入云端同步,也可以基于这些结构继续扩展。


五、数据流向示例

以“新增一笔支出”为例:

用户选择支出分类
  -> 输入金额和备注
  -> 选择账单日期
  -> 点击完成
  -> addBalance.ets 组装 BillingInfo
  -> DBManager.addBillingInfo() 写入 RDB
  -> router.back() 返回首页
  -> Index.onPageShow() 重新读取账单
  -> 首页统计、账单列表、图表同步刷新

这个流程覆盖了鸿蒙应用里常见的页面跳转、状态更新、本地数据库读写和 UI 刷新。


六、开发中的关键处理

1. 首页账单和账单页保持一致

首页的最近账单和底部导航中的账单页,都基于同一批本月账单数据过滤。

关键点是统一使用:

item.timestamp >= start && item.timestamp < end

这样首页和账单页不会出现“新增了账单,但某个页面看不到”的问题。

2. 日期边界使用半开区间

按月统计时不要只判断月份数字,最好使用明确的开始和结束时间。

本月账单 = timestamp >= 本月月初 && timestamp < 下月月初

这种方式能覆盖本月所有时间,也不会误算下月数据。

3. 保存日期时保留时间

如果只保存选中日期的零点时间,部分筛选逻辑会在边界处出问题。项目中保存账单时会保留当前时分秒,让当天新增记录更稳定地出现在列表中。

4. 图表点线坐标统一

趋势图中折线、圆点、月份标签必须使用同一套坐标。否则折线看起来会偏移,尤其在移动端宽度变化时更明显。

5. 页面文案保持克制

项目界面只保留标题、字段名、按钮名、状态提示和错误提示。欢迎语、宣传语、重复说明都删除掉,让页面更像真实工具,而不是展示页。


七、适合继续扩展的方向

这个项目可以继续扩展:

  • 预算设置
  • 账单搜索
  • 分类管理
  • 账单删除和编辑
  • 数据导出
  • 多账户数据隔离
  • 云端同步
  • 图表筛选和年度对比

如果想继续提高完整度,可以优先做账单编辑、删除、搜索和预算提醒,这些功能和记账 App 的使用场景最接近。


八、项目总结

鸿蒙记账本项目覆盖了 HarmonyOS 实战开发中比较常见的能力:

  • ArkUI 页面搭建
  • ArkTS 状态管理
  • 页面路由跳转
  • 本地登录注册
  • Preferences 轻量存储
  • RDB 数据库存储
  • 月度账单筛选
  • 日期分组列表
  • 自定义图表绘制

它的功能不复杂,但能把页面、组件、数据、存储和状态刷新串起来。对于正在学习 HarmonyOS 的同学来说,这类项目比单独写组件更容易建立完整的开发思路。

Logo

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

更多推荐