|
|
|
@ -35,7 +35,7 @@ interface FlowEditorMainProps {
|
|
|
|
nodeTypes: NodeTypes;
|
|
|
|
nodeTypes: NodeTypes;
|
|
|
|
setNodes: React.Dispatch<React.SetStateAction<Node[]>>;
|
|
|
|
setNodes: React.Dispatch<React.SetStateAction<Node[]>>;
|
|
|
|
setEdges: React.Dispatch<React.SetStateAction<Edge[]>>;
|
|
|
|
setEdges: React.Dispatch<React.SetStateAction<Edge[]>>;
|
|
|
|
useDefault:boolean;
|
|
|
|
useDefault: boolean;
|
|
|
|
reactFlowInstance: any;
|
|
|
|
reactFlowInstance: any;
|
|
|
|
reactFlowWrapper: React.RefObject<HTMLDivElement>;
|
|
|
|
reactFlowWrapper: React.RefObject<HTMLDivElement>;
|
|
|
|
menu: any;
|
|
|
|
menu: any;
|
|
|
|
@ -184,8 +184,79 @@ const FlowEditorMain: React.FC<FlowEditorMainProps> = (props) => {
|
|
|
|
edgeTypes={edgeTypes}
|
|
|
|
edgeTypes={edgeTypes}
|
|
|
|
snapToGrid={true}
|
|
|
|
snapToGrid={true}
|
|
|
|
snapGrid={[2, 2]}
|
|
|
|
snapGrid={[2, 2]}
|
|
|
|
|
|
|
|
onBeforeDelete={async ({ nodes }) => {
|
|
|
|
|
|
|
|
// 检查是否有开始或结束节点
|
|
|
|
|
|
|
|
const hasStartOrEndNode = nodes.some(node => node.type === 'start' || node.type === 'end');
|
|
|
|
|
|
|
|
if (hasStartOrEndNode) {
|
|
|
|
|
|
|
|
console.warn('开始和结束节点不允许删除');
|
|
|
|
|
|
|
|
return false; // 阻止删除操作
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否有循环节点(这里只是检查,实际删除逻辑在onNodesDelete中处理)
|
|
|
|
|
|
|
|
const loopNodes = nodes.filter(node =>
|
|
|
|
|
|
|
|
node.data?.type === 'LOOP_START' || node.data?.type === 'LOOP_END'
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 允许删除操作继续进行
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}}
|
|
|
|
onNodesDelete={(deleted) => {
|
|
|
|
onNodesDelete={(deleted) => {
|
|
|
|
setNodes((nds) => nds.filter((n) => !deleted.find((d) => d.id === n.id)));
|
|
|
|
console.log('deleted:', deleted);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否有循环节点
|
|
|
|
|
|
|
|
const loopNodes = deleted.filter(node =>
|
|
|
|
|
|
|
|
node.data?.type === 'LOOP_START' || node.data?.type === 'LOOP_END'
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (loopNodes.length > 0) {
|
|
|
|
|
|
|
|
// 处理循环节点删除
|
|
|
|
|
|
|
|
let nodesToRemove = [...deleted];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 为每个循环节点找到其配对节点
|
|
|
|
|
|
|
|
loopNodes.forEach(loopNode => {
|
|
|
|
|
|
|
|
const component = loopNode.data?.component as { customDef?: string } | undefined;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (loopNode.data?.type === 'LOOP_START' && component?.customDef) {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
const customDef = JSON.parse(component.customDef);
|
|
|
|
|
|
|
|
const relatedNodeId = customDef.loopEndNodeId;
|
|
|
|
|
|
|
|
// 添加关联的结束节点到删除列表
|
|
|
|
|
|
|
|
const relatedNode = nodes.find(n => n.id === relatedNodeId);
|
|
|
|
|
|
|
|
if (relatedNode) {
|
|
|
|
|
|
|
|
nodesToRemove.push(relatedNode);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
|
|
console.error('解析循环开始节点数据失败:', e);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (loopNode.data?.type === 'LOOP_END' && component?.customDef) {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
const customDef = JSON.parse(component.customDef);
|
|
|
|
|
|
|
|
const relatedNodeId = customDef.loopStartNodeId;
|
|
|
|
|
|
|
|
// 添加关联的开始节点到删除列表
|
|
|
|
|
|
|
|
const relatedNode = nodes.find(n => n.id === relatedNodeId);
|
|
|
|
|
|
|
|
if (relatedNode) {
|
|
|
|
|
|
|
|
nodesToRemove.push(relatedNode);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
|
|
console.error('解析循环结束节点数据失败:', e);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 去重
|
|
|
|
|
|
|
|
nodesToRemove = nodesToRemove.filter((node, index, self) =>
|
|
|
|
|
|
|
|
index === self.findIndex(n => n.id === node.id)
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 删除所有相关节点
|
|
|
|
|
|
|
|
setNodes((nds) => nds.filter((n) => !nodesToRemove.find((d) => d.id === n.id)));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
|
|
|
// 普通节点删除
|
|
|
|
|
|
|
|
setNodes((nds) => nds.filter((n) => !deleted.find((d) => d.id === n.id)));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
setIsEditModalOpen(false);
|
|
|
|
setIsEditModalOpen(false);
|
|
|
|
}}
|
|
|
|
}}
|
|
|
|
onNodesChange={onNodesChange}
|
|
|
|
onNodesChange={onNodesChange}
|
|
|
|
|