源码教程:原生对话框、DOM 弹窗与人机协作
这三类能力的实现对象不同:原生对话框由浏览器事件提供,DOM 弹窗是普通网页节点,人工请求是服务端维护的协作状态。它们不能共用“找到一个确定按钮就点”的逻辑。
1. 原生对话框记录
页面出现 alert、confirm 或 prompt 时,监听器保存最近一次对话框信息并按配置处理。读取命令返回的是记录,不保证对话框现在还在屏幕上。
| 命令 | 实现 |
|---|---|
get_dialog、get_js_dialog | 两个名字调用同一 getDialog 方法;consume 为 true 时读后清除 |
clear_dialog、clear_js_dialog | 清空最近对话框记录,不是关闭 DOM 窗口 |
set_dialog_behavior | 设置后续原生对话框采用接受还是取消策略,参数为 dismiss |
通过 seq、timestamp 区分新旧记录。不要在某次提交后读到很久以前的 alert,就误判本次提交结果。修改默认处理方式也不代表回放之前的对话框。
2. DOM 弹窗发现和关闭
get_modals 在页面执行弹窗识别逻辑,结合语义、框架特征及几何线索收集候选,输出标题、按钮及点击坐标。固定页头可能与弹窗一样有较高 z-index,所以不能仅按 z-index 判定。
close_modal 支持 which、title、button 选择目标。默认优先关闭顶部弹窗,使用真实鼠标,并在操作后检查弹窗数量等状态是否真的变化。closed=false 时不应循环重复点击,因为可能产生更多确认层。
{"id":"1001","method":"get_modals","params":{}}
先读取再决定是否关闭;短信验证、条款或业务确认并不一定应被关闭。get_modals 没找到候选也不能证明页面没有任何遮挡,仍可从快照文本和点击命中探针排查。
3. 人工请求的状态机
prompt 与非空 steps 至少提供一个;expiresAt 是毫秒时间戳,设置后优先于 timeoutSeconds。
request_human_input 创建 requestId,保存 prompt、expiresAt 和可选 steps;有图片目标时复用元素截图,可选 OCR。请求可以将当前页提到前台,但不会自动把信息推送到用户正在使用的聊天界面,宿主仍需要展示提示。
submit_human_input 根据 requestId 写入 answer,或根据 stepId/answers 更新多步请求。get_human_input 查询状态,允许短时间等待。多步完成一部分时可返回 partial,未完成且超过 expiresAt 时返回 expired。
创建 → pending
部分步骤答复 → partial(仍有待办)
全部答复 → answered
待答复且超过有效期 → expired
requestId 与浏览器任务 ID 不是同一个标识。用户直接在浏览器里完成操作,不一定同时更新人工请求记录;此时必须读取页面确认真实结果,不能只轮询 pending。
{"id":"1001","method":"request_human_input","params":{"prompt":"请在当前页面完成登录,完成后告知","timeoutSeconds":300}}
后续查询必须使用实际返回的 requestId。本教程不记录真实密码或验证码。过期请求不代表验证成功,不能凭时间流逝继续依赖该验证的步骤。
4. 验证方法
fixture 分别触发 alert 与 DOM 弹窗,验证两套查询不会混淆;再叠加两个 DOM 窗口验证目标选择和关闭回读。人工请求测试覆盖单步、多步部分答复、过期和不存在 requestId。测试“已答复”与网站“已登录”是两个不同断言,不能用一个替代另一个。
注册参数与 Java 入口
以下按 CommandTable 实际读取参数整理。* 表示注册层使用必填读取器;其余字段省略后由服务决定默认行为。带条件的入口仍需满足正文说明,例如上传文件来源、元素定位二选一。外层 id 不重复列出。
| 命令 | params 字段 | Java 入口 |
|---|---|---|
get_dialog | consume | getDialog |
clear_dialog | 无 | clearDialog |
get_js_dialog | consume | getDialog |
clear_js_dialog | 无 | clearDialog |
set_dialog_behavior | dismiss | setDialogBehavior |
get_modals | 无 | getModals |
close_modal | which、title、button | closeModal |
request_human_input | steps、prompt、index、selector、timeoutSeconds、expiresAt、ocr、ocrLanguage、inline、frame | requestHumanInput |
get_human_input | requestId*、timeoutSeconds | getHumanInput |
submit_human_input | requestId*、answer、stepId、answers | submitHumanInput |
