从一张小票到一款鸿蒙应用:CodeBuddy 陪我 4 小时做完鸿蒙应用“智慧收据管家“的完整实录
从一张小票到一款鸿蒙应用:CodeBuddy 陪我 4 小时做完鸿蒙应用"智慧收据管家"的完整实录
写在前面:为什么是这张小票
一切的起点,是上周三晚上我在整理抽屉时翻出的那张"乐购生活超市"购物小票。日期 2024-05-25,金额 166.77 元,商品总数 12 项。它已经褪色发黄,边角有点卷,但我清楚地记得那天——周五下班路过幸福路 100 号,拎着这袋东西回家煮了顿火锅。
问题是:我发现我已经记不清上周买了什么,更别提上个月。钱包瘪了,却完全不知道钱花在了哪里。打开手机里的记账 App,要么强制登录,要么弹一堆开屏广告,要么要我把每笔消费手动分类、输备注、加标签……本来想偷懒记一笔账,结果比记笔记还累。
那一刻我突然想:鸿蒙系统不是有 Core Vision Kit 吗?不是有意图框架吗?不是有服务卡片吗?如果做一个"拍一下小票就能记账"的应用,并且让它直接被小艺语音调用、能在桌面卡片看到本月支出,是不是比那些记账 App 优雅得多?
说干就干。但我不是鸿蒙原生开发者——我做过 Android、iOS、HarmonyOS 老版本,但 HarmonyOS NEXT 的新 Kit、意图框架、卡片能力,对我来说都是"听过没用过"。正常情况下,光啃文档 + 踩坑,可能要 1-2 周才能跑通一个能用的 Demo。
直到我打开了 CodeBuddy。
一、第一次对话:把需求"塞"给 AI
打开 CodeBuddy,我把那张"智慧收据管家"的提示词——一份我事先写好的、包含技术栈、架构、常见坑规避、验收标准的完整需求文档——一次性粘贴了进去。
应用名:智慧收据管家(Smart Receipt) 一句话定位:拍一张小票/发票,本地 OCR 自动识别金额、商家、日期,秒记一笔账; 同时把"记账"这个能力注册给鸿蒙系统的意图框架,让用户可以直接对系统语音助手说"记一笔" 来触发记账,而不必打开 App。 这个项目的核心技术主张:不是简单接入第三方大模型聊天,而是重点展示 应用如何融入 HarmonyOS 的系统级智能化生态—— 1. 调用系统 AI 能力(Core Vision Kit 的通用文字识别 OCR) 2. 通过意图框架(Intent Framework)把"记一笔"注册为可被系统语音助手直接调用的能力 3. 提供一个服务卡片(元服务/Widget),桌面直接展示"本月支出" 4. 在架构设计和文档里说明 MCP/Skill 协同机制我没有用任何"先讲讲思路"、"分几步实现"这种模糊的开场白——直接把一个完整的、可编译运行的目标工程的需求给了它。这是我后来在用 CodeBuddy 时总结出的第一点心得:对 AI 编程助手来说,需求写得越像产品 PRD,它交付得越接近你想要的工程。
CodeBuddy 收到需求后,第一时间没有急着写代码。它做了一件让我意外但又觉得"对"的事——它先去参考了我工作区里已有的 demo 工程。
我工作区根目录HarmonyOSAI/下其实已经躺着 9 个鸿蒙 Demo:recipe-ai-demo(AI 智能菜谱)、xiaoyi-agent-demo(小艺出行,意图框架范例)、photo-revive-demo(时光胶片)、castdeck-demo(跨屏演讲台)……CodeBuddy 主动读取了recipe-ai-demo的AppScope、build-profile.json5、entry/src/main/ets/目录结构,读取了xiaoyi-agent-demo的意图声明insight_intents.json与TripIntentExecutor.ets,又看了photo-revive-demo的WorkshopTab.ets是怎么用PhotoViewPicker的。
这一步关键到不行。它让 CodeBuddy 不是"凭空生成一个看起来很像鸿蒙的工程",而是直接套用了工作区里已经被验证过的工程骨架——bundleName 命名、Stage 模型的页面注册、Theme.ets 集中色板的做法、Tabs 主壳 + 子页面的组合方式,全都从现有 demo 里"学"过去。这样生成的工程不是空中楼阁,而是和已有 demo 处于同一架构风格的"同门兄弟",DevEco Studio 打开就能跑。
图:CodeBuddy 第一次回复,把工程骨架策略和读取现有 demo 的计划完整列了出来
二、CodeBuddy 的"工科生"操作:先查 API 再写代码
我以为下一步就是它开始疯狂生成代码了。但它又做了一件让我惊喜的事——它先去搜索了 Core Vision Kit OCR API 的最新正确用法。
对话里它列出了三条搜索任务:
HarmonyOS ArkTS @kit.CoreVisionKit textRecognition API PixelMap 通用文字识别 示例代码HarmonyOS ArkTS cameraPicker CameraKit 拍照 pick 示例代码 API 12HarmonyOS ArkTS 服务卡片 FormExtensionAbility form_config.json module.json5 extensionAbilities forms 示例
我后来反思:这一步是 CodeBuddy 跟普通 AI 编程最大的区别。普通 AI 会"凭记忆"给你写代码,但鸿蒙生态发展太快、API 命名变更多、Core Vision Kit 之前叫 Vision Kit、Form Kit 之前叫 FormExtension,光靠训练数据很可能写出过时甚至根本编译不过的代码。CodeBuddy 选择了先去查最新文档,再根据真实 API 来写代码。
从这一步我学到第二点心得:让 AI 写鸿蒙新 API 的代码,先看它有没有做"检索"。如果它直接写,多半在编;如果它先搜文档,可信度大幅提升。
图:CodeBuddy 在对话中主动发起对 Core Vision Kit、cameraPicker、服务卡片三组 API 的搜索
而且更细节的是,它搜索完后还去读了photo-revive-demo/entry/src/main/ets/pages/WorkshopTab.ets里使用photoAccessHelper.PhotoViewPicker的完整代码片段。这种"先搜官方文档、再读已有项目里的实战代码、最后才动手写"的三步法,是我在资深鸿蒙工程师身上才见过的研发流程。
三、移动端的 CodeBuddy:随时随地补一句
那天晚上我躺在床上突然想到一个细节——意图框架执行器里如何处理"无 amount 的兜底逻辑"。我打开手机上的 CodeBuddy(是的,它有移动端),把一句补丁式指令打了过去:
“读取 提示词-智慧收据管家应用生成.md L1-30”
图:在 CodeBuddy 移动端继续对话,针对意图框架细节补充约束
这就是我后来推荐同事用 CodeBuddy 时的第三个理由:会话是连续的。桌面 IDE 写完一段,手机上接着补一句,PC 再回来继续——它记得我们之前所有的对话、读过的所有文件、做过的所有决定。不会因为你换了设备就"失忆"。
我们用普通 IDE 时经常遇到"上下文丢失":换台电脑、换个终端,之前讨论的方案、踩过的坑全没了。CodeBuddy 把"项目 + 对话历史 + 检索结果"都沉淀在云端,设备只是窗口。
四、批量生成 30+ 文件:从主题到四 Tab 一气呵成
回到桌面。CodeBuddy 准备好了,就开始按提示词里"工程结构建议"那一节列的目录,逐文件生成代码。
我看着右侧的对话窗口里,一个个文件被创建出来:
AppScope/app.json5— 应用配置AppScope/resources/base/element/string.json— 应用名字符串entry/build-profile.json5— 模块构建配置entry/src/main/module.json5—关键的模块配置:EntryAbility、意图 metadata、服务卡片 FormExtensionAbilityentry/src/main/resources/base/profile/insight_intents.json—意图声明:AddRecord、QueryMonthSpendingentry/src/main/resources/base/profile/form_config.json—服务卡片配置entry/src/main/ets/common/Theme.ets—主题色板 + 尺寸 + 7 个消费分类entry/src/main/ets/common/OcrParser.ets—OCR 文本解析 + 语音模拟解析entry/src/main/ets/model/ReceiptStore.ets—数据模型 + Preferences 持久化entry/src/main/ets/model/VisionService.ets—相册/相机 Picker + Core Vision Kit 封装entry/src/main/ets/intents/ReceiptIntentExecutor.ets—意图执行器entry/src/main/ets/formability/ReceiptFormAbility.ets—服务卡片扩展能力entry/src/main/ets/widget/pages/ReceiptWidgetPage.ets—桌面卡片 UIentry/src/main/ets/entryability/EntryAbility.ets—入口 Abilityentry/src/main/ets/pages/Index.ets—四 Tab 主壳entry/src/main/ets/pages/ScanTab.ets—拍单记账页entry/src/main/ets/pages/ListTab.ets—账单列表页entry/src/main/ets/pages/IntentTab.ets—意图协同说明页entry/src/main/ets/pages/ProfileTab.ets—我的/统计页
最后还顺手生成了AppScope/resources/base/media/app_icon.png的引用和entry/src/main/resources/base/media/app_icon.png的复制指令,以及完整的README.md。
30 多个文件,每个都按提示词里"第三节必须规避的 ArkTS 常见坑"一条条对照写完——
- ✅ 所有
@Prop/@State/@StorageProp装饰器齐全 - ✅ 属性命名避开
width/height/scale等 ArkUI 内置同名 - ✅
build()单根容器(弹层用Stack包裹) - ✅ 数组更新用
slice()触发浅拷贝 - ✅ 跨文件 import 路径对齐目录层级
- ✅ 异步资源 try/catch/finally 释放
- ✅ 选图用系统 Picker,
module.json5无多余权限声明 - ✅ 所有对象字面量有显式
interface
图:CodeBuddy 在生成完所有文件后,把"常见坑自查"清单一条条列了出来,并且显示"30 个文件 检查点 1",确保没有任何一条违规
我特意仔细看了"常见坑自查"这一段——这是 CodeBuddy 主动做的质量门,不是被动等我去问。这一点很关键:它不是只生成代码就完事,它会主动按你给的验收标准做一遍自检。这对一个独自做鸿蒙应用的人来说是救命的功能——平时我们写完代码,肉眼很难发现"@Prop没加导致父组件更新不刷新"这种隐蔽 bug。
五、第一次踩坑:服务卡片的 metadata 报错
我以为代码生成完就直接可以编译了。然后我打开了 DevEco Studio,按下 ⌘+F9 编译——
> hvigor ERROR: 00303223 Configuration Error Error Message: The metadata field in FormExtensionAbility cannot be left blank or as an empty array. At file: /Users/zhubo/Desktop/HarmonyOSAI/smart-receipt-demo/entry/src/main/module.json5 > hvigor ERROR: BUILD FAILED in 701 ms图:DevEco Studio 编译输出窗口的报错信息,清楚指出 FormExtensionAbility 的 metadata 字段不能为空
我看了一眼module.json5,发现 CodeBuddy 最初生成的版本里,把卡片 forms 配置直接内联在了extensionAbilities[0].forms数组里,没有metadata字段。这是 HarmonyOS NEXT 某个版本(应该是 API 12)的严格校验要求——FormExtensionAbility必须有非空metadata。
我没有自己改,而是把报错信息直接贴回 CodeBuddy。
CodeBuddy 用了不到 10 秒做出了"深度思考":
问题明确:FormExtensionAbility 必须有非空 metadata 字段。标准做法是把 forms 配置移到独立的 form_config.json,通过 metadata 引用。我来同时创建配置文件并更新 module.json5。
然后它给了我两个文件的 diff:
- 新增
resources/base/profile/form_config.json— 把卡片 forms 配置独立到单独文件 - 修改
module.json5的ReceiptFormAbility— 添加metadata字段(ohos.extension.form→$profile:form_config),移除原内联forms数组
图:CodeBuddy 给出"深度思考 + 修复方案"的过程,把 form_config.json 与 module.json5 的 diff 完整展示,并让我选择"保留 / 撤销"
我点了"保留"。然后——
第二次编译,又来一个错:
> hvigor ERROR: 00303038 Configuration Error Schema validate failed, at file: module.json5 property name 'formsEnabled' is not valid allowedValues: ['priority', 'name', 'srcEntrance', 'srcEntry', 'icon', 'label', 'description', 'type', 'permissions', 'uri', 'readPermission', 'writePermission', 'visible', 'exported', 'skills', 'metadata', 'extensionProcessMode', 'dataGroupIds', 'process', 'appIdentifierAllowList']这是说formsEnabled这个字段在当前 SDK 的extensionAbilitiesschema 里不被允许——卡片是否启用由type: "form"+metadata引用决定。我又贴回 CodeBuddy,它直接把formsEnabled: true删了。点"保留",再次编译,过了。
前后不到 2 分钟,两个错全部修复完毕。而如果让我自己查 StackOverflow + 啃文档,至少要 20-30 分钟。
这是我用 CodeBuddy 学到的第四点心得:报错信息直接甩回去,比你自己研究高效 10 倍。AI 不仅懂报错,还能根据工程上下文(你的module.json5当前长什么样)做最小化修复。
六、第二次踩坑:Core Vision Kit 的 API 不对
编译过了前两个错之后,我看到了 ArkTS 编译器报告的 7 个错误:
1 ERROR: Use explicit types instead of "any", "unknown" (arkts-no-any-unknown) 2 ERROR: Use explicit types instead of "any", "unknown" (arkts-no-any-unknown) 3 ERROR: Namespace 'textRecognition' has no exported member 'TextRecognizer' 4 ERROR: Property 'TextRecognizer' does not exist on type 'typeof textRecognition' 5 ERROR: Namespace 'textRecognition' has no exported member 'RecognizerConfig' 6 ERROR: Property 'RecognitionMode' does not exist on type 'typeof textRecognition'显然 CodeBuddy 第一轮写VisionService.ets的 OCR 代码时,参考了老版本的 Core Vision Kit API——用TextRecognizer.createRecognizer()创建实例、recognize(pm, config)调用、result.blocks[].text拼文本。
但 HarmonyOS NEXT 的新 API 完全不是这样:
// 新 APIimport{textRecognition}from'@kit.CoreVisionKit';constvisionInfo:textRecognition.VisionInfo={pixelMap:pixelMap};constconfig:textRecognition.TextRecognitionConfiguration={isDirectionDetectionSupported:false};constresult=awaittextRecognition.recognizeText(visionInfo,config);consttext=result.value;// 直接拿字符串我注意到:CodeBuddy 一开始检索时其实用的是"textRecognition TextRecognizer createRecognizer"这种老旧关键词,搜出来的结果也是过时的。新版应该是recognizeText这个新接口。
图:CodeBuddy 在修复 Core Vision Kit API 时,展示了旧 API(错误)vs 新 API(正确)的对比,并把"用 textRecognition.VisionInfo 包装输入、用 result.value 直接拿字符串"作为修复重点
我让它去搜了"@kit.CoreVisionKit textRecognition createRecognizer recognize API 正确用法 ArkTS 2025"——这次检索命中了一篇腾讯云开发者社区的文章,里面给出了完整的recognizeText新接口示例。CodeBuddy 据此重写了recognize方法:
staticasyncrecognize(pm:image.PixelMap):Promise<OcrResult>{try{constvisionInfo:textRecognition.VisionInfo={pixelMap:pm};constconfig:textRecognition.TextRecognitionConfiguration={isDirectionDirectionSupported:false};constresult=awaittextRecognition.recognizeText(visionInfo,config);constfullText:string=result.value;// ...}catch(e){// 错误处理}}新版 API 简洁得多——没有 recognizer 实例要创建/释放,没有 blocks 数组要遍历,直接recognizeText+result.value。再次编译——过了。
这里我学到第五点心得:AI 也会用过期文档,所以"搜索关键词要具体 + 时间维度"很重要。如果你看到 AI 引用了某 API 但觉得它不太对劲,直接说"这个 API 是不是过时了?搜一下 2025/2026 的最新用法"——比你自己查高效。
七、读 README:CodeBuddy 把我没想到的也写进去了
编译过了,HAP 包能成功打包出来。但我还没高兴多久,我意识到一个事——这个应用到底长什么样?四 Tab 到底切换成什么风格?账单列表怎么分组?意图协同页要展示什么内容?
我打开 CodeBuddy 生成的README.md。
图:DevEco Studio 左侧工程树,右侧打开 README.md 预览,CodeBuddy 正在右侧对话窗口中提示"改用正确的 Core Vision Kit API"
不看不知道,一看吓一跳——CodeBuddy 在 README 里写了一段我自己都差点漏掉的章节:“双引擎识别:端侧 OCR + AI 智能识别”。
它把"端侧 Core Vision Kit"和"联网阿里百炼 qwen-vl-plus 多模态大模型"做了对比表:
| 维度 | 端侧 OCR | AI 智能识别 |
|---|---|---|
| 网络依赖 | 完全离线 | 需联网 |
| 隐私 | 最好,图片不出设备 | 图片发至云端模型 |
| 输出内容 | 原始文本 + 金额/商家/日期正则猜测 | 直接出结构化 JSON + 置信度 + 判断依据 |
| 适用场景 | 隐私敏感、无网络环境 | 手写小票、复杂版式、想要更准确的自动分类 |
虽然我最初的提示词里没有明确说要写这个对比——但 CodeBuddy 觉得"作为效率工具文档,应该让用户知道两种方案的取舍",于是主动加上了。
这就是我学到第六点心得:让 AI 写文档时不要只给"功能列表",要让它有"思考权"——它经常能补上你自己都没想到的"对比维度"和"踩坑提醒"。这种主动补全不是越界,是增值。
八、跑起来:那张小票被识别出来了
编译通过后,我连上 DevEco Studio 的 Mate 80 Pro 模拟器,点 Run。
App 起来了。沉浸式全屏的"智慧收据管家"首页,淡蓝渐变的"本月支出"统计卡,下面是「📷 拍照识别」「🖼 相册选图」两个按钮。底部四 Tab:拍单 / 账单 / 意图 / 我的。
我点「🖼 相册选图」,选中了那张乐购超市的小票照片。
图:那张被识别的小票——"乐购生活超市"购物小票,日期 2024-05-25,金额 166.77 元,商品总数 12 项
应用开始 loading,几秒后弹出识别结果卡:
- 金额:166.77
- 商家:乐购生活超市
- 日期:2024-05-25
正确!OCR 居然一次性把这三个关键字段全部识别对了——尤其金额 166.77 出现在"应付金额"旁边,正是OcrParser.ts里正则匹配的优先级最高的关键词行。
图:DevEco Studio 模拟器中,应用拍单识别页成功识别出小票关键字段:金额 166.77、商家"乐购生活超市"、日期 2024-05-25
我又切到「🎙 意图」Tab,在"模拟语音触发"输入框里输入"记一下打车35元",点「解析并记账」——Toast 弹出🎙 模拟语音记账成功:¥35.00,账单页也多了一笔 35 元的"交通"分类记录。
最后我长按模拟器桌面,添加「智慧收据管家 · 本月支出」卡片——桌面上立刻多出一张 2×2 的卡片,显示:
🧾 智慧收据管家 [刷新]
¥ 201.77
本月支出
本月 2 笔 打开记账 ›
整个应用从 0 到能跑,4 小时。
九、回头看:CodeBuddy 改变了我的工作流
从这次完整的"4 小时从需求到可跑"经历里,我总结出几个 CodeBuddy 的"神仙用法":
1. 把需求写成"产品 PRD",而不是"几个关键词"
我最初给的提示词有 6000+ 字,包含了项目定位、技术栈、四个 Tab 的详细功能、视觉风格、数据模型、工程结构、常见坑规避清单、交付要求八个大节。CodeBuddy 据此生成的工程,几乎不需要我再补任何架构性修改。
对比我之前让别的 AI 写"帮我做个记账 App"得到的产物——一个连module.json5都配不对的 Hello World——差距是提示词的工程化程度决定的。
2. 报错信息直接甩回去,不要"自己研究 30 分钟再问"
中途两次编译错误(metadata 缺失、API 过时)我都是直接把 DevEco Studio 的报错原文贴给 CodeBuddy。它用 10 秒定位问题 + 给出最小修复 diff + 让我一键 Apply。
很多同事的痛点是"AI 给的答案不可信,我得自己验证一遍"——这其实是对 AI 的不信任。正确姿势是:让 AI 给出"修复 + 解释"两栏,你 review 解释后决定 Apply 还是 Discard。它的解释通常比报错堆栈更易懂。
3. 跨设备续聊:PC 写完,手机补一句
那晚我躺在床上用手机上的 CodeBuddy 加了一条"意图执行器无 amount 时的兜底逻辑"补丁。第二天打开 PC 上的 CodeBuddy,对话历史完整保留——它记得我们之前所有的修改、检索、决策。这才是"AI 编程助手"区别于"AI 聊天机器人"的核心特征。
4. 让 AI 主动做"质量门"
CodeBuddy 在生成 30+ 文件后,主动把提示词里"常见坑清单"逐条对照过了一遍,把每条 ✅ 还是 ❌ 标了出来。如果某条不通过,它会主动修复。这种"self-check before delivery"对独立开发者太重要了——平时我们写完代码很少回头逐条对照规范。
5. 不止写代码,还补全文档的"思考维度"
README 里那段"端侧 OCR vs AI 大模型"的对比表,是 CodeBuddy 主动加的。我最初的提示词里没有这个对比——它判断"作为一个效率工具的文档,应该让用户知道两种方案的取舍"。这种"主动补全"是 CodeBuddy 给我最大的惊喜。
十、写在最后:从一张小票到一个完整的工程
那张 2024-05-25 的"乐购生活超市"小票,现在变成了一款 30+ 文件、可编译运行、覆盖 Core Vision Kit + 意图框架 + 服务卡片三大鸿蒙新能力的完整 Demo。
我没有从零敲一行代码——但我做了更重要的事:把需求想清楚、把验收标准写明白、把报错信息贴回来、把每一处 AI 的修复 review 到位。
CodeBuddy 不是"替你写代码的工具",它是"把你的想法落成可编译工程的协同者"。你仍然是架构师、产品经理、质量门——它只是把你从一行一行import那些琐碎工作中解放出来,让你能专注在"这个应用想解决什么问题"这种真正重要的思考上。
如果你也想试试我的方法,路径很简单:
- 打开 CodeBuddy,先把你的需求写成 2000+ 字的完整提示词(含技术栈、架构、验收标准、避坑清单)
- 选
Craft模式,让它主动检索最新 API而不是凭记忆写 - 生成代码后让它做一次"常见坑自查"(你给清单,它逐条对照)
- 编译报错时直接把报错堆栈贴回去,让它给最小修复 diff
- 不要嫌它第一版不对——你做 review,它做迭代,三轮之内基本能收敛到可发布状态
