diff --git a/src/main/capabilities/desktop.ts b/src/main/capabilities/desktop.ts index ae3b614..e369ed2 100644 --- a/src/main/capabilities/desktop.ts +++ b/src/main/capabilities/desktop.ts @@ -152,13 +152,15 @@ function psCharLiteral(text: string): string { const keyboardSend: CapabilityHandler = async (_ctx, node, args) => { // 字段: words=输入内容(键盘输入), keys/key=按键组合(按键系列), interval=输入间隔(V1毫秒/基础版秒), fuctype=输入方式(0后台接口/1人工模拟/2剪贴板粘贴), window_title=输入目标窗口(留空=当前焦点窗口) + // 文本输入语义组件: Keyboard_Send/Keyboard_Send_V1/键盘驱动输入家族(DriveSend 委托至此, 字段同为 words+interval); + // 按键组合组件(Keyboard_Press/PressNew)字段是 keys/key, 内容保留 SendKeys 语法(^s {ENTER} %{F4})不做转义 + const isTextSend = node.componentId === "Keyboard_Send" || node.componentId === "Keyboard_Send_V1" || node.componentId.startsWith("Keyboard_DriveSend"); const keys = text(args, ["words", "keys", "key", "text", "value"]); if (!keys) throw new RuntimeError("validation_error", "键盘输入为空", { nodeId: node.id, componentId: node.componentId }); await manualDelay(); const rawInterval = number(args, ["interval"], 0); const intervalMs = node.componentId === "Keyboard_Send" ? Math.max(0, Math.round(rawInterval * 1000)) : Math.max(0, Math.round(rawInterval)); const mode = text(args, ["fuctype"], "0"); - const isTextSend = node.componentId === "Keyboard_Send" || node.componentId === "Keyboard_Send_V1"; // 指定目标窗口时先激活再输入,内容才会进到目标窗口而不是运行时的焦点窗口 const targetTitle = text(args, ["window_title", "target_window", "window_obj", "match_title", "select_title"]); const activate = targetTitle ? `${activateWindowScript(targetTitle)}; Start-Sleep -Milliseconds 300; ` : ""; diff --git a/src/main/capabilities/keyboard-send-smoke.test.ts b/src/main/capabilities/keyboard-send-smoke.test.ts index 78c3215..3977536 100644 --- a/src/main/capabilities/keyboard-send-smoke.test.ts +++ b/src/main/capabilities/keyboard-send-smoke.test.ts @@ -3,6 +3,7 @@ import type { CatalogComponent, FlowNode } from "../../shared/types"; import { getHandler } from "../engine/registry"; import type { RunContext } from "../engine/types"; import "./desktop"; +import "./common-final"; const component = {} as CatalogComponent; const node = (id: string): FlowNode => ({ id: "smoke-kb", componentId: id, position: { x: 0, y: 0 }, values: {}, options: {} }); @@ -45,6 +46,27 @@ describe("键盘输入组件真实冒烟", () => { console.log("[键盘输入] 人工模拟+中文标点+智能引号 ✓"); }, 60000); + it("兼容性: Keyboard_Press 组合键语法(^s {ENTER} %{F4})不被文本转义破坏", async () => { + // 组合键必须保留 SendKeys 原语法:^=Ctrl %=Alt {ENTER}=回车 + const out = await invoke("Keyboard_Press", { keys: "^s", interval: "10" }); + expect(out).toBe("^s"); + const out2 = await invoke("Keyboard_PressNew", { keys: "{ENTER}%{F4}" }); + expect(out2).toBe("{ENTER}%{F4}"); + console.log("[键盘输入] 组合键 SendKeys 语法保留 ✓"); + }, 60000); + + it("兼容性: Keyboard_DriveSend_V2(键盘驱动输入,委托组件)按文本输入语义转义特殊字符", async () => { + const out = await invoke("Keyboard_DriveSend_V2", { words: "驱动(a*100%)", interval: "5", keyboard_type: "1" }); + expect(out).toBe("驱动(a*100%)"); + console.log("[键盘输入] DriveSend 委托文本转义 ✓:", out); + }, 60000); + + it("兼容性: 基础版 Keyboard_Send interval 秒级换算", async () => { + const out = await invoke("Keyboard_Send", { words: "秒", interval: "0.01" }); + expect(out).toBe("秒"); + console.log("[键盘输入] 基础版秒级间隔 ✓"); + }, 60000); + it("剪切板粘贴模式: 原文进入剪贴板并发送 Ctrl+V", async () => { const content = `粘贴${Date.now()}`; const out = await invoke("Keyboard_Send_V1", { words: content, fuctype: "2" });