|
|
|
|
@ -7,7 +7,7 @@ import {
|
|
|
|
|
Node,
|
|
|
|
|
Edge
|
|
|
|
|
} from '@xyflow/react';
|
|
|
|
|
import { refPublish, setMainFlow, setMainFlowNew } from '@/api/appRes';
|
|
|
|
|
import { refPublish, setMainFlow, setMainFlowNew, setSubFlowNew } from '@/api/appRes';
|
|
|
|
|
import { Message } from '@arco-design/web-react';
|
|
|
|
|
import { nodeTypeMap, registerNodeType } from '@/components/FlowEditor/node';
|
|
|
|
|
import { convertFlowData, reverseConvertFlowData, revertFlowData } from '@/utils/convertFlowData';
|
|
|
|
|
@ -15,7 +15,7 @@ import { localNodeData } from '@/pages/flowEditor/sideBar/config/localNodeData';
|
|
|
|
|
import { useAlignmentGuidelines } from '@/hooks/useAlignmentGuidelines';
|
|
|
|
|
import LocalNode from '@/components/FlowEditor/node/localNode/LocalNode';
|
|
|
|
|
import LoopNode from '@/components/FlowEditor/node/loopNode/LoopNode';
|
|
|
|
|
import { updateCanvasDataMap, resetNodeStatus, updateIsRunning } from '@/store/ideContainer';
|
|
|
|
|
import { updateCanvasDataMap, resetNodeStatus, updateIsRunning, updateEventListOld } from '@/store/ideContainer';
|
|
|
|
|
import {
|
|
|
|
|
validateAllNodes,
|
|
|
|
|
showValidationErrors,
|
|
|
|
|
@ -30,9 +30,11 @@ import { projectFlowHandle } from '@/pages/flowEditor/utils/projectFlowHandle';
|
|
|
|
|
import { appFLowHandle } from '@/pages/flowEditor/utils/appFlowhandle';
|
|
|
|
|
|
|
|
|
|
import { Dispatch } from 'redux';
|
|
|
|
|
import { runMainFlow } from '@/api/apps';
|
|
|
|
|
import { runMainFlow, stopApp } from '@/api/apps';
|
|
|
|
|
import store from '@/store';
|
|
|
|
|
import { updateAppEvent } from '@/api/appEvent';
|
|
|
|
|
import { updateAppEvent, updateAppEventChannel, updateAppFlowData } from '@/api/appEvent';
|
|
|
|
|
import { sleep } from '@/utils/common';
|
|
|
|
|
import { queryEventItemBySceneIdOld } from '@/api/event';
|
|
|
|
|
|
|
|
|
|
export const useFlowCallbacks = (
|
|
|
|
|
nodes: Node[],
|
|
|
|
|
@ -93,6 +95,7 @@ export const useFlowCallbacks = (
|
|
|
|
|
}, 100);
|
|
|
|
|
}
|
|
|
|
|
}, [nodes, edges]);
|
|
|
|
|
|
|
|
|
|
// 边变更处理
|
|
|
|
|
const onEdgesChange = useCallback((changes: any) => {
|
|
|
|
|
const newEdges = applyEdgeChanges(changes, edges);
|
|
|
|
|
@ -121,8 +124,8 @@ export const useFlowCallbacks = (
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取源节点和目标节点的参数信息
|
|
|
|
|
const sourceParams = sourceNode.data?.parameters || {};
|
|
|
|
|
const targetParams = targetNode.data?.parameters || {};
|
|
|
|
|
const sourceParams: any = sourceNode.data?.parameters || {};
|
|
|
|
|
const targetParams: any = targetNode.data?.parameters || {};
|
|
|
|
|
|
|
|
|
|
// 获取源handle和目标handle的类型 (api或data)
|
|
|
|
|
const sourceHandleType = getHandleType(params.sourceHandle, sourceParams);
|
|
|
|
|
@ -142,7 +145,52 @@ export const useFlowCallbacks = (
|
|
|
|
|
|
|
|
|
|
// 如果验证通过,创建连接
|
|
|
|
|
setEdges((edgesSnapshot: Edge[]) => {
|
|
|
|
|
const newEdges = addEdge({ ...params, type: 'custom' }, edgesSnapshot);
|
|
|
|
|
// 创建带有事件信息的连接
|
|
|
|
|
const edgeParams = { ...params, type: 'custom' };
|
|
|
|
|
|
|
|
|
|
// 检查源节点和目标节点是否都有事件信息
|
|
|
|
|
const sourceApi = (sourceParams.apiOuts || []).find((api: any) =>
|
|
|
|
|
api.name === params.sourceHandle || api.id === params.sourceHandle);
|
|
|
|
|
const targetApi = (targetParams.apiIns || []).find((api: any) =>
|
|
|
|
|
api.name === params.targetHandle || api.id === params.targetHandle);
|
|
|
|
|
|
|
|
|
|
// 如果源节点有事件topic信息
|
|
|
|
|
if (sourceApi && sourceApi.topic) {
|
|
|
|
|
// 如果目标节点的topic是**empty**或没有topic,则使用源节点的事件信息
|
|
|
|
|
if (!targetApi || !targetApi.topic || targetApi.topic.includes('**empty**')) {
|
|
|
|
|
edgeParams.data = {
|
|
|
|
|
displayData: {
|
|
|
|
|
name: sourceApi.name,
|
|
|
|
|
eventId: sourceApi.eventId,
|
|
|
|
|
topic: sourceApi.topic
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
// 如果两个节点都有非empty的topic,则以源节点为准
|
|
|
|
|
else if (sourceApi.topic && targetApi.topic &&
|
|
|
|
|
!sourceApi.topic.includes('**empty**') &&
|
|
|
|
|
!targetApi.topic.includes('**empty**')) {
|
|
|
|
|
edgeParams.data = {
|
|
|
|
|
displayData: {
|
|
|
|
|
name: sourceApi.name,
|
|
|
|
|
eventId: sourceApi.eventId,
|
|
|
|
|
topic: sourceApi.topic
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 如果源节点没有事件信息,但目标节点有
|
|
|
|
|
else if (targetApi && targetApi.topic && !targetApi.topic.includes('**empty**')) {
|
|
|
|
|
edgeParams.data = {
|
|
|
|
|
displayData: {
|
|
|
|
|
name: targetApi.name,
|
|
|
|
|
eventId: targetApi.eventId,
|
|
|
|
|
topic: targetApi.topic
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const newEdges = addEdge(edgeParams, edgesSnapshot);
|
|
|
|
|
|
|
|
|
|
// 连接建立后记录历史
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
@ -433,7 +481,6 @@ export const useFlowCallbacks = (
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
localStorage.setItem('copiedNode', JSON.stringify(nodeData));
|
|
|
|
|
console.log('复制节点:', node);
|
|
|
|
|
}, [initialData?.appId]);
|
|
|
|
|
|
|
|
|
|
// 粘贴节点
|
|
|
|
|
@ -958,7 +1005,7 @@ export const useFlowCallbacks = (
|
|
|
|
|
const emptyEvent = eventList.find(item => item.topic.includes('**empty**'));
|
|
|
|
|
newNode.data.component = {
|
|
|
|
|
type: nodeType,
|
|
|
|
|
customDef: { eventId: emptyEvent.id, name: emptyEvent.name, topic: emptyEvent.topic }
|
|
|
|
|
customDef: { eventId: emptyEvent?.eventId ?? null, name: emptyEvent.name, topic: emptyEvent.topic }
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
// 将未定义的节点动态追加进nodeTypes
|
|
|
|
|
@ -1001,7 +1048,7 @@ export const useFlowCallbacks = (
|
|
|
|
|
// endregion
|
|
|
|
|
|
|
|
|
|
// 保存所有节点和边数据到服务器,更新事件相关数据
|
|
|
|
|
const updateEvent = (revertedData) => {
|
|
|
|
|
const updateEvent = (revertedData, appid) => {
|
|
|
|
|
// 初始化参数对象
|
|
|
|
|
const params: any = {
|
|
|
|
|
eventListenes: [],
|
|
|
|
|
@ -1034,28 +1081,31 @@ export const useFlowCallbacks = (
|
|
|
|
|
// 事件接收节点
|
|
|
|
|
params.eventListenes.push({
|
|
|
|
|
nodeName: nodeConfig.nodeName || '',
|
|
|
|
|
eventId: eventConfig?.eventId || '',
|
|
|
|
|
eventId: eventConfig?.eventId || null,
|
|
|
|
|
topic: eventConfig?.topic || '',
|
|
|
|
|
eventName: eventConfig?.name || '',
|
|
|
|
|
dataOuts: nodeConfig.dataOuts || []
|
|
|
|
|
dataOuts: nodeConfig.dataOuts || [],
|
|
|
|
|
nodeId: nodeConfig.nodeId
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else if (nodeType === 'EVENTSEND') {
|
|
|
|
|
// 事件发送节点
|
|
|
|
|
params.eventSends.push({
|
|
|
|
|
nodeName: nodeConfig.nodeName || '',
|
|
|
|
|
eventId: eventConfig?.eventId || '',
|
|
|
|
|
eventId: eventConfig?.eventId || null,
|
|
|
|
|
topic: eventConfig?.topic || '',
|
|
|
|
|
eventName: eventConfig?.name || '',
|
|
|
|
|
dataIns: nodeConfig.dataIns || []
|
|
|
|
|
dataIns: nodeConfig.dataIns || [],
|
|
|
|
|
nodeId: nodeConfig.nodeId
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
// 调用更新事件的API
|
|
|
|
|
if (params.eventListenes.lengrh > 0 || params.eventSends.length > 0) {
|
|
|
|
|
updateAppEvent(initialData.appId, params);
|
|
|
|
|
if (params.eventListenes.length > 0 || params.eventSends.length > 0) {
|
|
|
|
|
return params;
|
|
|
|
|
}
|
|
|
|
|
else return null;
|
|
|
|
|
};
|
|
|
|
|
const upDatePublish = async (revertedData) => {
|
|
|
|
|
const { currentAppData } = store.getState().ideContainer;
|
|
|
|
|
@ -1093,25 +1143,48 @@ export const useFlowCallbacks = (
|
|
|
|
|
const revertedData = revertFlowData(nodes, edges);
|
|
|
|
|
const upDatePublishCB = await upDatePublish(revertedData.nodeConfigs);
|
|
|
|
|
const newRevertedData = reverseConvertFlowData(nodes, edges, upDatePublishCB);
|
|
|
|
|
const { flowData, currentAppData } = store.getState().ideContainer;
|
|
|
|
|
// console.log('revertedData:', revertedData);
|
|
|
|
|
// console.log('newRevertedData:', newRevertedData);
|
|
|
|
|
const params = {
|
|
|
|
|
const { flowData, currentAppData, info } = store.getState().ideContainer;
|
|
|
|
|
let params = {};
|
|
|
|
|
// 更新复合组件/子流程
|
|
|
|
|
if (currentAppData.key.includes('sub')) {
|
|
|
|
|
const appEventDefinition = updateEvent(revertedData.nodeConfigs, initialData.appId);
|
|
|
|
|
params = {
|
|
|
|
|
...currentAppData?.compData || {},
|
|
|
|
|
components: newRevertedData,
|
|
|
|
|
appEventDefinition,
|
|
|
|
|
sceneId: info.id
|
|
|
|
|
};
|
|
|
|
|
const res: any = await setSubFlowNew(params, currentAppData.parentAppId);
|
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
Message.success('保存成功');
|
|
|
|
|
// 更新事件枚举表
|
|
|
|
|
const res1: any = await queryEventItemBySceneIdOld(info.id);
|
|
|
|
|
if (res1.code === 200) dispatch(updateEventListOld(res1.data));
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
Message.error(res.message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 更新主流程
|
|
|
|
|
else {
|
|
|
|
|
const appEventDefinition = updateEvent(revertedData.nodeConfigs, initialData.appId);
|
|
|
|
|
params = {
|
|
|
|
|
...flowData[currentAppData.id]?.main || {},
|
|
|
|
|
components: newRevertedData
|
|
|
|
|
components: newRevertedData,
|
|
|
|
|
appEventDefinition,
|
|
|
|
|
sceneId: info.id
|
|
|
|
|
};
|
|
|
|
|
// return;
|
|
|
|
|
updateEvent(revertedData.nodeConfigs);
|
|
|
|
|
// 旧版数据结构
|
|
|
|
|
// const res: any = await setMainFlow(revertedData, initialData.appId);
|
|
|
|
|
// 新版数据结构
|
|
|
|
|
const res: any = await setMainFlowNew(params, initialData.appId);
|
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
Message.success('保存成功');
|
|
|
|
|
// 更新事件枚举表
|
|
|
|
|
const res1: any = await queryEventItemBySceneIdOld(info.id);
|
|
|
|
|
if (res1.code === 200) dispatch(updateEventListOld(res1.data));
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
Message.error(res.message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error saving flow data:', error);
|
|
|
|
|
Message.error('保存失败');
|
|
|
|
|
@ -1122,13 +1195,56 @@ export const useFlowCallbacks = (
|
|
|
|
|
nodes,
|
|
|
|
|
edges
|
|
|
|
|
};
|
|
|
|
|
console.log('params:', params);
|
|
|
|
|
const appFlowParams = {
|
|
|
|
|
appEventList: {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
nodes.forEach(node => {
|
|
|
|
|
appFlowParams.appEventList[node.id] = {
|
|
|
|
|
x: node.position.x,
|
|
|
|
|
y: node.position.y
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const eventMap = new Map();
|
|
|
|
|
edges.forEach((edge: any) => {
|
|
|
|
|
// 应用组件的桩点id就是事件id
|
|
|
|
|
const sourceId = edge.sourceHandle;
|
|
|
|
|
const targetId = edge.targetHandle;
|
|
|
|
|
const topic = edge.data.displayData.topic;
|
|
|
|
|
|
|
|
|
|
if (eventMap.has(topic)) {
|
|
|
|
|
// 如果topic已存在,将eventId添加到数组中
|
|
|
|
|
eventMap.get(topic).eventId.push(sourceId);
|
|
|
|
|
eventMap.get(topic).eventId.push(targetId);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// 如果topic不存在,创建新的条目
|
|
|
|
|
eventMap.set(topic, {
|
|
|
|
|
eventId: [sourceId, targetId],
|
|
|
|
|
topic: topic
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
// 对eventId数组进行去重处理
|
|
|
|
|
const appEventParams = Array.from(eventMap.values()).map(item => ({
|
|
|
|
|
...item,
|
|
|
|
|
eventId: Array.from(new Set(item.eventId))
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
updateAppFlowData(appFlowParams);
|
|
|
|
|
if (appEventParams.length > 0) {
|
|
|
|
|
for (const item of appEventParams) {
|
|
|
|
|
await sleep(500);
|
|
|
|
|
updateAppEventChannel(item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}, [nodes, edges, initialData?.appId]);
|
|
|
|
|
// 运行处理函数
|
|
|
|
|
const handleRun = useCallback(async (running: boolean) => {
|
|
|
|
|
if (running) {
|
|
|
|
|
const { currentAppData, socketId } = store.getState().ideContainer;
|
|
|
|
|
if (running) {
|
|
|
|
|
// 启动运行
|
|
|
|
|
const params = {
|
|
|
|
|
appId: currentAppData.id,
|
|
|
|
|
@ -1156,6 +1272,8 @@ export const useFlowCallbacks = (
|
|
|
|
|
// 设置运行状态为false
|
|
|
|
|
dispatch(updateIsRunning(false));
|
|
|
|
|
|
|
|
|
|
stopApp(currentAppData.id);
|
|
|
|
|
|
|
|
|
|
// 停止运行
|
|
|
|
|
setEdges((eds) => eds.map(edge => ({
|
|
|
|
|
...edge,
|
|
|
|
|
|