了解了仓颉的特性后,我把双栏对照从 ArkTS 推到仓颉:当时 13 个 .cj 文件、ets/ 清掉、assembleHap 签名成功,类型检查 0 错误。模拟器首跑挂了。后来真机又证伪了两件事:独立 JSRuntime 读不了 picker 的 file://docs,JS 桥关不掉 PC Enhance 三键。语言生成够用;「尽可能全部仓颉」卡在系统壳。

绑定的模拟器(MateBook / PC 镜像)和官方纯仓颉 demo 一样起不来,问题不在业务代码。真机共测把窗口和示例对照跑起来之后,外部授权文件和系统三键仍过不去——那才把分工改成仓颉做产品、ArkTS 做 Ability 壳。

这篇按发生过的顺序写:产品面从哪来、为什么换栈、ZCode 踩过哪些坑、后来为什么改成混合。过程里的「清掉 ets/」「JsBridge 扛系统 API」是当时判断;终态以「仓颉 / ArkTS 分步拆分」那一节为准。
 

全文一图流:迁栈时间线 · 五个翻车点 · 仓颉/ArkTS 终态分工

ArkTS 第一版怎么写出来

起点很明确:要在鸿蒙 PC 上做出一款「足够像」Beyond Compare 的文本 / 文件夹对照应用。主战场当时是 Grok CLI(grok-4.6,子代理常开 high / xhigh):先 /deepinit 生成分层 AGENTS,约束 2in1、无联网登录;文本对照后来有保存,和 Office / PDF 只读不是同一件事。再开 explore / designer / code-reviewer 一类子代理并行推进。

产品决策先于改码。我要求先按 frontend-design 思路出 HTML 设计稿(current / mac / text-compare 几版),审核通过再改 ArkUI;并多次纠正「Mac 风格不等于 Mac 键位和控件位置」——人审设计意图,AI 执行。对标缺口驱动迭代:左右应用与共存、行内差异、批量应用、树形目录、拖入、查找 Ctrl+F、撤销……算法也被追问到「足够像」的可实现定义,而不是模糊的「看起来差不多」。

文件夹双栏对照(产品面)
行级 diff 与写回入口

真机是另一条线。Documents 写回失败、权限与 Profile 不一致、主线程卡顿、会话切换卡顿——典型「AI 先通再优化」环。并行还有 Cursor Background Agent 合入写入完整性 / 路径解析质量 PR:不改公开 API,环境缺鸿蒙 SDK 时用 Node 等价脚本验收。上架阶段审核驳回「功能简单 / 名称笼统」,于是改名「双栏对照」、补截图与申诉文案,商店侧产品名就此定下来。

这一段的优点是:设计先行 + 对标缺口 + 真机闭环,把产品面钉死了。缺点也清楚:根 AGENTS 后来会滞后于仓颉分支;Grok 甚至曾把未跟踪的 cangjie 目录误判成「不要提交」——人审不可省。但 ArkTS 版已经能讲清「双栏对照是什么」;后面换栈要保住的,正是这些交互,而不是「换一门语言交差」。

为什么换仓颉

ArkTS 第一版是用 Grok 冲出来的。产品面已经能讲故事:双栏、行级 diff、上架改名,日常迭代也熟了。换栈不是因为 ArkTS「不能用」,而是我想摸一层更硬的边界——在仓颉硬性任务之下,看「尽可能全部仓颉」到底卡在哪:picker / fileShare、模拟器镜像、真机外部目录、文档只读扩展,哪些能用官方 interop 扛住,哪些必须诚实降级。

转折来得更实际。那时 ZCode coding plan 有一段夜里免费窗口:大约晚上 11 点到早上 9 点。白天用 Grok 继续打磨 ArkTS 产品面;夜里就把长跑交给 ZCode,专门啃仓颉全量迁移——同一会话里开分支、打编译、拉多 subagent 审查、对模拟器与真机。免费档不是广告卖点,是我排期上的真实约束:贵的白天留给产品决策,便宜的长跑留给换栈实验。

所以动机可以收成两句:一是硬性任务逼出「纯仓颉边界」必须被验证——验证结果是系统 API 扛不住,不是全量仓颉成功了;二是夜里免费窗口让重写的 token 成本变得可承受。过闸之后,才轮到 ZCode 把 ETS 推成 CJ。

人侧要先过仓颉体验版 / 公测、DevEco 勾选 Cangjie(Experiment) 或 Install Plugin from Disk、配好 SDK 路径。这些是开工条件,不是本文重点,不展开安装步骤。

一夜级 ETS→CJ:编译绿了,模拟器却挂起

