From ced89e26cff8bc2f50bb7f490c002de834b4c2e9 Mon Sep 17 00:00:00 2001 From: yu <191972707@qq.com> Date: Wed, 28 Oct 2026 11:27:26 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=BD=91=E9=A1=B5?= =?UTF-8?q?=E8=BE=93=E5=85=A5=E8=81=9A=E7=84=A6=E4=B8=8E=E9=99=8D=E7=BA=A7?= =?UTF-8?q?=E5=86=99=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/browser/session.ts | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/main/browser/session.ts b/src/main/browser/session.ts index 5c4191d..c6f410a 100644 --- a/src/main/browser/session.ts +++ b/src/main/browser/session.ts @@ -391,7 +391,17 @@ export class BrowserSession implements BrowserLike { async type(selector: unknown, text: string, clearFirst = true, timeoutMs?: number): Promise { const info = await this.locate(selector, timeoutMs); + this.win.show(); + this.win.focus(); await this.mouseClick(info.rect.x + info.rect.width / 2, info.rect.y + info.rect.height / 2); + const focused = await this.withElement(selector, ` + el.focus({ focusVisible: true }); + return document.activeElement === el || el.contains(document.activeElement); + `); + if (!focused) { + const direct = await this.setValueDirect(selector, clearFirst ? text : `${info.value || ""}${text}`); + return { selector: info.selector, value: direct }; + } if (clearFirst) { await this.cdp("Input.dispatchKeyEvent", { type: "rawKeyDown", key: "a", code: "KeyA", windowsVirtualKeyCode: 65, modifiers: 2 }); await this.cdp("Input.dispatchKeyEvent", { type: "keyUp", key: "a", code: "KeyA", windowsVirtualKeyCode: 65, modifiers: 2 }); @@ -400,11 +410,32 @@ export class BrowserSession implements BrowserLike { await this.cdp("Input.insertText", { text }); await new Promise((resolve) => setTimeout(resolve, 120)); const expected = clearFirst ? text : `${info.value || ""}${text}`; - const actual = await this.evaluate(`(() => { const el = document.activeElement; return el ? (el.value ?? el.textContent ?? '') : ''; })()`); - if (actual !== expected) throw new RuntimeError("evaluate_error", `输入校验失败:期望「${expected}」,实际「${actual}」`, { recommendation: "检查输入框状态或重新拾取元素" }); + const actual = await this.withElement(selector, `return String(el.value ?? el.textContent ?? '')`); + if (actual !== expected) { + const fallback = await this.setValueDirect(selector, clearFirst ? text : expected); + if (fallback !== expected) { + throw new RuntimeError("evaluate_error", `输入校验失败:期望「${expected}」,实际「${fallback}」`, { recommendation: "检查输入框状态或重新拾取元素" }); + } + return { selector: info.selector, value: fallback }; + } return { selector: info.selector, value: actual }; } + private async setValueDirect(selector: unknown, text: string): Promise { + return this.withElement(selector, ` + if (el.isContentEditable) { + el.textContent = ${JSON.stringify(text)}; + } else { + const prototype = el instanceof HTMLTextAreaElement ? HTMLTextAreaElement.prototype : HTMLInputElement.prototype; + const descriptor = Object.getOwnPropertyDescriptor(prototype, 'value'); + descriptor?.set?.call(el, ${JSON.stringify(text)}); + } + el.dispatchEvent(new Event('input', { bubbles: true })); + el.dispatchEvent(new Event('change', { bubbles: true })); + return String(el.value ?? el.textContent ?? ''); + `); + } + async getText(selector: unknown, attribute?: string): Promise { const info = await this.locate(selector); if (attribute) {