fix(web): iPhone 键盘收起后顶栏复位,积分块与盘面芯片同高
Independent Staging Quality Gate / validate (push) Successful in 11m21s
Independent Staging Quality Gate / publish (push) Successful in 10m46s

This commit is contained in:
jesse-ux
2026-09-17 13:13:39 +08:00
parent 77e3626a5c
commit 1b508d5e9a
11 changed files with 345 additions and 10 deletions
+32
View File
@@ -11970,3 +11970,35 @@
- 相关记录:BUG-478(两个聊天面统一用 `useConversationScrollAnchor``JumpToLatestButton`,并把浮层改成居中)、7a4360d8(同一现象 2026-08-25 的旧修法是把胶囊右对齐,已被 BUG-478 的居中统一取代,本轮未推翻它)、BUG-918
- 复发自:无
- 修复版本:待发布
## BUG-920 | iPhone 键盘收起 / 刷新后整页上移,顶栏点不到
- 状态:resolved
- 首次发现:2026-09-17
- 最近更新:2026-09-17
- 影响面:`ViewportScrollLock``layout.tsx`
- 用户现象:刷新或收起键盘后顶栏滚出屏幕,底部留下空白,点不到 tab。
- 触发条件:iPhone Safari 上聚焦输入框弹出键盘,随后收起或带着偏移刷新。
- 根因:iOS 不支持 `interactive-widget=resizes-content`,键盘弹出时滚动 `window``html, body { overflow: hidden }` 挡住用户拉回,reload 又按 `scrollRestoration=auto` 还原 `scrollY`。代码里原先没有 window 级复位。
- 修复:挂载时 `history.scrollRestoration = "manual"``scrollTo(0,0)``visualViewport` resize/scroll、pageshow、orientationchange、focusout300ms)在键盘已收且 `scrollY > 0` 时复位。键盘打开期间不动。
- 验证:`frontend/tests/mobile-viewport-scroll-lock-20260917.test.ts`。真机待核。
- 防复发:不得靠用户自己滚回去;键盘打开时不得抢 Safari 的露出输入框滚动。
- 相关记录:BUG-918、BUG-919、BUG-921
- 复发自:无
- 修复版本:待发布
## BUG-921 | 顶栏积分块比「当前盘面」扁
- 状态:resolved
- 首次发现:2026-09-17
- 最近更新:2026-09-17
- 影响面:`.credit-button``.chat-header-rectification .rectification-board-peek`、手机顶栏行高
- 用户现象:手机顶栏右侧积分「✦ N」又宽又矮,和旁边「当前盘面」不成一套。
- 触发条件:校正页顶栏同时出现盘面芯片与积分块。
- 根因:`.chat-header-actions button` 把高度写成 32px,比 `.credit-button` 更具体,积分块被压到 32px 却仍强制 `min-width: 64px`、13px 字。盘面芯片用另一套 44px / 14px。两枚都塞在 46px 行里。
- 修复:两枚共用 40px 高、14px tabular、同圆角同内边距;去掉积分 `min-width``::before` inset -2px 把热区扩到 44px。≤767px 顶栏行 `52px + safe-area`(原 64px 覆盖改为与任务书 52px 对齐)。
- 验证:CSS 声明断言高度/字号/圆角一致、无 64px min-width`touch-target-contract` 仍绿。
- 防复发:顶栏两枚芯片必须走同一组声明,不得再各写一套高度。
- 相关记录:BUG-695、BUG-920
- 复发自:无
- 修复版本:待发布
@@ -0,0 +1,23 @@
# 进度 · 手机顶栏可点 + 积分块不扁(2026-09-17
基线:`origin/staging` @ `77e3626a`
分支:`codex/mobile-viewport-scroll-lock-20260917`
BUG920、921。Skill 未 bump。
## 做了什么
- **T1 / BUG-920**`viewport-scroll-lock.ts` + `ViewportScrollLock` 挂在 `layout.tsx`,与 `StaleClientRecovery` 并列。`scrollRestoration=manual`,键盘收起后 `window.scrollTo(0,0)`。键盘打开(visualViewport 矮于 innerHeight100)不动。`focusout` 按让步做 300ms 兜底。未改 `html, body overflow: hidden`,未动 `page.tsx` 状态。
- **T3 / BUG-921**`.chat-header-actions .credit-button` 与顶栏 `.rectification-board-peek` 共用 40px / 14px / 同圆角。积分去掉 `min-width: 64px``::before` 2px 扩到 44px 热区。≤767px 顶栏行从 `64px + safe-area` 收到 `52px + safe-area`(任务书按 46→52 写;手机原先已是 64px 覆盖,现与 52px 对齐)。
- **T2**BUG_HISTORY / CHANGELOG / DESIGN / 真机清单。
## 测试
| 项 | 结果 |
| --- | --- |
| `tsc --noEmit` | 0 错 |
| 改动文件 eslint | 0 error |
| 本单 + touch-target + 顶栏相关 | **84 passed / 0 fail**(含 BUG-695 触屏热区) |
| Python | 未改,不跑快速门 |
| `next build` | worktree junction,留给 Gitea |
无 iOS / Chrome,真机清单留给产品。
+1 -1
View File
@@ -105,7 +105,7 @@
| `TASK-rectification-dead-d9-choice-20260916.md` | `PROGRESS-rectification-dead-d9-choice-20260916.md` | 真机(6aabbe38):删卡流程已通,但**P0** D9 感情题没有自己的探针,`stampChoiceSchemaWithProbe` 退到最高增益探针,盖上了 **D24 学业六星座对照探针**BUG-375 (1) 复发):答「没有」按 D24 计分,04:48–04:59 收窄不可信;GET 投影又匹配不上 → 无卡(BUG-912);打字答「没有」后平局直接出交付卡待回放定性(BUG-913);`NAKSHATRA_TRAITS` 整对塞进一个 option,卡头把相反两极列成共同点(BUG-914)。**串行在 year-focus-overlay 验收之后** | **验收未通过(P0** | `227a7571`+`8d7dfbf0`:不借探针、一列一句、BUG-913 定性均过;但自建探针只在盖戳时注入内存 state,生产答题路径读持久化 state → `stale_probe` 报错、GET 无卡、idle 立刻 superseded(生产路径回放实证)。修复单见下一行 |
| `TASK-rectification-dead-d9-choice-fix-20260916.md` | `PROGRESS-rectification-dead-d9-choice-fix-20260916.md` | **验收修复单**:自建分盘探针照 `withNakshatraBoundaryProbe` 模式在每个读 state 的地方(盖戳 / 答题 / `previousInferenceFromReceipt` / GET 投影 / idle 过期判定 / 计划承接)从 receipt 确定性重建(BUG-915);测试改走生产路径、删手工塞探针的 fixture;顺带 host 前置挪到会话校验之后、登记 phase(BUG-916);死卡不得配 `collect_waiting` 占位(BUG-917);**产品决策 1c**:风格题默认不作全额计分(沿用 09-09 ±1 拍板),无事件探针就走下一条线。**staging 现状:风格题答不了,先跳过**。§1d 已记 **产品决策 (b)** | 已验收 | `5113d457`BUG-915~917,产品拍板 (b) 风格题不计分)。Claude 独立验收:生产路径测试(receipt 不含自建探针)答题 applied / GET 出卡 / idle 不误伤;合并候选门禁 tsc 0 / lint 0 error / npm test 3427 条 31 红与基线逐条相同 / `/` Static / 首屏 gzip 620,107→620,193+0.01%/ pytest 63 绿 / 快速门 Python 798 绿。真机清单 `docs/testing/rectification-dead-d9-choice-fix-20260916.md` |
| `TASK-rectification-mobile-timeline-readout-20260917.md` | `PROGRESS-rectification-mobile-timeline-readout-20260917.md` | 手机截图:时间轴读数第四项被裁成「已…」(nowrap + inset 内边距,BUG-918);「跳到最新」浮层压住选项 C(BUG-919)。灰卡与「再说一件」矛盾归修复单 BUG-915/917 | 已验收 | `e8e98bbd`(合入时重放为本分支提交,BUG-918/919)。时间轴相关 71 条 + 全量同上;手机上隐藏「已对照 N 件」符合 DESIGN §10;桌面是否也移除待产品拍板。真机清单 `docs/testing/rectification-mobile-timeline-readout-20260917.md` |
| `TASK-mobile-viewport-scroll-lock-20260917.md` | `PROGRESS-mobile-viewport-scroll-lock-20260917.md` | iPhone 上键盘收起 / 刷新后整页上移、顶栏点不到(BUG-920):iOS 不支持 `interactive-widget`,键盘弹出时 Safari 滚动 window`html/body overflow: hidden` 让用户拉不回来,reload 又还原 `scrollY`;代码里无任何 window 级复位。补 `ViewportScrollLock``scrollRestoration=manual` + `visualViewport` 复位)。与今天两单无关,既有缺陷。**T3 顶栏积分块「有点扁」(BUG-921)**:两枚芯片 44px 塞在 46px 顶栏里、字号/内边距/圆角各一套、积分块强制 64px 最小宽度;统一尺寸并把手机顶栏放到 52px | 待领取 | |
| `TASK-mobile-viewport-scroll-lock-20260917.md` | `PROGRESS-mobile-viewport-scroll-lock-20260917.md` | iPhone 上键盘收起 / 刷新后整页上移、顶栏点不到(BUG-920):iOS 不支持 `interactive-widget`,键盘弹出时 Safari 滚动 window`html/body overflow: hidden` 让用户拉不回来,reload 又还原 `scrollY`;代码里无任何 window 级复位。补 `ViewportScrollLock``scrollRestoration=manual` + `visualViewport` 复位)。与今天两单无关,既有缺陷。**T3 顶栏积分块「有点扁」(BUG-921)**:两枚芯片 44px 塞在 46px 顶栏里、字号/内边距/圆角各一套、积分块强制 64px 最小宽度;统一尺寸并把手机顶栏放到 52px | 待验收 | `codex/mobile-viewport-scroll-lock-20260917` |
### 聊天主链路与首页
@@ -0,0 +1,9 @@
# 真机清单 · 手机顶栏可点、芯片不扁(2026-09-17)
在 iPhone Safari 的 staging 上走。本机无 iOS,下列条目留给产品负责人。
1. 打开一段对话或生时校正,点输入框弹出键盘,再收起键盘:顶栏(侧栏按钮、标题、当前盘面、积分)仍在屏幕顶部,点得到。
2. 键盘还开着时刷新同一 URL:顶栏仍在顶部,底部没有整页上移留下的空白带。
3. 横屏再竖屏:没有空白带,顶栏可点。
4. 顶栏右侧「当前盘面」与积分「✦ N」两枚芯片一样高、一样圆角,积分块不扁。
5. Android Chrome:弹键盘、收起、刷新,顶栏行为与修之前一样,没有新的跳动。