diff --git a/src/api/appRes.ts b/src/api/appRes.ts index 58772ee..af9c356 100644 --- a/src/api/appRes.ts +++ b/src/api/appRes.ts @@ -9,6 +9,12 @@ export function getAppInfo(data: string) { return axios.get(`${urlPrefix}/appRes/${data}`); } +// 获取应用资源 +export function getAppInfoNew(data: string) { + return axios.get(`${urlPrefix}/appRes/${data}/new`); +} + + // 更新主流程 export function setMainFlow(data: FlowDefinition, appId: string) { return axios.post(`${urlPrefix}/appRes/${appId}/updateMain`, data); diff --git a/src/hooks/useFlowCallbacks.ts b/src/hooks/useFlowCallbacks.ts index 4ebc6bb..7502345 100644 --- a/src/hooks/useFlowCallbacks.ts +++ b/src/hooks/useFlowCallbacks.ts @@ -445,14 +445,16 @@ export const useFlowCallbacks = ( // 初始化画布数据 const initializeCanvasData = useCallback(() => { - if (canvasDataMap[initialData?.id]) { - const { edges, nodes } = canvasDataMap[initialData?.id]; + if (canvasDataMap[initialData?.appId]) { + const { edges, nodes } = canvasDataMap[initialData?.appId]; setNodes(nodes); setEdges(edges); } else { // 首次进入 - const { nodes: convertedNodes, edges: convertedEdges } = convertFlowData(initialData); + const { nodes: convertedNodes, edges: convertedEdges } = convertFlowData(initialData?.main.components, true); + + // return; // 为所有边添加类型 const initialEdges: Edge[] = convertedEdges.map(edge => ({ ...edge, @@ -462,10 +464,10 @@ export const useFlowCallbacks = ( setNodes(convertedNodes); setEdges(initialEdges); - if (initialData?.id) { + if (initialData?.appId) { dispatch(updateCanvasDataMap({ ...canvasDataMap, - [initialData.id]: { nodes: convertedNodes, edges: initialEdges } + [initialData.appId]: { nodes: convertedNodes, edges: initialEdges } })); } } @@ -476,15 +478,15 @@ export const useFlowCallbacks = ( // 实时更新 canvasDataMap const updateCanvasDataMapEffect = useCallback(() => { - if (initialData?.id) { - updateCanvasDataMapDebounced(dispatch, canvasDataMap, initialData.id, nodes, edges); + if (initialData?.appId) { + updateCanvasDataMapDebounced(dispatch, canvasDataMap, initialData.appId, nodes, edges); } // 清理函数,在组件卸载时取消防抖 return () => { // 取消防抖函数 }; - }, [nodes, edges, initialData?.id, dispatch, canvasDataMap]); + }, [nodes, edges, initialData?.appId, dispatch, canvasDataMap]); // 关闭编辑弹窗 const closeEditModal = useCallback(() => { @@ -593,7 +595,8 @@ export const useFlowCallbacks = ( data: { ...nodeDefinition.data, title: nodeDefinition.nodeName, - type: nodeType + type: nodeType, + compId: nodeDefinition.id } }; @@ -609,6 +612,29 @@ export const useFlowCallbacks = ( // 删除旧边 setEdges((eds: Edge[]) => eds.filter(e => e.id !== edgeForNodeAdd.id)); + // 确定新边的句柄 + // 对于第一条边 (source -> new node): 使用原始边的 sourceHandle,目标句柄根据节点类型确定 + // 对于第二条边 (new node -> target): 源句柄根据节点类型确定,使用原始边的 targetHandle + + // 获取新节点的默认句柄 + let newNodeSourceHandle = 'done'; // 默认源句柄 + let newNodeTargetHandle = 'start'; // 默认目标句柄 + + // 如果新节点有参数定义,尝试获取更准确的句柄信息 + if (newNode.data?.parameters) { + const { apiOuts, apiIns } = newNode.data.parameters; + + // 获取第一个api输出作为源句柄(如果存在) + if (apiOuts && apiOuts.length > 0) { + newNodeSourceHandle = apiOuts[0].name || apiOuts[0].id || newNodeSourceHandle; + } + + // 获取第一个api输入作为目标句柄(如果存在) + if (apiIns && apiIns.length > 0) { + newNodeTargetHandle = apiIns[0].name || apiIns[0].id || newNodeTargetHandle; + } + } + // 创建新边: source -> new node, new node -> target const newEdges = [ ...edges.filter(e => e.id !== edgeForNodeAdd.id), @@ -616,12 +642,16 @@ export const useFlowCallbacks = ( id: `e${edgeForNodeAdd.source}-${newNode.id}`, source: edgeForNodeAdd.source, target: newNode.id, + sourceHandle: edgeForNodeAdd.sourceHandle, + targetHandle: newNodeTargetHandle, type: 'custom' }, { id: `e${newNode.id}-${edgeForNodeAdd.target}`, source: newNode.id, target: edgeForNodeAdd.target, + sourceHandle: newNodeSourceHandle, + targetHandle: edgeForNodeAdd.targetHandle, type: 'custom' } ]; @@ -658,6 +688,7 @@ export const useFlowCallbacks = ( return; } + // 创建新节点 const newNode = { id: `${nodeType}-${Date.now()}`, @@ -666,7 +697,8 @@ export const useFlowCallbacks = ( data: { ...nodeDefinition.data, title: nodeDefinition.nodeName, - type: nodeType + type: nodeType, + compId: nodeDefinition.id } }; @@ -716,7 +748,7 @@ export const useFlowCallbacks = ( console.log('revertedData:', revertedData); // return; - const res: any = await setMainFlow(revertedData, initialData.id); + const res: any = await setMainFlow(revertedData, initialData.appId); if (res.code === 200) { Message.success('保存成功'); } @@ -727,7 +759,7 @@ export const useFlowCallbacks = ( console.error('Error saving flow data:', error); Message.error('保存失败'); } - }, [nodes, edges]); + }, [nodes, edges, initialData?.appId]); // 初始化WebSocket hook const ws = useWebSocket({ @@ -771,7 +803,7 @@ export const useFlowCallbacks = ( ws.disconnect(); setIsRunning(false); } - }, [initialData?.id, ws]); + }, [initialData?.appId, ws]); return { // Event handlers diff --git a/src/pages/ideContainer/sideBar.tsx b/src/pages/ideContainer/sideBar.tsx index caf2490..4b52f32 100644 --- a/src/pages/ideContainer/sideBar.tsx +++ b/src/pages/ideContainer/sideBar.tsx @@ -20,6 +20,7 @@ import { useDispatch, useSelector } from 'react-redux'; import { updateMenuData, updateFlowData } from '@/store/ideContainer'; import { addApp, getProjectEnv, editApp, deleteApp } from '@/api/apps'; import _ from 'lodash'; +import { getAppInfoNew } from '@/api/appRes'; const TreeNode = Tree.Node; const FormItem = Form.Item; @@ -255,7 +256,8 @@ const SideBar: React.FC = ({ const parentKey = menu[activeKey]?.key; const currentMenu = _.cloneDeep(menuData[identity]); const index = currentMenu.findIndex(v => v.key === parentKey); - const res: any = await getProjectEnv(data.id); + // const res: any = await getProjectEnv(data.id); + const res: any = await getAppInfoNew(data.id); if (res.code === 200) { const children = currentMenu[index].children.find(v => v.id === data.id); children.children[0].children = res.data.events.map(item => { @@ -282,7 +284,7 @@ const SideBar: React.FC = ({ // 更新 menuData 中的数据 dispatch(updateMenuData({ ...menuData, [identity]: currentMenu })); // 更新 flowData 中的数据 - dispatch(updateFlowData({ [data.id]: res.data.app })); + dispatch(updateFlowData({ [data.id]: res.data })); // 同时更新本地 menu 状态以触发重新渲染 setMenu(prevMenu => { diff --git a/src/pages/orchestration/project/index.tsx b/src/pages/orchestration/project/index.tsx index 1b64813..561537b 100644 --- a/src/pages/orchestration/project/index.tsx +++ b/src/pages/orchestration/project/index.tsx @@ -4,14 +4,9 @@ import { useSelector } from 'react-redux'; const ProjectContainer = ({ selected }) => { const { flowData } = useSelector(state => state.ideContainer); - const [selectedFlowData, setSelectedFlowData] = useState({}); - - useEffect(() => { - setSelectedFlowData(flowData[selected.id]); - }, [selected]); return ( - + ); }; diff --git a/src/utils/convertFlowData.ts b/src/utils/convertFlowData.ts index ba26d84..6a673eb 100644 --- a/src/utils/convertFlowData.ts +++ b/src/utils/convertFlowData.ts @@ -1,6 +1,7 @@ import { nodeTypeMap, registerNodeType } from '@/components/FlowEditor/node'; import LocalNode from '@/components/FlowEditor/node/localNode/LocalNode'; import LoopNode from '@/components/FlowEditor/node/loopNode/LoopNode'; +import store from '@/store/index'; /** * 将提供的数据结构转换为适用于 flow editor 的 nodes 和 edges @@ -11,8 +12,9 @@ import LoopNode from '@/components/FlowEditor/node/loopNode/LoopNode'; export const convertFlowData = (flowData: any, useDefault = true) => { const nodes: any[] = []; const edges: any[] = []; + const currentProjectCompData = getCurrentProjectStoreData(); - if (!flowData || Object.keys(flowData).length === 0 || flowData.main.nodeConfigs.length === 0) { + if (!flowData || Object.keys(flowData).length === 0) { // 如果useDefault为true且flowData为空,则返回默认的开始和结束节点 if (useDefault) { return { @@ -55,167 +57,157 @@ export const convertFlowData = (flowData: any, useDefault = true) => { return { nodes, edges }; } - // 处理节点配置 - const nodeConfigs = flowData.main?.nodeConfigs || []; - for (const nodeConfig of nodeConfigs) { + // 处理新格式的数据结构 + // 先处理所有节点 + const nodeEntries = Object.entries(flowData); + + for (const entry of nodeEntries) { + const nodeId: string = entry[0]; + const nodeConfig: any = entry[1]; + // 确定节点类型 let nodeType = 'BASIC'; - if (nodeConfig.nodeId === 'start') { + if (nodeId === 'start') { nodeType = 'start'; } - else if (nodeConfig.nodeId === 'end') { + else if (nodeId === 'end') { nodeType = 'end'; } - else if (nodeConfig.component.type === 'LOOP_START' || nodeConfig.component.type === 'LOOP_END') { + else if (nodeConfig.component?.type === 'LOOP_START' || nodeConfig.component?.type === 'LOOP_END') { nodeType = 'LOOP'; } else { - nodeType = nodeConfig.component.type; + nodeType = nodeConfig.component?.type || 'BASIC'; } // 解析位置信息 - 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); - } - - // 构建循环节点的默认参数和外壳 - if (nodeType === 'LOOP') { - // 创建循环开始节点 - 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: '', - loopStartNodeId: loopStartNode.id // 这里的参数是为了提供在组件内部处理数据是使用,最后这个字段要序列化后放进customDef - } - } - }; - - loopStartNode.data.component = { - type: 'LOOP_START', - customDef: JSON.stringify({ loopEndNodeId: loopEndNode.id }) - }; - - // 将未定义的节点动态追加进nodeTypes - const nodeMap = Array.from(Object.values(nodeTypeMap).map(key => key)); - if (!nodeMap.includes('LOOP')) { - registerNodeType('LOOP', LoopNode, '循环'); - } - } - - console.log('nodeConfig:', nodeConfig); + const position = nodeConfig.position || { x: 0, y: 0 }; // 构造节点数据 const node: any = { - id: nodeConfig.nodeId, + id: nodeId, type: nodeType, position, data: { - title: nodeConfig.nodeName || nodeConfig.nodeId, + title: nodeConfig.componentName || nodeId, parameters: { - apiIns: [{ - name: buildNodeId(nodeConfig.nodeId,'in'), - id: buildNodeId(nodeConfig.nodeId,'in'), - desc: '', - dataType: '', - defaultValue: '' - }], - apiOuts: [{ - name: buildNodeId(nodeConfig.nodeId,'out'), - id: buildNodeId(nodeConfig.nodeId,'out'), - desc: '', - dataType: '', - defaultValue: '' - }], - dataIns: nodeConfig.dataIns?.map((input: any) => ({ - name: input.id, - id: input.id, - desc: input.desc, - dataType: input.dataType, - defaultValue: input.defaultValue - })) || [], - dataOuts: nodeConfig.dataOuts?.map((output: any) => ({ - name: output.id, - id: output.id, - desc: output.desc, - dataType: output.dataType, - defaultValue: output.defaultValue - })) || [] + apiIns: getNodeApiIns(nodeId, nodeConfig, currentProjectCompData), + apiOuts: getNodeApiOuts(nodeId, nodeConfig, currentProjectCompData), + dataIns: nodeConfig.dataIns || [], + dataOuts: nodeConfig.dataOuts || [] }, - type: nodeType === 'LOOP' ? nodeConfig.component.type : nodeType + type: nodeConfig.component?.type || nodeType } }; // 添加组件标识信息 if (nodeConfig.component) { - node.data.component = { - compIdentifier: nodeConfig.component.compIdentifier, - compInstanceIdentifier: nodeConfig.component.compInstanceIdentifier, - customDef: nodeConfig.component?.customDef, - type: nodeConfig.component.type - }; + node.data.component = { ...nodeConfig.component }; + node.data.compId = nodeConfig.component.compId; } - // 将未定义的节点动态追加进nodeTypes + // 注册循环节点类型 + if (nodeType === 'LOOP') { + const nodeMap = Array.from(Object.values(nodeTypeMap).map(key => key)); + if (!nodeMap.includes('LOOP')) { + registerNodeType('LOOP', LoopNode, '循环'); + } + } + + // 注册其他节点类型 const nodeMap = Array.from(Object.values(nodeTypeMap).map(key => key)); - // 目前默认添加的都是系统组件/本地组件 - if (!nodeMap.includes(nodeType)) registerNodeType(nodeType, LocalNode, nodeConfig.nodeName); + if (!nodeMap.includes(nodeType) && nodeType !== 'start' && nodeType !== 'end' && nodeType !== 'LOOP') { + registerNodeType(nodeType, LocalNode, nodeConfig.componentName); + } 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 - }; + // 用于存储已添加的边,避免重复 + const addedEdges = new Set(); + + // 处理连接关系 - 只处理下游连接,避免重复创建连接线 + for (const entry of nodeEntries) { + const nodeId: string = entry[0]; + const nodeConfig: any = entry[1]; + + // 处理 API 下游连接 + if (nodeConfig.apiDownstream && Array.isArray(nodeConfig.apiDownstream)) { + nodeConfig.apiDownstream.forEach((targetArray: string[]) => { + // 确保 targetArray 是数组并且包含字符串元素 + if (Array.isArray(targetArray)) { + targetArray.forEach(target => { + if (typeof target === 'string' && target.includes('$$')) { + const [targetNodeId, targetHandle] = target.split('$$'); + + // 动态获取源句柄,而不是使用默认值 + const sourceNode = flowData[nodeId]; + // 统一旧版本逻辑,开始节点的输出句柄是start + let sourceHandle = sourceNode.id === 'start' ? 'start' : 'done'; // 默认值 + if (sourceNode && sourceNode.component && sourceNode.component.type) { + // 根据节点类型获取正确的源句柄 + sourceHandle = getNodeApiOutHandle(nodeId, sourceNode); + } + else if (sourceNode && sourceNode.data && sourceNode.data.parameters && + sourceNode.data.parameters.apiOuts && sourceNode.data.parameters.apiOuts.length > 0) { + // 从apiOuts中获取第一个句柄 + sourceHandle = sourceNode.data.parameters.apiOuts[0].name || + sourceNode.data.parameters.apiOuts[0].id || sourceHandle; + } + + // 创建边的唯一标识符 + const edgeId = `${nodeId}-${targetNodeId}-${sourceHandle}-${targetHandle}`; + + // 检查是否已添加此边 + if (!addedEdges.has(edgeId)) { + addedEdges.add(edgeId); + edges.push({ + id: `${edgeId}`, + source: nodeId, + target: targetNodeId, + sourceHandle, + targetHandle + }); + } + } + }); + } + }); + } - edges.push(edge); + // 处理数据下游连接 + if (nodeConfig.dataDownstream && Array.isArray(nodeConfig.dataDownstream)) { + nodeConfig.dataDownstream.forEach((connectionGroup: string[]) => { + // 确保 connectionGroup 是数组并且至少包含两个元素 + if (Array.isArray(connectionGroup) && connectionGroup.length >= 2) { + // 第一个元素是源节点和句柄信息 + const [sourceInfo, targetInfo] = connectionGroup; + + if (typeof sourceInfo === 'string' && sourceInfo.includes('@@') && + typeof targetInfo === 'string' && targetInfo.includes('@@')) { + + const [sourceNodeId, sourceHandle] = sourceInfo.split('@@'); + const [targetNodeId, targetHandle] = targetInfo.split('@@'); + + // 创建边的唯一标识符 + const edgeId = `${sourceNodeId}-${targetNodeId}-${sourceHandle}-${targetHandle}`; + + // 检查是否已添加此边 + if (!addedEdges.has(edgeId)) { + addedEdges.add(edgeId); + + edges.push({ + id: `${edgeId}`, + source: sourceNodeId, + target: targetNodeId, + sourceHandle: sourceHandle, + targetHandle: targetHandle + }); + } + } + } + }); + } } return { nodes, edges }; @@ -269,7 +261,8 @@ export const revertFlowData = (nodes: any[], edges: any[]) => { nodeConfig.component = { type: nodeType, compIdentifier: node.data.component.compIdentifier || '', - compInstanceIdentifier: node.data.component.compInstanceIdentifier || '' + compInstanceIdentifier: node.data.component.compInstanceIdentifier || '', + compId: node.data.compId || '' }; if (node.data.component?.customDef) nodeConfig.component.customDef = node.data.component.customDef; } @@ -279,6 +272,7 @@ export const revertFlowData = (nodes: any[], edges: any[]) => { type: nodeType }; } + if (['BASIC'].includes(nodeType)) nodeConfig.component.compId = node.data.compId || ''; // 处理参数信息 const parameters = node.data?.parameters || {}; @@ -297,7 +291,7 @@ export const revertFlowData = (nodes: any[], edges: any[]) => { // 处理 dataOuts(输出数据) if (parameters.dataOuts && parameters.dataOuts.length > 0) { nodeConfig.dataOuts = parameters.dataOuts.map((output: any) => ({ - id: output.name, + id: output.name || output.id, desc: output.desc, dataType: output.dataType, defaultValue: output.defaultValue, @@ -309,7 +303,7 @@ export const revertFlowData = (nodes: any[], edges: any[]) => { }); } -// 转换连线数据 + // 转换连线数据 if (edges && edges.length > 0) { flowData.lineConfigs = edges.map((edge, index) => { // 查找源节点和目标节点以确定连线类型 @@ -324,11 +318,11 @@ export const revertFlowData = (nodes: any[], edges: any[]) => { } // 判断是否为API类型的连线 else if (edge.sourceHandle && (edge.sourceHandle === 'apiOuts' || - sourceNode?.data?.parameters?.apiOuts?.some((out: any) => out.name === edge.sourceHandle))) { + sourceNode?.data?.parameters?.apiOuts?.some((out: any) => (out.name || out.id) === edge.sourceHandle))) { lineType = 'API'; } else if (edge.targetHandle && (edge.targetHandle === 'apiIns' || - targetNode?.data?.parameters?.apiIns?.some((inp: any) => inp.name === edge.targetHandle))) { + targetNode?.data?.parameters?.apiIns?.some((inp: any) => (inp.name || inp.id) === edge.targetHandle))) { lineType = 'API'; } @@ -350,19 +344,139 @@ export const revertFlowData = (nodes: any[], edges: any[]) => { return flowData; }; +// 获取节点的API输入参数 +const getNodeApiIns = (nodeId: string, nodeConfig: any, currentProjectCompData: any[]) => { + // 对于特定类型的节点使用预定义值 + if (nodeConfig.component?.type === 'LOOP_START') { + return [{ name: 'start', desc: '', dataType: '', defaultValue: '' }]; + } + else if (nodeConfig.component?.type === 'LOOP_END') { + return [{ name: 'continue', desc: '', dataType: '', defaultValue: '' }]; + } + else if (nodeId === 'end') { + return [{ name: 'end', desc: '', dataType: '', defaultValue: '' }]; + } + else { + const comp = currentProjectCompData.filter(item => item.id === nodeConfig?.component?.compId); + if (comp && comp.length > 0) { + return comp[0].def.apis.map(v => { + return { + ...v, + name: v.id, + desc: v.desc, + dataType: v?.dataType || '', + defaultValue: v?.defaultValue || '' + }; + }); + } + else { + return [{ name: 'start', desc: '', dataType: '', defaultValue: '' }]; + } + } +}; -// 通过nodeType先区分是否需要使用特殊nodeId,不需要就正常分类开始结束的句柄id -const buildNodeId = (nodeId, type) => { - if (nodeId.includes('LOOP_START')) { - if (type === 'in') return 'start'; - else return 'done'; +// 获取节点的API输出参数 +const getNodeApiOuts = (nodeId: string, nodeConfig: any, currentProjectCompData: any[]) => { + // 对于特定类型的节点使用预定义值 + if (nodeConfig.component?.type === 'LOOP_START') { + return [{ name: 'done', desc: '', dataType: '', defaultValue: '' }]; } - else if (nodeId.includes('LOOP_END')) { - if (type === 'in') return 'continue'; - else return 'break'; + else if (nodeConfig.component?.type === 'LOOP_END') { + return [{ name: 'break', desc: '', dataType: '', defaultValue: '' }]; + } + else if (nodeId === 'start') { + return [{ name: 'start', desc: '', dataType: '', defaultValue: '' }]; } else { - if (type === 'in') return 'start'; - else return nodeId === 'end' ? 'end' : 'done'; + const comp = currentProjectCompData.filter(item => item.id === nodeConfig?.component?.compId); + if (comp && comp.length > 0) { + return [{ + ...comp[0].def.apiOut, + dataType: '', + defaultValue: '' + }]; + } + else { + return [{ name: 'done', desc: '', dataType: '', defaultValue: '' }]; + } } + }; + +// 获取节点的API输出句柄名称 +const getNodeApiOutHandle = (nodeId: string, nodeConfig: any) => { + if (nodeConfig.component?.type === 'LOOP_START') { + return 'done'; + } + else if (nodeConfig.component?.type === 'LOOP_END') { + return 'break'; + } + else if (nodeId === 'start') { + return 'start'; + } + else if (nodeId === 'end') { + return 'end'; + } + return 'done'; +}; + +// 获取当前工程下组件列表并扁平化处理 +const getCurrentProjectStoreData = () => { + const { info, projectComponentData } = store.getState().ideContainer; + const compData = projectComponentData[info?.id] || {}; + + const result: any[] = []; + + // 处理projectCompDto中的数据 + if (compData.projectCompDto) { + const { mineComp = [], pubComp = [], teamWorkComp = [] } = compData.projectCompDto; + + // 添加mineComp数据 + mineComp.forEach((item: any) => { + result.push({ + ...item, + type: 'mineComp' + }); + }); + + // 添加pubComp数据 + pubComp.forEach((item: any) => { + result.push({ + ...item, + type: 'pubComp' + }); + }); + + // 添加teamWorkComp数据 + teamWorkComp.forEach((item: any) => { + result.push({ + ...item, + type: 'teamWorkComp' + }); + }); + } + + // 处理projectFlowDto中的数据 + if (compData.projectFlowDto) { + const { mineFlow = [], pubFlow = [] } = compData.projectFlowDto; + + // 添加mineFlow数据 + mineFlow.forEach((item: any) => { + result.push({ + ...item, + type: 'mineFlow' + }); + }); + + // 添加pubFlow数据 + pubFlow.forEach((item: any) => { + result.push({ + ...item, + type: 'pubFlow' + }); + }); + } + + return result; + +}; \ No newline at end of file