From 225776d99a0d2bbbf929f4651b04010c064ee712 Mon Sep 17 00:00:00 2001 From: ZLY Date: Thu, 23 Oct 2025 10:30:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(flow):=20=E6=96=B0=E5=A2=9E=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E6=95=B0=E6=8D=AE=E5=8F=8D=E5=90=91=E8=BD=AC=E6=8D=A2?= =?UTF-8?q?=E4=B8=8E=E6=9B=B4=E6=96=B0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/appRes.ts | 5 ++ src/hooks/useFlowCallbacks.ts | 31 ++++++--- src/utils/convertFlowData.ts | 118 ++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+), 10 deletions(-) diff --git a/src/api/appRes.ts b/src/api/appRes.ts index af9c356..8e40c69 100644 --- a/src/api/appRes.ts +++ b/src/api/appRes.ts @@ -20,6 +20,11 @@ export function setMainFlow(data: FlowDefinition, appId: string) { return axios.post(`${urlPrefix}/appRes/${appId}/updateMain`, data); } +// 更新主流程-新数据结构 +export function setMainFlowNew(data: FlowDefinition, appId: string) { + return axios.post(`${urlPrefix}/appRes/${appId}/updateMainNew`, data); +} + // 新增子流程 export function addSub(appId: string, data?: FlowDefinition[]) { return axios.post( diff --git a/src/hooks/useFlowCallbacks.ts b/src/hooks/useFlowCallbacks.ts index 5e16544..e54cdff 100644 --- a/src/hooks/useFlowCallbacks.ts +++ b/src/hooks/useFlowCallbacks.ts @@ -7,10 +7,10 @@ import { Node, Edge } from '@xyflow/react'; -import { setMainFlow } from '@/api/appRes'; +import { setMainFlow, setMainFlowNew } from '@/api/appRes'; import { Message } from '@arco-design/web-react'; import { nodeTypeMap, registerNodeType } from '@/components/FlowEditor/node'; -import { convertFlowData, revertFlowData } from '@/utils/convertFlowData'; +import { convertFlowData, reverseConvertFlowData, revertFlowData } from '@/utils/convertFlowData'; import { localNodeData } from '@/pages/flowEditor/sideBar/config/localNodeData'; import { useAlignmentGuidelines } from '@/hooks/useAlignmentGuidelines'; import LocalNode from '@/components/FlowEditor/node/localNode/LocalNode'; @@ -843,6 +843,7 @@ export const useFlowCallbacks = ( if (nodeType === 'EVENTLISTENE') { // 事件接收节点 params.eventListenes.push({ + nodeName: nodeConfig.nodeName || '', eventId: eventConfig?.eventId || '', topic: eventConfig?.topic || '', eventName: eventConfig?.name || '', @@ -852,6 +853,7 @@ export const useFlowCallbacks = ( else if (nodeType === 'EVENTSEND') { // 事件发送节点 params.eventSends.push({ + nodeName: nodeConfig.nodeName || '', eventId: eventConfig?.eventId || '', topic: eventConfig?.topic || '', eventName: eventConfig?.name || '', @@ -860,9 +862,8 @@ export const useFlowCallbacks = ( } } }); - // 调用更新事件的API - if (initialData?.appId && params.eventListenes.lengrh > 0 && params.eventSends.length > 0) { + if (params.eventListenes.lengrh > 0 || params.eventSends.length > 0) { updateAppEvent(initialData.appId, params); } }; @@ -885,11 +886,21 @@ export const useFlowCallbacks = ( // 转换会原始数据类型 const revertedData = revertFlowData(nodes, edges); - console.log('revertedData(中断):', revertedData); + const newRevertedData = reverseConvertFlowData(nodes, edges); + const { flowData, currentAppData } = store.getState().ideContainer; + // console.log('revertedData(中断):', revertedData); + // console.log('newRevertedData(中断):', newRevertedData); + const params = { + ...flowData[currentAppData.id]?.main || {}, + components: newRevertedData + }; // return; updateEvent(revertedData.nodeConfigs); - const res: any = await setMainFlow(revertedData, initialData.appId); + // 旧版数据结构 + // const res: any = await setMainFlow(revertedData, initialData.appId); + // 新版数据结构 + const res: any = await setMainFlowNew(params, initialData.appId); if (res.code === 200) { Message.success('保存成功'); } @@ -919,13 +930,13 @@ export const useFlowCallbacks = ( socketId }; runMainFlow(params); - + // 设置运行状态为true dispatch(updateIsRunning(true)); - + // 重置节点状态 dispatch(resetNodeStatus()); - + // 开始运行时动画 setEdges((eds) => eds.map(edge => ({ ...edge, @@ -939,7 +950,7 @@ export const useFlowCallbacks = ( else { // 设置运行状态为false dispatch(updateIsRunning(false)); - + // 停止运行 setEdges((eds) => eds.map(edge => ({ ...edge, diff --git a/src/utils/convertFlowData.ts b/src/utils/convertFlowData.ts index 95cad7b..39f5e8c 100644 --- a/src/utils/convertFlowData.ts +++ b/src/utils/convertFlowData.ts @@ -468,6 +468,121 @@ export const revertFlowData = (nodes: any[], edges: any[]) => { return flowData; }; +/** + * 将 React Flow 的 nodes 和 edges 数据结构反向转换为 convertFlowData 可以处理的格式 + * @param nodes - React Flow 节点数组 + * @param edges - React Flow 边数组 + * @returns 可用于 convertFlowData 的数据结构 + */ +export const reverseConvertFlowData = (nodes: any[], edges: any[]) => { + // 初始化返回的数据结构 + const flowData: any = {}; + + // 转换节点数据 + if (nodes && nodes.length > 0) { + nodes.forEach(node => { + const nodeId = node.id; + + // 构造节点配置对象 + const nodeConfig: any = { + id: nodeId, + componentName: node.data?.title || nodeId, + position: node.position || { x: 0, y: 0 } + }; + + // 处理 component 信息 + if (node.data?.component) { + nodeConfig.component = { ...node.data.component }; + } + else { + nodeConfig.component = null; + } + + // 处理参数信息 + const parameters = node.data?.parameters || {}; + + // 处理 apiIns(输入API) + if (parameters.apiIns && parameters.apiIns.length > 0) { + nodeConfig.apiIns = parameters.apiIns; + } + else { + nodeConfig.apiIns = []; + } + + // 处理 apiOuts(输出API) + if (parameters.apiOuts && parameters.apiOuts.length > 0) { + nodeConfig.apiOuts = parameters.apiOuts; + } + else { + nodeConfig.apiOuts = []; + } + + // 处理 dataIns(输入数据) + if (parameters.dataIns && parameters.dataIns.length > 0) { + nodeConfig.dataIns = parameters.dataIns; + } + else { + nodeConfig.dataIns = []; + } + + // 处理 dataOuts(输出数据) + if (parameters.dataOuts && parameters.dataOuts.length > 0) { + nodeConfig.dataOuts = parameters.dataOuts; + } + else { + nodeConfig.dataOuts = []; + } + + // 初始化连接数组 + nodeConfig.apiDownstream = []; + nodeConfig.apiUpstream = []; + nodeConfig.dataDownstream = []; + nodeConfig.dataUpstream = []; + + // 将节点配置添加到 flowData 对象中 + flowData[nodeId] = nodeConfig; + }); + } + + // 处理连接关系 + if (edges && edges.length > 0) { + // 分析边的连接关系 + edges.forEach(edge => { + const sourceNode = edge.source; + const targetNode = edge.target; + const sourceHandle = edge.sourceHandle || 'done'; + const targetHandle = edge.targetHandle || 'start'; + + // 确定连接类型(API 还是 DATA) + const sourceNodeData = nodes.find(n => n.id === sourceNode); + const targetNodeData = nodes.find(n => n.id === targetNode); + + const isApiConnection = + (sourceNodeData?.data?.parameters?.apiOuts?.some((out: any) => out.name === sourceHandle)) || + (targetNodeData?.data?.parameters?.apiIns?.some((inp: any) => inp.name === targetHandle)) || + sourceHandle === 'start' || targetHandle === 'end' || + sourceHandle === 'end' || targetHandle === 'start'; + + if (isApiConnection) { + // API 连接 + // 添加下游连接 + flowData[sourceNode].apiDownstream.push([`${targetNode}$$${targetHandle}`]); + + // 添加上游连接 + flowData[targetNode].apiUpstream.push([`${sourceNode}$$${sourceHandle}`]); + } + else { + // 数据连接 + const dataConnection = [`${sourceNode}@@${sourceHandle}`, `${targetNode}@@${targetHandle}`]; + flowData[sourceNode].dataDownstream.push(dataConnection); + flowData[targetNode].dataUpstream.push(dataConnection); + } + }); + } + + return flowData; +}; + // 获取节点的API输入参数 const getNodeApiIns = (nodeId: string, nodeConfig: any, currentProjectCompData: any[]) => { // 对于特定类型的节点使用预定义值 @@ -562,6 +677,9 @@ const getNodeApiOuts = (nodeId: string, nodeConfig: any, currentProjectCompData: else if (nodeId === 'start') { return [{ name: 'start', desc: '', dataType: '', defaultValue: '' }]; } + else if (nodeId === 'end') { + return []; + } else { const comp = currentProjectCompData.filter(item => item.id === nodeConfig?.component?.compId); if (comp && comp.length > 0) {