PRA-only-demo/packages/rpa-core/src/capabilities/word.ts
yu caa8e19332 阶段1-rpa-core建包: engine+31个纯Node能力迁入packages/rpa-core, 领域类型单一源化, createEngine工厂收拢模块级状态
- engine/(registry/types/runtime/expression)物理迁入包, 解耦shared/types(域类型归包, 宿主type-only re-export)
- 31个纯Node能力+27个测试迁入包; 宿主留守Electron/浏览器/AI依赖能力, index.ts经@rpa/core/capabilities拉起
- 新增createEngine()/defaultEngine: excel缓存/Excel句柄/db连接/FTP客户端/OCR实例/拟真设置挂引擎实例
- remaining-core子流程依赖改为host-bridge注入, 包内不再import宿主flows
- 宿主main/index.ts启动时注入子流程源; electron-vite/vitest/tsconfig配@rpa/core源码别名
- 验证: typecheck绿, 快照909个id diff为零, 332测试过(2个桌面冒烟因会话无交互SetForegroundWindow被拒, 环境阻塞)
2026-11-04 12:36:03 +08:00

45 lines
2.4 KiB
TypeScript

import path from "node:path";
import { register } from "../engine/registry";
import { powershell, psString } from "./desktop";
interface WordHandle { path: string; }
function text(args: Record<string, unknown>, keys: string[], fallback = ""): string {
for (const key of keys) if (args[key] !== undefined && args[key] !== null && args[key] !== "") return String(args[key]);
return fallback;
}
function handlePath(args: Record<string, unknown>): string {
const raw = args.objWord ?? args.filePath ?? args.path ?? args.file;
if (typeof raw === "object" && raw !== null && "path" in raw) return path.resolve(String((raw as WordHandle).path));
return path.resolve(String(raw || ""));
}
function ensure(value: string, label: string): string {
if (!value.trim()) throw new Error(`${label}为空`);
return value;
}
function wordScript(body: string): string {
return `$word = $null; $doc = $null; try { $word = New-Object -ComObject Word.Application; $word.Visible = $false; $word.DisplayAlerts = 0; ${body} } finally { if ($doc -ne $null) { try { $doc.Close() } catch {} ; try { [void][Runtime.InteropServices.Marshal]::ReleaseComObject($doc) } catch {} }; if ($word -ne $null) { try { $word.Quit() } catch {} ; try { [void][Runtime.InteropServices.Marshal]::ReleaseComObject($word) } catch {} }; [GC]::Collect(); [GC]::WaitForPendingFinalizers() }`;
}
register("Word_New", async (_ctx, _node, args) => {
const folder = ensure(text(args, ["filePath", "folder", "path"]), "Word目录");
const name = text(args, ["name"], "新建文档.docx");
const filePath = path.resolve(folder, path.extname(name) ? name : `${name}.docx`);
await powershell(wordScript(`$doc = $word.Documents.Add(); $doc.SaveAs2(${psString(filePath)}); ${psString(filePath)}`));
return { path: filePath } satisfies WordHandle;
});
register("Word_Open", async (_ctx, _node, args) => ({ path: handlePath(args) } satisfies WordHandle));
register("Word_Write", async (_ctx, _node, args) => {
const filePath = ensure(handlePath(args), "Word文件路径");
const content = text(args, ["text", "content"]);
await powershell(wordScript(`$doc = $word.Documents.Open(${psString(filePath)}); $range = $doc.Content; $range.Collapse(0); $range.InsertAfter(${psString(content)}); $doc.Save()`));
return { path: filePath } satisfies WordHandle;
});
register(["Word_Save", "Word_SaveAs"], async (_ctx, _node, args) => ({ path: handlePath(args) } satisfies WordHandle));