Files
next-tjwater-frontend/src/features/workbench/utils/investigation-dev-cases.ts
T
jiang c0e4231b83
Generic Container CI/CD / test-build-publish (push) Successful in 1m52s
Frontend CI/CD / build-test-publish-and-deploy (push) Successful in 1m52s
feat: expand intelligent investigation workspace
2026-10-30 17:30:19 +08:00

285 lines
9.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { AnswerUiBlock } from "@/features/agent";
import type { InvestigationPresentationCommand } from "../api/investigation-presentation";
import type { InvestigationMapTarget } from "../api/investigation-report";
import {
createInvestigationDevSample,
createPresentationRecord,
createUiRecord,
normalizeDevCenter,
serializeInvestigationDevJsonl
} from "./investigation-dev-preview";
export const investigationDevCases = [
{
id: "combined",
label: "组合联动",
expected: "合成空间点、压力曲线、候选表格与数据一同展示;有调查地图目标时同时高亮。"
},
{
id: "map_targets",
label: "地图定位与高亮",
expected: "显示地图中心附近的合成点,并高亮所选调查已有的地图目标;无目标时仅显示合成点。"
},
{
id: "pressure_line",
label: "压力趋势对比",
expected: "打开两条合成压力曲线,核对时间轴、单位、图例和数据表。"
},
{
id: "impact_bar",
label: "影响用户统计",
expected: "打开合成用户数柱状图;统计仅供展示测试,不是实际停水户数。"
},
{
id: "impact_area",
label: "合成影响范围",
expected: "在当前地图中心附近显示一个合成面;不代表真实隔离边界。"
},
{
id: "complaint_heatmap",
label: "投诉热力分布",
expected: "显示三个带非负权重的合成投诉点,按热力模式渲染。"
},
{
id: "candidates_table",
label: "候选管段对比",
expected: "展示两条合成候选数据和对比表格,不查询或高亮虚拟管段。"
},
{
id: "valves_table",
label: "隔离阀门清单",
expected: "展示两条合成阀门数据和核查表格,不执行关阀或发布处置方案。"
},
{
id: "data_only",
label: "纯 JSONL 数据",
expected: "仅展示候选与影响数据;数据行中出现 action 字段也不会触发地图动作。"
},
{
id: "invalid_json",
label: "错误:JSON 语法",
expected: "第 2 行报语法错误,整批不执行;可点击执行验证拦截结果。"
},
{
id: "invalid_command",
label: "错误:不支持的动作",
expected: "第 1 行展示指令被拒绝,不执行任意命令。"
},
{
id: "invalid_chart",
label: "错误:图表数据不齐",
expected: "第 1 行图表校验失败,时间轴和序列长度不一致时不能执行。"
}
] as const;
export type InvestigationDevCaseId = (typeof investigationDevCases)[number]["id"];
const jsonl = serializeInvestigationDevJsonl;
const presentation = createPresentationRecord;
// Invalid cases deliberately bypass the validated writer to exercise rejection.
const invalidJsonl = (records: unknown[]) =>
records.map((record) => JSON.stringify(record)).join("\n");
const data = (record_type: string, fields: Record<string, unknown>) => ({
record_type,
origin: "synthetic",
source_evidence_refs: [],
...fields
});
function table(id: string, title: string, columns: string[], rows: string[][]): unknown {
const block: AnswerUiBlock = {
version: "answer-ui@1",
block_id: `dev-case-${id}`,
fallback_text: `${title},仅供本地展示测试。`,
spec: {
root: "table",
elements: {
table: { type: "Table", props: { title, columns, rows }, children: [] }
}
}
};
return createUiRecord(block);
}
/** Fixtures use current map coordinates and existing task targets, never invented query IDs. */
export function createInvestigationDevCase(
caseId: InvestigationDevCaseId,
center: [number, number],
target?: InvestigationMapTarget
): string {
const [longitude, latitude] = normalizeDevCenter(center);
if (caseId === "combined") return createInvestigationDevSample([longitude, latitude], target);
const point = (dx = 0, dy = 0): [number, number] => [
Math.max(-180, Math.min(180, longitude + dx)),
latitude + dy
];
const overlay = (
mode: "geometry" | "heatmap",
title: string,
features: Extract<
InvestigationPresentationCommand,
{ action: "set_overlay" }
>["data"]["features"]
) =>
presentation({
action: "set_overlay",
overlay_id: `dev-case-${caseId}`,
title,
mode,
evidence_id: "dev:synthetic",
data: { type: "FeatureCollection", features }
});
switch (caseId) {
case "map_targets":
return jsonl([
...(target
? [
presentation({
action: "highlight_features",
layer: target.source_id,
feature_ids: [target.feature_id],
effect: "pulse"
})
]
: []),
overlay("geometry", "本地合成定位点", [
{
type: "Feature",
properties: { origin: "synthetic" },
geometry: { type: "Point", coordinates: point() }
}
])
]);
case "pressure_line":
return jsonl([
presentation({
action: "open_chart",
chart_id: "dev-case-pressure-line",
evidence_refs: ["dev:synthetic"],
chart: {
title: "本地合成压力对比",
chart_type: "line",
x_data: ["08:00", "08:15", "08:30", "08:45"],
series: [
{ name: "异常日压力水头(m)", data: [32, 18, 22, 30] },
{ name: "基线压力水头(m)", data: [33, 32, 32, 33] }
]
}
})
]);
case "impact_bar":
return jsonl([
presentation({
action: "open_chart",
chart_id: "dev-case-impact-bar",
evidence_refs: ["dev:synthetic"],
chart: {
title: "本地合成影响用户统计",
chart_type: "bar",
x_data: ["合成片区 A", "合成片区 B", "合成片区 C"],
series: [{ name: "合成用户数(户)", data: [120, 80, 45] }]
}
})
]);
case "impact_area":
return jsonl([
overlay("geometry", "本地合成影响范围", [
{
type: "Feature",
properties: { origin: "synthetic", purpose: "display_test_only" },
geometry: {
type: "Polygon",
coordinates: [
[
point(-0.002, -0.0015),
point(0.002, -0.0015),
point(0.002, 0.0015),
point(-0.002, 0.0015),
point(-0.002, -0.0015)
]
]
}
}
])
]);
case "complaint_heatmap":
return jsonl([
overlay(
"heatmap",
"本地合成投诉热力",
[-0.0015, 0, 0.0015].map((offset, index) => ({
type: "Feature",
properties: { origin: "synthetic", weight: [1, 3, 2][index] },
geometry: { type: "Point", coordinates: point(offset, offset / 2) }
}))
)
]);
case "candidates_table":
return jsonl([
table(
"candidates",
"合成候选管段对比",
["候选", "优先级", "核查依据"],
[
["DEMO-PIPE-01", "1", "合成压力降幅较大,待核查"],
["DEMO-PIPE-02", "2", "合成相关性较弱,待排除"]
]
),
data("candidate", { element_id: "DEMO-PIPE-01", rank: 1, status: "unverified" }),
data("candidate", { element_id: "DEMO-PIPE-02", rank: 2, status: "unverified" })
]);
case "valves_table":
return jsonl([
table(
"valves",
"合成隔离阀门清单",
["阀门", "操作建议", "核查要求"],
[
["DEMO-VALVE-01", "待评估", "位置与可操作性未核实"],
["DEMO-VALVE-02", "待评估", "连通性与影响范围未核实"]
]
),
data("valve", { element_id: "DEMO-VALVE-01", status: "unverified", executed: false }),
data("valve", { element_id: "DEMO-VALVE-02", status: "unverified", executed: false })
]);
case "data_only":
return jsonl([
data("candidate", {
element_id: "DEMO-PIPE-03",
action: "clear_highlights",
status: "data_only"
}),
data("impact", {
item: "合成片区 A",
estimated_users: 120,
unit: "户",
status: "example_only"
})
]);
case "invalid_json":
return `${jsonl([presentation({ action: "clear_highlights" })])}\n{"record_type":"candidate",`;
case "invalid_command":
return invalidJsonl([
{ record_type: "presentation", command: { action: "unsupported_test_action" } }
]);
case "invalid_chart":
return invalidJsonl([
{
record_type: "presentation",
command: {
action: "open_chart",
chart_id: "dev-invalid-chart",
evidence_refs: ["dev:synthetic"],
chart: {
title: "错误案例:数据长度不齐",
chart_type: "line",
x_data: ["08:00", "08:15"],
series: [{ name: "合成压力水头(m)", data: [32] }]
}
}
}
]);
}
}