feat(charts): manage investigation charts in a scrolling workspace
Generic Container CI/CD / test-build-publish (push) Successful in 2m7s
Frontend CI/CD / build-test-publish-and-deploy (push) Successful in 2m8s

This commit is contained in:
2026-11-10 17:56:23 +08:00
parent 865491cb23
commit 0ae0a41e61
80 changed files with 4672 additions and 470 deletions
@@ -3,9 +3,9 @@ import type { AnswerUiBlock } from "@/features/agent";
import { createPresentationRecord, createUiRecord, serializeInvestigationDevJsonl } from "./investigation-dev-preview";
export const complexInvestigationDevCases = [
{ id: "complex_investigation", label: "复杂调查:多图多表联动", expected: "3 张图、2 张表与合成覆盖面;可同时放大对比,单位分别展示,不查询真实要素。" },
{ id: "complex_investigation", label: "复杂调查:多图多表联动", expected: "压力与管流分别聚合,另有方案柱状图、2 张表与合成覆盖面;右侧切换对象,下方控制图例。" },
{ id: "complex_tables", label: "复杂表格:宽表、长文本与边界数据", expected: "50 行 8 列宽表、空表和含零值、负数、重复值的对照表;检查搜索、数值排序和横向滚动。" },
{ id: "complex_charts", label: "复杂图表:多测点与长时序", expected: "96 个时间点、8 条压力序列,另有流量与方案柱状图;可切换数据表、筛选区间并独立放大。" }
{ id: "complex_charts", label: "复杂图表:多测点与长时序", expected: "8 个压力点与 4 个管段各含 96 个时刻、当前曲线与七日历史散点,聚合为 2 个子图表,由总图表窗口统一管理,另有方案柱状图。" }
] as const;
type ComplexCaseId = (typeof complexInvestigationDevCases)[number]["id"];
@@ -19,25 +19,40 @@ const ui = (id: string, node: Node) => createUiRecord({
const table = (id: string, title: string, columns: string[], rows: string[][]) =>
ui(id, { type: "Table", props: { title, columns, rows }, children: [] });
const times = Array.from({ length: 96 }, (_, index) => `${String(Math.floor(index / 4)).padStart(2, "0")}:${String(index % 4 * 15).padStart(2, "0")}`);
const pressure = {
title: "合成全天压力对比", chart_type: "line" as const, x_data: times,
series: Array.from({ length: 8 }, (_, series) => ({
name: `合成节点 ${INVESTIGATION_DEV_NETWORK.nodeAnchors[series].id} · ${series < 4 ? "主干管" : "末端支线"}压力水头(m)`,
data: times.map((_, index) => Number((34 + series * 0.6 + Math.sin(index / 7 + series) * 2.4 - (index >= 32 && index < 44 ? 7 - series * 0.4 : 0)).toFixed(2)))
}))
};
const flow = {
title: "合成分区流量趋势", chart_type: "line" as const, x_data: times,
series: Array.from({ length: 4 }, (_, series) => ({ name: `合成分区 ${series + 1} 流量(m³/h)`,
data: times.map((_, index) => Number((120 + series * 28 + Math.sin(index / 9 + series) * 24 + (index >= 32 && index < 44 ? 38 : 0)).toFixed(1))) }))
};
const comparisonChart = (id: string, title: string, axis: string, baseline: number[], current: number[]) => ({
title: `${id} ${title}`, chart_type: "time_comparison" as const,
x_axis_name: "时间", y_axis_name: axis, x_data: times,
series: [{ name: `${id} 当前 2026-07-16`, type: "line" as const, data: current,
sample_times: times.map((time) => `2026-07-16T${time}:00+08:00`) },
...Array.from({ length: 7 }, (_, day) => {
const date = `2026-07-${String(9 + day).padStart(2, "0")}`;
return { name: `${id} ${date}`, type: "scatter" as const,
data: times.map((_, index) => index >= 40 && index <= 42 ? Number((baseline[index] + day * 0.1).toFixed(2)) : null),
sample_times: times.map((time, index) => index >= 40 && index <= 42 ? `${date}T${time}:00+08:00` : null) };
})]
});
const pressure = Array.from({ length: 8 }, (_, object) => {
const baseline = times.map((_, index) => Number((34 + object * 0.6 + Math.sin(index / 7 + object) * 2.4).toFixed(2)));
return comparisonChart(INVESTIGATION_DEV_NETWORK.nodeAnchors[object].id, "合成全天压力对比", "压力水头(m)", baseline,
baseline.map((value, index) => Number((value - (index >= 32 && index < 44 ? 7 - object * 0.4 : 0)).toFixed(2))));
});
const flow = Array.from({ length: 4 }, (_, object) => {
const baseline = times.map((_, index) => Number((120 + object * 28 + Math.sin(index / 9 + object) * 24).toFixed(1)));
return comparisonChart(INVESTIGATION_DEV_NETWORK.pipeIds[object], "合成分区流量趋势", "流量(m³/h)", baseline,
baseline.map((value, index) => Number((value + (index >= 32 && index < 44 ? 38 : 0)).toFixed(1))));
});
const chart = (id: string, value: ReturnType<typeof comparisonChart>) => createPresentationRecord({
action: "open_chart", chart_id: `dev-complex-${id}`, evidence_refs: ["dev:synthetic"], chart: value
});
const objectCharts = () => [
...pressure.map((value, index) => chart(`pressure-${index + 1}`, value)),
...flow.map((value, index) => chart(`flow-${index + 1}`, value))
];
const comparison = {
title: "合成候选方案影响对比", chart_type: "bar" as const,
x_data: ["合成方案 A:局部隔离", "合成方案 B:扩大核查", "合成方案 C:保持供水", "合成方案 D:分段验证", "合成方案 E:待补充资料"],
series: [{ name: "合成影响用户数(户)", data: [245, 610, 0, 128, 72] }]
};
const chart = (id: string, value: typeof pressure | typeof flow | typeof comparison) =>
ui(id, { type: "Chart", props: { ...value, source: "本地确定性合成数据,仅供展示测试;曲线变化和方案名称均非实际分析结果。" }, children: [] });
const columns = ["序号", "管段 ID", "合成片区", "长度(m)", "压力变化(m)", "影响户数(户)", "核查状态", "核查说明"];
const rows = Array.from({ length: 50 }, (_, index) => [
@@ -53,7 +68,8 @@ const rows = Array.from({ length: 50 }, (_, index) => [
export function createComplexInvestigationDevCase(caseId: ComplexCaseId, [longitude, latitude]: [number, number]): string {
if (caseId === "complex_charts") return serializeInvestigationDevJsonl([
chart("pressure", pressure), chart("flow", flow), chart("comparison", comparison)
...objectCharts(),
createPresentationRecord({ action: "open_chart", chart_id: "dev-complex-plans", evidence_refs: ["dev:synthetic"], chart: comparison })
]);
if (caseId === "complex_tables") return serializeInvestigationDevJsonl([
table("wide-table", "合成候选核查宽表", columns, rows),
@@ -69,7 +85,7 @@ export function createComplexInvestigationDevCase(caseId: ComplexCaseId, [longit
createPresentationRecord({ action: "set_overlay", mode: "geometry", overlay_id: "dev-complex-coverage", title: "合成分区覆盖示意", evidence_id: "dev:synthetic",
data: { type: "FeatureCollection", features: [-0.002, 0.002].map((dx, index) => ({ type: "Feature", properties: { project_code: INVESTIGATION_DEV_NETWORK.projectCode, origin: "synthetic", label: `合成片区 ${index + 1}` },
geometry: { type: "Polygon", coordinates: [[point(dx - 0.001, -0.001), point(dx + 0.001, -0.001), point(dx + 0.001, 0.001), point(dx - 0.001, 0.001), point(dx - 0.001, -0.001)]] } })) } }),
chart("pressure", pressure), chart("flow", flow),
...objectCharts(),
createPresentationRecord({ action: "open_chart", chart_id: "dev-complex-plans", evidence_refs: ["dev:synthetic"], chart: comparison }),
table("candidates", "合成候选方案核查", columns, rows.slice(0, 24)),
table("valves", "合成阀门核查清单", ["阀门", "合成片区", "位置描述", "核查要求", "当前状态"],