diff --git a/doc/research/U2_ELEMENT_SELECTORS.md b/doc/research/U2_ELEMENT_SELECTORS.md index 3cbf648..6125bab 100644 --- a/doc/research/U2_ELEMENT_SELECTORS.md +++ b/doc/research/U2_ELEMENT_SELECTORS.md @@ -85,6 +85,44 @@ --- +## 三·补:抓取弹窗"老是错位"的根因 —— **截图和元素树不是同一时刻** + +(2026-09-13 追加,用户反馈"抓取的窗口老是会错位") + +先把几个常见猜测逐一排除(都实测过): + +| 猜测 | 实测结果 | +|------|---------| +| 两条通道元素树不一致 | ✗ 排除:节点数/各 id 个数逐项相同 | +| 截图被 CSS 缩放了、框没跟着缩 | ✗ 排除:`scaleX=clientWidth/naturalWidth` 算得对,实测框位置与理论值一致 | +| 窗口 resize 后没重算 | ✗ 排除:预览列固定 320px,resize 不影响 | +| 列表索引与框的 `data-idx` 对不上 | ✗ 排除:用 `indexOf` 保住原始序号,过滤后也不乱 | + +**真因:截图与元素树分两次取,中间隔了 1~2 秒。** + +| 取数方式 | 截图 | 元素树 | 两者时间差 | +|---|---|---|---| +| 现在(`/api/uiauto/screenshot` + `/api/uiauto/elements` 两次请求,走 uiautodev)| 0.4s | 1.8s | **约 1.8 秒** | +| 原生 u2 背靠背(同一个连接)| 0.3s | 1.4s | **约 1.4 秒** | + +元素树的 dump 本身就要 1.3~1.8 秒(设备端 uiautomator 的开销,改不动)。 +界面**只要在动**(抖音信息流、视频、加载动画…),两秒足够让元素位置全变 → +**框永远落在旧位置上** —— 这就是"老是错位",不是偶发。 + +### 解法 + +1. **一次请求取齐**(推荐,也是用户说的"用原始 u2"): + 新增 `GET /api/uiauto/snapshot?serial=X`,服务端用**一个 u2 连接**背靠背 + `dump_hierarchy()` + `screenshot()`,返回 `{image, elements}`; + 前端只调这一个接口 → 天然同源,间隔从 ~2.2s 降到 ~1.4s。 +2. **双截图校验**(关键:让失败可见而不是悄悄错位): + 抓取时前后各截一张,两张**不一致就明确提示**"界面在抓取过程中变化了, + 请让设备停在目标界面再抓",而不是给一个已经错位的框。 +3. 文档里明确写:**抓元素要让设备停在静止界面**(设置页、已加载完的页面), + 别在视频播放/信息流滑动中抓。 + +--- + ## 四、建议的改动(待排期) 1. **抓取器(`core/uiauto_helper.py`)**:同一 id 出现多个实例时,**优先产出 @@ -96,3 +134,5 @@ 其余在编辑器里逐个复核。 4. **运行期**:`click` 未命中时,日志里顺带 dump 一下"同 id 现在有几个实例", 让"序号错位"当场可诊断(现在是干巴巴一句"未找到元素")。 +5. **(针对第三节的"抓取错位")** 抓取接口合并成一个快照接口 + 双截图校验, + 具体见第三节「解法」。