docs: 鸿蒙客户端(ArkUI)构筑计划 GUI-PLAN-HARMONY.md

This commit is contained in:
dsh
2026-09-07 07:26:04 +08:00
parent 89a4784c10
commit 9cdf4b9e3f

225
docs/GUI-PLAN-HARMONY.md Normal file
View File

@ -0,0 +1,225 @@
# AgentMail 鸿蒙客户端ArkUI构筑计划
> 邮件驱动·多智能体协作平台 — HarmonyOS 客户端
> 构筑者dsh | 版本v0.1 | 日期2026-09-07
> 上游接口契约:[docs/API.md](API.md) · 平台规划:[docs/PLAN.md](PLAN.md)
---
## 0. 定位与分工
- jianf发起人→ 收件方 pi 负责 **ele 客户端**Win/Linux并作为长期维护者给我方提供 API 解读与支持;
- dsh→ 负责 **鸿蒙客户端**ArkUI本计划即鸿蒙侧的构筑蓝图。
- 平台后端是 **同一个 Gateway**Go + SQLiteHTTP REST + SSE鸿蒙客户端调用其**人类接口**
`/api/v1/me/*` 等),与 WebUI 完全等价,没有私有通道。
- 交付形态:一套 Stage 模型 ArkTS 工程,以 HAP 形式运行于 HarmonyOS 手机/平板/2in1
覆盖 WebUI 的「邮件收发 + 会话 + 联系人 + 权限决策」核心功能面。
**本机工具链(已勘察确认)**
| 组件 | 版本/位置 |
|---|---|
| DevEco CLI | 26.0.0 Beta2`/opt/huawei/command-line-tools``devecocli` 1.3.0 已包装在 `/usr/local/bin` |
| HarmonyOS SDK | 6.1.0API 23Version 6.1.0.105 Release`/opt/huawei/harmonyos/ohos-sdk/linux` |
| 包管理 | `ohpm`command-line-tools/ohpm |
| 模拟器 | `HarmonyPhone`phone / HarmonyOS 6.1.1(24)KVM 加速,按需 `harmony-emu start` |
| 真机 | 可选hdc 无线调试(动态 IP签名 hap 走 `devecocli signature generate`,材料在 `~/.ohos/config` |
**鸿蒙生态约束(真机安装必须签名)**:模拟器可装 unsigned hap真机一律要签名。
签名材料已就绪,`devecocli signature generate --force` 可随时重新生成。
---
## 1. 目标功能面(与 WebUI 对齐的裁剪集)
首版M1-M3做「个人邮件客户端」核心闭环管理员面用户管理/Agent 密钥/默认预算)不在鸿蒙侧首版
范围内 —— 那是 Web 管理台的职责,鸿蒙端聚焦日常使用。
| 模块 | 功能 | 对应 API |
|---|---|---|
| 登录/凭证 | 账号密码登录用户密钥登录跨设备场景Bearer | `POST /auth/login``GET /auth/me``POST /auth/logout``POST /me/keys` |
| 收件箱/发件箱 | 未读/全部列表、未读标记、发件箱 | `GET /me/mail/inbox?s=unread\|all``GET /me/mail/sent` |
| 会话列表 | 我参与的会话(卡片/列表视图)、未读数、预算徽标 | `GET /me/sessions``GET /contacts``GET /contacts/suggest` |
| 邮件详情 | Markdown 正文渲染、附件清单、抄送显示、对话树 | `GET /mail/{id}``GET /mail/{id}/thread` |
| 写信 | 收件人三段式补全、抄送、正文、往返预算、附件上传、会话别名(`.new` 时) | `POST /me/mail/send``POST /me/attachments` |
| 回复/转发 | 回复落回原会话、转发开新线索(附件随行) | `POST /me/mail/{id}/forward` |
| 权限决策 | 待决请求列表、同意/拒绝/备注 | `GET /permission/pending``POST /permission/decide` |
| 实时推送 | 新邮件、权限决策、会话更新SSE | `GET /events/stream?access_token=` |
| 会话管理 | 改名、预算调整、改名提议展示/接受/驳回、归档 | `PUT /sessions/{id}/alias``GET\|PUT /sessions/{id}/budget``rename-proposal` 组、`POST /contacts/archive` |
| 附件 | 下载(保存到本地/分享) | `GET /me/attachments/{id}` |
明确**不做**首版管理员后台、Agent 侧接口、日历(`/calendar/*`Web 端新功能,待 api 解读后二版评估)。
---
## 2. 技术方案
### 2.1 工程形态
- Stage 模型 + `@ohos/http`(默认网络库,无需三方依赖),`entry` 单模块起步;
若 UI 面膨胀再拆 `common`/`feature` 多模块,首版不预先拆。
- 语言:**纯 ArkTS**(严格模式,`arkts-*` lint 全开),不用 JS/TS 混写。
- 状态管理:首版用组件内 `@State`/`@Link`/`@Provide` 即可跨页共享登录态、token、未读数
提炼为**单例 Service 层**`@ohos.data.preferences` 持久化凭证),不引第三方状态库。
### 2.2 API 层(核心设计)
对齐 WebUI 的 `src/api/` 思路,鸿蒙侧实现一份同构的客户端:
```
entry/src/main/ets/
├── ability/ EntryAbility.ets
├── pages/ 登录 / 主界面 / 会话 / 邮件详情 / 写信 / 权限
├── api/
│ ├── ApiClient.ets # 统一 request()base + headers + 错误归一化400/401/403/404/409/429
│ ├── AuthApi.ets # login / logout / me / keys
│ ├── MailApi.ets # inbox / sent / detail / thread / send / forward / read
│ ├── SessionApi.ets # sessions / alias / budget / rename-proposal
│ ├── ContactApi.ets # contacts / suggest / archive
│ ├── PermissionApi.ets # pending / decide
│ ├── AttachmentApi.ets # upload / download
│ └── SseClient.ets # SSE 流式解析 + 指数退避重连
├── model/ # 领域模型Mail/Session/Contact/…,与 API.md 字段一一对应)
├── store/ # 单例SessionStore / MailStore / UnreadStore跨页共享
├── components/ # MailListItem / SessionCard / AddressInput / PermissionCard / MarkdownView …
└── common/ # 常量BASE_URL、事件名、工具相对时间、rune 截断、Markdown 渲染)
```
要点:
- **基地址与凭证**集中在 `common/config``apiBase` 可运行时配置(设置页填写网关地址),
与 WebUI 的 `window.__AGENTMAIL_API_BASE__` 同思路 —— 一个构建产物可指向任意后端。
- **认证双通道**Cookie账号密码登录`@ohos.http` 手动管理 Cookie
`Authorization: Bearer <user_key>`密钥登录。SSE 与附件下载这两个浏览器侧只能走 query 令牌的端点,
鸿蒙侧可以带请求头,优先 Bearer避免令牌进 URL 日志。
- **错误归一化**:统一把服务端 `{"error": "中文可操作描述"}` 与 HTTP 状态码翻译成
`ApiError { code, message }`401 统一触发「回登录页」429/403 文案原样上屏。
### 2.3 SSE 实时(关键难点)
`@ohos.http` 的流式响应(`on('dataReceive')`)用于解析 SSE 帧:
- 手工按 `\n\n` 分帧,解析 `event:` / `data:` 行;事件表与 API.md 一致:
`new_mail` / `permission_decision` / `session_update` / `session_archived` / `agent_online`
- **断线重连**:指数退避 1s→15s 上限(对齐 Web 端 `api/sse.ts``AbortController` 优雅停止。
- `new_mail` 到达 → 通知 MailStore 刷新收件箱与未读数;`permission_decision` → 刷新权限卡片。
- 生命周期App 前台订阅、后台/退到 `onBackground` 暂停,回到前台重连(省电 + 避免无谓重连风暴)。
### 2.4 Markdown 渲染
鸿蒙没有现成 react-markdown。选择按优先级
1. **首版:轻量自研解析子集** —— 标题/粗体/斜体/行内代码/代码块/列表/引用/链接/分割线,
`Span`/`RichText` 逐段渲染;**raw HTML 一律不渲染**、链接协议白名单http/https
守住 Web 端 Markdown XSS 回归测试立下的同一条纪律(见 PLAN.md 6.4)。
2. 若正文复杂度超预期,评估 `@ohos/webview` 加载本地渲染页(需白名单校验后再注入,引入 XSS 面,慎用)。
### 2.5 附件
- 上传:`@ohos.request` / `http` multipart 到 `POST /me/attachments`(字段名 file
返回 `attachment_id` 后随 `send``attachment_ids` 使用 —— 两步流程与 Web 端一致。
- 下载:`GET /me/attachments/{id}` → 写入应用沙箱文件目录,用 `@ohos.file.picker` /
`@ohos.share` 交出去(保存到相册/分享)。注意服务端**强制 octet-stream + attachment**
按响应头 `Content-Disposition` 解析文件名API.md 七、已暴露该响应头)。
### 2.6 UI 布局ArkUI
| 界面 | 结构 |
|---|---|
| 登录页 | 服务器地址 + 账号/密码 或 用户密钥;「保存地址」入 preferences |
| 主界面(手机) | 底部 Tab收件 / 会话 / 联系人 / 权限 / 我的;顶栏未读徽标 |
| 主界面(平板/2in1 | 两栏/三栏自适应:左列表 + 右详情;`@ohos.mediaquery` 断点切换 |
| 会话列表 | 列表/卡片视图切换;卡片含主题、最新一封发件人+摘要、预算徽标(剩 1 橙 / 用尽红 / 不限不显示) |
| 邮件详情 | Markdown 正文 + 附件行 + 抄送行 + 权限卡片 + 底部「回复 / 转发」+ 对话树入口 |
| 对话树 | 缩进 + 连接线(不引图形库),分块加载:`dir=around` 首屏 + `up/down` 增量 |
| 写信页 | 收件人补全(三段式 suggest+ 抄送 + 主题 + 正文 + 预算档位 + 附件 + 会话别名(仅 `.new` |
| 设置 | 网关地址、退出登录、密钥管理(`/me/keys` 创建/吊销,展示 token_hint |
窄屏三维地址补全:`/contacts/suggest` 无参 → name带 name → path带 name+path → 别名+`new`
逐级展开,方向键选择(对齐 Web 端 AddressInput 交互)。
---
## 3. ArkTS 工程注意点(本机实操约束)
在写第一行 `.ets` 前先加载 `arkts-grammar-standards` 技能,按规范落地:
- 严格模式:禁 `any`、禁未声明类型、`undefined` 处理显式化(`??` / optional chain 白名单内)。
- 组件用 `struct` + `@Component`,状态用 `@State`/`@Prop`/`@Provide`;列表用 `LazyForEach`
(邮件量可能上百,`ForEach` 全量渲染会卡)。
- 网络模型用 `interface` 描述(与 API.md 字段对齐),服务端多余字段不枚举。
- Sendable / Actor 需求确认:首版无跨线程共享大对象,先不进;若 SSE 解析放 worker 再评估。
- `@ohos.http` 需在 `module.json5` 声明 `ohos.permission.INTERNET`(示例项目已带,照抄)。
- 构建:`devecocli build` / `hvigorw assembleHap` 产出 `entry-default-signed.hap`
模拟器 `hdc install`unsigned 亦可),真机走签名 hap + `hdc tconn`
---
## 4. 里程碑与验收
### M0 脚手架0.5 天)
- `devecocli create` 建 Stage 工程(包名 `com.agentmail.harmony`API 23
- 空壳 App 在 HarmonyPhone 模拟器跑通(`harmony-emu start` → build → install → 截图);
- 签名配置写入 `build-profile.json5`(复用 `~/.ohos/config` 材料)。
**验收**:启动图标进桌面,`devecocli ui screenshot` 可见主页面。
### M1 API 层 + 登录1-2 天)
- `ApiClient`Base + 错误归一化 + 双认证通道)+ `AuthApi`
- 登录页(账号密码 / 用户密钥)+ token/凭证持久化 + 401 全局回落登录。
**验收**:连本机 Gateway`http://localhost:8180`)用真实账号登录成功,
`GET /auth/me` 返回当前用户;错密码显示服务端中文文案。
### M2 邮件闭环3-5 天)
- 收件箱/发件箱列表未读态、分页、邮件详情Markdown 渲染 + 附件行 + 抄送)、
回复/转发、写信页(三段式补全 + 预算档位 + 附件上传两步流 + `.new` 会话别名)。
**验收**:人 → Agent → 人 端到端:给 pi/opencode 发一封带抄送与附件的任务邮件,
Agent 回信后在本端看到详情并可继续回复;新信未读计数正确。
### M3 实时 + 会话 + 权限2-3 天)
- `SseClient`(解析 + 退避重连 + 生命周期);未读徽标与列表随事件刷新;
- 会话列表(列表/卡片)、改名提议条(接受/驳回)、预算调整;
- 权限待决列表 + 决策卡片。
**验收**:另一浏览器标签给本账号发信,鸿蒙端 ≤3s 内未读 +1SSE 路径);
Agent 权限请求出现在待决列表,决策后 Agent 侧收到(对照 Web 端行为一致)。
### M4 对话树 + 附件落盘 + 打磨2-3 天)
- 对话树分块加载(`around/up/down` + 滚动位置补偿);
- 附件下载到沙箱 → picker/share 导出;平板/2in1 自适应布局、深色模式(如有余力)。
**验收**251 封长链线索在鸿蒙端分页取完、depth 连续;真机(若可用)安装签名 hap 全流程跑通。
### M5 联调 + 文档1-2 天)
- 与 ele 端pi在**同一 Gateway** 上双端并行联调:双端同账号互斥/一致性问题暴露;
- 对照 `PLUGIN-CONTRACT.md` 的验收清单做客户端视角补测;
- 更新本计划为「已落地」,同步 README 接入说明。
**预计总工时**:约 2-3 周(含联调与返工缓冲)。
---
## 5. 风险与依赖
| 风险 | 对策 |
|---|---|
| `@ohos.http` 流式 SSE 稳定性(长连接、断流) | 退避重连 + 生命周期暂停;降级方案:轮询 `/me/mail/inbox`SSE 仅作加速) |
| ArkTS 严格模式对三方库不友好 | 尽量零三方依赖;网络/存储/文件全走系统 API |
| Markdown 渲染面 | 首版渲染子集 + 协议白名单;复杂稿需时评估 webview 方案并单独过 XSS 评审 |
| 真机签名链路 | 材料已就绪;`devecocli signature generate --force` 兜底;无真机时模拟器验收为主 |
| 服务端接口变更 | 依赖方pi的 API 解读;所有模型层集中在 `model/`,变更只动一处 |
| 日历等 Web 新功能 | 首版明确排除M5 后按 API 解读评估二版 |
**需要 jianf / pi 提供的支持**
1. 一个稳定的测试 Gateway 地址(开发联调用,含可登录账号);
2. 接口变化时按 `docs/API.md` 格式及时更新 —— 鸿蒙端模型层严格对齐该文档。
---
## 6. 与 ele 端pi的协同点
- 两端共用**同一份 API.md 契约**建议把「API 解读」沉淀为 `docs/API-INTERPRETATION.md`
(字段语义、边界行为、踩坑),供双端引用,避免各自重复踩;
- 后端新增字段时(如日历),双端各自按需跟进;鸿蒙端涉及协议层的问题由 pi 提供解读支持(按分工)。