Files
MailUI4Agents/docs/GUI-PLAN-HARMONY.md

229 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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=` |
| 会话管理 | 改名、预算调整、**权限档位调整plan / workspace / full**、改名提议展示/接受/驳回、归档 | `PUT /sessions/{id}/alias``GET\|PUT /sessions/{id}/budget``PUT /sessions/{id}/permission``rename-proposal` 组、`POST /contacts/archive` |
| 权限档位 | 会话头部展示当前档位与强制力(`permission_mode` / `permission_enforcement`),可随时调整 | 见会话管理行;档位三值 `plan / workspace / full` |
| 附件 | 下载(保存到本地/分享) | `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`
pi 梳理补充:`new_mail``session_update` 事件还带 `session_alias` /
`permission_mode` / `permission_enforcement` 字段 —— 鸿蒙端模型层按此定义,
会话卡片同时显示档位徽标。)
- **断线重连**:指数退避 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 提供解读支持(按分工)。