feat(harmony): P2a —— 收件箱按会话折叠 + 联系人页卡片视图(判据直接跑同一份逻辑)

按 pi 的结论落地 P2a 的前一半:**先补视图与折叠,再删平级「会话」tab**(tab 本轮保留)。

## 判据怎么"点用户真正会点的那一层"

鸿蒙侧没有设备(`hdc list targets` 为空、模拟器在本机沙箱下起不来),"点一下"暂时
无法自动验。应对不是编个能过的新判据,而是把会点的那一层的内核抽成纯逻辑:
`entry/src/main/ets/model/MailGrouping.ts`(无 UI 依赖),判据用 node 的
`--experimental-strip-types` **执行同一份代码**(`test/harmony-logic.test.mjs`,14 条),
断言的是行为而不是"源码里出现过某个字符串":

- 折叠后组头是不是**最新一封**、组内是否时间倒序、组间排序、同一时刻用 `mail_id` 倒序兜底;
- 时间解析失败**不能让顺序依赖入参**(WebUI 侧踩过的 NaN 比较坑);
- 多账号合并下同名 `session_id` 不能被错并成一组;`session_id` 缺失时各自成组;
- 预算档位与 WebUI `BudgetChip` 完全一致(剩 0 用尽 / ≤1 将尽 / 上限 0 不显示);
- 视图切换与卡片上"最新一封是人还是 Agent"的判据。

页面那一层另用源码判据钉"确实调了这些函数",两层合起来覆盖「逻辑对」+「页面接上了」。
**变异验证 4 处全部判红**:去掉组内排序(2 条红)、预算阈值 `<=1` 改 `<1`、
分组键去掉账号前缀、页面不再区分单封组。

## 收件箱折叠

- 组头取组内最新一封的别名与主题,带未读数徽标与「N 封」,点它展开/收起;
- **单封不成组、平铺**(与 WebUI `isFlatGroup` 同结论:给孤立一封信套组头只是多一次点击);
- 多账号是鸿蒙特有:分组键带账号前缀;`session_id` 缺失按 `mail:<id>` 各自成组。

## 顺带修掉一个"看起来是总数、其实是未读数"的显示

`/me/mail/inbox` 的 `total` 是 **`CountUnread`(未读总数)**,不是总封数
(`server/internal/handler/me.go`)。鸿蒙底部原写「共 N 封」⇒ 同一屏出现
「共 7 封」和「未读 7」两行自相矛盾的字。改成:未读数用服务端 `total`(权威,
原来数这一页会少报);「共 N 封」→「已加载 N 封」;**这一页取满时如实提示
「已加载 50 封(本页上限 50,可能还有更多)」** —— 客户端没有可信总封数,
就不能把 50 封说成全部(pi 提醒的"别让只取 50 封伪装成只有这么多会话")。
WebUI 侧不读这个字段,故只影响鸿蒙。

## 联系人页补卡片视图(撤 tab 的前置)

- 右上角切列表/卡片,标题「联系人」/「工作列表」(与 WebUI 同词),切换规则在
  `nextContactView()`;
- 卡片对应 WebUI 的 `WorkCard`:Agent 名 + 工作目录 + 未读徽标、会话别名、
  **主题当主角**、最新摘要 + 人/Agent 标记、`N 封 · 时间`、权限档位徽标、
  **往返预算条**(同一档位判据)。
- 平级「会话」tab 暂留:撤 tab 按 pi 的顺序排在后面单独一步(撤早了预算/status/from_agent 没处看)。

## 验证

- `hvigorw assembleHap` **BUILD SUCCESSFUL**(`.ts` 纯逻辑模块被 `.ets` 引用,实测可行)。
- `npm test` **退出码 0**:窄屏布局全通过、主题 30、背景 34、cross-client 8、
  harmony-logic 14、packaging 3、vitest 258/258;新判据已接进 `npm test`。
- **视觉与点击仍未验**(无设备):展开手感、卡片间距、组头命中区没有任何自动判据
  能代替人眼 —— 交付按"结构/逻辑已验证、观感未验"写,未写成已完成。
This commit is contained in:
2026-09-14 13:36:05 +08:00
parent e07e3bf1a1
commit 3729afd96f
7 changed files with 845 additions and 44 deletions

View File