立项后我让同一 ZCode 会话继续长跑:探工具链 → 逻辑层 → UI。当时交付是 13 个 .cj 文件、工程内去掉 ets/,picker / fileShare 走 ohos.ark_interopassembleHap 签名成功,类型检查 0 错误。目录从 main 侧 ArkTS 树迁成更扁平的 .cj 布局,模块仍按 LineDiff / IO / Bridge / View 切开。当时形态如此;Ability 壳后来加回来,见分步拆分那一节。

先正面写清:一夜级 ETS→CJ、模块齐、assembleHap 绿——这说明现模型的仓颉语言生成能力已经够用,迁移不是卡在「不会写 .cj」。后面语义坑与镜像,定性为验收与环境门,不是模型不会仓颉;编译绿仍只是门口,绝不能停在 cjc。

main ArkTS 目录树 ↔ cangjie 扁平 .cj 树

但我绑定的模拟器目标(127.0.0.1:5557)首跑并不顺:生命周期超时一类失败会把「编译过」打回原形。官方纯仓颉 demo 在同一类环境也能复现卡死 / 起不来,说明问题未必只在业务代码。优点是:Agent 能把构建链打通到签名 HAP;缺点是:停在 cjc / 类型检查,距离「能跑」还差一整层运行时与镜像。

/goal 在这里的作用很实际:我把「cangjie 化 + DevEco 编译 + 模拟器自测」写成可引用的 session target,长跑中会被反复提醒。目标写清楚,不等于环境一定配合——但至少不会在聊天里把「编过」偷换成「测过」。构建侧还有一批琐碎但致命的记忆点:SDK 路径漏设会直接找不到仓颉工具链;增量构建偶发不重编时需要 clean;deviceTypes 声明与安装目标不一致会报安装错误码。这些我都要求写进 memories,而不是每次靠人肉回忆。

多 Subagent 审查:编译过不等于能跑

我让 ZCode 并行开了几路只读审查(API 语义、与 ArkTS 等价、运行时卡死、UI)。当时主要做了类型检查,首跑仍炸出一批 P0——ifv、UTF-8 切片这类。三份有效报告推进了修复;UI 那一路几乎空窗,后来靠真机共测补。多 Agent 不是自动完备,空窗必须记账。

模拟器镜像:MateBook 没有仓颉 ArkUI

我纠正 Agent:「仓颉是支持在模拟器运行的,你再试试。」这句把排查从「再改业务代码」推进到环境级对照:5557 对应的是 PC / MateBook 镜像,缺少仓颉 ArkUI 组件实现;即便 escape 打包拉起 runtime,仍可能报 Row.ti: symbol not found。当时要 phone_all_arm 一类镜像(例如 Mate X7 / Pura 90)才带组件库——这是模拟器退路,只能证明仓颉 ArkUI 能起来,不能拿来冒充 2in1 产品过线。产品验收后来在 HarmonyOS PC 真机。

运行时子代理的价值在于:正确区分「代码 bug vs 环境」,用官方 demo 与镜像内库文件扫一眼,避免在应用代码上空转。优点是环境结论可沉淀进 memories;缺点是设备折腾成本高——PC 镜像、escape、phone 镜像、真机断连 / 锁屏,都会吃掉长跑时间,goal 绑定的那台模拟器也可能长期不可用。

模拟器起不来,是仓颉 6.1 运行时和 PC 镜像的事,不是业务代码。分账记在这里:编译绿、类型检查过、官方 demo 也挂——不要把锅甩给 EntryView。

真机共测:闪退、黑按钮、全屏 1300002

我连上真机并反馈:「我装上了,直接闪退。」修好后窗口能完整显示「双栏对照」。紧接着我又反馈:「图标 button 都显示的全黑了,下拉选择器也全黑了。」根因是数值色 TRANSPARENT = 0 被当成不透明黑;改成真正的透明色常量后 UI 恢复。仓颉侧缺少部分资源宏习惯时,颜色更容易被写成裸数值,这类坑属于「编译看不见、一眼看得到」。

全屏路径也踩过坑:裸 resize 在异常窗口态抛 1300002 This window state is abnormal,未捕获会直接把进程打掉——我的体感是「点全屏变成关闭了」。修完后我明确分工:「功能我自己测」——Agent 负责构建、单点验证与平台探针,深度功能验收留在我这边。标题栏隐藏、最大化与恢复是否合并为同一按钮等产品细节,也要在与 main 对齐时逐项核对,不能假设「迁完语言交互自然还在」。

