公司动态

ArkTS+AGC构建鸿蒙记账应用:从架构设计到云函数集成的实战笔记

📅 2026/8/31 12:19:13
ArkTS+AGC构建鸿蒙记账应用:从架构设计到云函数集成的实战笔记
简介本资源是一套基于HarmonyOS生态的ArkTS语言实战项目——网吧会员终端应用面向鸿蒙应用开发者、高校移动开发学习者及转岗工程师解决从零构建完整商用级鸿蒙应用的核心能力训练问题。项目覆盖引导页、登录注册、密码管理、网吧浏览、会员充值、数据查询等12个核心功能模块所有业务数据统一落库至关系型数据库SQLite并辅以首选项存储用户轻量配置体现鸿蒙平台典型的数据持久化实践路径。压缩包含343个文件主体为24个ArkTS源码.ets、77个JS逻辑脚本、37个JSON配置、40张JPG/PNG资源图及36个protobin协议文件总大小36.58MB结构清晰、模块解耦便于逐层理解UI组件、状态管理与数据库交互逻辑。已有227人下载学习可直接导入DevEco Studio运行调试获取完整可执行HAP包、分层代码结构、真实业务场景下的ArkTS语法应用范例及跨模块通信实现方案。 最近几个月我一直在折腾 HarmonyOS 应用开发主力语言就是 ArkTS。手上的项目是一个完整的个人记账账单服务系统前端用 ArkTS 在 DevEco Studio 里从零搭起来后端直接挂在 AGCAppGallery Connect上包含用户认证、账单记录、分类管理、统计分析、预算管理五个核心模块。这篇文章把从技术选型到每个功能落地的完整过程整理一遍适合刚接触 HarmonyOS 开发、想用 ArkTS 独立完成一个含前后端真实项目的开发者参考。这篇文章不是贴一堆官网文档而是把我实际开发中踩过的坑、验证过的写法、取舍时考虑的理由一次性讲清楚。你把它当一份带评论的实操笔记来看就行照着思路走能少走不少弯路。1. 项目定位与整体设计为什么选 HarmonyOS ArkTS 做记账应用1.1 ArkTS 到底适合做什么样的项目先说结论ArkTS 是 HarmonyOS 原生应用的首选开发语言基于 TypeScript 语法做过裁剪和强化配合 ArkUI 声明式 UI 框架写页面比传统命令式 UI 要快很多。它和 JS/Java 那套老开发方式最大的区别是状态驱动视图——你把数据声明成状态数据一变界面自动跟着刷新不需要手动操作 DOM 或组件节点。我在设计这个项目时第一反应不是能不能用 ArkTS而是这个项目的复杂度和 ArkTS 的定位匹不匹配。记账类应用有几个特点页面数量多列表、表单、报表、设置、数据状态频繁变化账单增删改、预算进度更新、还需要和云侧数据实时同步。这些场景刚好是声明式 UI 的强项。反过来如果你只是做个静态展示页用 ArkTS 反而有点杀鸡用牛刀。另一个现实因素是生态。现在 HarmonyOS 的第三方组件库虽然没有 Android 那么丰富但核心场景基本都覆盖了。记账系统里最需要的表格、图表、下拉刷新、日期选择器在 OpenHarmony 三方库中心都能找到可用版本。而且项目里用的是 AGC 后端ArkTS 前端调用 AGC 云函数、云数据库的 SDK 也是官方维护的链路是通的。1.2 个人记账系统的业务需求拆解这个系统本质上就是个人的轻量级财务管家。我在整理需求时把它拆成了五个模块每个模块的边界要非常清晰用户认证注册、登录、退出登录以及登录态保持。后端用 AGC 的认证服务支持手机号、邮箱、匿名登录我最后选了邮箱 密码的方案便于测试和后期扩展。账单记录核心功能支持收入和支出两种类型每条账单包含金额、分类、备注、日期四个必要字段。支持按时间范围筛选、按分类筛选。分类管理预置常用分类餐饮、交通、购物、工资等同时允许用户自定义分类。分类是账单分析的基础设计时必须保证每个账单只能归属一个分类。统计分析按月份、按分类汇总收支金额用饼图展示支出占比用折线图展示近六个月的收支趋势。预算管理用户可以给某个分类设置月度预算或者设置总体月度预算系统实时计算剩余额度超支时给出提醒。数据流设计上前端所有的写操作都通过 AGC 云函数完成云函数负责校验参数和写云数据库读操作优先走云数据库的查询接口配合本地缓存做加速。用户身份通过 AGC 认证服务统一管理每个账单记录带 userId 字段保证用户之间的数据完全隔离。2. 开发环境搭建与工程架构2.1 DevEco Studio 环境配置要点开发这个项目我用的 DevEco Studio 是 5.x 版本API 级别按最新稳定版来。环境配置有几个容易出问题的地方先说清楚SDK 下载首次创建工程时IDE 会提示下载 HarmonyOS SDK网络不好的话容易失败。我建议在设置里先配置好 SDK 镜像源再创建工程。签名配置真机调试必须配置签名否则装不上设备。项目刚创建时用的自动签名第一次连真机时需要在 Project Structure 里检查签名证书是否已生成并且让手机开启开发者模式、连接电脑后授权调试。模拟器 vs 真机纯 UI 阶段我用模拟器跑但涉及 AGC 认证、云数据库时模拟器偶尔会有网络或服务异常这时候直接换真机。DevEco Studio 创建工程时语言选 ArkTS模板选 Empty Ability 就行。生成的工程默认带 entry 模块所有页面代码都在 entry/src/main/ets 下面。这个工程结构后面可以自己扩展成多模块但对于记账系统这种规模的 App单 entry 足够别过度设计。2.2 工程目录与代码分层我最终的代码结构是这样的按UI 层 / 业务层 / 数据层三层来组织entry/src/main/ets/ ├── entryability/ // 应用入口 │ └── EntryAbility.ets ├── pages/ // 页面层 │ ├── LoginPage.ets │ ├── BillListPage.ets │ ├── BillEditPage.ets │ ├── CategoryPage.ets │ ├── StatisticsPage.ets │ └── BudgetPage.ets ├── components/ // 可复用的 UI 组件 │ ├── BillCard.ets │ ├── SummaryBar.ets │ └── CategoryIcon.ets ├── model/ // 数据模型 │ ├── BillModel.ets │ ├── CategoryModel.ets │ └── BudgetModel.ets ├── service/ // 云服务调用封装 │ ├── AuthService.ets │ ├── BillService.ets │ └── StatsService.ets └── common/ // 常量、工具类 ├── Constants.ets └── DateUtils.ets分层的好处是页面里只负责 UI 渲染和用户交互不直接碰云函数调用所有跟 AGC 打交道的逻辑集中在 service 层后面如果换后端实现只改 service 层就行。我当时踩过的坑是第一版把云函数调用写在页面里结果多个页面都要查账单时代码复制粘贴越来越乱后来才统一抽到 service 层。2.3 接入 AGC 后台服务AGC 接入的流程很多人觉得繁琐其实核心就三步第一步在 AppGallery Connect 控制台创建应用。登录 AGC 后台新建项目然后添加应用包名要和 DevEco Studio 工程里的包名完全一致否则后面 SDK 初始化会失败。包名建议用反域名格式例如 com.example.mycashbook。第二步开通需要的服务。记账系统里我开通了认证服务、云数据库、云函数三个。认证服务用来处理用户登录云数据库存账单、分类、预算数据云函数放统计聚合等复杂业务逻辑。在控制台里都是一键开通但要注意后续的权限配置和集合创建。第三步把 agconnect-services.json 文件放到工程指定位置。这个文件是 AGC 服务的身份证包含应用 ID、密钥等信息。下载后放到 entry/src/main/resources/rawfile 目录下然后代码里就能用 AGC 的 SDK 了。第一次配置时容易漏掉这个文件导致运行时报AGC SDK not initialized之类的错误别问我怎么知道的。3. 核心业务模块的实现思路与关键代码3.1 用户认证模块用 AGC Auth 做登录和登录态保持AGC 认证服务支持多种认证方式我选的是邮箱注册登录。之所以不选手机号是因为测试阶段邮箱不需要真实走短信验证流程更顺。在 ArkTS 里调用认证服务第一步是初始化然后调用注册接口。这里直接贴核心代码import { auth } from kit.AGCKit; export class AuthService { static async register(email: string, password: string): Promiseboolean { try { const result await auth.AuthClient.getInstance() .createUser({ email: email, password: password }); return result.user ! null; } catch (error) { console.error(register failed: JSON.stringify(error)); return false; } } static async login(email: string, password: string): Promiseboolean { try { const result await auth.AuthClient.getInstance() .signInWithPassword({ email: email, password: password }); return result.user ! null; } catch (error) { console.error(login failed: JSON.stringify(error)); return false; } } }这里有个经验注册和登录接口都要做错误捕获而且要把错误码映射成用户能看懂的中文提示。比如用户已存在密码错误网络异常不能直接弹一坨英文错误对象给用户看。登录态保持也要单独处理。AGC Auth 默认有本地会话保持App 杀掉再重启后理论上用户还是登录状态。但我发现偶尔会出现会话失效但本地没感知的情况。所以我在 EntryAbility 的 onWindowStageCreate 里加了一个令牌校验逻辑启动时调用 getUser 接口如果取不到用户就强制跳转登录页。3.2 账单记录与分类管理数据模型与增删改查账单记录是整个系统的心脏。我先定义 ArkTS 数据模型export class BillItem { id: string; amount: number; categoryId: string; type: expense | income; note: string; date: string; // 格式 yyyy-MM-dd HH:mm:ss userId: string; constructor() { this.id ; this.amount 0; this.categoryId ; this.type expense; this.note ; this.date ; this.userId ; } }注意ArkTS 语法上对类字段声明有要求所有字段必须显式初始化不能在构造函数里才赋值。我第一次用 TypeScript 的习惯直接写id: string编译直接报错必须给初始值。这一点是 ArkTS 和标准 TS 的一个明显差异后面会专门讲。云数据库里我建了一个叫 bills 的集合每条记录的字段和 BillItem 类一一对应。新增账单时前端把数据传给云函数云函数校验通过后写入数据库然后返回给前端新纪录的 id。前端拿到 id 后直接把这条记录追加到本地的账单列表状态里不需要重新拉全量数据这样列表刷新会非常快。分类管理相对简单。预置分类放在一个常量表里用户自定义分类则写入 categories 集合。分类数据在 App 启动时加载一次缓存在全局单例里。因为分类数量少不需要做分页一次查全。3.3 统计分析模块云函数聚合 图表展示统计是记账系统里最有技术含量的模块。要实现按月汇总各分类支出近六个月收支趋势最简单的做法是前端把所有账单拉下来在本地算。但如果账单数据量到几千条这种方案会越来越卡。我在初期就决定把聚合逻辑放到云函数里数据库算完只返回汇总结果前端只负责展示。这里贴一个云函数里统计月度分类支出的核心逻辑云函数运行环境是 Node.js语法是 JavaScript/TypeScriptexports.myHandler async function (event, context, callback) { const { cloud } require(agconnect/cloud); const cloudDb cloud.database(); const { userId, month } event; const startTime new Date(${month}-01T00:00:00); const endTime new Date(startTime); endTime.setMonth(startTime.getMonth() 1); try { const res await cloudDb.collection(bills) .where({ userId: userId, type: expense, date: { $gte: startTime, $lt: endTime } }) .limit(1000) .get(); // 在云函数里做聚合 const stats {}; res.data.forEach(bill { const catId bill.categoryId; if (stats[catId]) { stats[catId] bill.amount; } else { stats[catId] bill.amount; } }); callback(null, stats); } catch (err) { callback(err); } };前端 ArkTS 调用云函数时我用的是kit.AGCKit里的 cloud 调用接口把 userId 和 month 作为参数传进去拿到返回的 stats 对象再映射到图表组件上。图表组件方面我用了三方库里的图形组件来做饼图和折线图。饼图的每个扇区对应一个分类颜色从分类配置里取。一开始我用了默认配色的饼图视觉效果一般。后来在统计页顶部加了一个渐变背景用 ArkUI 的 linearGradient 接口从黑色 #000000 透明度 80% 渐变到完全透明背景色和饼图形成对比后整体高级感提升了不少。具体写法LinearGradient({ angle: 180, colors: [[#000000, 0.8], [#00000000, 0.0]] })这个写法里0.8 表示颜色在渐变起始位置的透明度比例0.0 是终点位置完全透明。ArkUI 的 linearGradient 颜色数组用的是[color, position]二元组position 表示该颜色在渐变中的位置。如果你想做从上到下的渐变angle 用 180 度就可以。3.4 预算管理模块实时计算剩余额度和超支提醒预算管理模块的核心是数据结构设计和进度计算逻辑。我在 budgets 集合里存了三种预算总体月度预算一个用户一条记录字段包含 budgetAmount、month、userId。分类月度预算每个分类一条记录包含 categoryId、budgetAmount、month、userId。单笔限额提醒这个属于附加功能比如单笔超过 1000 元时提醒我用一个统一字段用于标记。预算进度计算也是放到云函数里做。逻辑是输入 userId 和 month云函数先取该月账单汇总金额再取预算总额然后算出已用比例和剩余金额。如果用户只想看某个分类的预算进度就传 categoryId 参数云函数按分类统计。前端展示上预算页面用进度条组件展示已用百分比并用颜色区分状态正常状态绿色、接近 90% 黄色、超支红色。超支提醒我用了两种方式一种是页面内弹窗另一种是系统通知。系统通知需要申请通知权限并且要处理用户拒绝授权的情况。第一版我直接弹窗提醒用户反应不够友好后来加了通知中心的通知体验才好起来。4. 开发过程中踩过的坑与排查技巧4.1 ArkTS 语法限制和 TypeScript 的差异对照ArkTS 是基于 TS 的但不是所有 TS 特性都支持。这个项目的开发过程中我整理了一份ArkTS 踩坑对照表非常有用场景标准 TS 写法ArkTS 里的正确写法变量类型let data: any {...}let data: Recordstring, Object {...}类字段id: string;id: string ;必须给初始值对象字面量const obj { a: 1 }需显式声明类型const obj: MyType { a: 1 }解构赋值const { name } data部分场景不支持建议逐字段赋值联合类型type A string | number基本支持但对象类型尽量用接口方法重载function f(a: string): void不支持用可选参数代替第一版代码里我大量使用了any类型和对象解构结果编译时报了几十个错误。后来学乖了所有数据模型都用 class 或 interface 定义好后端返回的数据通过一个 mapper 函数逐字段复制到前端模型里虽然代码多写了几行但类型安全让后续维护省心太多。还有一个细节ArkTS 里Recordstring, Object用起来比any安全但取值时要先做类型转换否则拿到的类型不确定。比如let obj: Recordstring, Object { value: 100 }; let v: number obj[value] as number;4.2 node-gyp 与鸿蒙原生依赖的兼容问题有段时间我在项目里想引入一个带原生代码的三方库结果编译时一直报 node-gyp 相关错误。node-gyp 通常用于 Node.js 原生模块编译在 HarmonyOS 开发里出现主要嫌疑是某个依赖在安装阶段尝试编译原生命令行工具但环境里缺少对应构建链。排查思路是这样的先看报错栈里有没有 node-gyp rebuild 字样有的话确认电脑上是否装了 Python、C 构建工具和对应版本的 Node.js。我按官方文档装齐之后错误就消失了。如果你也遇到这个坑先不要动工程配置先补环境安装 Python 3.x并加入系统 PATH安装 Visual Studio Build Tools勾选 C 开发组件安装 Node.js LTS 版本和 DevEco Studio 要求的版本匹配如果补完环境依然报错那就得考虑放弃这个带原生代码的库换一个纯 JS/TS 实现的库。HarmonyOS 生态里不是所有库都做过原生适配这一点在选型时要提前查清楚。4.3 第三方组件库选型下拉刷新和图表库的取舍第三方库方面我试过下拉刷新库 pulltorefreshv2。这个库的交互效果很流畅但接入时要注意版本和 HarmonyOS API 的匹配。我第一版引入的版本已经和 API 12 兼容后来升级到 API 13 后发现刷新动画有点异常查了版本记录才知道要同步升级到 v2 的更高版本才能兼容。图表库也踩过坑。我试过用ohos生态里一个 Canvas 图表库功能是挺全但打包体积太大而且冷启动时图表初始化有明显的卡顿感。后来我换了一个体积更小的图表组件虽然配置项少一些但针对记账系统的饼图和折线图已经完全够用。这里给个经验第三方库不是越大越全就越好要自己的页面复杂度来选。4.4 AGC 云函数冷启动与数据同步问题AGC 云函数是 Serverless 架构存在冷启动的问题。所谓冷启动就是函数长时间没被调用时下一次请求会有一个初始化耗时有时候可能要 1~3 秒。记账系统在打开统计页时如果正好赶上冷启动那个转圈动画会明显卡顿。我的解决办法有两个一是启动 App 后在后台预加载当月账单数据提前触发云函数调用等于人为预热二是前端做好加载状态在云函数返回前先展示本地缓存的统计数据返回后无缝刷新。实测下来用户感知到的等待时间大幅降低。数据同步方面AGC 云数据库有实时数据推送的能力但我没有选择实时监听整个 bills 集合而是采用增删改后手动刷新列表的策略。理由很简单记账场景下数据变化频率低而且只影响当前用户手动刷新足够还能省掉监听带来的复杂逻辑和数据流量。4.5 几个高频问题的排查速查表开发到后期我把团队里同事们常遇到的问题整理成一个速查表特别适合新手问题现象可能原因解决办法编译报错Property xxx does not exist对象被隐式推断成窄类型给对象变量显式加类型注解真机调试时提示签名失效调试证书过期或设备未信任在 DevEco Studio 中重新生成证书并到手机设置里信任开发者证书AGC 云数据库写入失败集合权限未开放到 AGC 控制台配置数据库安全规则调用云函数超时函数默认超时时间太短在云函数配置里调大超时时间例如从默认值调至 30s页面刷新后数据消失没有做本地持久化用 Preferences 或关系型数据库做本地缓存渐变背景不生效linearGradient 位置系数范围错误确认 position 值在 0.0~1.0 之间这里特别说一下数据库安全规则。AGC 云数据库在不同业务场景下访问权限需要人工配置。我的规则是所有数据库读写都通过云函数代理所以数据库本身对客户端关闭了直接读写权限只允许云函数访问。这个规则在 AGC 控制台的数据库模块里配置语法类似 JSON配置一次后所有客户端的直连请求都会被拒绝。5. 项目最后的优化方向与个人经验总结整个项目做到这里功能已经完整应用也能在真机上稳定跑起来。但我还留了几个优化方向给后续迭代做准备一是多设备适配目前主要布局针对手机后续要适配平板折叠屏二是数据导出功能用户可以把账单导成 CSV 文件方便自己做备份和深度分析三是桌面卡片HarmonyOS 的特征之一就是服务卡片做一个当月预算进度的卡片放在桌面上比打开 App 看进度要方便得多。最后说点个人体会。如果你之前只写过 Web 前端或只写过 AndroidArkTS 的上手门槛其实没有想象中那么高。它保留了声明式 UI 的思想只要你理解状态驱动视图这个核心概念大部分页面开发都非常顺。真正花时间的地方反而是跟 AGC 服务集成、处理类型约束、排查原生依赖兼容这类坑。我自己在开发这个项目的过程中最大的收获不是会调用了多少 API而是建立了一套先定义好模型和接口再写页面的工程习惯。以前写小项目喜欢边写边改到了 ArkTS 里因为类型系统严格、前后端数据契约必须清晰这种习惯逼着我把所有数据模型、云函数出入参提前定义好反而让整个开发过程变得很顺畅。如果你也要用 ArkTS 做一个类似的业务系统我给的建议是第一步先把数据模型定义清楚包括本地实体和云数据库字段结构第二步把 AGC 服务接入和调试跑通再做具体页面第三步页面开发时严格分层不要图省事把业务逻辑全堆在组件里。做到这三点你的项目大概率不会在中途陷入改一处坏一处的泥潭。个人记账应用只是一个样板ArkTS 能做的事情远不止于此。把这个流程玩熟以后你会发现用 HarmonyOS 原生技术栈做全栈应用开发比想象中更顺手。本文还有配套的精品资源点击获取