Files
MailUI4Agents/docs/HARMONY-ALIGN-PLAN.md
JianFeeeee e07e3bf1a1 docs(harmony): 记入交接核对结果与 pi 回复的落地(P2a/P2b 顺序、判据、真 bug)
第五节:收到 pi 移交信后的核对 —— 移交信里属实的两条(构建成功、cross-client 6/6 绿)、
三处纠正(P3 接口名写错、判据只挡枚举、导航差距其实是信息架构差距),
以及一条与鸿蒙无关但该让 pi 知道的(WebUI `npm test` 在 HEAD 上恒红)。

第六节:pi 回复的落地 ——
- 「会话」入口的结论:不是删功能,是联系人页的**卡片视图** + 收件箱按会话折叠,
  两件到位后再删 tab(在那之前删 = 丢信息:轮次预算 / status / from_agent 无处可看)。
  ⇒ 分期顺序改为 P2a 联系人双视图 + 收件箱折叠 → P2b 通信页签 → P3 授权 → P4 主题壁纸
  → P5 悬浮玻璃导航 → P6 日历 → 最后删 tab。
- 遮罩拆两段式;WebUI 侧不立同名令牌(立了没人用、判据只能验"它存在",是自证)。
- 两条红判据的 patch 已落地且验证过能判红;background 判据 32 → 34 通过。
- 顺手修掉的真 bug:生成 CSS 头注释提前闭合导致 `.bg-amber-100` 那条规则被整条丢掉。
- 一条判据从来没被跑过:cross-client 判据不在 `npm test` 链里,已加进去。
- `npm test` 现在全绿(退出码 0);deb 目标在本机打不出来(fpm),要确认是否影响交付平台。
- 仍未验的:鸿蒙侧的视觉与点击(模拟器起不来),到 P2a 必须有人眼或设备。
2026-09-14 13:30:03 +08:00

16 KiB
Raw Blame History

鸿蒙客户端与 WebUI 的对齐计划

用户2026-09-14「安排对齐」「鸿蒙 ui 应当交给对这一块更熟悉的 dsh 负责」。 这份文档把差距分期写清楚,免得每轮都从"感觉还差什么"重新猜。

负责人dsh2026-09-14 起由 jianf 指定)。移交信: 线索 harmony-ui-alignmentdsh@/home/program/agentmail 信里交代了状态、判据纪律与踩过的坑(判据要点"用户真正会点的那一层"、 不许新写死颜色、不要给单个面单独做深色、模糊只由壁纸层负责、 列表项每项一张卡、ArkTS 编译坑、视觉不可验要如实标注)。

pi保留 WebUI/Electron 侧:需要两边一起加令牌之类的配合,回信给 pi。

一、现在的差距(有据可查)

能力 WebUI 鸿蒙 差距性质
收件箱
会话 (通信页签) (独立 tab 交互不同
联系人
发件箱 (通信页签) 缺页面(数据现成)
授权(权限决策) (通信页签 + 详情内决策) 缺页面API 现成)
日历 缺页面(最大一块)
管理(用户管理) (我的页底部,管理员可见) 缺页面 + 权限判定
写信 共用 Composer 独立实现 组件未统一
底部/侧边导航 悬浮玻璃条 ⚠️ 系统 TabBar 观感不同
主题 / 壁纸(账号级) 服务端同步 未接
设计令牌 :root Theme.ets 已对齐(判据钉住)

二、已经做完的(本轮之前)

  • 设计令牌共用common/Theme.ets 与 WebUI 的 :root 一一对应 (品牌蓝、圆角 14/8、导航玻璃 0.72、语义色、字号),并由 client/electron/test/cross-client-theme.test.mjs 钉住取值一致性。
  • 旧调色板清除:页面里的 #1A73E8Google 蓝)/#333333/#F5F7FA 等 与 WebUI 不同的写死色值全部换成令牌203 处)。
  • 修掉只剩第一个 tab 高亮的 bugcurrentIndex === 0 写死)。

三、分期(按"能独立验收"切)

P1 设计语言pi 已完成) —— 令牌 + 颜色替换 + 编译通过。以下 P2P6 归 dsh。

P2 发件箱:复用现有列表组件,接口 /mail/sent。验收:能看到已发邮件、 点开进详情;空态有说明。为什么先做它:与收件箱同构,风险最低。

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 传递)。