这一段的优点是人机闭环极短:我装包 → 反馈 → Agent 定点修。缺点是:当时真机外部目录遍历仍受平台策略约束,文件夹对照在仓颉独立 JSRuntime 里不能假装和桌面端完全同构。没有拖拽、没有 GBK、暗色主题暂用亮色常量——适合写进说明,而不是藏进演示稿。picker 读和关三键后来迁到 ArkTS,见分步拆分。

文档对照:JsBridge 只读,先不对齐写回幻想

产品继续往前:我问怎么比对 Word / Excel / PDF / PPT?写回呢?Beyond Compare 是不是就能写回?分析之后的关键结论是:BC 对 Office / PDF 也常见「加载时转纯文本再比」,并不能把编辑存回原格式。仓颉侧用已验证的 JsBridge 模式扩展能力:从 entry 视图到 picker / doc_bridge,再到 js_bridge 调系统模块(zlib、PDF Kit 等),把文档归一成行后复用现有 LineDiff。

entry_view → picker/doc_bridge → js_bridge → 系统模块

我拍板:「做吧,就先做只读吧。」Mate X7 模拟器上 docx / xlsx / pptx E2E 可通过;PDF 在缺 Kit 的模拟器上降级提示。本地验证界面如下——这是「先调研、再编码、再缩小范围」的产品决策,而不是一上来承诺写回原格式。OOXML 本质是 zip + XML,配合 zlib 解压后再抽文本,路径清晰;PDF 则依赖 Kit,环境缺失时必须有降级文案,不能静默失败。

仓颉分支文档对照相关界面(本地验证)

文档对照这条链路,沙箱里的 zlib / PDF Kit 仍可以走 JsBridge。picker 授权后的外部读不行,关 PC Enhance 三键也不行——系统壳后来还给 ArkTS。

仓颉 / ArkTS 分步拆分:系统壳必须还给 ArkTS

纯仓颉把界面和 diff 写出来之后,两件事在真机上被证伪。一件是独立 JSRuntime 里调 file.fs.readText 读 picker 给的 file://docspersistPermission 能回报成功,随后读文件仍是 No such file or directory / Permission denied,不能把「授权成功」当成「可读」。另一件是关 PC Enhance 三键:JS 桥传 boolean / "false" / new Function 都会「成功」,但 EnhanceMaximizeBtn 仍 visible。仓颉 WindowStage 没有 disableWindowDecor,官方还要求在 loadContent 之前调用;模块里一旦出现 .ets,hvigor 又要求 ArkTS 做 Ability 入口。

所以改成分工,而不是再把系统 API 塞进仓颉运行时。仓颉继续做产品:界面、diff、会话、沙箱文件。ArkTS 只做必须带 Ability token、或必须在 loadContent 之前调用的系统壳。不要再从仓颉 JSRuntimefile.fs,也不要把 FileHost 做成独立 HAR 再 requireArkModule——那仍在仓颉运行时里跑,token 问题还在。仓颉调 ArkTS 走官方互操作(registerJSFunc / 导出函数),AppStorage 不能跨语言。

混合脚手架本身也踩过坑。DevEco 模板的 @cangjie/cjhybridview 会去加载一份 HAP / SDK 6.1 里没有的 so,真机直接杀进程。可用的是 @cangjie/cjhybridcomponent@1.1.1。还要在模块级登记 pages,并把仓颉 so 做成 NAPI 模块。ArkTS 在 Index.aboutToAppear 里把 Ability context 交给仓颉;AppStorage 不能跨语言。

门禁按步过,不过不进下一步。设备是 HAD-W24,HarmonyOS 6.1。用 uitest dumpLayout 对主文案和控件树,不要只看截图——桌面「开发者选项」窗也有一组 Enhance 三键,不要和 DualPane 窗搞混。

做什么

真机结果

0 混合宿主

ArkTS Ability + 宿主页嵌仓颉 EntryView,不改对照逻辑

启动仍是「双栏对照」;帮助里示例 docx 对照能进(状态「文档对照(docx · 只读)」)

1 关三键

loadContent 前试 disableWindowDecor;加载后再走公开装饰接口关系统三键

disableWindowDecor 是系统 API,三方调用会杀进程,必须接住。公开接口从 Ability 调才生效。DualPane 窗内无 Enhance*Btn,只剩自绘 – □ ✕;树上还能看到的 Enhance 属于设置窗

2 FileHost 读

ArkTS 做 picker / persist 读 / readText / listFile;仓颉互操作拿 URI + 文本,再走现有对照

左右各选一对外部 cl.h 进入「文本对照」。hilog 是 arkts pick okarkts readText okfile://docs 先 miss,落地路径成功),不再是仓颉独立运行时读失败

