perf: 探索图减少卡顿(数据未变不重建 + 只渲染可见节点)

- graph-tab:轮询按签名判重,图数据无变化时跳过 setState,避免整图重建;
  拖动不再被 20s 轮询打断
- ExplorationGraph:ReactFlow 加 onlyRenderVisibleElements,屏幕外节点不渲染
This commit is contained in:
Autumn-27 committed 2026-08-18 13:18:32 -04:00
1 parent 08cdac2362
commit 24a94cf8e5
2 files changed
+15 -2

No files matched your search

@@ -10,16 +10,28 @@ import type { Edge, TaskNode } from "@/lib/types";
export function GraphTab({ taskId }: { taskId: string }) {
const [nodes, setNodes] = React.useState<TaskNode[]>([]);
const [edges, setEdges] = React.useState<Edge[]>([]);
// 上一次图数据的签名:轮询拿到相同数据时跳过 setState,避免整图无谓重建(拖动时
// 才不会被 20s 轮询打断而顿挫)。只取影响渲染的字段。
const sigRef = React.useRef("");
React.useEffect(() => {
let cancelled = false;
sigRef.current = ""; // 换任务:强制下一次刷新
const load = () => {
api
.explorationGraph(taskId)
.then((g) => {
if (cancelled) return;
setNodes(g.nodes ?? []);
setEdges(g.edges ?? []);
const ns = g.nodes ?? [];
const es = g.edges ?? [];
const sig = JSON.stringify([
ns.map((n) => [n.id, n.type, n.state, n.priority, n.payload]),
es.map((e) => [e.src, e.dst, e.rel]),
]);
if (sig === sigRef.current) return; // 无变化 → 不重建
sigRef.current = sig;
setNodes(ns);
setEdges(es);
})
.catch(() => {
/* keep last good data */
+1
View File
@@ -444,6 +444,7 @@ function ExplorationGraphInner({
fitView
fitViewOptions={{ padding: 0.2 }}
proOptions={{ hideAttribution: true }}
onlyRenderVisibleElements
minZoom={0.1}
className="!bg-[#f0f2f7] dark:!bg-neutral-950"
>