我用 ArkTS 自研了一个鸿蒙原生思维导图组件,已上架 ohpm,并让 DeepSeek 驱动它渲染复盘脑图
一行命令安装:
ohpm install mindmap-harmonyohpm 详情页:ohpm.openharmony.cn/#/cn/detail… 组件源码:
github.com/725lizi/Min… 落地应用:
一、先看成果
这是一个 HarmonyOS NEXT 原生(ArkUI + ArkTS)思维导图 HAR 组件库,零 WebView、零三方依赖,已经通过 ohpm 中心仓审核正式上架(v1.0.0,MIT 协议,整包 59KB)。
它能做的事:
-
传入一棵标准树节点 JSON,自动完成树形布局、节点渲染、缩放平移、节点编辑;
-
支持 JSON 序列化 / 反序列化、组件截图、一键保存 PNG 到系统相册;
-
内置自研的后序轮廓紧凑布局算法,不对称的树也能排得紧凑、不重叠;
-
74 个本地单元测试守护,覆盖数据模型、布局算法、视口状态机、序列化、编辑控制、主题。
更有意思的是,我在自己的另一个应用 FocusTimer(鸿蒙专注计时 + DeepSeek AI)里真实使用了它:把用户一周的专注记录交给 DeepSeek,让大模型输出思维导图结构化 JSON,再由这个组件直接在 App 内渲染出「效率复盘脑图」;断网、没配 Key、AI 返回脏数据时,自动降级为一棵本地规则树,页面永远不白屏。
整条链路:
本地专注记录 → 组装上下文 Prompt → DeepSeek 流式输出
→ JSON 清洗/纠错/归一化 → 反序列化为 MindTree → 自研组件渲染
  ↓ 任何一步失败
  本地规则树兜底渲染
