feat: 图片Base64编解码组件统一(Encode并入方向切换,Decode隐藏), 验证任务归并: 图像OCR未测任务 41->7 (Base64/CV/OCR票据卡证证照通用离线)

This commit is contained in:
yu 2026-11-03 14:28:23 +08:00
parent 4486c57536
commit 8fdc62d98d
4 changed files with 96 additions and 8 deletions

View File

@ -5610,6 +5610,13 @@
"name": "插入分页符",
"status": "keep",
"reason": "唯一能力"
},
{
"id": "Image_Base64Decode",
"name": "图片base64编码转二进制",
"canonical": "Image_Base64Encode",
"status": "hide",
"reason": "与图片Base64编解码(Image_Base64Encode)互逆重复, 已统一为转换方向切换, 保留执行兼容"
}
]
}

View File

@ -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"
]

View File

@ -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;

View File

@ -29,6 +29,12 @@ export function fieldIsActive(componentId: string, key: string, values: Record<s
}
}
if (componentId === "System_ScreenSaverShowV1" && key === "password") return truthy(values.set_password);
// Image_Base64Encode(图片Base64编解码): path 仅编码方向, val/output 仅解码方向
if (componentId === "Image_Base64Encode") {
const b64mode = String(values.mode ?? "encode");
if (key === "path") return b64mode === "encode";
if (key === "val" || key === "output") return b64mode === "decode";
}
// Image_Screenshot: 区域坐标仅截图范围为「框选区域」时显示
if (componentId === "Image_Screenshot" && key === "position") return String(values.shotRange ?? "1") === "2";
// Window_*_v1 series: conditional fields based on get_type mode