diff --git a/src/hooks/useFlowCallbacks.ts b/src/hooks/useFlowCallbacks.ts index 20a199b..e198bfd 100644 --- a/src/hooks/useFlowCallbacks.ts +++ b/src/hooks/useFlowCallbacks.ts @@ -598,6 +598,149 @@ export const useFlowCallbacks = ( const nodeDefinition = localNodeData.find(n => n.nodeType === nodeType) || node; if (!nodeDefinition) return; + // 特殊处理循环节点,添加开始和结束节点 + if (nodeType === 'LOOP') { + // 获取源节点和目标节点的位置 + const sourceNode = nodes.find(n => n.id === edgeForNodeAdd.source); + const targetNode = nodes.find(n => n.id === edgeForNodeAdd.target); + + if (!sourceNode || !targetNode) return; + + // 计算中点位置 + const position = { + x: (sourceNode.position.x + targetNode.position.x) / 2, + y: (sourceNode.position.y + targetNode.position.y) / 2 + }; + + // 创建循环开始和结束节点 + const loopStartNode = { + id: `LOOP_START-${Date.now()}`, + type: 'LOOP', + position: { x: position.x, y: position.y }, + data: { + title: '循环开始', + type: 'LOOP_START', + parameters: { + apiIns: [{ name: 'start', desc: '', dataType: '', defaultValue: '' }], + apiOuts: [{ name: 'done', desc: '', dataType: '', defaultValue: '' }], + dataIns: [], + dataOuts: [] + }, + component: {} + } + }; + + const loopEndNode = { + id: `LOOP_END-${Date.now()}`, + type: 'LOOP', + position: { x: position.x + 400, y: position.y }, + data: { + title: '循环结束', + type: 'LOOP_END', + parameters: { + apiIns: [{ name: 'continue', desc: '', dataType: '', defaultValue: '' }], + apiOuts: [{ name: 'break', desc: '', dataType: '', defaultValue: '' }], + dataIns: [{ + 'arrayType': null, + 'dataType': 'INTEGER', + 'defaultValue': 10, + 'desc': '最大循环次数', + 'id': 'maxTime' + }], + dataOuts: [] + }, + component: { + type: 'LOOP_END', + customDef: JSON.stringify({ + apiOutIds: ['continue', 'break'], + conditions: [], + loopStartNodeId: loopStartNode.id + }), + loopStartNodeId: loopStartNode.id + } + } + }; + + loopStartNode.data.component = { + type: 'LOOP_START', + customDef: JSON.stringify({ loopEndNodeId: loopEndNode.id }) + }; + + // 创建连接边(连接循环开始和结束节点的顶部连接点) + const groupEdge = { + id: `${loopStartNode.id}-${loopEndNode.id}-group`, + source: loopStartNode.id, + target: loopEndNode.id, + sourceHandle: `${loopStartNode.id}-group`, + targetHandle: `${loopEndNode.id}-group`, + type: 'custom' + }; + + // 创建连接原有节点到循环开始节点,以及循环结束节点到目标节点的边 + const connectionEdges = [ + { + id: `e${edgeForNodeAdd.source}-${loopStartNode.id}`, + source: edgeForNodeAdd.source, + target: loopStartNode.id, + sourceHandle: edgeForNodeAdd.sourceHandle, + targetHandle: 'start', // 循环开始节点的输入句柄 + type: 'custom' + }, + { + id: `e${loopEndNode.id}-${edgeForNodeAdd.target}`, + source: loopEndNode.id, + target: edgeForNodeAdd.target, + sourceHandle: 'break', // 循环结束节点的输出句柄 + targetHandle: edgeForNodeAdd.targetHandle, + type: 'custom' + } + ]; + + // 将未定义的节点动态追加进nodeTypes + const nodeMap = Array.from(Object.values(nodeTypeMap).map(key => key)); + if (!nodeMap.includes('LOOP')) { + registerNodeType('LOOP', LoopNode, '循环'); + } + + // 更新节点和边 + setNodes((nds: Node[]) => { + const newNodes = [...nds, loopStartNode, loopEndNode]; + + // 添加节点后记录历史 + setTimeout(() => { + const event = new CustomEvent('takeSnapshot', { + detail: { nodes: [...newNodes], edges: [...edges, groupEdge, ...connectionEdges] } + }); + document.dispatchEvent(event); + }, 0); + + return newNodes; + }); + + setEdges((eds: Edge[]) => { + // 删除原来的边,添加新的边 + const updatedEdges = [...eds.filter(e => e.id !== edgeForNodeAdd.id), groupEdge, ...connectionEdges]; + + // 添加边后记录历史 + setTimeout(() => { + const event = new CustomEvent('takeSnapshot', { + detail: { + nodes: [...nodes, loopStartNode, loopEndNode], + edges: [...updatedEdges] + } + }); + document.dispatchEvent(event); + }, 0); + + return updatedEdges; + }); + + // 关闭菜单 + setEdgeForNodeAdd(null); + setPositionForNodeAdd(null); + return; + } + // 获取源节点和目标节点 const sourceNode = nodes.find(n => n.id === edgeForNodeAdd.source); const targetNode = nodes.find(n => n.id === edgeForNodeAdd.target); @@ -704,7 +847,7 @@ export const useFlowCallbacks = ( }); document.dispatchEvent(event); }, 0); - }, [edgeForNodeAdd, nodes, reactFlowInstance, edges]); + }, [edgeForNodeAdd, nodes, reactFlowInstance, edges, addLoopNodeWithStartEnd]); // 在画布上添加节点 const addNodeOnPane = useCallback((nodeType: string, position: { x: number; y: number }, node?: any) => {