项目概述

本项目是一个基于HarmonyOS的账单管理应用,是基于鸿蒙开发者社区中的记账本模版的二次创作,提供账单记录、分类管理、数据统计和可视化展示等功能。应用采用模块化架构,包含数据层、工具层和UI层,实现完整的财务管理流程。

一、架构设计

1.1 整体架构图

1.2 技术栈

  • 开发框架: ArkTS/ArkUI
  • 数据存储:
    • 关系型数据库 (@ohos.data.relationalStore)
    • 轻量级首选项 (@ohos.data.preferences)
  • UI组件: ArkUI声明式UI
  • 状态管理: @State、@Link、@Prop装饰器
  • 模块化: Common模块共享代码

二、数据模型设计

2.1 核心数据实体

2.1.1 账单方向枚举 (BillDirection)

typescript

export enum BillDirection {

  IN = 0,    // 收入

  OUT = 1    // 支出

}

2.1.2 账单信息接口 (BillInfo)

typescript

export interface BillInfo {

  id?: number;          // 唯一标识

  type: BillType;       // 账单类型

  amount: number;       // 金额

  direction: BillDirection; // 收支方向

  timestamp: number;    // 时间戳

  remark?: string;      // 备注

  image?: string;       // 图片路径

}

2.1.3 账单类型接口 (BillType)

typescript

export interface BillType {

  icon: Resource;      // 图标资源

  name: string;        // 类型名称

}

2.2 数据库设计

2.2.1 BILL表结构

字段名

类型

说明

约束

ID

INTEGER

主键

PRIMARY KEY AUTOINCREMENT

TYPE

TEXT

账单类型(JSON)

NOT NULL

AMOUNT

REAL

金额

NOT NULL

DIRECTION

INTEGER

收支方向

NOT NULL

TIMESTAMP

INTEGER

时间戳

NOT NULL

REMARK

TEXT

备注

可选

IMAGE

TEXT

图片路径

可选

2.2.2 BILL_TYPE表结构

字段名

类型

说明

约束

ID

INTEGER

主键

PRIMARY KEY AUTOINCREMENT

ICON

TEXT

图标资源(JSON)

NOT NULL

NAME

TEXT

类型名称

NOT NULL

三、核心模块实现

3.1 数据库管理模块 (DBManager)

3.1.1 设计模式:单例模式

typescript

// 使用全局变量实现单例

public static getInstance(context: Context): DBManager {

  if (globalThis.__dbManager__ == undefined)

    globalThis.__dbManager__ = new DBManager(context??globalThis.context);

  return globalThis.__dbManager__;

}

3.1.2 异步初始化处理

