fix(workbench): stabilize investigation presentation rendering

Keep investigation graphs stable during updates, defer expensive chart rendering, and prevent stale results when switching tasks. Adopt reference annotations and consolidate frontend documentation.
This commit is contained in:
2026-11-11 19:10:41 +08:00
parent 0ae0a41e61
commit a617aa95e9
35 changed files with 1268 additions and 715 deletions
@@ -35,7 +35,7 @@ test("调查 SVG 兼容 HTML 换行并保留节点交互与错误兜底", async
};
const root = createRoot(document.getElementById("diagrams"));
const render = () => root.render(React.createElement(React.Fragment, null,
React.createElement(InvestigationDiagramView, { diagram, running: true,
React.createElement(InvestigationDiagramView, { diagram,
renderDetails: () => React.createElement("p", null, "已保存的 SCADA 引用依据") }),
React.createElement(InvestigationDiagramView, { diagram: { title: "错误兜底检查", mermaid: "flowchart TD\nA[未闭合", node_refs: [] },
renderDetails: () => null })
@@ -47,7 +47,7 @@ test("调查 SVG 兼容 HTML 换行并保留节点交互与错误兜底", async
await expect(graph.locator("svg .node")).toHaveCount(3);
await expect(graph.locator("svg foreignObject br")).toHaveCount(2);
await expect(graph.locator("svg .cluster-label")).toContainText("证据核对");
await expect(graph.locator("svg .tjRunning")).toHaveCount(1);
await expect(graph.locator("svg .tjReference")).toHaveCount(3);
await expect(graph).not.toContainText("This page contains the following errors");
await graph.locator(".node").filter({ hasText: "读取SCADA" }).click();
await expect(graph.getByLabel("节点详情 上游监测")).toContainText("已保存的 SCADA 引用依据");
@@ -81,10 +81,17 @@ test("调查 SVG 兼容 HTML 换行并保留节点交互与错误兜底", async
await graph.getByRole("button", { name: "放大查看", exact: true }).click();
await expect(detail.locator("svg .node")).toHaveCount(3);
expect(await page.evaluate(() => (window as unknown as { diagramRenderCount: number }).diagramRenderCount)).toBe(1);
await detail.evaluate(async (element) => {
await Promise.allSettled(element.getAnimations()
.filter((animation) => Number.isFinite(Number(animation.effect?.getComputedTiming().endTime)))
.map((animation) => animation.finished));
});
const narrowBox = (await detail.boundingBox())!;
expect(narrowBox.width).toBeLessThanOrEqual(343);
expect(narrowBox.height).toBeLessThanOrEqual(688);
expect(narrowBox.x).toBeGreaterThanOrEqual(15);
const viewport = page.viewportSize()!;
expect(narrowBox.x).toBeGreaterThanOrEqual(0);
expect(narrowBox.y).toBeGreaterThanOrEqual(0);
expect(narrowBox.x + narrowBox.width).toBeLessThanOrEqual(viewport.width);
expect(narrowBox.y + narrowBox.height).toBeLessThanOrEqual(viewport.height);
await detail.screenshot({ path: testInfo.outputPath("diagram-expanded-narrow.png") });
await page.evaluate(() => (window as unknown as { updateDiagram: () => void }).updateDiagram());
await expect(detail.locator("svg .node")).toHaveCount(4);