From 1b7596954a51080228af18bb35ceb956238040e9 Mon Sep 17 00:00:00 2001 From: rookie4show Date: Sat, 28 Feb 2026 00:38:53 +0800 Subject: [PATCH] fix(flow): stabilize preview import and dynamic-group rendering - hide dynamic-group containers in preview graph sanitization - keep dynamic-group plugin registered in render-only/interactive presets - refresh canvas immediately after JSON import --- src/YysEditorEmbed.vue | 18 ++++++++++++++---- src/components/Toolbar.vue | 2 +- src/flowRuntime.ts | 8 ++++---- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/YysEditorEmbed.vue b/src/YysEditorEmbed.vue index 98497df..7a77580 100644 --- a/src/YysEditorEmbed.vue +++ b/src/YysEditorEmbed.vue @@ -111,12 +111,15 @@ const sanitizeLabelProperty = (properties: unknown): Record | undef return nextProperties } -const sanitizeGraphData = (input?: GraphData | null): GraphData => { +const sanitizeGraphData = ( + input?: GraphData | null, + options?: { hideDynamicGroups?: boolean } +): GraphData => { if (!input || !Array.isArray(input.nodes) || !Array.isArray(input.edges)) { return { nodes: [], edges: [] } } - const nodes = input.nodes + const rawNodes = input.nodes .filter((node): node is NodeData => isPlainObject(node)) .map((node) => { const nextNode: NodeData = { ...node } @@ -127,6 +130,12 @@ const sanitizeGraphData = (input?: GraphData | null): GraphData => { return nextNode }) + const hiddenDynamicGroup = options?.hideDynamicGroups === true + const nodes = hiddenDynamicGroup + ? rawNodes.filter((node) => node.type !== 'dynamic-group') + : rawNodes + const nodeIdSet = new Set(nodes.map((node) => node.id)) + const edges = input.edges .filter((edge): edge is EdgeData => isPlainObject(edge)) .map((edge) => { @@ -137,6 +146,7 @@ const sanitizeGraphData = (input?: GraphData | null): GraphData => { } return nextEdge }) + .filter((edge) => !hiddenDynamicGroup || (nodeIdSet.has(edge.sourceNodeId) && nodeIdSet.has(edge.targetNodeId))) return { nodes, edges } } @@ -328,7 +338,7 @@ const initPreviewMode = () => { // 渲染数据 if (props.data) { - previewLf.value.render(sanitizeGraphData(props.data)) + previewLf.value.render(sanitizeGraphData(props.data, { hideDynamicGroups: true })) } } @@ -362,7 +372,7 @@ const getGraphData = (): GraphData | null => { } const setGraphData = (data: GraphData) => { - const safeData = sanitizeGraphData(data) + const safeData = sanitizeGraphData(data, { hideDynamicGroups: props.mode === 'preview' }) if (props.mode === 'edit') { const lfInstance = getLogicFlowInstance() if (lfInstance) { diff --git a/src/components/Toolbar.vue b/src/components/Toolbar.vue index 244c727..0597202 100644 --- a/src/components/Toolbar.vue +++ b/src/components/Toolbar.vue @@ -928,7 +928,7 @@ const handleImport = () => { const target = e.target as FileReader; const data = JSON.parse(target.result as string); filesStore.importData(data); - // refreshLogicFlowCanvas('LogicFlow 画布已重新渲染(导入数据)'); + refreshLogicFlowCanvas('LogicFlow 画布已重新渲染(导入数据)'); } catch (error) { console.error('Failed to import file', error); showMessage('error', '文件格式错误'); diff --git a/src/flowRuntime.ts b/src/flowRuntime.ts index 5af7027..bd3d221 100644 --- a/src/flowRuntime.ts +++ b/src/flowRuntime.ts @@ -1,5 +1,5 @@ import type LogicFlow from '@logicflow/core' -import { Menu, Label, Snapshot, SelectionSelect, MiniMap, Control } from '@logicflow/extension' +import { Menu, Label, Snapshot, SelectionSelect, MiniMap, Control, DynamicGroup } from '@logicflow/extension' import { register } from '@logicflow/vue-node-registry' import ImageNode from './components/flow/nodes/common/ImageNode.vue' @@ -27,8 +27,9 @@ const DEFAULT_FLOW_NODES: FlowNodeRegistration[] = [ ] const FLOW_PLUGIN_PRESETS: Record = { - 'render-only': [Snapshot], - interactive: [Menu, Label, Snapshot, SelectionSelect, MiniMap, Control] + // 预览模式也需要 DynamicGroup,避免包含 dynamic-group 节点的图在只读渲染时报错 + 'render-only': [DynamicGroup, Snapshot], + interactive: [DynamicGroup, Menu, Label, Snapshot, SelectionSelect, MiniMap, Control] } export function getFlowPluginsByCapability(capability: FlowCapabilityLevel): FlowPlugin[] { @@ -60,4 +61,3 @@ export function registerFlowNodes(lfInstance: LogicFlow, nodes?: FlowNodeRegistr const registrations = resolveFlowNodes(nodes) registrations.forEach((registration) => register(registration, lfInstance)) } -