Files
Jyotisha/docs/tasks/PROGRESS-rectification-mobile-timeline-readout-20260917.md
T
Jesse_ChenandClaude Fable 5.1 662672c153 fix(web): 手机上时间轴读数不再被裁,「跳到最新」不再压住选项
375px 下读数第四项被 ellipsis 裁成「已…」、第五项整项不可见:compact
段仍加 44px 头像缩进(每侧 60px,可用内容只剩 255px),而 cfb41daf 又把
读数从四项变成五项,按 13px 逐字估宽需要 383px。compact 段改为只取
`space-4`、`column-gap` 收到 `space-2`、第五项 `已对照 N 件` 在 767px 以下
`display: none`(仍在 DOM 与轴 aria-label 里),四项约 292px / 可用 343px。
桌面段、条高 64/56px、滚动锚定逻辑均未动。

「跳到最新」浮层占 composer 上方 56px 带,而 `.message-list` 底部留白恰好
也是 56px,末条选项贴在浮层按钮正下方、正中间点不动。留白改为
`calc(clearance + space-3)`,静止时末条下方 84px = 56px 带 + 28px 空气;
`.conversation` 追加同高 `scroll-padding-block-end`。浮层位置、居中与可见
条件未动。

顺带记一条待产品裁决的口径冲突:DESIGN §10 禁列表写明「已对照 N 件经历」
不上条、仍归交付卡,`cfb41daf` 却把它加上且未改 DESIGN;本轮只在手机上把
它移出可见行,桌面保留原状。

BUG-918、BUG-919

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JUei7K13cYxLHE3Axe4A45
2026-09-17 00:53:21 +00:00

