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) => ({ 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] }] } } } ]); } }