feat(flow): 添加流程连接线校验功能

- 引入 Edge 类型定义用于连接线校验- 实现 validateAllEdges 函数校验连接线完整性
- 校验连接线源节点和目标节点的存在性
- 检查未连接的非开始/结束节点- 验证各节点类型的连接规则(如条件节点、开始节点、结束节点)
- 在保存流程时增加连接线校验步骤
- 优化校验错误信息展示逻辑
master
钟良源 4 months ago
parent e8ff97ecdc
commit a925326557

@ -1,4 +1,5 @@
import { Message } from '@arco-design/web-react';
import { Edge } from '@xyflow/react';
export interface ValidationResult {
isValid: boolean;
@ -365,6 +366,130 @@ export const validateAllNodes = (nodes: any[]): ValidationResult => {
};
};
/**
* 线
* @param edges 线
* @param nodes
* @returns
*/
export const validateAllEdges = (edges: Edge[], nodes: any[]): ValidationResult => {
const allErrors: string[] = [];
// 创建节点ID到节点标题的映射方便错误信息展示
const nodeTitleMap = new Map<string, string>();
const nodeMap = new Map<string, any>();
nodes.forEach(node => {
const nodeTitle = node.data?.title || node.id;
nodeTitleMap.set(node.id, nodeTitle);
nodeMap.set(node.id, node);
});
// 检查连接线的基本信息
edges.forEach((edge, index) => {
// 检查连接线是否有源节点和目标节点
if (!edge.source) {
allErrors.push(`${index + 1}条连接线缺少源节点`);
return;
}
if (!edge.target) {
allErrors.push(`${index + 1}条连接线缺少目标节点`);
return;
}
// 检查源节点和目标节点是否存在
if (edge.source && !nodeTitleMap.has(edge.source)) {
allErrors.push(`${index + 1}条连接线的源节点"${edge.source}"不存在`);
}
if (edge.target && !nodeTitleMap.has(edge.target)) {
allErrors.push(`${index + 1}条连接线的目标节点"${edge.target}"不存在`);
}
});
// 检查是否有未连接的节点(开始节点和结束节点除外)
const connectedNodeIds = new Set<string>();
edges.forEach(edge => {
if (edge.source) connectedNodeIds.add(edge.source);
if (edge.target) connectedNodeIds.add(edge.target);
});
nodes.forEach(node => {
// 如果节点没有被任何连接线连接
if (!connectedNodeIds.has(node.id)) {
const nodeType = node.data?.type || node.type;
// 开始节点和结束节点可以不连接
if (nodeType !== 'start' && nodeType !== 'end') {
const nodeName = node.data?.title || node.id;
allErrors.push(`节点"${nodeName}"未连接任何连线`);
}
}
});
// 检查节点的连接是否符合规则
const sourceCount = new Map<string, number>(); // 每个节点作为源节点的次数
const targetCount = new Map<string, number>(); // 每个节点作为目标节点的次数
edges.forEach(edge => {
if (edge.source) {
sourceCount.set(edge.source, (sourceCount.get(edge.source) || 0) + 1);
}
if (edge.target) {
targetCount.set(edge.target, (targetCount.get(edge.target) || 0) + 1);
}
});
// 检查每个节点的连接情况
nodes.forEach(node => {
const nodeId = node.id;
const nodeType = node.data?.type || node.type;
const nodeName = node.data?.title || node.id;
const sourceEdges = sourceCount.get(nodeId) || 0;
const targetEdges = targetCount.get(nodeId) || 0;
// 特定节点类型可能有特殊的连接规则
switch (nodeType) {
case 'SWITCH':
// 条件节点应该有至少一个输出连接
if (sourceEdges === 0) {
allErrors.push(`条件节点"${nodeName}"缺少输出连接`);
}
break;
case 'start':
// 开始节点应该有输出连接,但不需要输入连接
if (sourceEdges === 0) {
allErrors.push(`开始节点"${nodeName}"缺少输出连接`);
}
break;
case 'end':
// 结束节点应该有输入连接,但不需要输出连接
if (targetEdges === 0) {
allErrors.push(`结束节点"${nodeName}"缺少输入连接`);
}
break;
default:
// 其他节点应该至少有一个输入和一个输出连接
if (targetEdges === 0) {
allErrors.push(`节点"${nodeName}"缺少输入连接`);
}
if (sourceEdges === 0) {
allErrors.push(`节点"${nodeName}"缺少输出连接`);
}
break;
}
});
return {
isValid: allErrors.length === 0,
errors: allErrors
};
};
/**
*
* @param errors

@ -24,7 +24,11 @@ import ImageNode from '@/components/FlowEditor/node/imageNode/ImageNode';
import CodeNode from '@/components/FlowEditor/node/codeNode/CodeNode';
import RestNode from '@/components/FlowEditor/node/restNode/RestNode';
import { updateCanvasDataMap } from '@/store/ideContainer';
import { validateAllNodes, showValidationErrors } from '@/components/FlowEditor/nodeEditors/validators/nodeValidators';
import {
validateAllNodes,
showValidationErrors,
validateAllEdges
} from '@/components/FlowEditor/nodeEditors/validators/nodeValidators';
import { Dispatch } from 'redux';
@ -782,9 +786,16 @@ export const useFlowCallbacks = (
const saveFlowDataToServer = useCallback(async () => {
try {
// 首先校验所有节点数据是否完整
const validation = validateAllNodes(nodes);
if (!validation.isValid) {
showValidationErrors(validation.errors);
const nodeValidation = validateAllNodes(nodes);
if (!nodeValidation.isValid) {
showValidationErrors(nodeValidation.errors);
return;
}
// 然后校验所有连接线是否有效
const edgeValidation = validateAllEdges(edges, nodes);
if (!edgeValidation.isValid) {
showValidationErrors(edgeValidation.errors);
return;
}

Loading…
Cancel
Save