# Web UI 换手机适配改造 · 操作记录
> 2026-07-09 会话产出的操作经验沉淀。换手机后开票流程报错的排查与改造全过程。
>
> 配套文档:[`device-adaptation.md`](./device-adaptation.md)(截屏节点与适配清单)、[`screen-adaptation.md`](./screen-adaptation.md)(理论全链路识图点)。
## 背景
用户换了手机后开票流程总报错。异常关机重启 UI 后,对话上下文丢失。通过跟踪 `work/web_runner.log` 实时日志 + 对照代码,定位换手机适配的三个根因,并完成 Web UI 的改造(校准入口 + 查缺补漏开关 + 进度表排序)。
## 关键决策
1. **不新建排查文档体系,复用已有 calibrate.py**:项目里已有完整的设备校准工具(`scripts/calibrate.py` + Web UI `/calibrate` 页),只是 `work/device_profile.json` 从未生成。换手机第一步是跑校准生成 profile,而非另造轮子。
2. **校准入口放首页顶部状态栏**:用 `.pill` 样式做链接按钮,与状态指示同区,不占用主操作区。
3. **查缺补漏做成 toggle 按钮而非 checkbox**:放"开始运行"按钮同一排,绿色=开/灰=关,状态可见。功能原本默认开启(`final_retry_pass=True`),之前用户不可见不可控。
4. **总进度表按 progress 行序排**:用户要求"完全按开票顺序"。`android_invoice_progress.csv` 的行顺序 = 处理顺序,以此为排序键,未处理项放最后。
## 调查与修改
### 1. 定位换手机报错根因(见 `device-adaptation.md`)
跟踪 `work/web_runner.log` 实测一次完整开票流程,确认 8 个截屏节点的触发频率:
| 节点 | 触发次数 | 风险 |
|---|---|---|
| vision_list_rows(列表识行) | 13 | 低(归一化坐标) |
| _vision_find_button("查看") | 3,全 found:false | 中(误判纠偏) |
| vision_detect_page(探测页面) | 3 | 低 |
| _vision_find_button("开具") | 3,全 found | 中 |
| _vision_find_button("确认") | 3,全 found | **高**(H5 必走视觉) |
| _vision_find_button("继续开票") | 3,**全 found:false** | **高**(当前机型已失效) |
| _vision_find_button("扫码开票") | 2 | 中(recover 路径) |
| _vision_find_qr_thumbnail | 2 | 低 |
根因三类:A 硬编码像素坐标(防熄屏 tap / 滑动)、B 滑动幅度按绝对像素、C 视觉 fallback 找不到按钮。A/B 已有 `device_profile.json` 机制但从未生成。
### 2. 首页加「设备校准」按钮
`scripts/web_ui.py:562` header statusbar 加链接:
```html
📱 设备校准
```
配套 CSS(`web_ui.py:480`)`.pill.calibrate-link` 蓝色高亮可点击样式。
### 3. 首页加「查缺补漏」toggle 按钮
- HTML(`web_ui.py:607`):`