PRA-only-demo/src/main/capabilities/word.ts

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