用 playwright 连本机共享 Chromium,在 390px(iPhone 14 Pro)与 320px (iPhone SE)量真实盒子。之前的窄屏适配是「照着规则写对」,实测发现 一个功能性 bug 加五处可用性问题。 ## 抽屉式侧栏遮挡底部导航(真 bug) 抽屉是 `fixed left-0 top-0 bottom-0 z-50`,铺满整个视口高度;底部导航没有 z-index。抽屉打开时点最左那一项「收件」,elementFromPoint 命中的是抽屉里的 SVG,不是导航按钮 —— 按钮在那里、尺寸也够、CSS 规则也没写错,只有命中测试 才能发现。 **删掉抽屉而不是给导航加 z-index**:抽屉装的六项(收件/发件/联系/用户/新建/ 管理)与底部导航完全重复,唯一独有的是退出登录。为一个按钮维护一套 fixed 层级加遮罩不划算,而它还附带「Esc 关不掉」「底层未锁滚」两个毛病。 退出登录移到「我的」页 —— 它与密码、密钥同属「账号自身」,而那页此前根本 没有退出入口。`NavToggle` 与 uiStore 的 navOpen/toggleNav/closeNav 一并删除。 ## 触摸命中区:新增 .tap 详情页那排工具按钮视觉高度只有 15-16px(实测「标记已读」48x16、「对话树」 54x16、「转发」42x16、「抄送」20x15),移动端下限是 44x44。 直接加 padding 会把本来就挤的头部撑散、320px 下换行,因此用居中的透明伪元素 扩大命中区:**视觉一像素不动**。只在 max-width:767px 生效 —— 桌面用鼠标精度 足够,而扩大后的命中区在密排工具栏里会互相重叠,点一个可能命中隔壁那个。 覆盖 MailView / ContactPanel / WorkCard / ModelScopePanel / AdminUsersPage / ComposePage / ThreadView / KeyPanel / QuotaPanel / Attachments / BackButton。 ## 看不见却按得动的按钮:新增 .reveal `opacity-0 group-hover:opacity-100` 在没有 hover 的设备上永远是 opacity:0, **但仍然接收点击** —— 实测联系人列表里 elementFromPoint 命中的就是那个看不见的 「归档」。一个看不见却按得动的破坏性按钮比没有按钮更糟:人以为点的是卡片, 实际归档了一条会话。 改为默认可见,只在 `(hover: hover) and (pointer: fine)` 时隐藏。 单看 hover 会把带触摸板的平板算进去。 ## 对话树 - 缩进随屏宽自适应:固定「每级 20px、上限 8 级」= 最多 160px,320px 屏还要 去掉 px-4 的 32px 与连接线 18px,卡片只剩 110px,发件人一行直接被 truncate 吃掉。窄屏改为每级 10px、上限 5 级 - 补返回出口:原先只有「关闭」。两者语义不同 —— 返回退出整个详情栏回到列表, 关闭只收起树、留在这封邮件上 ## 把实测脚本留进仓库 `web/test/manual/`(`npm run test:narrow` / `test:wide`),不进 npm test —— 要一个跑着的浏览器加一个活的 Gateway。 留着而不是用完即删,是因为结构性断言守不住「按钮实际多大、点下去命中谁」, 而这次最严重的 bug 恰好只有 elementFromPoint 能发现。helper 里两个函数专门 为此:tapTargets() 量 .tap 的真实命中区(伪元素尺寸,不是 boundingBox), hitTest() 验每个元素点下去是否命中自己。 ## 验证 - 窄屏 13 项 + 宽屏 5 项全通过。宽屏回归特意验了两件只该在窄屏生效的事: .tap 伪元素 content 为 none、没有返回按钮 - narrow-layout.test.mjs 从 20 条扩到 28 条,逐条钉住上面每个修复 - 无横向溢出:390px 与 320px 下 scrollWidth === clientWidth - 生产已部署
59 lines
2.4 KiB
Markdown
59 lines
2.4 KiB
Markdown
# 手工浏览器实测脚本
|
||
|
||
不进 `npm test` —— 它们需要一个跑着的 Chromium 与一个活的 Gateway。
|
||
日常回归靠 `../narrow-layout.test.mjs`(读源码验形态,无外部依赖)。
|
||
|
||
## 为什么两套都要
|
||
|
||
结构性断言守住「代码写成了什么形态」,量不出「按钮实际多大、点下去命中谁」。
|
||
|
||
窄屏那轮修复里最严重的一个 bug 是抽屉式侧栏(`fixed ... z-50` 铺满视口高度)
|
||
把底部导航最左那一项盖住 —— 按钮在那里、尺寸也够、`md:hidden` 之类的规则也
|
||
没写错,**只有 `elementFromPoint` 才能发现它命中的是抽屉里的 SVG**。
|
||
|
||
## 用法
|
||
|
||
```bash
|
||
# 窄屏:390px(iPhone 14 Pro)+ 320px(iPhone SE)
|
||
ADMIN_PW=<密码> npm run test:narrow
|
||
|
||
# 宽屏回归:窄屏修复不能把桌面改坏
|
||
ADMIN_PW=<密码> npm run test:wide
|
||
```
|
||
|
||
环境变量:
|
||
|
||
| 变量 | 默认 | 说明 |
|
||
|---|---|---|
|
||
| `ADMIN_PW` | 无(必填) | 管理员密码 |
|
||
| `ADMIN_USER` | `admin` | 登录用户名 |
|
||
| `AGENTMAIL_URL` | `https://mail.jianfgit.xyz` | 目标地址 |
|
||
| `CDP_URL` | `http://127.0.0.1:9222` | 浏览器 CDP 端点 |
|
||
| `PLAYWRIGHT` | `/usr/lib/node_modules/playwright/index.mjs` | playwright 入口 |
|
||
|
||
浏览器用的是本机 systemd 托管的共享 Chromium(`homeagent-browser.service`),
|
||
通过 CDP 连上去开自己的标签页,用完关掉。没有它时先
|
||
`systemctl start homeagent-browser`。
|
||
|
||
## 文件
|
||
|
||
| 文件 | 作用 |
|
||
|---|---|
|
||
| `narrow-probe-helper.mjs` | 连浏览器、登录、量盒子/溢出/命中区/命中测试 |
|
||
| `narrow-verify.mjs` | 窄屏 13 项验收 |
|
||
| `wide-regression.mjs` | 宽屏 5 项回归 |
|
||
|
||
`narrow-probe-helper.mjs` 里两个函数值得单独知道:
|
||
|
||
- `tapTargets(page, labels)` —— 量 `.tap` 按钮的**真实**命中区(`::after`
|
||
伪元素的尺寸)。`.tap` 刻意不改变视觉尺寸,所以只看 `boundingBox` 会误判成偏小
|
||
- `hitTest(page, selector)` —— 每个元素点下去是否命中自己。遮挡类 bug 只能这样查
|
||
|
||
## 已知限制
|
||
|
||
headless Chromium 报告 `hover: none`,因此 `.reveal`(只在支持悬停的设备上隐藏)
|
||
在这里永远是可见的 —— 脚本只能验「触摸设备上可见」这一半,
|
||
「鼠标设备上隐藏」那一半靠 `../narrow-layout.test.mjs` 检查 CSS 规则存在。
|
||
|
||
没有像素级视觉比对:字体差异下极脆,维护成本高于收益。
|