From 60f6b7916785ff6432a50fbee877b5e447ae531b Mon Sep 17 00:00:00 2001 From: v-zhangjc9 Date: Sat, 12 Jul 2025 19:09:47 +0800 Subject: [PATCH] =?UTF-8?q?feat(web):=20=E5=A2=9E=E5=8A=A0=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E5=88=86=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/flow/FlowChecker.tsx | 4 +- .../client/src/components/flow/FlowEditor.tsx | 16 ++++--- .../src/components/flow/NodeRegistry.tsx | 42 ++++++++++++------- 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/service-web/client/src/components/flow/FlowChecker.tsx b/service-web/client/src/components/flow/FlowChecker.tsx index bdbae18..db7bbdb 100644 --- a/service-web/client/src/components/flow/FlowChecker.tsx +++ b/service-web/client/src/components/flow/FlowChecker.tsx @@ -1,6 +1,6 @@ import {type Connection, type Edge, getOutgoers, type Node} from '@xyflow/react' import {find, has, isEmpty, isEqual, lpad, toStr} from 'licia' -import NodeRegistry from './NodeRegistry.tsx' +import {NodeRegistryMap} from './NodeRegistry.tsx' export class CheckError extends Error { readonly id: string @@ -83,7 +83,7 @@ export const checkSave: (inputSchema: Record>, nodes throw nodeTypeNotFound() } let nodeType = node.type! - let nodeDefine = NodeRegistry[nodeType] + let nodeDefine = NodeRegistryMap[nodeType] for (let checker of nodeDefine.checkers) { let checkResult = checker(nodeId, inputSchema, nodes, edges, data) if (checkResult.error) { diff --git a/service-web/client/src/components/flow/FlowEditor.tsx b/service-web/client/src/components/flow/FlowEditor.tsx index bf97b69..cd72673 100644 --- a/service-web/client/src/components/flow/FlowEditor.tsx +++ b/service-web/client/src/components/flow/FlowEditor.tsx @@ -1,14 +1,14 @@ import {PlusCircleFilled, RollbackOutlined, SaveFilled} from '@ant-design/icons' import {Background, BackgroundVariant, Controls, MiniMap, ReactFlow} from '@xyflow/react' import {Button, Dropdown, message, Popconfirm, Space} from 'antd' -import {arrToMap, randomId} from 'licia' +import {arrToMap, isEqual, randomId, unique} from 'licia' import {useEffect} from 'react' import {useNavigate} from 'react-router' import styled from 'styled-components' import '@xyflow/react/dist/style.css' import {commonInfo} from '../../util/amis.tsx' import {checkAddConnection, checkAddNode, checkSave} from './FlowChecker.tsx' -import NodeRegistry from './NodeRegistry.tsx' +import {NodeRegistry, NodeRegistryMap} from './NodeRegistry.tsx' import {useContextStore} from './store/ContextStore.ts' import {useDataStore} from './store/DataStore.ts' import {useFlowStore} from './store/FlowStore.ts' @@ -88,7 +88,13 @@ function FlowEditor(props: FlowEditorProps) { ({key: key, label: NodeRegistry[key]!.name})), + items: unique(NodeRegistry.map(i => i.group)) + .map(group => ({ + type: 'group', + label: group, + children: NodeRegistry.filter(i => isEqual(group, i.group)) + .map(i => ({key: i.key, label: i.name})) + })), onClick: ({key}) => { try { if (commonInfo.debug) { @@ -97,7 +103,7 @@ function FlowEditor(props: FlowEditorProps) { checkAddNode(key, nodes, edges) let nodeId = randomId(10, 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM') - let define = NodeRegistry[key] + let define = NodeRegistryMap[key] setDataById( nodeId, @@ -171,7 +177,7 @@ function FlowEditor(props: FlowEditorProps) { } }} // @ts-ignore - nodeTypes={arrToMap(Object.keys(NodeRegistry), key => NodeRegistry[key]!.component)} + nodeTypes={arrToMap(Object.keys(NodeRegistryMap), key => NodeRegistryMap[key]!.component)} > diff --git a/service-web/client/src/components/flow/NodeRegistry.tsx b/service-web/client/src/components/flow/NodeRegistry.tsx index f5f8aa8..3f280bd 100644 --- a/service-web/client/src/components/flow/NodeRegistry.tsx +++ b/service-web/client/src/components/flow/NodeRegistry.tsx @@ -14,7 +14,7 @@ const inputVariableChecker: NodeChecker = (id, inputSchema, nodes, edges, data) if (!isEmpty(inputs)) { let outputVariables = new Set([ ...getAllIncomerNodeOutputVariables(id, nodes, edges, data).map(i => `${i.id}.${i.variable}`), - ...Object.keys(inputSchema) + ...Object.keys(inputSchema), ]) for (const key of Object.keys(inputs)) { let variable = inputs[key]?.variable ?? '' @@ -31,43 +31,55 @@ const inputVariableChecker: NodeChecker = (id, inputSchema, nodes, edges, data) } type NodeDefine = { + key: string, + group: string, name: string, description: string, component: any, checkers: NodeChecker[], } -const NodeRegistry: Record = { - 'output-node': { - name: '输出', - description: '定义输出变量', - component: OutputNode, - checkers: [inputVariableChecker], - }, - 'llm-node': { +export const NodeRegistry: NodeDefine[] = [ + { + key: 'llm-node', + group: '普通节点', name: '大模型', description: '使用大模型对话', component: LlmNode, checkers: [inputVariableChecker], }, - 'knowledge-node': { + { + key: 'knowledge-node', + group: '普通节点', name: '知识库', description: '', component: KnowledgeNode, checkers: [inputVariableChecker], }, - 'code-node': { + { + key: 'code-node', + group: '普通节点', name: '代码执行', description: '执行自定义的处理代码', component: CodeNode, checkers: [inputVariableChecker], }, - 'switch-node': { - name: '分支节点', + { + key: 'switch-node', + group: '逻辑节点', + name: '分支', description: '根据不同的情况前往不同的分支', component: SwitchNode, checkers: [], }, -} + { + key: 'output-node', + group: '输出节点', + name: '输出', + description: '定义输出变量', + component: OutputNode, + checkers: [inputVariableChecker], + }, +] -export default NodeRegistry +export const NodeRegistryMap: Record = NodeRegistry.reduce((a, v) => ({...a, [v.key]: v}), {})