feat(harmony)★★: 背景档与预设改用官方 Chip,删掉重复的同步指示器
承接 2026-09-29 的反馈,本批改动是那一轮工作的收尾。
## 1. 自绘 Text → 官方 `Chip`
背景档与预设两排原来是**自绘 `Text`**,而且与设置页主题那排
**圆角/内边距不一致**(预设那排 `borderRadius(4)`,另两处是
`radiusControl`)。改用 `import { Chip, AccessibilitySelectedType,
LengthMetrics } from '@kit.ArkUI'`。
## 2. 删掉 `@Prop statusText`(一个数两个指示器)
它原来是「外观」卡右上角那个「已同步」的**第二份**:页面把同一个
`statusLabel(this.appearanceStatus)` 既画在卡片级标题行、又透传进来
画在「背景」小标题右边 ⇒ 同一屏两个「已同步」,永远同值。
删掉透传这一份,值只从页面进、只画一处。
## 3. Surface.ets(32 行)/ Theme.ets(51 行)/ ContactsTab.ets(21 行)
配套:Chip 的尺寸档、主题色取用、联系人页的调用点。
## 判据
- `test/harmony-appearance.test.mjs`:外观判据随实现更新
- `test/mutants/baseline.sha`:变异体自证底本同步
### ⚠️ 设备端判据本机跑不了(不是代码问题)
node --test test/harmony-appearance.test.mjs
pass 26 / fail 3
失败的 3 条**全部**是设备端断言:
★ 设备:打开背景开关后,壁纸上真的出现了
AssertionError: 要能拉起我们的应用并等到它到前台
★ 设备:窗格内容不得超出屏幕
AssertionError: 要能拉起应用
★ 设备:切换主题后界面真的整体换色了
AssertionError: 设备连续 10 轮拉不起应用(本条已连续 3 轮没真跑)
即**本机没有接 Harmony 设备**,不是断言挂在代码上。
判据文本本身断言「设备连续 10 轮拉不起」——它自己在如实报告
「这条从未在真机上跑过」。**需要真机补验**,这里不假装它通过了。
## docs
API.md / GUI-PLAN-HARMONY.md / PLAN.md 同步上述改动。
This commit is contained in:
25
docs/PLAN.md
25
docs/PLAN.md
@ -764,7 +764,7 @@ execute: {
|
||||
两处不一致时无法判断谁对。直接用递归 CTE 在 mails 上查(`idx_mails_parent` 已有)。
|
||||
|
||||
- [x] `repo/thread.go`:`AncestorsRaw`(向上)/ `DescendantsRaw`(向下)两个方向的递归 CTE
|
||||
- [x] `GET /mail/{id}/thread?dir=around|up|down&offset=N&limit=N`
|
||||
- [x] `GET /mail/{id}/thread?offset=N&limit=N`(自线索根整树 BFS)
|
||||
- [x] **树可跨会话**:转发把线索引到新会话,但 parent 仍指向原件。
|
||||
这正是树视图比会话内平铺更有价值的地方 —— 能看出线索分叉去了哪里
|
||||
- [x] **按会话逐个鉴权**:A 转发给 B 之后,B 与 C 在新会话里的往来不能回流给 A。
|
||||
@ -780,15 +780,16 @@ execute: {
|
||||
|
||||
原先实现是深度上限 100 直接截断,超长线索看不到全貌。改为按方向分页:
|
||||
|
||||
- [x] 首屏 `dir=around` 取锚点附近一块(limit 在两个方向各分一半);
|
||||
`dir=up|down` + `offset` 增量加载,两端各自带 `has_more_*` 与 `next_*`
|
||||
- [x] **游标用「相对锚点的层号/节点偏移」而不是 mail_id**:
|
||||
偏移量每次从锚点重走一遍,无状态、不可伪造;
|
||||
- [x] **从线索根整树 BFS**(`ThreadRootOf` 上溯到根,再 `DescendantsRaw` 展开):
|
||||
弃掉原先 `dir=around|up|down` 三方向分页 —— 那种做法下**兄弟分支整条落在盲区里**:
|
||||
一封抄送给两个 Agent 的邮件会收到两个回复,二者互为兄弟,从其中一个看树看不到另一个;
|
||||
挂在原件上的转发分支同理。先到根再整棵展开,兄弟、平行回复、转发分支都是根的子孙
|
||||
- [x] **游标是「自根起的节点数」而不是 mail_id**:偏移量每次从根重走一遍,无状态、不可伪造;
|
||||
用 mail_id 做游标就必须允许传入**不可见**的邮件(不可见的中间段要穿过去),
|
||||
那还得单独证明它确实是锚点的祖先,反而更绕。
|
||||
祖先方向的层号天然稳定 —— 新邮件只会追加成叶子,不会插进已有链条中间
|
||||
- [x] `depth` 改为**相对锚点**(0 = 锚点,负 = 祖先,正 = 子孙):
|
||||
分块加载时根可能还没取到,绝对深度无从得知
|
||||
那还得单独证明它确实是根的祖先,反而更绕。
|
||||
节点顺序天然稳定 —— 新邮件只会追加成叶子,不会插进已有链条中间
|
||||
- [x] `depth` 为**距线索根**的绝对层级(0 = 根,恒 ≥ 0):从根展开后根一定在结果里,
|
||||
绝对深度总是可知(`AncestorsRaw` 内部的负 depth 在 handler 层加回 `anchorDepth` 抵消)
|
||||
- [x] repo 层**不做可见性过滤**:不可见的中间段必须能穿过(转发把线索引进别人的会话,
|
||||
再往上却可能仍是自己参与的往来)。过滤放在 handler 层,那里才知道调用者是谁
|
||||
- [x] 前端 `IntersectionObserver` 双哨兵(rootMargin 200px 提前触发)+
|
||||
@ -797,8 +798,10 @@ execute: {
|
||||
(`setState` 异步,读 state 会双双看到 false)
|
||||
- [x] 实测 251 封长链:7 页取完,depth 连续无缺口,取到真正的根;
|
||||
311 封(含 60 个转发分支)9 页取完,`depth=1` 恰为 61 个
|
||||
- [x] `limit` 夹到 [1,200],非法值回落默认 40(分页参数不该因笔误让整个请求失败);
|
||||
`limit=1` 时两方向各保底 1,否则算出 `downLimit=0` 连锚点自己都不返回
|
||||
- [x] `limit` 夹到 [1,200],非法值回落默认 60(分页参数不该因笔误让整个请求失败)
|
||||
- [x] 锚点回填上限 `anchorPathBudget = 60` 层:锚点没落在 BFS 首页时把「根 → 锚点」
|
||||
那条路径补进第一页,保证点开的那封一定在树里;超过 60 层则锚点之上留断点。
|
||||
递归 CTE 另有 `descendantDepthCap = 10000` 兜底,仅防数据损坏成环
|
||||
|
||||
**工作列表卡片视图(已完成)**:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user