You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

237 lines
7.1 KiB
TypeScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import { nodeTypeMap, registerNodeType } from '@/components/FlowEditor/node';
import LocalNode from '@/components/FlowEditor/node/localNode/LocalNode';
/**
* 将提供的数据结构转换为适用于 flow editor 的 nodes 和 edges
* @param flowData - 原始数据结构
* @returns 包含 nodes 和 edges 的对象
*/
export const convertFlowData = (flowData: any) => {
const nodes: any[] = [];
const edges: any[] = [];
if (!flowData || Object.keys(flowData).length === 0) return { nodes, edges };
// 处理节点配置
const nodeConfigs = flowData.main?.nodeConfigs || [];
for (const nodeConfig of nodeConfigs) {
// 确定节点类型
let nodeType = 'BASIC';
if (nodeConfig.nodeId === 'start') {
nodeType = 'start';
}
else if (nodeConfig.nodeId === 'end') {
nodeType = 'end';
}
else {
nodeType = nodeConfig.component.type;
}
// 解析位置信息
let position = { x: 0, y: 0 };
try {
const x6Data = JSON.parse(nodeConfig.x6);
position = x6Data.position || { x: 0, y: 0 };
} catch (e) {
console.warn('Failed to parse position for node:', nodeConfig.nodeId);
}
// 构造节点数据
const node: any = {
id: nodeConfig.nodeId,
type: nodeType,
position,
data: {
title: nodeConfig.nodeName || nodeConfig.nodeId,
parameters: {
apiIns: [{
name: 'start',
desc: '',
dataType: '',
defaultValue: ''
}],
apiOuts: [{
name: nodeConfig.nodeId === 'end' ? 'end' : 'done',
desc: '',
dataType: '',
defaultValue: ''
}],
dataIns: nodeConfig.dataIns?.map((input: any) => ({
name: input.id,
desc: input.desc,
dataType: input.dataType,
defaultValue: input.defaultValue
})) || [],
dataOuts: nodeConfig.dataOuts?.map((output: any) => ({
name: output.id,
desc: output.desc,
dataType: output.dataType,
defaultValue: output.defaultValue
})) || []
},
type: nodeType
}
};
// 如果是机械臂节点,添加组件标识信息
if (nodeConfig.component) {
node.data.component = {
compIdentifier: nodeConfig.component.compIdentifier,
compInstanceIdentifier: nodeConfig.component.compInstanceIdentifier,
customDef: nodeConfig.component?.customDef,
type: nodeConfig.component.type
};
}
// 将未定义的节点动态追加进nodeTypes
const nodeMap = Array.from(Object.values(nodeTypeMap).map(key => key));
// 目前默认添加的都是系统组件/本地组件
if (!nodeMap.includes(nodeType)) registerNodeType(nodeType, LocalNode, nodeConfig.nodeName);
nodes.push(node);
}
// 处理连线配置
const lineConfigs = flowData.main?.lineConfigs || [];
for (const lineConfig of lineConfigs) {
const edge: any = {
id: lineConfig.id,
source: lineConfig.prev.nodeId,
target: lineConfig.next.nodeId,
sourceHandle: lineConfig.prev.endpointId,
targetHandle: lineConfig.next.endpointId
};
edges.push(edge);
}
return { nodes, edges };
};
/**
* 将 flow editor 的 nodes 和 edges 数据结构转换回原始数据结构
* @param nodes - flow editor 的节点数组
* @param edges - flow editor 的连线数组
* @returns 原始数据结构
*/
export const revertFlowData = (nodes: any[], edges: any[]) => {
// 初始化返回的数据结构
const flowData: any = {
id: 'main',
nodeConfigs: [],
lineConfigs: []
};
// 转换节点数据
if (nodes && nodes.length > 0) {
flowData.nodeConfigs = nodes.map(node => {
// 确定 nodeId 和 nodeName
const nodeId = node.id;
const nodeName = node.data?.title || nodeId;
// 确定节点类型
let nodeType = node.type;
// 特殊处理 start 和 end 节点
if (nodeId === 'start') {
nodeType = 'start';
}
else if (nodeId === 'end') {
nodeType = 'end';
}
// 构造 x6 数据(位置信息)
const x6 = JSON.stringify({
position: node.position
});
// 构造 nodeConfig 对象
const nodeConfig: any = {
nodeId,
nodeName,
x6
};
// 处理 component 信息
if (node.data?.component) {
nodeConfig.component = {
type: nodeType,
compIdentifier: node.data.component.compIdentifier,
compInstanceIdentifier: node.data.component.compInstanceIdentifier
};
if (node.data.component?.customDef) nodeConfig.component.customDef = node.data.component.customDef;
}
else if (nodeType !== 'start' && nodeType !== 'end') {
// 对于非 start/end 节点,添加基本的 component 信息
nodeConfig.component = {
type: nodeType
};
}
// 处理参数信息
const parameters = node.data?.parameters || {};
// 处理 dataIns输入数据
if (parameters.dataIns && parameters.dataIns.length > 0) {
nodeConfig.dataIns = parameters.dataIns.map((input: any) => ({
id: input.name,
desc: input.desc,
dataType: input.dataType,
defaultValue: input.defaultValue
}));
}
// 处理 dataOuts输出数据
if (parameters.dataOuts && parameters.dataOuts.length > 0) {
nodeConfig.dataOuts = parameters.dataOuts.map((output: any) => ({
id: output.name,
desc: output.desc,
dataType: output.dataType,
defaultValue: output.defaultValue
}));
}
return nodeConfig;
});
}
// 转换连线数据
if (edges && edges.length > 0) {
flowData.lineConfigs = edges.map((edge, index) => {
// 查找源节点和目标节点以确定连线类型
const sourceNode = nodes.find(node => node.id === edge.source);
const targetNode = nodes.find(node => node.id === edge.target);
let lineType = 'DATA'; // 默认为DATA类型
// 判断是否为CONVERT类型的连线
if (targetNode && ['JSONCONVERT', 'JSON2STR', 'STR2JSON'].includes(targetNode.type)) {
lineType = 'CONVERT';
}
// 判断是否为API类型的连线
else if (edge.sourceHandle && (edge.sourceHandle === 'apiOuts' ||
sourceNode?.data?.parameters?.apiOuts?.some((out: any) => out.name === edge.sourceHandle))) {
lineType = 'API';
}
else if (edge.targetHandle && (edge.targetHandle === 'apiIns' ||
targetNode?.data?.parameters?.apiIns?.some((inp: any) => inp.name === edge.targetHandle))) {
lineType = 'API';
}
return {
id: edge.id || `edge_${index}`, // 如果没有 id则生成一个
lineType, // 添加lineType属性
prev: {
nodeId: edge.source,
endpointId: edge.sourceHandle || 'done' // 默认使用 'done'
},
next: {
nodeId: edge.target,
endpointId: edge.targetHandle || 'start' // 默认使用 'start'
}
};
});
}
return flowData;
};