修正 PID 空结果、目标类型判断与转换、毫秒等待。 让关闭程序和命令行按所选模式显示并校验参数。 统一 PowerShell 输出编码,修正 BAT 路径引号处理。 明确屏保和屏幕唤醒的实际能力,补充缺陷回归测试。 验证:类型检查、构建与组件回归检查通过。 BREAKING CHANGE: 判断数据类型改为返回布尔值。 需要类型名称的旧流程请改用 Basic_Type。 屏保 V1 移除未实现参数,旧自定义密码节点需重新添加。
94 lines
3.4 KiB
TypeScript
94 lines
3.4 KiB
TypeScript
import { register } from "../engine/registry";
|
||
import { BreakSignal, ContinueSignal, RuntimeError, StopSignal } from "../engine/types";
|
||
import { interpolate, toNumber } from "../engine/expression";
|
||
|
||
function sleep(ms: number, signal: AbortSignal): Promise<void> {
|
||
if (ms <= 0) return Promise.resolve();
|
||
return new Promise((resolve, reject) => {
|
||
const timer = setTimeout(() => {
|
||
signal.removeEventListener("abort", onAbort);
|
||
resolve();
|
||
}, ms);
|
||
const onAbort = () => {
|
||
clearTimeout(timer);
|
||
reject(new RuntimeError("cancelled", "运行已取消"));
|
||
};
|
||
if (signal.aborted) return onAbort();
|
||
signal.addEventListener("abort", onAbort, { once: true });
|
||
});
|
||
}
|
||
|
||
register(["Trigger.Manual", "Trigger.Schedule", "Trigger.FileArrival"], () => null);
|
||
|
||
register("Basic_Delay_V2", async (ctx, node, args) => {
|
||
const random = String(args.is_random ?? "0") === "1" || String(args.is_random) === "true";
|
||
const seconds = random
|
||
? toNumber(args.min_second, 1) + Math.random() * Math.max(0, toNumber(args.max_second, 5) - toNumber(args.min_second, 1))
|
||
: toNumber(args.second, 1);
|
||
ctx.log(`等待 ${seconds.toFixed(2)} 秒`, "info", node.id);
|
||
await sleep(Math.max(0, seconds) * 1000, ctx.signal);
|
||
return seconds;
|
||
});
|
||
|
||
register("Basic_Delay_V1", async (ctx, node, args) => {
|
||
const seconds = toNumber(args.second ?? args.time ?? 1, 1);
|
||
await sleep(Math.max(0, seconds) * 1000, ctx.signal);
|
||
return seconds;
|
||
});
|
||
|
||
register("Basic_Delay", async (ctx, node, args) => {
|
||
const milliseconds = Number(args.mileSecond ?? 1000);
|
||
if (!Number.isFinite(milliseconds) || milliseconds < 0 || milliseconds > 2_147_483_647) {
|
||
throw new RuntimeError("validation_error", "延时时间必须是 0~2147483647 范围内的毫秒数", { nodeId: node.id, componentId: node.componentId });
|
||
}
|
||
await sleep(milliseconds, ctx.signal);
|
||
return milliseconds / 1000;
|
||
});
|
||
|
||
register("Basic_DebugOutput", (ctx, node, args) => {
|
||
const message = String(args.msg ?? args.message ?? "");
|
||
ctx.log(message || "(空)", "info", node.id);
|
||
return message;
|
||
});
|
||
|
||
register("Basic_SetVariable", (ctx, node, args) => {
|
||
const name = String(node.options?.outputVar || "").trim();
|
||
const value = args.value;
|
||
if (!name) {
|
||
throw new RuntimeError("validation_error", "「设置变量」未配置输出变量", {
|
||
nodeId: node.id,
|
||
componentId: node.componentId,
|
||
recommendation: "在属性面板的输出变量里填写变量名"
|
||
});
|
||
}
|
||
ctx.vars[name] = value;
|
||
ctx.log(`${name} = ${typeof value === "object" ? JSON.stringify(value) : String(value)}`, "info", node.id);
|
||
return value;
|
||
});
|
||
|
||
register("logic_control_var", (ctx, node, args) => {
|
||
const name = String(interpolate(args.var_name ?? node.options?.outputVar ?? "", ctx.vars) || "").trim();
|
||
if (!name) {
|
||
throw new RuntimeError("validation_error", "「设置变量」未填写变量名称", {
|
||
nodeId: node.id,
|
||
componentId: node.componentId
|
||
});
|
||
}
|
||
const value = interpolate(args.var_value ?? args.value, ctx.vars);
|
||
ctx.vars[name] = value;
|
||
ctx.log(`${name} = ${typeof value === "object" ? JSON.stringify(value) : String(value)}`, "info", node.id);
|
||
return value;
|
||
});
|
||
|
||
register("logic_control_break_for", () => {
|
||
throw new BreakSignal();
|
||
});
|
||
|
||
register("logic_control_next_for", () => {
|
||
throw new ContinueSignal();
|
||
});
|
||
|
||
register(["logic_control_stop", "logic_control_stop_return"], () => {
|
||
throw new StopSignal();
|
||
});
|