:本文所有图片已随稿放在
article_images文件夹,在掘金 / 华为开发者社区编辑器里按下方「配图清单」逐张拖入对应位置即可(平台会自动托管图片,不依赖外链)。
配图清单(按文中出现顺序):
| 序号 | 文件 | 出现位置 / 说明 |
|---|---|---|
| 1 | focus-timer-ai.png | 第一节成果,AI 成功路径(紫色 ✨ AI 徽章) |
| 2 | basic.png | 4.1/4.2 布局与整树适配,基础渲染真机图 |
| 3 | gesture.png | 4.2 手势交互,双击 / 平移 / 捏合 |
| 4 | edit.png | 4.3 键盘流编辑与选中描边 |
| 5 | export.png | 4.4 序列化往返与保存 PNG 到相册 |
| 6 | focus-timer-rule.png | 第五节,断网 / 无 Key 规则兜底路径 |
二、为什么要自己造这个轮子
市面上的鸿蒙脑图方案大多是两种:WebView 套一个 H5 脑图库(启动慢、包体大、手势跟手性差),或者只给一堆节点让你自己摆坐标。我想要的是:
-
纯原生:ArkUI 组件直接绘制,双指缩放、单指平移要跟手;
-
数据驱动:调用方只管给树数据,坐标全部由布局算法算,不需要手摆;
-
职责干净:组件库不内置任何 AI、网络依赖,其他开发者
ohpm install之后不需要配置任何 API Key; -
能被真实项目使用,而不是只跑在 Demo 里。
第 3 点是整个项目最重要的架构决策,后面会专门讲 ——AI 能力全部放在上层 App,组件只认标准 JSON。正是这条边界,让同一个组件既能被普通开发者当纯 UI 库用,也能被我自己拿来渲染大模型的输出。
三、三行代码接入
import { MindTree, MindNode, MindMapView } from 'mindmap-harmony';
const tree = new MindTree('中心主题');
tree.addChildTo(tree.root.id, new MindNode('n1', '分支一'));
// build() 中挂载;编辑后把 refreshTick 自增即可触发重新布局
MindMapView({ root: this.tree.root, refreshTick: this.tick })
组件只认这样一份标准树节点 JSON 契约(也兼容大模型 / 后端直接吐出的裸根节点):
{
  "id": "root",
  "text": "中心主题",
  "children": \[
  { "id": "n1", "text": "分支一", "children": \[] }
  ]
}
四、核心技术点拆解
4.1 自研紧凑树形布局:后序轮廓(tidier)算法
脑图布局的难点不在对称的「教科书树」,而在不对称的真实树:一个分支有 3 层、另一个分支是叶子,怎么排才能既不重叠又紧凑?
我实现的是经典 tidy tree(Reingold–Tilford 思想)的后序轮廓版本:
-
后序遍历:先排好所有子树,再处理父节点;
-
每个子树维护自己的左 / 右轮廓(每一层最靠外的节点坐标);
-
相邻兄弟子树按轮廓逐层计算最小避让距离,只做一次整树平移,不反复重排;
-
父节点居中在孩子上方,连线天然不穿透。
复杂度是 O (n・深度)。一棵典型 G4 形态的小树(根下 A、B 两支,A 有多层后代、B 是叶子),紧凑布局后整树高度从 212 收到 182,叶子 B 自动收在 A 的子树下方,没有大片空洞。
这部分是纯逻辑:输入树结构,输出每个节点的 x/y 和连线表,不 import 任何 ArkUI 能力,所以可以在 Node 里离线单测,也可以在大模型辅助生成后用黄金坐标独立验收。
4.2 视口状态机:把「缩放平移」做成纯逻辑
手势代码最容易写成一团面糊。我的做法是把视口状态(scale、offsetX、offsetY)和手势识别分开:
-
ViewportController是一个纯状态机:zoomBy / panBy / clampScale / clampOffset / reset,缩放上下限、平移钳制(不让内容被拖出视野)全在这里,有独立单测; -
computeFitView是一个整树适配纯函数:输入内容宽高、视口宽高、留白,输出「让整棵树完整居中」的初始缩放比和平移量; -
ArkUI 侧只负责把手势事件翻译成对状态机的调用,再把结果映射到
scale()/translate()。
由此得到几个体验:首次进入自动 fit-to-screen 整树居中;双击在「放大 2x / 回到适配视图」之间切换;用户一旦手动缩放 / 平移过,布局刷新就不会再抢视口。
4.3 键盘流编辑与选中态
按钮点选适合触屏,但高频录入需要键盘流(XMind/MindNode 的肌肉记忆):
-
回车:在选中节点后加一个同级节点(选中根节点时降级为加子级);
-
Tab:下沉一层加子级,并消费掉按键事件、拦住默认焦点跳转;
-
输入框为空时按 Delete:删除选中节点(根节点受保护),输入框有文字时不拦截,保证正常删字。
渲染层新增一个可选入参 selectedId:命中的节点用主题里预留的琥珀色(#F59E0B)画 2px 描边,其余节点维持默认灰边;不传这个参数的页面视觉零变化。选中态放在组件库内部而不是让每个页面自己画框,接入方就能免费得到一致的选中反馈。
编辑操作统一走 EditController 一个入口,渲染层只读树、不改树 —— 单一数据源让撤销 / 刷新 / 测试都简单很多。
4.4 图片导出:用新 API,不留弃用调用
组件截图走的是 UIContext.ComponentSnapshot#get 新 API(全局 componentSnapshot.get 从 API 18 起弃用),ImageExporter.saveToGallery 再通过 photoAccessHelper 保存 PNG 到系统相册,内部处理了运行时权限申请和成功 / 失败 / 拒绝授权三种状态。
一个工程细节:HAR 包本身不声明任何权限,权限由宿主 App 在自己的 module.json5 里声明 —— 组件不越权替接入方做决定。
4.5 序列化:宽容读、严格写
JsonSerializer 反序列化时兼容两种输入:完整信封 {format, version, root} 和裸根节点 {id, text, children};对非法输入抛出带错误码的异常(空输入、JSON 非法、缺字段、类型错误),而不是返回一棵半残的树让渲染层崩溃。这个「宽容读、严格写、错误可识别」的设计,恰好是后面接大模型输出的关键。
五、和 DeepSeek 闭环:组件保持纯净,容错全部在上层
这是整个项目我最喜欢的部分。FocusTimer 是一个已经接好 DeepSeek(兼容 OpenAI 协议、流式返回)的专注计时应用,我让它基于用户一周的专注数据生成复盘脑图。
5.1 为什么 AI 绝不写进组件库
如果组件库里内置 AI 调用,会立刻带来三个问题:所有安装者都要配 API Key;网络 / 模型的不确定性污染纯 UI 组件;单测要 mock 网络。所以边界划得非常硬:
-
组件库:只接收标准 MindNode JSON,负责渲染 / 交互 / 导出,零网络、零 AI import;
-
App 业务层:负责组 Prompt、调 DeepSeek、清洗返回 JSON、失败兜底。
5.2 容错链路(重点)
大模型不可怕,可怕的是它「偶尔不听话」。真实返回里可能裹着 ```json 代码围栏、带解释性文字、id 重复或缺失、节点文本超长、children 不是数组。我在业务层做了三道工序:
-
MindMapPromptBuilder:把专注统计(本周 / 上周时长、科目分布、打断次数等)注入 Prompt,固定输出四个分支(总体情况 / 科目分布 / 专注质量 / 下周行动),约束 8~20 个节点、深度 2~3 层、叶子文案不超过 16 个汉字,
stream:true流式返回; -
MindMapJsonExtractor:剥围栏、截取第一个
{到最后一个};归一化时根节点固定 id、缺失 / 重复 id 按层序补全、空白文本给默认值、超长文本截断、非法 children 置空,且整个过程幂等;解析失败给出明确错误码(空 / 无 JSON / 非法 JSON); -
RuleMindMapBuilder:只要出现「没配 Key / 断网 / 流式报错 / JSON 解析失败」中任意一种,直接用本地统计数据拼一棵四分支齐全的规则树,页面照常出图,并给用户一条橙色提示说明当前是本地结果。
DeepSeek 正常 → 紫色「✨ AI 生成」徽章 + 绿色提示
无 Key/断网/坏 JSON → 灰色「本地规则」徽章 + 橙色提示
组件的 deserialize 是最后一道闸:业务层归一化后的数据还要再过一遍组件自己的严格校验,双层保险。
六、质量工程:我怎么敢说它「能用」
这个项目我刻意用了比一般课设项目严格得多的验证方式:
-
组件库 74 个 hypium 本地单元测试:数据模型、布局、视口、序列化、编辑、主题全覆盖;
-
黄金坐标 + 随机不变量审计:布局算法先由大模型产出,我独立手算 9~12 组黄金坐标逐位比对,再在 Node 里重写一遍函数,跑 2 万组随机树,断言「无重叠、连线不穿透、必装得下」等不变量,全部为 0 违例才冻结;
-
AI 纯函数 25 个单测 + 跨项目审计:FocusTimer 侧的 Prompt 构建 / JSON 清洗 / 规则兜底是纯函数,25 个用例离线跑;还用 2 万组随机摘要和恶意脏树文本,真实穿过组件库的反序列化器做跨项目审计,验证任何脏数据都不会让组件崩溃;
-
三路径装机手测:在线出 AI 树、断网 / 无 Key 出规则树、返回重进无残留且原 AI 周报零回归。
一个方法论:不 import ArkUI、输入数字输出数字的纯逻辑,交给大模型写并配黄金用例;碰组件生命周期、手势、现有类签名的 UI 接线,由更懂鸿蒙的代码模型处理。两类任务分开路由,再用独立验收(而不是看模型自己说「通过了」)兜底,效率和质量都最高。
七、ohpm 上架实战:四个没人提前告诉你的坑
上架本身不要钱,但审核是真的会退包。把我踩平的四个坑列出来,帮你少走弯路:
-
SSH 公钥必须 ≥ 4096 位。2048 位网站直接提示「公钥长度太小」,用
ssh-keygen -t rsa -b 4096生成; -
私钥必须带口令,而且只认经典 PEM 加密格式。无口令私钥直接被拒;新版 OpenSSH 格式(
BEGIN OPENSSH PRIVATE KEY,即使已加密)也不认,必须加-m PEM,生成后文件头应包含Proc-Type: 4,ENCRYPTED。口令不能明文写进配置,要用 ohpm 的加密组件加密后存到.ohpmrc的key_passphrase;私钥文件权限还要收紧到仅所有者可读; -
author 字段必须带邮箱和网址。只写一个名字会被 400 退回(
no author url or author email),要写成{name, email, url}; -
包内必须有非空 CHANGELOG.md。README、LICENSE 之外,审核还要求更新日志,放在模块根目录并确认被打进 HAR。
另外:同一版本号提交后不能重复发布,被退回改完要升版本号(如 1.0.1);「包内含源码」的警告对 MIT 开源项目是正常的,不用处理。最终我的包 59.1KB、21 个文件,提交后进入自动化扫描 + 人工审核,通过后 ohpm install mindmap-harmony 即可安装。
八、写在最后:这个项目的简历叙事
很多简历项目要么「只调了一下大模型 API」,要么「写了个组件但没人用」。这套东西把两件事缝成了闭环:
-
会造底层可复用的轮子:自研布局算法、手势状态机、序列化、导出,74 个测试,发布到 ohpm 中心仓,任何开发者都能安装;
-
会把轮子结合大模型做成产品:真实 App 里消费这个组件,处理流式返回、脏 JSON、离线兜底等工程问题;
-
有明确的架构判断力:AI 在上、组件纯净,通过标准 JSON 契约解耦,两个仓库 README 互相引用、都有真机截图。
面试时可以直接演示:打开 ohpm 详情页 → 新建工程一行命令装上 → 打开 FocusTimer 现场生成一棵 AI 复盘脑图 → 断网再点一次,降级成规则树。能现场跑通的东西,比十行「精通鸿蒙开发」有说服力得多。
资源链接
-
ohpm 安装:
ohpm install mindmap-harmony -
落地应用 FocusTimer:github.com/725lizi/Foc…
本文涉及的组件版本为 mindmap-harmony 1.0.0,基于 HarmonyOS API 24 / DevEco Studio 6.1。