203 lines
6.0 KiB
TypeScript
203 lines
6.0 KiB
TypeScript
import type {
|
|
ScheduledConditionRecord,
|
|
ScheduledConditionStatus,
|
|
ScheduledConditionTaskId
|
|
} from "@/features/workbench/types";
|
|
|
|
export type RunningWorkflowStepDefinition = {
|
|
id: string;
|
|
title: string;
|
|
detail: string;
|
|
};
|
|
|
|
export type RunningWorkflowDefinition = {
|
|
title: string;
|
|
reportLabel: string;
|
|
steps: RunningWorkflowStepDefinition[];
|
|
};
|
|
|
|
export type RunningWorkflowStepStatus = "done" | "current" | "pending";
|
|
|
|
export const runningWorkflowDefinitions: Record<ScheduledConditionTaskId, RunningWorkflowDefinition> = {
|
|
"scada-diagnosis": {
|
|
title: "SCADA 诊断流程",
|
|
reportLabel: "生成诊断报告",
|
|
steps: [
|
|
{
|
|
id: "ingest-telemetry",
|
|
title: "读取 SCADA 遥测",
|
|
detail: "拉取压力、流量和关键阀门测点,校验时间戳与回传频率。"
|
|
},
|
|
{
|
|
id: "freshness-check",
|
|
title: "检查新鲜度完整率",
|
|
detail: "按测点组计算缺测、延迟和连续异常样本比例。"
|
|
},
|
|
{
|
|
id: "consistency-check",
|
|
title: "压流一致性诊断",
|
|
detail: "比对压力变化、流量变化和相邻测点趋势是否符合水力逻辑。"
|
|
},
|
|
{
|
|
id: "isolate-sources",
|
|
title: "标记异常数据源",
|
|
detail: "圈定疑似通信异常或越界测点,给后续模拟和调度提供屏蔽建议。"
|
|
},
|
|
{
|
|
id: "diagnosis-report",
|
|
title: "整理诊断结论",
|
|
detail: "汇总数据质量、异常证据和是否允许进入后续工况任务。"
|
|
}
|
|
]
|
|
},
|
|
"smart-dispatch": {
|
|
title: "智能调度流程",
|
|
reportLabel: "生成调度指令",
|
|
steps: [
|
|
{
|
|
id: "read-condition",
|
|
title: "读取实时工况",
|
|
detail: "汇总目标分区压力、流量、泵站出水和阀门开度。"
|
|
},
|
|
{
|
|
id: "candidate-actions",
|
|
title: "生成候选动作",
|
|
detail: "枚举泵站目标压力、阀门边界和高频复核测点的可执行动作。"
|
|
},
|
|
{
|
|
id: "simulate-impact",
|
|
title: "模拟影响范围",
|
|
detail: "预估指令执行后的压力改善、分区压差和关键用户影响。"
|
|
},
|
|
{
|
|
id: "rank-actions",
|
|
title: "排序调度方案",
|
|
detail: "按改善幅度、操作代价和数据可信度筛选建议指令。"
|
|
},
|
|
{
|
|
id: "dispatch-draft",
|
|
title: "形成复核清单",
|
|
detail: "输出待调度员确认的管网要素调整指令和复核条件。"
|
|
}
|
|
]
|
|
},
|
|
"network-simulation": {
|
|
title: "定时模拟流程",
|
|
reportLabel: "生成模拟报告",
|
|
steps: [
|
|
{
|
|
id: "sync-boundary",
|
|
title: "同步模型边界",
|
|
detail: "读取最新泵站启停、阀门开度、需水量和 SCADA 边界条件。"
|
|
},
|
|
{
|
|
id: "run-hydraulic-model",
|
|
title: "运行水力模型",
|
|
detail: "滚动计算全网节点压力、管段流量和分区边界平衡。"
|
|
},
|
|
{
|
|
id: "compare-telemetry",
|
|
title: "比对实测偏差",
|
|
detail: "将模拟压力、流量与在线测点回传值进行偏差校验。"
|
|
},
|
|
{
|
|
id: "locate-deviation",
|
|
title: "定位偏差来源",
|
|
detail: "识别模型参数、边界条件或遥测源导致的主要偏差区域。"
|
|
},
|
|
{
|
|
id: "simulation-report",
|
|
title: "输出模型复核",
|
|
detail: "给出可信度、关注指标和是否允许用于调度决策。"
|
|
}
|
|
]
|
|
},
|
|
"pump-energy": {
|
|
title: "泵站能耗流程",
|
|
reportLabel: "生成能耗报告",
|
|
steps: [
|
|
{
|
|
id: "read-pump-load",
|
|
title: "读取泵组负载",
|
|
detail: "采集泵站频率、电流、出水压力、出水量和启停记录。"
|
|
},
|
|
{
|
|
id: "calculate-energy",
|
|
title: "计算单位电耗",
|
|
detail: "按当前窗口排水量折算单位排水电耗和效率偏差。"
|
|
},
|
|
{
|
|
id: "compare-efficiency",
|
|
title: "比对经济区间",
|
|
detail: "结合泵组效率曲线判断当前组合是否处于低效并联区间。"
|
|
},
|
|
{
|
|
id: "pressure-guard",
|
|
title: "校验供压约束",
|
|
detail: "复核节能建议不会引发末端低压或分区边界异常。"
|
|
},
|
|
{
|
|
id: "energy-advice",
|
|
title: "形成节能建议",
|
|
detail: "输出启停优化、压力设定和继续观察条件。"
|
|
}
|
|
]
|
|
}
|
|
};
|
|
|
|
export function getRunningWorkflowDefinition(condition: ScheduledConditionRecord) {
|
|
return runningWorkflowDefinitions[condition.taskId];
|
|
}
|
|
|
|
export function getRunningWorkflowState(
|
|
condition: ScheduledConditionRecord,
|
|
workflow: RunningWorkflowDefinition,
|
|
nowMs: number
|
|
) {
|
|
if (condition.status !== "running") {
|
|
return { currentStepIndex: workflow.steps.length - 1, progress: getCompletedProgress(condition.status) };
|
|
}
|
|
|
|
const scheduledAtMs = Date.parse(condition.scheduledAt);
|
|
const startedAtMs = Number.isFinite(scheduledAtMs) ? scheduledAtMs : nowMs;
|
|
const durationMs = Math.max(condition.durationMinutes ?? 1, 1) * 60_000;
|
|
const elapsedMs = Math.max(0, nowMs - startedAtMs);
|
|
const rawRatio = elapsedMs / durationMs;
|
|
const runningRatio = Math.min(Math.max(rawRatio, 0), 0.999);
|
|
const currentStepIndex = Math.min(
|
|
workflow.steps.length - 1,
|
|
Math.floor(runningRatio * workflow.steps.length)
|
|
);
|
|
const progress = Math.min(99, Math.max(0, Math.floor(runningRatio * 100)));
|
|
|
|
return { currentStepIndex, progress };
|
|
}
|
|
|
|
export function getWorkflowStepStatus(
|
|
condition: ScheduledConditionRecord,
|
|
stepIndex: number,
|
|
currentStepIndex: number
|
|
): RunningWorkflowStepStatus {
|
|
if (condition.status !== "running") {
|
|
return "done";
|
|
}
|
|
|
|
if (stepIndex < currentStepIndex) {
|
|
return "done";
|
|
}
|
|
|
|
if (stepIndex === currentStepIndex) {
|
|
return "current";
|
|
}
|
|
|
|
return "pending";
|
|
}
|
|
|
|
function getCompletedProgress(status: ScheduledConditionStatus) {
|
|
if (status === "error") {
|
|
return 0;
|
|
}
|
|
|
|
return 100;
|
|
}
|