diff --git a/packages/x-flow/src/XFlow.tsx b/packages/x-flow/src/XFlow.tsx index b35f14e75..32e534410 100644 --- a/packages/x-flow/src/XFlow.tsx +++ b/packages/x-flow/src/XFlow.tsx @@ -99,10 +99,11 @@ const XFlow: FC = memo(props => { connectionLineComponent, } = props; const nodeEditorRef = useRef(null); - const { copyNode, pasteNodeSimple } = useFlow(); + const { copyNode, pasteNodeSimple, deleteNode } = useFlow(); const { undo, redo } = useTemporalStore(); const isNodeCopyingRef = useRef(false); // 是否正在进行节点复制 const lastClickedNodeRef = useRef(false); // 最后一次点击是否是节点 + const isPanelRenderingRef = useRef(false); // 面板是否正在渲染中 useEffect(() => { zoomTo(0.8); @@ -333,11 +334,14 @@ const XFlow: FC = memo(props => { onClick={async e => { // 记录用户点击了节点 lastClickedNodeRef.current = true; + // 标记面板开始渲染 + isPanelRenderingRef.current = true; if (nodeEditorRef?.current?.validateForm) { const result = await nodeEditorRef?.current?.validateForm(); if (!result) { message.error('请检查必填项!'); + isPanelRenderingRef.current = false; return; } } @@ -353,6 +357,10 @@ const XFlow: FC = memo(props => { setOpenPanel(true); } setOpenLogPanel(true); + + setTimeout(() => { + isPanelRenderingRef.current = false; + }, 1000); // 给面板一点时间完成渲染 }} onDelete={()=>{ // 删除节点并关闭弹窗 @@ -437,30 +445,42 @@ const XFlow: FC = memo(props => { message.warning(`${blockedNodes.map(n => n.data?.title || n.id).join(', ')}节点不允许删除!`); return false; } - return true + + // 检查是否删除的是当前激活的节点 + const hasActiveNode = nodesToDelete.some(node => node.id === activeNode?.id); + if (hasActiveNode) { + // 立即关闭面板和清除激活状态 + setOpenPanel(false); + setActiveNode(null); + } + + const executeDelete = () => { + nodesToDelete.forEach(node => { + deleteNode(node.id); + }); + }; + + // 如果面板正在渲染中,延迟执行删除避免状态冲突 + if (isPanelRenderingRef.current) { + setTimeout(() => { + executeDelete(); + }, 150); + } else { + // 面板未在渲染,立即执行删除 + executeDelete(); + } + + return false; }} onConnect={onConnect} onNodesChange={changes => { - changes.forEach(change => { - if (change.type === 'remove') { - record(() => { - onNodesChange([change]); - }); - } else { - onNodesChange([change]); - } - }); + const nonRemoveChanges = changes.filter(c => c.type !== 'remove'); + if (nonRemoveChanges.length > 0) { + onNodesChange(nonRemoveChanges); + } }} onEdgesChange={changes => { - changes.forEach(change => { - if (change.type === 'remove') { - record(() => { - onEdgesChange([change]); - }); - } else { - onEdgesChange([change]); - } - }); + onEdgesChange(changes); }} onEdgeMouseEnter={(_, edge: any) => { if(!edge.style.stroke || edge.style.stroke === '#c9c9c9'){ @@ -472,8 +492,8 @@ const XFlow: FC = memo(props => { getUpdateEdgeConfig(edge, '#c9c9c9'); } }} - onNodesDelete={() => { - setActiveNode(null); + onNodesDelete={(nodes) => { + // setActiveNode(null); }} onNodeClick={(event, node) => { onNodeClick && onNodeClick(event, node); diff --git a/packages/x-flow/src/hooks/useFlow.ts b/packages/x-flow/src/hooks/useFlow.ts index 14455810c..04b2232b1 100644 --- a/packages/x-flow/src/hooks/useFlow.ts +++ b/packages/x-flow/src/hooks/useFlow.ts @@ -129,14 +129,20 @@ export const useFlow = () => { // 关闭mousemove监听 storeApi.getState().setIsAddingNode(false); + // 清除 selected 状态,避免粘贴的节点被意外选中 + const copyNodesWithoutSelection = storeApi.getState().copyNodes.map(node => ({ + ...node, + selected: false, + })); + const newEdges = { id: uuid(), source: nodeId, - target: storeApi.getState().copyNodes[0].id, + target: copyNodesWithoutSelection[0].id, ...data }; record(() => { - storeApi.getState().addNodes(storeApi.getState().copyNodes, false); + storeApi.getState().addNodes(copyNodesWithoutSelection, false); }) storeApi.getState().addEdges(newEdges); storeApi.setState({ @@ -163,8 +169,10 @@ export const useFlow = () => { x: mousePosition.elementX, y: mousePosition.elementY, }); + // 清除 selected 状态,避免粘贴的节点被意外选中 const copyNodes = storeApi.getState().copyNodes.map(node => ({ ...node, + selected: false, position: { x: flowPos.x, y: flowPos.y, @@ -191,10 +199,6 @@ export const useFlow = () => { .edges.filter( edge => edge.source !== nodeId && edge.target !== nodeId ), - }); - }); - record(() => { - storeApi.setState({ nodes: storeApi.getState().nodes.filter(node => node.id !== nodeId), }); });