P4 主题/壁纸同步:接 GET/PUT /me/appearance + 图片走带认证的 fetch。 验收:换账号后外观跟随;服务端"无记录"时以本地为准(不要用默认值覆盖 —— 同 WebUI

P5 玻璃悬浮导航:自定义底栏(圆角 + 半透明 + backgroundBlurStyle 取代系统 TabBar。注意:视觉验收需要设备或签名 HAP 本机 hdc list targets 为空 ⇒ 只能保证编译与结构,观感要人眼确认。

P6 日历:网格 + 事件读写 + 左右滑动翻页(复用 WebUI 的手势阈值: 水平 ≥40px、≥1.5× 垂直、<600ms。这一块最大单独排。

四、验收纪律(照 WebUI 那套)

  1. 每个页面都要有点它的判据WebUI 侧就是因为只验结构没验点击, 漏掉了"侧栏点了不翻页")。
  2. 判据不许只看截图:要量几何/对比度/命中区。
  3. 无法验证的要如实标注(例如"编译通过、视觉未验"),不能写成"已完成"。

五、交接核对dsh2026-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/decidebody {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-* 比鸿蒙令牌,防"看起来差不多")。

③ 导航的差距不止"观感不同",是信息架构不同。 WebUI2026-09-14 用户 「导航项就只剩通信,日历,联系人」)已是:**通信(收件箱/发件箱/授权,内部页签

  • 未读红/待决策橙徽标)/ 日历 / 联系人**,底部另有"我的(含管理)+ 主题 + 退出" 新建是通信页内悬浮圆形加号;鸿蒙还是 收件箱 / 会话 / 联系人 三个平级 tab 没有发件、授权、日历,而「会话」在 WebUI 里没有对应入口WebUI 是按会话把 收件箱分组,没有独立会话页)。 ⇒ P2/P3 不是"再加两个页面",得先对齐信息架构,否则加完还是两套导航。

5.3 一条与鸿蒙无关、但该让 pi 知道的

WebUI 侧 npm testHEAD 上就是红的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(实例 HarmonyPhonehdc 在 /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-700WebUI 侧不需要动代码; overlay 是唯一没有对应物的WebUI 弹层不压遮罩)。若 pi 认为 WebUI 侧也该 立同名令牌,我再改。 → 已答(见 5.6WebUI 侧不立同名令牌;鸿蒙侧的 overlay 拆成 overlayColor + overlayAlpha

六、pi 的回复已落地dsh2026-09-14 下午)

6.1 「会话」入口的结论pi 作为 WebUI 侧负责人)

不是删功能,是两个 tab 合成一个页面的两种视图联系人页就是会话列表 ContactPanel.tsx 有列表 / 卡片两个视图 —— ContactRow ≈ 现在的 ContactsTab WorkCard「工作列表」≈ 现在的 SessionsTab主题、最新一封摘要、权限档位徽标、 往返预算 = 现在的 used_rounds/max_rounds),而收件箱里会话是组织方式 mailGroups.tsgroupMailsBySession()session_id 折叠、组头取最新一封, isFlatGroup() 让单封不成组)。

落地顺序(原样采纳):

  1. 给「联系人」页补列表 / 卡片切换,卡片视图承接预算条 / status / 对方 Agent 收件箱加按会话折叠(组头带未读)。折叠前先看 total —— 别让"只取了 50 封" 被折叠伪装成"只有这么多会话"。
  2. 两件都到位后再删平级「会话」tab。在那之前删 = 丢信息:轮次预算、statusfrom_agent 会无处可看,而"预算跑满"正是需要人介入的信号。

合并后导航正好是 通信 / 日历 / 联系人 三项P4P6 都在这个形态上做。 ⇒ 分期顺序调整为:P2a 联系人双视图 + 收件箱按会话折叠 → P2b 通信页签(收件/发件/授权) → P3 授权页 → P4 主题壁纸 → P5 悬浮玻璃导航 → P6 日历 → 最后删「会话」tab

6.2 遮罩令牌

overlay 拆成 overlayColor + overlayAlphaWebUI 是 --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/componentstest/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:1hover 还会在白导航上闪出一块近黑。已换成 .nav-item + border-gray-200未加"Sidebar 里不许有 chrome-*"的判据Sidebar.tsx 另有一处 bg-chrome-600 text-chrome-100 是实心小色块(正常用法),一刀切会误红。

6.8 仍未验的

鸿蒙侧视觉与点击仍未验(模拟器在本机沙箱下起不来,见 5.4)—— 本轮的鸿蒙改动只有颜色令牌,判据能覆盖;到 P2a 一定要有人眼或设备 否则"点页签落在哪个 pane"这条判据无法证明。