From 9a4187a8c3a81f09c036f7e1b7babdf4851596fc Mon Sep 17 00:00:00 2001 From: ZLY Date: Mon, 1 Sep 2025 16:00:51 +0800 Subject: [PATCH] =?UTF-8?q?feat(flowEditor):=20=E9=87=8D=E6=9E=84=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E7=BC=96=E8=BE=91=E6=A8=A1=E6=80=81=E6=A1=86=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E8=87=AA=E5=AE=9A=E4=B9=89=E8=8A=82=E7=82=B9?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 拆分 NodeEditModal 组件中的节点编辑逻辑 - 新增独立的节点编辑器组件:EndNodeEditor、StartNodeEditor、BasicNodeEditor、LocalNodeEditor - 实现节点编辑器的动态加载和注册机制 - 优化节点数据的管理和更新逻辑 --- .../flowEditor/components/nodeEditModal.tsx | 57 ++---- .../nodeEditors/BasicNodeEditor.tsx | 39 ++++ .../components/nodeEditors/EndNodeEditor.tsx | 174 ++++++++++++++++++ .../nodeEditors/LocalNodeEditor.tsx | 112 +++++++++++ .../nodeEditors/StartNodeEditor.tsx | 28 +++ .../components/nodeEditors/index.tsx | 46 +++++ 6 files changed, 419 insertions(+), 37 deletions(-) create mode 100644 src/pages/flowEditor/components/nodeEditors/BasicNodeEditor.tsx create mode 100644 src/pages/flowEditor/components/nodeEditors/EndNodeEditor.tsx create mode 100644 src/pages/flowEditor/components/nodeEditors/LocalNodeEditor.tsx create mode 100644 src/pages/flowEditor/components/nodeEditors/StartNodeEditor.tsx create mode 100644 src/pages/flowEditor/components/nodeEditors/index.tsx diff --git a/src/pages/flowEditor/components/nodeEditModal.tsx b/src/pages/flowEditor/components/nodeEditModal.tsx index 9fdbe34..4e42e73 100644 --- a/src/pages/flowEditor/components/nodeEditModal.tsx +++ b/src/pages/flowEditor/components/nodeEditModal.tsx @@ -1,6 +1,7 @@ import React, { useState, useEffect } from 'react'; import { Node } from '@xyflow/react'; -import { Modal, Input, Form, Select } from '@arco-design/web-react'; +import { Modal } from '@arco-design/web-react'; +import { getNodeEditorByType } from './nodeEditors'; interface NodeData { type?: string; @@ -57,43 +58,24 @@ const NodeEditModal: React.FC = ({ })); }; - // 根据节点类型渲染不同的内容 - const renderContent = () => { + // 获取节点编辑器组件 + const getNodeEditor = () => { const nodeType = node?.type || 'basic'; + // 检查是否为本地节点(通过nodeTypeMap中不存在的类型来判断) + const isLocalNode = nodeType && !['start', 'end', 'basic'].includes(nodeType.toLowerCase()); - switch (nodeType) { - case 'start': - case 'end': - case 'basic': - default: - return ( -
- - updateNodeData('title', value)} - /> - - - updateNodeData('description', value)} - /> - - - updateNodeData('title', value)} + /> + + + updateNodeData('description', value)} + /> + + + handleSave({ ...record, id: value })} + /> + ) + }, + { + title: '数据类型', + dataIndex: 'dataType', + render: (_, record) => ( + handleSave({ ...record, arrayType: value })} + placeholder="请选择数组类型" + /> + ) : ( + + ) + ) + }, + { + title: '描述', + dataIndex: 'desc', + render: (_, record) => ( + handleSave({ ...record, desc: value })} + /> + ) + }, + { + title: '默认值', + dataIndex: 'defaultValue', + render: (_, record) => ( + handleSave({ ...record, defaultValue: value })} + /> + ) + }, + { + title: '操作', + dataIndex: 'op', + render: (_, record) => ( + + ) + } + ]; + + + const handleSave = (row) => { + const newData = [...data]; + const index = newData.findIndex((item) => row.key === item.key); + if (index >= 0) { + newData.splice(index, 1, { ...newData[index], ...row }); + } + else { + newData.push(row); + } + setData(newData); + // 更新节点数据 + updateNodeData('parameters', { + ...nodeData.parameters, + dataIns: newData + }); + }; + + const removeRow = (key) => { + const newData = data.filter((item) => item.key !== key); + setData(newData); + + // 更新节点数据 + updateNodeData('parameters', { + ...nodeData.parameters, + dataIns: newData + }); + }; + + const addRow = () => { + const newKey = Date.now(); + const newRow = { + key: newKey, + id: '', + dataType: '', + arrayType: '', + desc: '', + defaultValue: '' + }; + const newData = [...data, newRow]; + setData(newData); + + // 更新节点数据 + updateNodeData('parameters', { + ...nodeData.parameters, + dataIns: newData + }); + }; + + return ( + <> + 输入参数 + + + + ); +}; + +export default EndNodeEditor; \ No newline at end of file diff --git a/src/pages/flowEditor/components/nodeEditors/LocalNodeEditor.tsx b/src/pages/flowEditor/components/nodeEditors/LocalNodeEditor.tsx new file mode 100644 index 0000000..ca92d67 --- /dev/null +++ b/src/pages/flowEditor/components/nodeEditors/LocalNodeEditor.tsx @@ -0,0 +1,112 @@ +import React from 'react'; +import { NodeEditorProps } from './index'; +import { Form, Input, Switch, Select } from '@arco-design/web-react'; + +const LocalNodeEditor: React.FC = ({ + node, + nodeData, + updateNodeData +}) => { + // 根据LocalNode的不同类型渲染不同的编辑界面 + const renderLocalNodeEditor = () => { + const localNodeType = nodeData.type || ''; + + switch (localNodeType) { + case 'CONDITION': + return ( + <> + + updateNodeData('title', value)} + /> + + + updateNodeData('expression', value)} + placeholder="请输入条件表达式" + /> + + + updateNodeData('enabled', value)} + /> + + + ); + + case 'WAIT': + return ( + <> + + updateNodeData('title', value)} + /> + + + updateNodeData('waitTime', value)} + type="number" + /> + + + ); + + case 'LOOP': + return ( + <> + + updateNodeData('title', value)} + /> + + + updateNodeData('loopCount', value)} + type="number" + /> + + + updateNodeData('condition', value)} + placeholder="请输入循环条件" + /> + + + ); + + default: + return ( + <> + + updateNodeData('title', value)} + /> + + + updateNodeData('description', value)} + /> + + + ); + } + }; + + return ( + + {renderLocalNodeEditor()} + + ); +}; + +export default LocalNodeEditor; \ No newline at end of file diff --git a/src/pages/flowEditor/components/nodeEditors/StartNodeEditor.tsx b/src/pages/flowEditor/components/nodeEditors/StartNodeEditor.tsx new file mode 100644 index 0000000..161cf7b --- /dev/null +++ b/src/pages/flowEditor/components/nodeEditors/StartNodeEditor.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { NodeEditorProps } from './index'; +import { Form, Input } from '@arco-design/web-react'; + +const StartNodeEditor: React.FC = ({ + node, + nodeData, + updateNodeData +}) => { + return ( +
+ + updateNodeData('title', value)} + /> + + + updateNodeData('description', value)} + /> + + + ); +}; + +export default StartNodeEditor; \ No newline at end of file diff --git a/src/pages/flowEditor/components/nodeEditors/index.tsx b/src/pages/flowEditor/components/nodeEditors/index.tsx new file mode 100644 index 0000000..608db0b --- /dev/null +++ b/src/pages/flowEditor/components/nodeEditors/index.tsx @@ -0,0 +1,46 @@ +import React from 'react'; +import { Node } from '@xyflow/react'; +import BasicNodeEditor from './BasicNodeEditor'; +import StartNodeEditor from './StartNodeEditor'; +import EndNodeEditor from './EndNodeEditor'; +import LocalNodeEditor from './LocalNodeEditor'; + +// 定义节点编辑器的属性接口 +export interface NodeEditorProps { + node: Node; + nodeData: any; + updateNodeData: (key: string, value: any) => void; +} + +// 节点编辑器映射 +export const nodeEditors: Record> = { + 'basic': BasicNodeEditor, + 'start': StartNodeEditor, + 'end': EndNodeEditor, + 'local': LocalNodeEditor // 用于所有本地节点类型的编辑器 +}; + +// 注册新的节点编辑器 +export const registerNodeEditor = ( + type: string, + component: React.FC +) => { + nodeEditors[type] = component; +}; + +// 根据节点类型获取对应的编辑器 +export const getNodeEditorByType = (nodeType: string, localNodeType?: string) => { + // 对于本地节点,使用专门的本地节点编辑器 + if (localNodeType) { + return nodeEditors['local'] || nodeEditors['basic']; + } + + // 对于预定义节点类型,直接返回对应编辑器 + return nodeEditors[nodeType] || nodeEditors['basic']; +}; + +export default { + nodeEditors, + registerNodeEditor, + getNodeEditorByType +}; \ No newline at end of file