@ -248,3 +248,69 @@ AppImage 与 `linux-unpacked` 正常 —— 交付前要确认这个环境问题
鸿蒙侧**视觉与点击**仍未验模拟器在本机沙箱下起不来 5.4)——
本轮的鸿蒙改动只有颜色令牌判据能覆盖** P2a 一定要有人眼或设备**
否则"点页签落在哪个 pane"这条判据无法证明
---
## 七、P2a 落地dsh2026-09-14 稍晚)
pi 给的顺序**先补视图与折叠再删 tab**。本轮做完前一半tab 保留
### 7.1 做法:把"用户真正会点的那一层"的内核抽出来,让判据**执行**它
没有设备"点一下"在鸿蒙上暂时无法自动验应对不是编个能过的新判据
而是把会点的那一层的内核抽成纯逻辑文件
`client/harmony/entry/src/main/ets/model/MailGrouping.ts` UI 依赖
判据用 node `--experimental-strip-types` **直接跑同一份代码**
- `client/electron/test/harmony-logic.test.mjs`14 )—— 断言的是**行为**
折叠后组头是不是最新一封单封是不是不成组同一时刻是否用 `mail_id` 倒序兜底
时间解析失败会不会让顺序依赖入参多账号同名会话会不会被错并预算剩 1 个来回是哪档
- 页面那一层用源码判据钉"确实调了这些函数"`groupMailsBySession` / `isFlatGroup` /
`toggleExpanded` / `budgetLabel` / `nextContactView` / `lastFromIsHuman`)——
两层合起来,「逻辑对页面接上了都有判据
- **变异验证4 全部判红**去掉组内排序 2 条红预算阈值 `<=1` `<1` 1 条红
分组键去掉账号前缀 1 条红页面不再区分单封组 1 条红
这条判据已接进 `npm test``node --experimental-strip-types --no-warnings --test`)。
### 7.2 收件箱:按会话折叠
- 组头取组内**最新一封**的别名与主题 WebUI `mailGroups.ts` 同口径
带未读数徽标与N 」;点组头展开/收起
- **单封不成组平铺** WebUI `isFlatGroup` 同结论给孤立的一封信套组头
只是多一次点击而收件箱里大多数人类来信就是孤立的一封
- 多账号是鸿蒙特有分组键带账号前缀同一 `session_id` 出现在两个账号是两件事
`session_id` 缺失时按 `mail:<id>` 各自成组
### 7.3 顺带修掉一个"看起来是总数、其实是未读数"的显示
`/me/mail/inbox` 返回的 `total` **`CountUnread`未读总数**不是总封数
`server/internal/handler/me.go` `MeGetInbox`)。鸿蒙底部原来写 N 」,
于是同一屏上会出现 7 未读 7这种自相矛盾的两行字
改法未读数**改用服务端 total**权威原来数这一页会少报
N 改成已加载 N 」;并且**这一页取满=50时如实提示
已加载 50 本页上限 50可能还有更多)」** —— 客户端手上根本没有可信的总封数
那就不能把 50 封说成全部这正是 pi 提醒的"别让只取 50 封伪装成只有这么多会话")。
WebUI 侧完全不读这个字段`mailStore` 里没有 `total`所以这条只影响鸿蒙
### 7.4 联系人页:补上卡片视图(为撤 tab 做准备)
- 右上角切换列表 / 卡片标题随视图变(「联系人」/「工作列表」, WebUI 同词
切换规则在 `nextContactView()`判据直接执行它
- 卡片对应 WebUI `WorkCard`Agent + 工作目录 + 未读徽标
会话别名空则「(未命名会话)」)、**主题当主角**、最新摘要 + /Agent 标记
`lastFromIsHuman`)、「N · 时间」、权限档位徽标、**往返预算条**
档位与 WebUI `BudgetChip` 同一判据 0 / 1 / 其余中性上限 0=不限则不显示)。
- 平级会话tab **暂时保留** —— 预算`status``from_agent` 现在卡片视图里都能看了
但按 pi 的顺序 tab 排在 P2b 之后作为独立一步撤早了会丢信息)。
### 7.5 本轮验证与如实标注
- `hvigorw assembleHap` **BUILD SUCCESSFUL**`.ts` 纯逻辑模块能被 `.ets` 引用
实测可行 —— 这是"判据能执行同一份代码"的前提)。
- `npm test` **退出码 0**窄屏布局全通过主题 30背景 34cross-client 8
harmony-logic 14packaging 3vitest 258/258
- **视觉与点击仍未验**无设备 / 模拟器起不来折叠展开的手感卡片间距
组头命中区是否够大这些**没有**任何自动判据能代替人眼 —— 交付时按"结构/逻辑已验证
观感未验"下一轮P2b 通信页签收件箱/发件箱/授权 + 徽标)。