diff --git a/src/components/FlowEditor/node/localNode/LocalNode.tsx b/src/components/FlowEditor/node/localNode/LocalNode.tsx
index 1356e72..f50b77d 100644
--- a/src/components/FlowEditor/node/localNode/LocalNode.tsx
+++ b/src/components/FlowEditor/node/localNode/LocalNode.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import { useStore } from '@xyflow/react';
import styles from '@/components/FlowEditor/node/style/baseOther.module.less';
import DynamicIcon from '@/components/DynamicIcon';
-import NodeContentOther from '@/pages/flowEditor/components/nodeContentOther';
+import NodeContentLocal from '@/pages/flowEditor/components/nodeContentLocal';
import NodeStatusIndicator, { NodeStatus } from '@/components/FlowEditor/NodeStatusIndicator';
import { useStore as useFlowStore } from '@xyflow/react';
@@ -83,7 +83,7 @@ const LocalNode = ({ data, id }: { data: any; id: string }) => {
{title}
-
+
);
};
diff --git a/src/pages/flowEditor/components/nodeContentLocal.tsx b/src/pages/flowEditor/components/nodeContentLocal.tsx
new file mode 100644
index 0000000..2495080
--- /dev/null
+++ b/src/pages/flowEditor/components/nodeContentLocal.tsx
@@ -0,0 +1,318 @@
+import React from 'react';
+import styles from '@/components/FlowEditor/node/style/baseOther.module.less';
+import { Handle, Position, useStore } from '@xyflow/react';
+import { deserializeValue, formatDataType, isJSON } from '@/utils/common';
+import cronstrue from 'cronstrue/i18n';
+import { useSelector } from 'react-redux';
+
+interface NodeContentData {
+ parameters?: {
+ dataIns?: any[];
+ dataOuts?: any[];
+ apiIns?: any[];
+ apiOuts?: any[];
+ };
+ showFooter?: boolean;
+ type?: string;
+
+ [key: string]: any;
+}
+
+// 定义通用的句柄样式
+const handleStyles = {
+ mainSource: {
+ background: '#2290f6',
+ width: '8px',
+ height: '8px',
+ border: '2px solid #fff',
+ boxShadow: '0 0 4px rgba(0,0,0,0.2)'
+ },
+ mainTarget: {
+ background: '#2290f6',
+ width: '8px',
+ height: '8px',
+ border: '2px solid #fff',
+ boxShadow: '0 0 4px rgba(0,0,0,0.2)'
+ },
+ data: {
+ background: '#555',
+ width: '6px',
+ height: '6px',
+ border: '1px solid #fff',
+ boxShadow: '0 0 2px rgba(0,0,0,0.2)'
+ }
+};
+
+// 渲染特殊节点(开始/结束节点)的句柄
+const renderSpecialNodeHandles = (isStartNode: boolean, isEndNode: boolean, dataIns: any[], dataOuts: any[], apiIns: any[], apiOuts: any[]) => {
+ const renderStartNodeHandles = () => {
+ if (!isStartNode) return null;
+
+ return (
+ <>
+ {apiOuts.map((_, index) => (
+
+ ))}
+ {dataOuts.length > 0 && dataOuts.map((_, index) => (
+
+ ))}
+ >
+ );
+ };
+
+ const renderEndNodeHandles = () => {
+ if (!isEndNode) return null;
+
+ return (
+ <>
+ {apiIns.map((_, index) => (
+
+ ))}
+ {dataIns.length > 0 && dataIns.map((_, index) => (
+
+ ))}
+ >
+ );
+ };
+
+ return (
+ <>
+ {renderStartNodeHandles()}
+ {renderEndNodeHandles()}
+ >
+ );
+};
+
+// 渲染普通节点的句柄
+const renderRegularNodeHandles = (dataIns: any[], dataOuts: any[], apiIns: any[], apiOuts: any[]) => {
+ return (
+ <>
+ {apiOuts.map((_, index) => (
+
+ ))}
+ {apiIns.map((_, index) => (
+
+ ))}
+
+ {/* 输入参数连接端点 */}
+ {dataIns.map((_, index) => (
+
+ ))}
+
+ {/* 输出参数连接端点 */}
+ {dataOuts.map((_, index) => (
+
+ ))}
+ >
+ );
+};
+
+const formatFooter = (data: any, eventListOld = []) => {
+ try {
+ switch (data?.type) {
+ case 'WAIT':
+ const { duration } = deserializeValue(data.customDef);
+ const hours = Math.floor(duration / 3600);
+ const minutes = Math.floor((duration % 3600) / 60);
+ const seconds = Math.floor(duration % 60);
+ return `${hours}小时${minutes}分钟${seconds}秒`;
+ case 'CYCLE':
+ const { intervalSeconds } = deserializeValue(data.customDef);
+ return cronstrue.toString(intervalSeconds, { locale: 'zh_CN' });
+ case 'EVENTSEND':
+ case 'EVENTLISTENE':
+ const parsedData = isJSON(data.customDef) ? JSON.parse(data.customDef) : null;
+ // 数据是JSON字符串,标识是接口回来的,数据是普通对象标识是当前操作
+ if (parsedData) {
+ const { eventId, topic, name } = parsedData;
+ if (topic.includes('**empty**')) return '';
+ const currentEvent = eventListOld.length > 0 ? eventListOld.find(item => item.eventId === eventId) : { name: '无' };
+ return `事件: ${currentEvent.name}`;
+ }
+ else {
+ const { name, topic } = data.customDef;
+ if (topic.includes('**empty**')) return '';
+ return `事件: ${name}`;
+ }
+ case 'BASIC':
+ return data.compIdentifier ? `当前实例:${data.compIdentifier}` : '';
+ default:
+ return '';
+ }
+ } catch (e) {
+ console.log(e);
+ }
+};
+
+const formatTitle = (text) => {
+ return text === 'start' || text === 'end' ? '' : text;
+};
+
+const NodeContentLocal = ({ data }: { data: NodeContentData }) => {
+ const { eventListOld } = useSelector((state) => state.ideContainer);
+ const apiIns = data.parameters?.apiIns || [];
+ const apiOuts = data.parameters?.apiOuts || [];
+ const dataIns = data.parameters?.dataIns || [];
+ const dataOuts = data.parameters?.dataOuts || [];
+ const showFooter = formatFooter(data.component) || false;
+ const footerData = (showFooter && data.component) || {};
+
+ // 判断节点类型
+ const isStartNode = data.type === 'start';
+ const isEndNode = data.type === 'end';
+ const isSpecialNode = isStartNode || isEndNode;
+
+ return (
+ <>
+ {/*content栏-api部分*/}
+
+
+ {apiIns.length > 0 && (
+
+ {apiIns.map((input, index) => (
+
+ {formatTitle(input.desc || input.id || input.name)}
+
+ ))}
+
+ )}
+
+ {apiOuts.length > 0 && (
+
+ {apiOuts.map((output, index) => (
+
+ {output.desc}
+
+ ))}
+
+ )}
+
+
+ {(dataIns.length > 0 || dataOuts.length > 0) && (
+ <>
+ {/*分割*/}
+
+
+
+
+ {/*content栏-data部分*/}
+
+
+
+ {dataIns.map((input, index) => (
+
+ {input.id || `输入${index + 1}`} {formatDataType(input.dataType)}
+
+
+ ))}
+
+
+ {dataOuts.length > 0 && !isEndNode && (
+
+ {dataOuts.map((output, index) => (
+
+ {formatDataType(output.dataType)} {output.id || `输出${index + 1}`}
+
+
+ ))}
+
+ )}
+
+
+ >
+ )}
+
+ {/*footer栏*/}
+ {showFooter && (
+
+ {formatFooter(footerData, eventListOld)}
+
+ )}
+
+ {/* 根据节点类型渲染不同的句柄 */}
+ {isSpecialNode
+ ? renderSpecialNodeHandles(isStartNode, isEndNode, dataIns, dataOuts, apiIns, apiOuts)
+ : renderRegularNodeHandles(dataIns, dataOuts, apiIns, apiOuts)}
+ >
+ );
+};
+
+export default NodeContentLocal;
\ No newline at end of file