95 lines
9.5 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.
# 进度记录 · 校正页移动端:时间轴读数被裁、「跳到最新」压住选项(2026-09-17)
任务书:`docs/tasks/TASK-rectification-mobile-timeline-readout-20260917.md`
分支:`codex/rectification-mobile-timeline-readout-20260917`,基线 `origin/staging` = `c32f81e7`(任务书写的 `8d7dfbf0` 已被 staging 超车,按指令取 `c32f81e7`)。
BUG:918、919。纯前端样式,未跑 Python 预检(AGENTS §9 允许)。
未触碰(并行会话所有):`frontend/src/components/rectification-agentic-chat.tsx``frontend/src/lib/rectification-agentic/**`、Python、Skill。也未动时间轴固定高度(64 / 56px)与 `use-conversation-scroll-anchor`
## 1. 做了什么
| 任务 | 文件 | 改动 |
| --- | --- | --- |
| T1 BUG-918 | `frontend/src/app/globals.css` | `@media (max-width: 767px)` 段:`.rectification-timeline``padding-inline``calc(var(--space-4) + var(--assistant-content-inset))` 改为 `var(--space-4)``.rectification-timeline__readout { column-gap: var(--space-2) }``.rectification-timeline__dated { display: none }`。桌面段未动。同时改掉基线注释里「四项短文本在 375px 下还有余量」这句被实证推翻的话。 |
| T1 BUG-918 | `frontend/src/components/rectification-timeline.tsx` | 只加注释:五个 span 永远无条件渲染,由 CSS 决定窄屏显示几项;轴 `aria-label` 仍由五项拼成;再加第六项必须重算宽度预算。无行为改动。 |
| T2 BUG-919 | `frontend/src/app/globals.css` | `.rectification-workspace__chat .message-list` 底部留白由 `var(--rectification-jump-clearance)` 改为 `calc(var(--rectification-jump-clearance) + var(--space-3))``.conversation` 追加 `scroll-padding-block-end: var(--rectification-jump-clearance)``--rectification-jump-clearance` 取值未变(时间轴 56px 条高仍与它同源,既有断言不受影响);浮层的位置、居中、可见条件未动。 |
| T3 | `docs/BUG_HISTORY.md``CHANGELOG.md``frontend/DESIGN.md``docs/testing/…`、本文件 | 记录。 |
## 2. 宽度预算(T1 的算术)
jsdom / happy-dom 不在本套件里,`scrollWidth``clientWidth` 都量不到,所以这是**按逐字保守估宽的算术**,不是测量。每字宽度一律向上取整(数字取 0.6em,而 -apple-system / Helvetica 的 tabular 数字约 0.556em),font-size 13px。测试里 `readoutWidthPx` 就是这套系数。
单项估宽(px):`04:4805:07` 77.5、`20 分钟` 45.2、`代表分钟 04:53` 91.1、`已答 6 题` 54.1、`已对照 3 件` 67.1。
| | 改前 | 改后 |
| --- | --- | --- |
| compact 每侧内边距 | 16 + 44 = 60px | 16px |
| 375px 可用内容宽 | 255px | 343px |
| 可见项数 / 列间距 | 5 项 / 12px | 4 项 / 8px |
| 读数需要宽度 | 383.0px | 291.9px |
| 375px 余量 | **128.0px(被裁)** | **+51.1px** |
| 390px 余量 | 113.0px | +66.1px |
| 320px 余量 | 143.0px | 3.9px |
375 与 390 两个目标宽度都放得下。**320px 差约 4px**:按系统实际字宽(数字 0.556em)重算是 283.3px ≤ 288px,能放下;按上面的保守系数差一点点。真机 320px 若尾部被裁一点属已知边界,已写进 `docs/testing/` 清单第「已知边界」段,范围和代表分钟在任何情况下都不会被裁。
让步顺序:没有用到。任务书让步 1(只做去 inset + 缩 gap)算下来是 5 项 335.0 + 4×8 = 367.0px > 343px,仍然放不下,所以第五项必须离开可见行;采用了任务书 T1 里的「只保留一项」分支,而不是合并成「N 题 · N 件」——合并需要原始计数,而计数只以 `已答 6 题` / `已对照 3 件` 这种成品字符串到达组件,要么去改 `frontend/src/lib/rectification-timeline-scale.ts`(超出本单文件范围),要么在组件里正则抠数字(脆弱)。隐藏这一项另有 DESIGN 依据,见第 4 节。
## 3. 「跳到最新」的几何(T2)
浮层占 composer 上方 56px 的带:按钮 44px + 浮层自身 `padding-bottom: var(--space-3)`。基线 `.message-list` 底部留白恰好也是 56px,与带严丝合缝,末条内容顶到按钮正下方;容器 `pointer-events: none` 只放行 44px 按钮本体,而按钮居中,正落在选项行中央 → 「遮一半 + 中间点不动」。
改后:`.message-list` 68px + `.conversation` 16px = 静止时末条下方 84px = 56px 带 + 28px 空气。
**做不到、也没有假装做到的部分**:把「任何滚动位置都不重叠」做成保证,需要留白 ≥ `conversationAnchorThreshold`(96px) + 56px = 152px。推导:设末条内容底为 E、尾部留白 P、距底 d,浮层带覆盖内容坐标 `[E+P-d-56, E+P-d]`,与真实内容重叠 ⟺ `d > P - 56`;而浮层可见 ⟺ `d > 96`。所以要让「浮层刚出现的那一刻」不压内容就得 `P - 56 ≥ 96`。152px 在 667px 高的手机上等于凭空吃掉一整行选项,且浮层只在读者已经主动向上滚过 96px 后才出现,所以按 CSS 注释记录理由后不做。本轮保证的是:**贴底静止时(浮层隐藏)末条选项整行可点且与输入框有 28px 空隙**;浮层可见时它浮在已滚上去的内容上,与两个聊天面一致,点一下即回到底。
未改浮层可见条件(任务书要求),也未把胶囊改回右对齐——`tests/rectification-agentic-entry.test.ts` 锁着 `justify-content: center`(BUG-478 的统一决策),右对齐是 2026-08-25 `7a4360d8` 的旧修法,已被取代,不擅自推翻。
## 4. 顺带发现的口径冲突(未擅自裁决,需产品拍板)
`frontend/DESIGN.md` §10 的「以下一律不得加回来」表里明确写着「已对照 N 件经历」不上条、仍归交付卡,理由是它和「已答 N 题」不是同一个量。但 `cfb41daf`2026-09-16BUG-740743)把 `datedEventLabel` 加到了读数上,且没有改 DESIGN。也就是说这第五项从进条那天起就与 DESIGN 的红线矛盾,而它正是压垮 375px 宽度预算的那一项。
本轮**只在 767px 以下把它移出可见行**(任务书授权范围内),桌面保留原状,并把这处冲突写进 BUG-918 的「相关记录」、DESIGN §10 和真机清单,等产品决定桌面是否也撤掉。没有单方面改桌面。
## 5. 测试
新增 `frontend/tests/rectification-mobile-timeline-readout-20260917.test.tsx`6 条):
1. 渲染断言:五项文本按序全在 DOM,且轴 `aria-label` 含全部五项。
2. 宽度预算断言:compact 可见四项 + 3×8px ≤ 343px375)与 ≤ 358px390);并反向断言旧口径 383px > 255px,把 Bug 的形状钉住。
3. compact 段声明断言:`padding-inline: var(--space-4)` 且段内不含 `--assistant-content-inset``column-gap: var(--space-2)``__dated` `display: none`;段内不得出现 `__range` / `__width` / `__working`(这两个数字任何宽度都不许隐藏或缩);不得放开 `flex-wrap` / `white-space`;条高仍 56px。段的切取是按大括号配平取出那一个 `@media` 块,不是 `slice` 到文件尾。
4. 桌面段断言:仍是 `calc(var(--space-8) + var(--assistant-content-inset))`,读数仍 `nowrap` + 13px。
5. T2 断言:留白表达式、`scroll-padding-block-end`
6. 浮层未动断言:`absolute` / `bottom: 100%` / `justify-content: center` / `pointer-events: none` / 按钮 44px,以及 `conversationAnchorThreshold = 96` 与 anchor hook 里不出现 scroll-padding。
文件头写明了「本套件没有 DOM 实现,所以几何断言是算术不是测量,真机走查必做」。
改写的既有断言 1 条 —— `frontend/tests/rectification-timeline-20260909.test.ts`「the mobile bar stays within the 44px touch rhythm」:
- 原值:`assert.match(mobile, /padding-inline: calc\(var\(--space-4\) \+ var\(--assistant-content-inset\)\);/)`
- 新值:`assert.match(mobile, /padding-inline: var\(--space-4\);/)`
- 原因:BUG-918。这条断言锁的正是造成裁切的那 44px 头像沟槽。条不在消息列里,手机上对齐头像列没有可见收益;同一测试里桌面那条 inset 断言未动,`--rectification-jump-clearance` 断言未动。
没有弱化其它任何断言,没有删测试。
## 6. 门禁数字
| 项 | 基线(`c32f81e7` | 改后 |
| --- | --- | --- |
| `./node_modules/.bin/tsc --noEmit` | — | **0 错** |
| `npm run lint` | — | **0 error**116 warning,与基线同为既有 `no-unused-vars`,未顺手修) |
| `npm test` | 3414 tests / 31 fail | **3420 tests / 31 fail**+6 新测试全绿) |
| 失败清单 | 31 条无 Docker 集 | **逐条相同**(排序后 `diff` 无输出) |
| `next build --webpack` | exit 0 | **exit 0** |
| `/` 路由 | `○ Static` | **`○ Static`** |
| 首屏 gzip | 620,106 B / 25 文件 | **620,128 B / 25 文件(+22 B, +0.004%** |
- 失败清单 31 条全部是既有无 Docker / 无凭据集(database-*、staging sync、billing、ephemeris 401 等),与 `BLOCKED.md` 一致。
- gzip 口径:把 `.next/server/app/index.html` 里引用到的每个 `/_next/static/*.js|css` 单独 `gzip -9` 后求和。唯一变化是首屏 CSS 分块 36,510 → 36,532 B。
- Turbopack 拒绝软链 `node_modules`,按环境说明用 `--webpack`
## 7. 环境缺口
- **无 Chrome、无真机**375 / 390 宽下「读数四项完整」「胶囊不压选项」只能人工确认,清单在 `docs/testing/rectification-mobile-timeline-readout-20260917.md`(7 条 + 已知边界)。第 2 节的宽度是算术,不是真机测量;第 3 节的 28px 空隙同样没有真机截图。
- **未部署**:本分支只推自己的分支,未推 staging,`deployment.gitCommit` 未核对。