- add scripts/annotate_roster_invoices.py: match passenger names to invoice PDFs, write status + relative encoded hyperlinks into roster xlsx - add scripts/add_invoice_passenger_name.py, scripts/calibrate.py - add .opencode/skills/invoice-wrapup skill - improve invoice_tool.py / web_ui.py / vision_fallback.py automation - add device/screen/windows adaptation docs - ignore out/ (delivered invoice PDFs contain sensitive data)
83 lines
5.2 KiB
Markdown
83 lines
5.2 KiB
Markdown
# 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
|
||
<a class="pill calibrate-link" href="/calibrate" title="换手机屏幕适配">📱 设备校准</a>
|
||
```
|
||
配套 CSS(`web_ui.py:480`)`.pill.calibrate-link` 蓝色高亮可点击样式。
|
||
|
||
### 3. 首页加「查缺补漏」toggle 按钮
|
||
|
||
- HTML(`web_ui.py:607`):`<button id="finalRetryPass" class="toggle-on">` 放 run-actions 排最后
|
||
- CSS(`web_ui.py:504`):`button.toggle-on`(绿)/ `button.toggle-off`(灰)
|
||
- JS(`web_ui.py:938`):点击切换 class + 文案
|
||
- 后端 `start_runner`(`web_ui.py:295`)加 `final_retry_pass` 参数,False 时 append `--no-final-retry-pass`
|
||
- `/api/start` handler(`web_ui.py:1141`)传参,前端 onclick(`web_ui.py:934`)读 `classList`
|
||
|
||
### 4. 总进度表按开票顺序排列
|
||
|
||
`status_payload`(`web_ui.py:208`):给每条 roster_status 记 `_progress_idx`(progress 表行号),排序后清除临时键。未在 progress 的用 `len(progress)` 排最后。
|
||
|
||
```python
|
||
progress_idx = next((i for i, r in enumerate(progress) if r is progress_row), len(progress))
|
||
# ...
|
||
roster_status.sort(key=lambda r: (r.get("_progress_idx", 0), r.get("_roster_idx", 0)))
|
||
```
|
||
|
||
## 产出物
|
||
|
||
- `docs/device-adaptation.md`(新建):换手机适配截屏节点清单 + 操作步骤
|
||
- `docs/web-ui-adaptation-log.md`(本文件):操作经验记录
|
||
- `scripts/web_ui.py`(修改):校准入口 + 查缺补漏按钮 + 进度表排序
|
||
|
||
## 踩坑与启示
|
||
|
||
1. **浏览器缓存是前端改动的头号陷阱**:改完 web_ui.py 后用户点按钮"没执行",根因是浏览器跑旧 JS。强制刷新 `Cmd+Shift+R` 或加 URL 参数 `?nocache=1` 绕过。后端用 `curl` 验证比盯浏览器快。
|
||
2. **截图单文件覆盖无法回溯**:`work/last_screenshot.png` 和 `work/_vision_find_tmp.png` 都是覆盖式,报错时已被后续节点覆盖。换手机排错时需手动备份或改代码按节点留档。
|
||
3. **"继续开票"按钮视觉恒 found:false**:当前机型已失效,靠 XML 硬编码 bounds 兜底。新手机 bounds 不同会直接失败--这是换手机的高风险点。
|
||
4. **after_verify 必超时 12s**:每个乘客都走 `network_or_loading` 超时纠偏,全靠视觉兜底。新手机 XML 更不稳时会放大。
|
||
5. **`is` 比较字典引用可行**:`by_person_key` 存的是 progress 列表里的字典引用,`next((i for i, r in enumerate(progress) if r is progress_row), ...)` 能正确找到行号。
|
||
|
||
## 未尽事项
|
||
|
||
- `work/device_profile.json` 仍未生成(需在 `/calibrate` 页点「保存设备配置」)
|
||
- 截图留档机制未改(仍是单文件覆盖)
|
||
- 校准工具缺「扫码开票」节点的 step(recover 路径无校准项)
|
||
- 真换手机后需实测验证滑动比例适配
|