第 0 步过了才有后面;混合嵌页会动焦点、快捷键、窗口拖动,所以单独验收。仓颉 Ability 入口已删,只剩 ArkTS。onBackground 经导出的 savePrefs() 触发仓颉偏好保存。自绘三键、对照算法、会话、示例文档仍留在仓颉。写回外部 URI 做了 FileHost 兜底,没有覆盖用户文件,另存为没点通——不算过门禁。

这一段把「纯仓颉 + JsBridge 扛系统 API」收了口。门禁可复现的是宿主、关三键、外部读;写回外部 URI 还缺一次不伤用户文件的验收。前面「工程内去掉 ets/」「外部目录不能同构」那两句,以这一节为准。

Memories 与「谨慎追求」:把坑写成可继承资产

长跑真正可复用的,不只是某次提交,而是项目 memories:每次 Bash 内联仓颉 / SDK 路径、当时用 phone_all_arm 只为让模拟器带上仓颉 ArkUI(不是 2in1 过线)、foreign func 与保留字、文件 API 限制、文档对照状态、以及协作偏好(中文沟通、「功能我自己测」、对标 Beyond Compare、偏谨慎低风险改进)。没有 memories,下一轮 Agent 会用相同代价再踩一遍镜像与路径坑。

我后来要求进入「谨慎追求模式」:候选改动先过收益 / 风险 / 验证门槛,小步提交 + 模拟器回归,并设停止条件。todos 清零不等于产品完结,而是质量轮有可复现的节奏。Token 成本很高,须写进排期——质量换得到,但不是免费。把成本写进排期,比事后抱怨「AI 太贵」更工程化。

双栏对照这条链写到混合拆分为止——ArkTS 产品面、换栈动机、ZCode 迁移坑、以及后来必须把系统壳还给 ArkTS 的真机证据。

再补一条协作经验:Agent 适合扛「全量翻译 + 构建探针 + 最小复现」,我不适合缺席「硬性任务定义、真机装包反馈、只读还是写回的产品拍板」。双栏对照这条链能走通,靠的是分工清楚,而不是模型单方面天才。把分工写进 /goal 与 memories,比事后复盘「那天到底谁说了算」便宜得多。若你的团队还在用「手搓每一行」衡量产出,迁移周会看起来像偷懒;若用验收衡量,你会看到编译绿只是起点。ZCode 管迁栈长跑;混合拆分是后来另开的真机验证,不要记到那一夜会话上。ArkTS 期 Grok 只作产品前史。

收益与代价

双栏对照仓颉端口:收益与代价

收益(优)

  • 先有可读的 ArkTS 产品面(设计过审、对标缺口、上架定名),再谈换栈——迁移保住的是交互,不是文件后缀。

  • 硬性任务逼出「纯仓颉边界」必须被验证;/goal 把目标写进可引用的 session target。验证结果是系统壳扛不住,不是全量仓颉成功了。

  • ZCode 单会话扛住迁栈长跑:可行性 → 重写 → 编译 → 多 Agent 对抗 → 镜像根因 → 真机 UI → 文档抽文本。语言生成够用;系统 API 后来另开混合拆分验证。

  • 并行 subagent + 声明文件对照,抓住「编译过 ≠ 能跑」的语言语义坑;真机共测闭环短。JsBridge 能扛沙箱文档抽文本;picker 读和关三键不行。memories 降低重复踩坑。

  • 产品决策先调研再编码:Office / PDF 对照只读,文本文件另有保存。两件事不要混成一句「产品只读」。

代价(缺)

  • 初判保守可能延误;UI 子代理失败导致审查视角空窗。

  • 类型检查 0 错误不等于可跑;仓颉插件 / SDK 需单独开通,不是开箱即用。模拟器与真机环境成本高,要单独算。

  • 平台能力缺口仍在(拖拽、GBK、PDF Kit 模拟器缺失)。外部目录读已在混合拆分后门禁通过;外部 URI 覆盖写还缺一次不伤用户文件的验收。写回原格式(Office/PDF)未启动。

  • Token 与时长可见且昂贵,必须写进排期,而不是事后惊讶。

一句话收束:现模型的仓颉能力已够扛产品迁移;系统壳必须还给 ArkTS。迁栈这条链要说清的是——从 ArkTS 产品面走到硬性任务换栈,ZCode 可以把对照逻辑推到本地可安装的仓颉分支,但绝不能在 cjc 全绿处停笔,也绝不等于「文件都变成 .cj」。终态是仓颉做产品,ArkTS 做 Ability 壳。

 #鸿蒙 #HarmonyOS 7(API 26)

Logo

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

更多推荐