From 6ba685d64e855e9bcf32490aab2dd42b38011fd8 Mon Sep 17 00:00:00 2001 From: ZLY Date: Wed, 22 Oct 2025 16:39:01 +0800 Subject: [PATCH] =?UTF-8?q?feat(flowEditor):=20=E6=B7=BB=E5=8A=A0=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E6=90=9C=E7=B4=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入 Input 组件和搜索状态管理 - 实现根据搜索关键词过滤节点列表- 自动切换到首个有搜索结果的标签页 - 添加搜索框样式和图标前缀 -优化节点分组渲染逻辑以支持过滤显示 --- .../flowEditor/components/addNodeMenu.tsx | 64 +++++++++++++++++-- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/src/pages/flowEditor/components/addNodeMenu.tsx b/src/pages/flowEditor/components/addNodeMenu.tsx index ac66fbc..98c8d41 100644 --- a/src/pages/flowEditor/components/addNodeMenu.tsx +++ b/src/pages/flowEditor/components/addNodeMenu.tsx @@ -1,7 +1,8 @@ -import React, { useCallback, useEffect, useState } from 'react'; -import { Menu, Tabs } from '@arco-design/web-react'; +import React, { useCallback, useEffect, useState, useMemo } from 'react'; +import { Input, Menu, Tabs } from '@arco-design/web-react'; import { localNodeData } from '@/pages/flowEditor/sideBar/config/localNodeData'; import { useSelector } from 'react-redux'; +import { IconSearch } from '@arco-design/web-react/icon'; const TabPane = Tabs.TabPane; @@ -17,6 +18,7 @@ const AddNodeMenu: React.FC = ({ const { projectComponentData, info } = useSelector((state: any) => state.ideContainer); const [groupedNodes, setGroupedNodes] = useState>({}); const [activeTab, setActiveTab] = useState('common'); + const [searchValue, setSearchValue] = useState(''); // 添加搜索状态 // 按分组组织节点数据 const formattedNodes = useCallback(() => { @@ -76,10 +78,56 @@ const AddNodeMenu: React.FC = ({ setGroupedNodes(initialGroupedNodes); }, [projectComponentData, info.id]); + // 根据搜索值过滤节点 + const filteredGroupedNodes = useMemo(() => { + if (!searchValue) return groupedNodes; + + const filteredNodes: Record = {}; + + Object.keys(groupedNodes).forEach(group => { + const nodes = groupedNodes[group]; + const filtered = nodes.filter(node => { + const nodeName = node.nodeName || node.name || ''; + return nodeName.toLowerCase().includes(searchValue.toLowerCase()); + }); + + if (filtered.length > 0) { + filteredNodes[group] = filtered; + } + }); + + return filteredNodes; + }, [groupedNodes, searchValue]); + + // 获取第一个有数据的tab + const getFirstAvailableTab = useCallback(() => { + const groupKeys = Object.keys(filteredGroupedNodes); + if (groupKeys.length > 0) { + return groupKeys[0]; + } + return 'common'; + }, [filteredGroupedNodes]); + + // 当搜索值改变时,自动选中第一个有结果的tab + useEffect(() => { + if (searchValue) { + const firstTab = getFirstAvailableTab(); + setActiveTab(firstTab); + } else { + // 如果搜索值为空,恢复默认选中tab + setActiveTab('common'); + } + }, [searchValue, getFirstAvailableTab]); + const handleAddNode = (nodeType: string, node: any) => { onAddNode(nodeType, node); }; + // 处理搜索输入变化 + const handleSearchChange = (value: string) => { + setSearchValue(value); + }; + // 分组名称映射 const groupNames: Record = { 'application': '基础组件', @@ -106,8 +154,16 @@ const AddNodeMenu: React.FC = ({ flexDirection: 'column' }} > - - {Object.entries(groupedNodes).map(([group, nodes]) => ( + } + style={{ marginRight: 16 }} + value={searchValue} + onChange={handleSearchChange} + /> + + {Object.entries(filteredGroupedNodes).map(([group, nodes]) => ( {/* 只有在当前 tab 激活时才渲染内容 */} {activeTab === group && (