diff --git a/docs/HARMONY-ALIGN-PLAN.md b/docs/HARMONY-ALIGN-PLAN.md index ebf1a64..943c106 100644 --- a/docs/HARMONY-ALIGN-PLAN.md +++ b/docs/HARMONY-ALIGN-PLAN.md @@ -43,8 +43,10 @@ **P2 发件箱**:复用现有列表组件,接口 `/mail/sent`。验收:能看到已发邮件、 点开进详情;空态有说明。**为什么先做它**:与收件箱同构,风险最低。 -**P3 授权页**:导航加一项「授权」,列表用 `permission_*` 字段, -决策走 `POST /permission/{id}/decide`;详情内也支持决策。 +**P3 授权页**:导航加一项「授权」(or 通信页内页签,见 5.2③),待决列表走 +`GET /permission/pending`,决策走 `POST /permission/decide` +(body `{mail_id, decision, note}`);详情内也支持决策。 +**(接口名已于 2026-09-14 由 dsh 核对修正,原写的 `/permission/{id}/decide` 不存在。)** 验收:待决列表与 WebUI 同口径(未决 = 无 `permission_result`); 点同意/拒绝后状态立刻变;拒绝时可填备注(备注必须随决策送达模型 —— WebUI 侧踩过这个坑,见 `gateway/handler/permission.go` 的 Note 传递)。 @@ -65,3 +67,184 @@ WebUI 侧踩过这个坑,见 `gateway/handler/permission.go` 的 Note 传递 漏掉了"侧栏点了不翻页")。 2. 判据不许只看截图:要量几何/对比度/命中区。 3. 无法验证的要**如实标注**(例如"编译通过、视觉未验"),不能写成"已完成"。 + +--- + +## 五、交接核对(dsh,2026-09-14 收到 pi 的移交信后) + +核对方式:跑构建、跑判据、读代码,不靠转述。 + +### 5.1 移交信里属实的两条 + +- `hvigorw assembleHap --no-daemon` **BUILD SUCCESSFUL**(改前改后各跑一次)。 +- `node --test client/electron/test/cross-client-theme.test.mjs` 6 条全绿。 + +### 5.2 三处纠正(照原计划直接做会踩空) + +**① P3 的接口名写错了。** 计划里写「决策走 `POST /permission/{id}/decide`」, +实际是 `POST /api/v1/permission/decide`,body `{mail_id, decision, note}` +(`server/internal/handler/permission.go:301`)。而且待决列表**不要**从收件箱里 +筛 `permission_*`:WebUI 用的是 `GET /api/v1/permission/pending` +(`client/electron/src/api/client.ts:623`),鸿蒙照这个走才同口径。 +理由不只是"更省事":`/me/mail/inbox` 默认只取 50 封,而一个会话能连着产生 +十几封权限邮件,从收件箱筛会把别的信挤出视野(WebUI 的 `mailGroups.ts` +开头就是为这件事写的)。**用 pending 接口,与 WebUI 同源。** + +**②"不许写死颜色"的判据原来只挡得住列出来的那 8 个旧色值。** +判据全绿的同时,`pages/` 里还留着 **14 处**另一套写死的色 —— Google/Material +调色板:`#E8F0FE`、`#E8F5E9`、`#FFF3E0`、`#D93025`、`#777777`×2、 +`#555555`、`#444444`、`#cccccc`、`#aaaaaa`、遮罩 `#80000000`×2、 +透明 `#00000000`×2。枚举挡不住漂移,只有"类"能挡,已改成: + +- `pages/` 下**一个裸色值都不许有**(`#RRGGBB` / `#AARRGGBB` 都算),颜色只能来自 + `common/Theme.ets`;页面清单也改成**扫目录**(旧版硬编码 7 个文件名, + 接下来要加的页面会自动逃出判据)。 +- 变异测试确认能判红:往 `InboxPage.ets` 塞一个 `#E8F0FE` → 判据红;撤回 → 绿。 +- 顺带把权限档位徽标的配色收进令牌:`Theme.permBg/permFg`,与 WebUI 的 + `PermissionChip.tsx` **同一映射**(plan=蓝 / workspace=绿 / full=琥珀)。 + 原先是 `full ? 绿 : 橙`(Material 色),与 WebUI 反着来。 +- 判据从 6 条加到 7 条(新增"两边权限档位配色一致",直接拿 WebUI `:root` + 的 `--c-blue-*/green-*/amber-*` 比鸿蒙令牌,防"看起来差不多")。 + +**③ 导航的差距不止"观感不同",是信息架构不同。** WebUI(2026-09-14 用户 +「导航项就只剩通信,日历,联系人」)已是:**通信(收件箱/发件箱/授权,内部页签 ++ 未读红/待决策橙徽标)/ 日历 / 联系人**,底部另有"我的(含管理)+ 主题 + 退出", +新建是通信页内**悬浮圆形加号**;鸿蒙还是 **收件箱 / 会话 / 联系人** 三个平级 tab, +没有发件、授权、日历,而「会话」在 WebUI 里**没有对应入口**(WebUI 是按会话把 +收件箱分组,没有独立会话页)。 +⇒ P2/P3 不是"再加两个页面",得先对齐信息架构,否则加完还是两套导航。 + +### 5.3 一条与鸿蒙无关、但该让 pi 知道的 + +WebUI 侧 `npm test` 在 **HEAD 上就是红的**(`test/background.test.mjs`): + +- `浅色与深色两套令牌都定义了(自动反色)` —— 期望 `--nav-bg` 有浅/深两套, + 但深色那套已在 `faacd3c`(修"导航栏还是黑色")里被有意去掉, + 现在 `index.css` 只剩 `--nav-bg: 255 255 255 / 0.72`。 +- `导航在壁纸模式下仍参与模糊` —— 期望 `html[data-bg='on'] .nav-rail` 里有 + `backdrop-filter: blur(`,而该规则现在**是空的**("模糊由壁纸层负责,这里不叠", + 见 `index.css:892`)。 + +两条判据编码的都是**已被有意回滚的设计**,判据没跟着改。红成了常态, +判据也就不再是判据 —— 这条纪律问题比色值本身更值得先修。 + +### 5.4 修订后的分期与"点它"判据 + +| 期 | 内容 | 判据(必须点到用户会点的那一层) | +|---|---|---| +| P1.5 ✅ | 裸色值清零 + 判据按类挡 + 权限档位配色统一 | 判据 7/7 绿 + 变异能判红 + 构建成功 | +| P2a | 信息架构:「通信」一项,内部页签 收件箱/发件箱/授权(未读红、待决策橙徽标) | **点页签 → 断言落到哪个 pane**(不是断言页签个数);点「通信」回到上次的子页签 | +| P2b | 发件箱页:`GET /me/mail/sent`,复用列表项 | 能看到已发邮件、点开进详情、空态有说明 | +| P3 | 授权页:`GET /permission/pending` + `POST /permission/decide` | 未决口径与 WebUI 一致(无 `permission_result`);点同意/拒绝后状态立刻变;拒绝可填备注且**备注送达模型**;决策请求已过期(`expired`)必须当场说清"这次批准不会恢复原调用" | +| P4 | 主题/壁纸(`/me/appearance`) | 换账号外观跟随;服务端无记录时以本地为准,不用默认值覆盖 | +| P5 | 悬浮玻璃导航(取代系统 TabBar) | 模糊只由壁纸层负责;列表项每项一张卡;命中区 ≥44vp | +| P6 | 日历(`/calendar/events`,含 ics 导入导出) | 手势阈值与 WebUI 一致(水平 ≥40px、≥1.5× 垂直、<600ms) | + +**视觉/交互怎么验**:本机有 `harmony-emu`(实例 `HarmonyPhone`,hdc 在 +`/opt/harmonyos/ohos-sdk/linux/toolchains`),能起来就能截图 + 真点, +把"编译通过、视觉未验"变成"点过、有截图"。 +**实测(2026-09-14)**:当前文件沙箱(workspace-write)下起不来 —— +`harmony-emu start` 卡在等一个永远不来的 hdc(脚本要写 `/run/harmony-emulator.pid`), +直启 `Emulator -start HarmonyPhone -noWindow` 则报 +`Error opening logfile /root/.Huawei/Emulator/deployed/HarmonyPhone/Log/qemu.log: Permission denied` +(实例目录在 `/root` 下,沙箱不许写)。**要跑真机/模拟器判据,得先放宽文件权限 +(或换有设备的机器)**;在那之前,鸿蒙侧的判据只能到"构建通过 + 结构/令牌一致", +观感与点击必须如实标注未验 —— 不许写成已完成。 + +### 5.5 待定(需要 pi 或用户一句话) + +1. **「会话」这个平级入口留不留?** WebUI 没有它(收件箱按会话分组)。 + 我倾向跟 WebUI 一致 —— 收件箱按会话折叠、去掉平级「会话」tab; + 但这是删入口,改之前要一句话确认。 + → **已答(见 5.6):不是删功能,是两个 tab 合成一个页面的两种视图;先补视图与折叠,再删 tab。** +2. 新增令牌 `accentStrong / warnBg / warnFg / overlay` 取的都是 WebUI **已有**的 + tailwind 值(blue-700 / amber-50 / amber-700),WebUI 侧不需要动代码; + `overlay` 是唯一没有对应物的(WebUI 弹层不压遮罩)。若 pi 认为 WebUI 侧也该 + 立同名令牌,我再改。 + → **已答(见 5.6):WebUI 侧不立同名令牌;鸿蒙侧的 `overlay` 拆成 `overlayColor` + `overlayAlpha`。** + +--- + +## 六、pi 的回复已落地(dsh,2026-09-14 下午) + +### 6.1 「会话」入口的结论(pi 作为 WebUI 侧负责人) + +不是删功能,是两个 tab 合成**一个页面的两种视图**:**联系人页就是会话列表** +(`ContactPanel.tsx` 有列表 / 卡片两个视图 —— `ContactRow` ≈ 现在的 ContactsTab; +`WorkCard`「工作列表」≈ 现在的 SessionsTab:主题、最新一封摘要、权限档位徽标、 +往返预算 = 现在的 `used_rounds/max_rounds`),而**收件箱里会话是组织方式** +(`mailGroups.ts` 的 `groupMailsBySession()` 按 `session_id` 折叠、组头取最新一封, +`isFlatGroup()` 让单封不成组)。 + +落地顺序(原样采纳): + +1. **先**给「联系人」页补列表 / 卡片切换,卡片视图承接预算条 / `status` / 对方 Agent; + 收件箱加**按会话折叠**(组头带未读)。折叠前先看 `total` —— 别让"只取了 50 封" + 被折叠伪装成"只有这么多会话"。 +2. **两件都到位后**再删平级「会话」tab。在那之前删 = 丢信息:轮次预算、`status`、 + `from_agent` 会无处可看,而"预算跑满"正是需要人介入的信号。 + +合并后导航正好是 **通信 / 日历 / 联系人** 三项,P4–P6 都在这个形态上做。 +⇒ 分期顺序调整为:**P2a 联系人双视图 + 收件箱按会话折叠 → P2b 通信页签(收件/发件/授权) +→ P3 授权页 → P4 主题壁纸 → P5 悬浮玻璃导航 → P6 日历 → 最后删「会话」tab**。 + +### 6.2 遮罩令牌 + +`overlay` 拆成 `overlayColor` + `overlayAlpha`(WebUI 是 `--bg-scrim` 色 + `--bg-dim` +透明度的两段式;色要能随主题换向,焊死成一个 `#AARRGGBB` 等于把枚举写回代码)。 +ArkUI 只认单值,故用 `Theme.overlay()` 组装。**WebUI 侧不立同名令牌**(立了没人用、 +判据只能验"它存在",那是自证)。判据第 8 条钉住这个形态。 + +### 6.3 那两条红判据的 patch:已落地,且验证过能判红 + +`test/background.test.mjs` 第 18 组三条按 pi 的 patch 重写:标签改回它真正断言的东西, +两条方向相反的断言取代原两条(`.dark` 不许单独给导航换色 / 模糊只由壁纸层负责)。 +变异验证: + +- 往某个 `.dark { }` 里塞一行 `--nav-bg: 15 23 42 / 0.72;` → **红**; +- 往 `html[data-bg='on'] .nav-rail` 里塞 `backdrop-filter: blur(18px);` → **红**; +- 撤回 → 绿。背景判据 32 → **34 通过**。 + +### 6.4 顺手发现并修掉的真 bug(构建只在日志里警告的那种) + +`src/background-takeover.generated.css` 的**头注释提前闭合**:生成器在注释里写了 +「src」加「/」加两颗星加「/」加「.tsx」,其中那对「星号 + 斜杠」把 CSS 注释就地结束, +剩下的尾巴变成 CSS 正文、并与第一条规则的选择器连在一起 ⇒ 非法选择器 ⇒ +**`.bg-amber-100` 那条接管规则被浏览器整条丢掉**(壁纸模式下它不再变半透明)。 +构建只给一条 `[WARNING] Unexpected "14" [css-syntax-error]`,不报错、不影响构建。 +改在生成器 `scripts/gen-background-takeover.mjs`(注释里只描述、不写 glob 字面量)并 +重新生成:压缩输出现在以 `html[data-bg=on] .bg-amber-100{` 起头、14 条规则全在、无告警。 +另加两条判据("头注释没提前闭合" + 自检)。 + +### 6.5 一条判据从来没被跑过 + +`cross-client-theme.test.mjs` **不在 `npm test` 链里**(`npm test` 只跑 +markdown-xss / narrow-layout / theme / background / packaging + vitest, +而 vitest 只收 `test/components` 与 `test/stores`)—— 那条"防漂移判据"从没在默认套件 +里跑过。已加进 `npm test`。 + +### 6.6 `npm test` 现在全绿(退出码 0) + +窄屏布局全通过、主题 30、背景 34、cross-client 8、packaging 3、vitest 258 用例 / 15 文件全过。 + +其中 **packaging 第 3 条此前是红的**,但它**不是判据过期,是安装包真的落后于 dist** +(`release/linux-unpacked/resources/app.asar` 里装的还是旧前端)。根因有点讽刺: +`npm test` 的 `&&` 链一直在 background 那条就中断,**packaging 从来没跑到过**。 +已 `npm run build` + `npx electron-builder --linux -c.electronDownload.isVerifyChecksum=false` 重打包。 +⚠️ **deb 目标在本机打不出来**(`fpm` 的 portable ruby 在 `Dir.chdir` 处退出), +AppImage 与 `linux-unpacked` 正常 —— 交付前要确认这个环境问题不影响目标平台。 + +### 6.7 WebUI 侧同源残留(pi 指出的第三处,已修) + +`Sidebar.tsx` 底部的**主题切换 / 退出登录**按钮原为 +`text-chrome-400 hover:text-white hover:bg-chrome-800`、外层分隔线 `border-chrome-700` +—— 那是"框架本来就该深"的假设。导航改白玻璃后 `chrome-400` 在白底上约 2.6:1 +(图标要 3:1),hover 还会在白导航上闪出一块近黑。已换成 `.nav-item` + `border-gray-200`。 +**未加"Sidebar 里不许有 chrome-*"的判据**:`Sidebar.tsx` 另有一处 +`bg-chrome-600 text-chrome-100` 是实心小色块(正常用法),一刀切会误红。 + +### 6.8 仍未验的 + +鸿蒙侧**视觉与点击**仍未验(模拟器在本机沙箱下起不来,见 5.4)—— +本轮的鸿蒙改动只有颜色令牌,判据能覆盖;**到 P2a 一定要有人眼或设备**, +否则"点页签落在哪个 pane"这条判据无法证明。