public constructor(context:Context) {

  relationalStore.getRdbStore(...).then(store=> {

    store.executeSql(...).then(() => {

      this.storeInstance = store; // 异步设置

    });

  });

3.1.3 核心操作方法

typescript

// 1. 获取所有账单

public async getAllBillInfo(): Promise<BillInfo[]>

// 2. 添加账单

public async addBillInfo(data: BillInfo): Promise<number>

// 3. 搜索账单

public async searchBillInfo(keyword: string): Promise<BillInfo[]>

// 4. 按日期范围搜索

public async searchBillInfoByDateRange(start: Date, end: Date): Promise<BillInfo[]>

// 5. 账单分类管理

public async addBillInfoType(type: BillType): Promise<number>

public async getAllBillInfoType(): Promise<BillType[]>

3.2 工具类模块 (Utils)

3.2.1 账单信息工具类 (BillInfoUtils)

typescript

// 数据转换:ResultSet → BillInfo[]

public static createBillInfoArrayFromResultSet(set: relationalStore.ResultSet): BillInfo[]

// 数据筛选:按日期范围

public static filterByDate(src: BillInfo[], start: Date, end?: Date): BillInfo[]

// 数据聚合:按月/年分解

public static explodeMonthlyArray(src: BillInfo[], month: Date): BillInfo[][]

public static explodeYearlyArray(src: BillInfo[], year: Date): BillInfo[][]

// 财务计算

public static calculateTotalIncome(src: BillInfo[]): number      // 总收入

public static calculateTotalOutBill(src: BillInfo[]): number     // 总支出

public static calculateTotalLeft(src: BillInfo[]): number        // 结余

3.2.2 其他工具类

  • DateUtils: 日期相关工具(如获取月份天数)
  • StringUtils: 字符串格式化(日期格式化)
  • Logger: 统一日志管理

3.3 设置管理模块 (SettingManager)

typescript

// 使用Preferences进行轻量级数据存储

export class SettingManager {

  private settingStore?: preferences.Preferences;

    // 设置值

  public set(k: string, v: SettingType)

    // 获取值(带默认值)

  public async get<T extends SettingType>(k: string, def: T)

}

四、UI层实现

4.1 页面结构设计

4.1.1 主页面 (Index.ets)

功能: 显示今日账单概览、提供快捷入口

typescript

@Entry

@Component

struct Index {

  @State selectedDate: Date = new Date();

  @State currentBillInfo: LocalBillInfo[] = [];

  @State totalIncome: number = 0.00;

  @State totalBalance: number = 0.00;

    build() {

    Column() {

      // 1. 顶部标题栏

      // 2. 收支概览组件 (BalanceViewer)

      // 3. 底部导航组件 (PageEntries)

      // 4. 账单列表组件 (BalanceList)

    }

  }

}

4.1.2 添加账单页面 (AddBalance.ets)

核心特性:

  1. 收入/支出选项卡切换
  2. 分类图标网格选择
  3. 自定义计算器键盘
  4. 日期选择器

交互流程:

text

选择分类 → 弹出输入面板 → 输入金额 → 添加备注 → 选择日期 → 保存

4.1.3 账单详情页 (BillInfoPage.ets)

功能: 按年度展示月度统计数据

text

┌─────────────────┐

│   年份选择器                      │

├─────────────────┤

│   年度收支概览                   │

├─────────────────┤

│ 月份 | 收入 | 支出 | 结余 │

│  1月 | 5000 | 3000 | 2000 │

│  2月 | 6000 | 4000 | 2000 │

└─────────────────┘

4.1.4 统计页面 (StatisticsPage.ets)

功能: 数据可视化展示

  • 柱状图对比收入支出
  • 总览数字卡片
  • 手动刷新机制
  • 具体如下图所示

4.2 可复用组件设计

4.2.1 收支概览组件 (BalanceViewer)

typescript

@Component

export struct BalanceViewer {

  @Link selectedDate: Date;

  @Link currentBillingInfo: string;

  @Link totalIncome: number;

  @Link totalBalance: number;

    // 显示当前月份、总收入、总余额

}

4.2.2 账单列表组件 (BalanceList)

typescript

@Component

export struct BalanceList {

  @Link currentBillInfo: LocalBillInfo[];

  // 显示带图标的账单列表

  // 支持空状态显示

}

4.2.3 底部导航组件 (PageEntries)

typescript

@Component

export struct PageEntries {

  // 三按钮导航:账单、图表、记账

  // 使用渐变色背景

}

4.2.4 柱状图组件 (BarChart)

typescript

@ComponentV2

export struct BarChart {

  @Param income: number = 0;     // 收入

  @Param expense: number = 0;    // 支出

  @Param title: string = '收支对比';

    // 自适应高度计算

  private calculateHeight(value: number): number

}

五、关键实现细节

5.1 数据流管理

5.1.1 页面间数据传递

核心代码

typescript

// 日期对象序列化/反序列化
router.pushUrl({
  params: {
    selectedDate: this.selectedDate.toISOString() // 转为字符串
  }
});

// 接收端
const params = router.getParams() as ESObject;
this.activeDate = new Date(params['selectedDate'] as string);

功能体现:页面跳转时携带完整上下文,并且日期等复杂对象正确传递,也可保持用户体验连贯性

5.1.2 组件间数据同步

typescript

// 父子组件数据同步

@Link currentBillInfo: LocalBillInfo[];

@Link selectedDate: Date;

// 在父组件中使用

BalanceList({

  currentBillInfo: $currentBillInfo,  // 双向绑定

  selectedDate: $selectedDate

})

5.2 错误处理与日志

5.2.1 统一错误处理

typescript

// 数据库操作错误处理

.catch((e:BusinessError) => {

  Logger.err(TAG, "error while adding billing info", e, bucket);

  ret(-1);  // 返回错误标识

})

​​​​​​​// 数据解析错误处理

try {

  // 解析操作

} catch (e) {

  Logger.err(TAG, "Failed to parse ResultSet", e);

  return BillInfoUtils.createEmptyBillInfo();  // 返回空对象

}

5.2.2 日志分级

typescript

export class Logger {

  static info(TAG: string, ...args: any[]) {

    console.info("BILL", TAG, ...args);

  }

  static warn(TAG: string, ...args: any[]) {

    console.warn("BILL", TAG, ...args);

  }

  static err(TAG: string, ...args: any[]) {

    console.error("BILL", TAG, ...args);

  }

}

5.3 数据处理

5.3.1 可视化图表 

核心代码

// 柱状图高度计算
private calculateHeight(value: number): number {
  const maxValue = Math.max(this.income, this.expense);
  if (maxValue === 0) return 0;
  return (value / maxValue) * 120; // 最大高度120vp
}

// 财务状态判断
private getFinancialStatus(): string {
  const balance = this.income - this.expense;
  if (balance > 0) return '盈余';
  if (balance < 0) return '赤字';
  return '平衡';
}

功能体现

  • StatisticsPage:收入/支出柱状对比图

  • 自适应高度,数据越大柱子越高

  • 颜色区分(收入绿、支出红)

  • 财务状态自动判断

5.3.2 数据验证

核心代码

// 提交前验证
if (this.balanceAmount == "0") {
  return; // 金额为0不保存
}
if (this.remark == "") {
  return; // 备注为空不保存
}
if (this.selectedTypeName == "") {
  return; // 未选分类不保存
}

功能体现

  • 必填项验证,确保数据完整性

  • 金额为0拦截,避免无意义记录

  • 即时反馈,用户立即知道问题所在

六、项目配置与常量管理

6.1 统一常量管理

typescript

export class Constants {

  // 字体大小

  public static readonly FONT_SIZE_12 = '12fp';

  public static readonly FONT_SIZE_14 = '14fp';

 

  // 颜色定义

  public static readonly THEME_COLOR = '#94B982';

  public static readonly INCOME_COLOR = '#FF9800';

  public static readonly EXPENSE_COLOR = '#4CAF50';

}

6.2 数据库配置

typescript

export const CommonConfiguration = {

  SETTING_PREFERENCE_STORE_KEY: 'bill_setting',

  DB_MANAGER: {

    DB_FILE_NAME: 'BillApp.db',

    SECURITY_LEVEL: relationalStore.SecurityLevel.S1,

    SQL: {

      INITIALIZE: "CREATE TABLE IF NOT EXISTS BILL (...)",

      GET_ALL_BILLS: "SELECT * FROM BILL ORDER BY TIMESTAMP DESC;",

      // ... 其他SQL语句

    }

  }

} as const;

6.3 预置分类数据

typescript

// 支出分类(18种)

export const defaultExpenseType: IBillType[] = [

  {title: "餐饮", img: $r("app.media.eatIcon")},

  {title: "购物", img: $r("app.media.shoppingIcon")},

  // ... 其他分类

];



// 收入分类(5种)

export const defaultIncomeType: IBillType[] = [

  {title: "工资", img: $r("app.media.salaryIcon")},

  {title: "理财", img: $r("app.media.foundationIcon")},

  // ... 其他分类

];

七、技术亮点

7.1 模块化架构设计

  • Common模块:数据库、工具类、数据模型,可复用

  • Entry模块:UI页面、组件、常量,专注展示

  • 依赖清晰:Common不依赖Entry,可独立测试

Logo

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

更多推荐