Files
next-tjwater-frontend/src/features/workbench/workspace/analysis-document-fixtures.ts
T

273 lines
12 KiB
TypeScript

import type { AnalysisArtifact } from "./workspace-model";
type FixtureFactory = (id: string, generatedAt: string) => AnalysisArtifact;
const PRESSURE_DIAGNOSIS: FixtureFactory = (id, generatedAt) => ({
id,
type: "diagnosis",
lifecycle: "reviewed",
revision: 3,
title: "北辰分区压力异常诊断",
subtitle: "Agent 汇总最近 6 小时 SCADA 压力、流量与泵组工况",
summary: "北辰低压由上游泵组扰动与局部供水缺口共同触发,7 个测点需要持续观察。",
scope: "北辰供水分区 · 最近 6 小时",
confidence: "92.6%",
generatedAt,
analyticalTimeRange: {
start: new Date(resolveFixtureTimestamp(generatedAt) - 6 * 60 * 60 * 1000).toISOString(),
end: new Date(resolveFixtureTimestamp(generatedAt)).toISOString()
},
preferredView: "map_split",
mapRelation: "required",
blocks: [
{
id: "pressure-metrics",
kind: "metric-grid",
title: "诊断摘要",
span: 12,
metrics: [
{ label: "异常测点", value: "7", detail: "较上一时段增加 2 个", tone: "danger" },
{ label: "最低压力", value: "0.186 MPa", detail: "BC-P-014 · 10:32", tone: "warning" },
{ label: "供水缺口", value: "3.8%", detail: "预计持续 42 分钟", tone: "info" },
{ label: "诊断置信度", value: "92.6%", detail: "126 个有效样本", tone: "success" }
]
},
{
id: "pressure-trend",
kind: "chart",
title: "关键节点压力曲线",
description: "BC-P-014 在 09:40 后持续低于调度下限",
span: 7,
chartType: "line",
categories: ["06:00", "07:00", "08:00", "09:00", "10:00", "11:00", "12:00"],
unit: "MPa",
series: [
{ name: "BC-P-014", values: [0.31, 0.304, 0.287, 0.264, 0.213, 0.186, 0.198], color: "#2563eb" },
{ name: "BC-P-021", values: [0.346, 0.351, 0.338, 0.329, 0.315, 0.306, 0.312], color: "#0f9f8f" },
{ name: "调度下限", values: [0.22, 0.22, 0.22, 0.22, 0.22, 0.22, 0.22], color: "#e05252" }
]
},
{
id: "pressure-ranking",
kind: "chart",
title: "异常偏差排名",
description: "按相对调度下限的压力偏差排序",
span: 5,
chartType: "bar",
categories: ["P-014", "P-008", "P-026", "P-031", "P-017"],
unit: "%",
series: [{ name: "偏差", values: [15.5, 11.8, 9.7, 7.2, 5.9], color: "#e05252" }]
},
{
id: "pressure-evidence",
kind: "data-table",
title: "证据链",
description: "对诊断结论贡献最高的观测证据",
span: 12,
columns: [
{ key: "time", label: "时间" },
{ key: "source", label: "数据源" },
{ key: "finding", label: "观测" },
{ key: "impact", label: "影响" },
{ key: "confidence", label: "置信度", numeric: true }
],
rows: [
{ time: "10:32", source: "BC-P-014", finding: "压力降至 0.186 MPa", impact: "低压风险", confidence: "97.2%" },
{ time: "10:28", source: "BC-F-006", finding: "流量较基线下降 8.4%", impact: "供水缺口", confidence: "91.6%" },
{ time: "10:21", source: "二泵站 2#", finding: "出口压力波动 0.041 MPa", impact: "上游扰动", confidence: "88.9%" }
]
}
],
sources: ["SCADA 压力遥测", "泵站运行记录", "供水分区拓扑"],
limitations: ["BC-P-026 在 09:12 至 09:24 存在数据缺口", "尚未纳入现场阀门开度复核结果"],
actions: [
{ id: "locate", label: "定位异常测点", description: "在地图中定位 7 个异常测点", tone: "primary" },
{ id: "review", label: "标记为已复核", description: "将当前版本进入复核完成状态", tone: "neutral" }
]
});
const SUPPLY_ZONE_ANALYSIS: FixtureFactory = (id, generatedAt) => ({
id,
type: "metric_analysis",
lifecycle: "draft",
revision: 2,
title: "供水服务分区平衡分析",
subtitle: "Agent 对比分区供水量、需求预测和关键连通通道",
summary: "北辰与东丽接近能力上限,津南仍有可调配余量,建议优先验证三条联络线。",
scope: "六个服务分区 · 今日峰值预测",
confidence: "88.4%",
generatedAt,
analyticalTimeRange: {
start: new Date(new Date(resolveFixtureTimestamp(generatedAt)).setHours(0, 0, 0, 0)).toISOString(),
end: new Date(new Date(resolveFixtureTimestamp(generatedAt)).setHours(23, 59, 59, 999)).toISOString()
},
preferredView: "focus",
mapRelation: "none",
blocks: [
{
id: "zone-metrics",
kind: "metric-grid",
title: "分区态势",
span: 12,
metrics: [
{ label: "分析分区", value: "6", detail: "覆盖 94.3% 用水需求", tone: "neutral" },
{ label: "高负荷分区", value: "2", detail: "北辰、东丽", tone: "warning" },
{ label: "可调配余量", value: "1.74 万m³", detail: "主要来自津南分区", tone: "success" },
{ label: "建议联络线", value: "3 条", detail: "预计缓解 6.1% 峰值压力", tone: "info" }
]
},
{
id: "zone-balance",
kind: "chart",
title: "分区供需对比",
description: "北辰与东丽当前需求已接近可用供水能力",
span: 7,
chartType: "bar",
categories: ["北辰", "东丽", "津南", "西青", "武清", "中心"],
unit: "万m³/d",
series: [
{ name: "可用能力", values: [9.82, 8.31, 10.46, 7.92, 6.83, 11.24], color: "#2563eb" },
{ name: "预测需求", values: [9.47, 8.08, 8.72, 6.84, 5.91, 9.86], color: "#f09a42" }
]
},
{
id: "zone-risk",
kind: "data-table",
title: "调配优先级",
description: "按负荷率、连续供水和通道可用性综合排序",
span: 5,
columns: [
{ key: "zone", label: "分区" },
{ key: "load", label: "负荷率", numeric: true },
{ key: "risk", label: "风险" },
{ key: "action", label: "建议" }
],
rows: [
{ zone: "北辰", load: "96.4%", risk: "高", action: "开启西北联络线" },
{ zone: "东丽", load: "97.2%", risk: "高", action: "提升三泵站频率" },
{ zone: "西青", load: "86.3%", risk: "中", action: "保留调节余量" },
{ zone: "中心", load: "87.7%", risk: "中", action: "监测夜峰变化" }
]
},
{
id: "zone-note",
kind: "narrative",
title: "Agent 结论",
span: 12,
paragraphs: [
"优先将津南分区的可调配余量通过南北联络线输送至东丽,再由中心环网承担北辰分区的部分峰值需求。",
"执行前需复核三泵站 2# 泵组可用状态,并确认阀门 V-BC-103、V-DL-047 的远控权限。"
]
}
],
sources: ["分区日供水量", "短期需求预测", "连通能力台账"],
limitations: ["需求预测未包含临时大型活动增量", "联络线能力采用最近一次校核值"],
actions: [
{ id: "compare", label: "生成方案对比", description: "基于当前结论创建调配模拟", tone: "primary" },
{ id: "export", label: "导出摘要", description: "导出当前分析摘要", tone: "neutral" }
]
});
const DISPATCH_FLOW: FixtureFactory = (id, generatedAt) => ({
id,
type: "simulation",
lifecycle: "published",
revision: 5,
title: "低压事件调度处置流程",
subtitle: "Agent 将诊断、复核、调度和验证步骤编排为受控流程",
summary: "建议方案预计在 20 分钟内恢复目标压力,执行前仍有 3 项权限与现场状态待确认。",
scope: "北辰低压事件 · 30 分钟模拟",
confidence: "90.8%",
generatedAt,
analyticalTimeRange: {
start: new Date(resolveFixtureTimestamp(generatedAt) - 30 * 60 * 1000).toISOString(),
end: new Date(resolveFixtureTimestamp(generatedAt)).toISOString()
},
preferredView: "map_split",
mapRelation: "required",
blocks: [
{
id: "flow-metrics",
kind: "metric-grid",
title: "执行状态",
span: 12,
metrics: [
{ label: "当前阶段", value: "现场复核", detail: "步骤 2 / 5", tone: "info" },
{ label: "已用时间", value: "18 分钟", detail: "目标时限 45 分钟", tone: "success" },
{ label: "待确认项", value: "3", detail: "含 1 项远控权限", tone: "warning" },
{ label: "影响用户", value: "1,284 户", detail: "暂无停水用户", tone: "neutral" }
]
},
{
id: "dispatch-process",
kind: "process-flow",
title: "处置路径",
description: "所有调度动作均需在执行前完成权限和现场状态确认",
span: 7,
nodes: [
{ id: "detect", label: "异常识别", detail: "确认压力与流量异常持续 10 分钟", status: "complete" },
{ id: "verify", label: "现场复核", detail: "复核二泵站出口压力与阀门状态", status: "active" },
{ id: "simulate", label: "方案模拟", detail: "比较联络线调配和泵组增压方案", status: "pending" },
{ id: "execute", label: "调度执行", detail: "确认后下发受控阀门与泵组操作", status: "pending" },
{ id: "observe", label: "效果验证", detail: "观察 15 分钟并更新事件结论", status: "pending" }
]
},
{
id: "dispatch-checklist",
kind: "data-table",
title: "执行清单",
description: "当前阶段需要完成的人员与系统确认",
span: 5,
columns: [
{ key: "owner", label: "责任方" },
{ key: "item", label: "确认项" },
{ key: "state", label: "状态" }
],
rows: [
{ owner: "值班调度", item: "核对 SCADA 时间戳", state: "完成" },
{ owner: "二泵站", item: "复核 2# 泵组出口压力", state: "进行中" },
{ owner: "管网运维", item: "确认 V-BC-103 现场状态", state: "待处理" },
{ owner: "系统管理员", item: "确认远控操作权限", state: "待处理" }
]
},
{
id: "dispatch-progress",
kind: "chart",
title: "处置前后压力预测",
description: "模拟结果显示执行后 20 分钟内压力回到调度区间",
span: 12,
chartType: "line",
categories: ["当前", "+5m", "+10m", "+15m", "+20m", "+30m"],
unit: "MPa",
series: [
{ name: "不采取动作", values: [0.186, 0.181, 0.178, 0.176, 0.179, 0.184], color: "#e05252" },
{ name: "执行建议方案", values: [0.186, 0.204, 0.226, 0.251, 0.267, 0.281], color: "#2563eb" }
]
}
],
sources: ["低压事件诊断 R3", "调度规则库", "水力模拟结果"],
limitations: ["模拟未计入突发大用户需求变化", "远控动作必须由值班调度二次确认"],
actions: [
{ id: "prepare", label: "准备受控执行", description: "生成执行前确认清单", tone: "primary" },
{ id: "archive", label: "归档方案", description: "保留当前模拟版本", tone: "neutral" }
]
});
const FIXTURE_FACTORIES = [PRESSURE_DIAGNOSIS, SUPPLY_ZONE_ANALYSIS, DISPATCH_FLOW] as const;
export function createAnalysisArtifactFixture(index: number, instance: number): AnalysisArtifact {
const factory = FIXTURE_FACTORIES[index % FIXTURE_FACTORIES.length] ?? PRESSURE_DIAGNOSIS;
const now = new Date();
return factory(
`analysis-${now.getTime().toString(36)}-${instance}`,
now.toLocaleTimeString("zh-CN", { hour12: false })
);
}
function resolveFixtureTimestamp(clock: string) {
const [hours = 0, minutes = 0, seconds = 0] = clock.split(":").map(Number);
const value = new Date();
value.setHours(hours, minutes, seconds, 0);
return value.getTime();
}