From 8fdc62d98d85683036a353d1107a792a5fa8f220 Mon Sep 17 00:00:00 2001 From: yu <191972707@qq.com> Date: Tue, 3 Nov 2026 14:28:23 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=9B=BE=E7=89=87Base64=E7=BC=96?= =?UTF-8?q?=E8=A7=A3=E7=A0=81=E7=BB=84=E4=BB=B6=E7=BB=9F=E4=B8=80(Encode?= =?UTF-8?q?=E5=B9=B6=E5=85=A5=E6=96=B9=E5=90=91=E5=88=87=E6=8D=A2,Decode?= =?UTF-8?q?=E9=9A=90=E8=97=8F),=20=E9=AA=8C=E8=AF=81=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E5=BD=92=E5=B9=B6:=20=E5=9B=BE=E5=83=8FOCR=E6=9C=AA=E6=B5=8B?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=2041->7=20(Base64/CV/OCR=E7=A5=A8=E6=8D=AE?= =?UTF-8?q?=E5=8D=A1=E8=AF=81=E8=AF=81=E7=85=A7=E9=80=9A=E7=94=A8=E7=A6=BB?= =?UTF-8?q?=E7=BA=BF)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/capability-duplicates.json | 7 ++ resources/catalog.json | 71 +++++++++++++++++-- src/main/capabilities/remaining-core.ts | 20 +++++- src/renderer/src/validation/flowValidation.ts | 6 ++ 4 files changed, 96 insertions(+), 8 deletions(-) diff --git a/resources/capability-duplicates.json b/resources/capability-duplicates.json index 86f97b0..1e0ae1c 100644 --- a/resources/capability-duplicates.json +++ b/resources/capability-duplicates.json @@ -5610,6 +5610,13 @@ "name": "插入分页符", "status": "keep", "reason": "唯一能力" + }, + { + "id": "Image_Base64Decode", + "name": "图片base64编码转二进制", + "canonical": "Image_Base64Encode", + "status": "hide", + "reason": "与图片Base64编解码(Image_Base64Encode)互逆重复, 已统一为转换方向切换, 保留执行兼容" } ] } \ No newline at end of file diff --git a/resources/catalog.json b/resources/catalog.json index 83c24cf..358689f 100644 --- a/resources/catalog.json +++ b/resources/catalog.json @@ -67363,22 +67363,25 @@ }, { "id": "Image_Base64Encode", - "name": "图片转base64编码", + "name": "图片Base64编解码", "kind": "vendor", "group": "vision", "categories": [ "image" ], "categorySignature": "image", - "description": "将图片转为base64编码。", - "messageTemplate": "将图片 $1 转base64编码, 然后把结果保存到 $0", + "description": "将图片文件转为 base64 编码,或将 base64 编码还原保存为图片文件。", + "messageTemplate": "对图片执行 base64 $1 , 然后把结果保存到 $0", "baseType": "Image_Base64Encode", "functionName": "Image.Base64Encode", "functionCalls": [ { "function": "Image.Base64Encode", "args": [ - "path" + "mode", + "path", + "val", + "output" ], "assignTo": "var_name" } @@ -67395,6 +67398,29 @@ "icon": "vision", "risk": "low", "fields": [ + { + "key": "mode", + "label": "转换方向", + "widget": "radio", + "type": "string", + "displayType": "buttonGroup", + "required": false, + "defaultValue": "encode", + "placeholder": "", + "description": "编码:图片文件转为 base64 字符串;解码:base64 字符串还原保存为图片文件", + "advanced": false, + "valueTypes": [], + "options": [ + { + "label": "图片 → Base64", + "value": "encode" + }, + { + "label": "Base64 → 图片", + "value": "decode" + } + ] + }, { "key": "path", "label": "图片对象", @@ -67404,17 +67430,48 @@ "required": true, "defaultValue": "", "placeholder": "截取或选择图像", - "description": "填写参数值,支持 ${变量} 引用上游输出", + "description": "编码方向的源图片路径,支持 ${变量} 引用上游输出(如上游截图的保存路径)", "advanced": false, "valueTypes": [ "rpa_str" ] + }, + { + "key": "val", + "label": "Base64编码", + "widget": "text", + "type": "string", + "displayType": "text-expression", + "required": true, + "defaultValue": "", + "placeholder": "如 ${图片编码值}", + "description": "解码方向的 base64 字符串,支持 ${变量} 引用上游输出;自动忽略 data:image/...;base64, 前缀", + "advanced": false, + "valueTypes": [ + "rpa_str" + ] + }, + { + "key": "output", + "label": "图片保存路径", + "widget": "file", + "type": "object", + "displayType": "selectFile", + "required": false, + "defaultValue": "", + "placeholder": "如 D:\\files\\restored.png", + "description": "解码方向的保存位置(含文件名);留空自动生成临时图片文件", + "advanced": false, + "valueTypes": [ + "rpa_str_file", + "rpa_str" + ] } ], "output": { "label": "输出到变量", "key": "var_name", - "suggestedName": "图片编码值", + "suggestedName": "结果值", "valueTypes": [ "rpa_str" ], @@ -67422,7 +67479,7 @@ { "key": "var_name", "label": "输出到变量", - "defaultValue": "图片编码值", + "defaultValue": "结果值", "valueTypes": [ "rpa_str" ] diff --git a/src/main/capabilities/remaining-core.ts b/src/main/capabilities/remaining-core.ts index 1411461..f78f178 100644 --- a/src/main/capabilities/remaining-core.ts +++ b/src/main/capabilities/remaining-core.ts @@ -165,7 +165,25 @@ async function captureScreen(file: string) { fs.mkdirSync(path.dirname(file), { recursive: true }); await powershell(`Add-Type -AssemblyName System.Drawing;Add-Type -AssemblyName System.Windows.Forms;$bounds=[System.Windows.Forms.Screen]::PrimaryScreen.Bounds;$bitmap=New-Object System.Drawing.Bitmap $bounds.Width,$bounds.Height;$graphics=[System.Drawing.Graphics]::FromImage($bitmap);$graphics.CopyFromScreen($bounds.Location,[System.Drawing.Point]::Empty,$bounds.Size);$bitmap.Save(${psString(file)});$graphics.Dispose();$bitmap.Dispose()`); } -register("Image_Base64Encode", async (_ctx, _node, args) => fs.readFileSync(path.resolve(text(args, ["path", "image"]))).toString("base64")); +// 图片Base64编解码: 统一组件按 mode 分流(encode=图片→Base64, decode=Base64→图片)。 +// Image_Base64Decode 已隐藏进该组件,但保留注册以防旧流程直接引用旧 id。 +register("Image_Base64Encode", async (_ctx, node, args) => { + const mode = text(args, ["mode"], "encode"); + if (mode === "decode") { + const value = text(args, ["val", "value"]).replace(/^data:[^;]+;base64,/, ""); + if (!value.trim()) throw new RuntimeError("validation_error", "Base64编码不能为空", { nodeId: node.id, componentId: node.componentId, recommendation: "填写 base64 字符串,或用 ${变量} 引用上游编码输出" }); + const custom = text(args, ["output"]).trim(); + const file = custom ? path.resolve(custom) : path.resolve(process.cwd(), `image-${Date.now()}.png`); + fs.mkdirSync(path.dirname(file), { recursive: true }); + fs.writeFileSync(file, Buffer.from(value, "base64")); + return file; + } + const imageArg = text(args, ["path", "image"]); + if (!imageArg.trim()) throw new RuntimeError("validation_error", "图片对象不能为空", { nodeId: node.id, componentId: node.componentId, recommendation: "填写源图片路径,或用 ${变量} 引用上游截图输出" }); + const source = path.resolve(imageArg); + if (!fs.existsSync(source)) throw new RuntimeError("validation_error", `找不到图片文件:${source}`, { nodeId: node.id, componentId: node.componentId, recommendation: "确认路径正确,或先用「屏幕截图」组件生成图片" }); + return fs.readFileSync(source).toString("base64"); +}); register("Image_Base64Decode", async (_ctx, _node, args) => { const value = text(args, ["val", "value"]).replace(/^data:[^;]+;base64,/, ""); const file = path.resolve(process.cwd(), `image-${Date.now()}.png`); fs.mkdirSync(path.dirname(file), { recursive: true }); fs.writeFileSync(file, Buffer.from(value, "base64")); return file; diff --git a/src/renderer/src/validation/flowValidation.ts b/src/renderer/src/validation/flowValidation.ts index 26b9195..0e2f6e5 100644 --- a/src/renderer/src/validation/flowValidation.ts +++ b/src/renderer/src/validation/flowValidation.ts @@ -29,6 +29,12 @@ export function fieldIsActive(componentId: string, key: string, values: Record