feat(flowEditor): 添加节点搜索功能

- 引入 Input 组件和搜索状态管理
- 实现根据搜索关键词过滤节点列表- 自动切换到首个有搜索结果的标签页
- 添加搜索框样式和图标前缀
-优化节点分组渲染逻辑以支持过滤显示
master
钟良源 4 months ago
parent d487c40dd4
commit 6ba685d64e

@ -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<AddNodeMenuProps> = ({
const { projectComponentData, info } = useSelector((state: any) => state.ideContainer);
const [groupedNodes, setGroupedNodes] = useState<Record<string, any[]>>({});
const [activeTab, setActiveTab] = useState('common');
const [searchValue, setSearchValue] = useState(''); // 添加搜索状态
// 按分组组织节点数据
const formattedNodes = useCallback(() => {
@ -76,10 +78,56 @@ const AddNodeMenu: React.FC<AddNodeMenuProps> = ({
setGroupedNodes(initialGroupedNodes);
}, [projectComponentData, info.id]);
// 根据搜索值过滤节点
const filteredGroupedNodes = useMemo(() => {
if (!searchValue) return groupedNodes;
const filteredNodes: Record<string, any[]> = {};
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<string, string> = {
'application': '基础组件',
@ -106,8 +154,16 @@ const AddNodeMenu: React.FC<AddNodeMenuProps> = ({
flexDirection: 'column'
}}
>
<Tabs defaultActiveTab="common" style={{ flex: '0 0 auto' }} onChange={handleTabChange}>
{Object.entries(groupedNodes).map(([group, nodes]) => (
<Input
size="large"
placeholder="搜索节点"
prefix={<IconSearch />}
style={{ marginRight: 16 }}
value={searchValue}
onChange={handleSearchChange}
/>
<Tabs activeTab={activeTab} style={{ flex: '0 0 auto' }} onChange={handleTabChange}>
{Object.entries(filteredGroupedNodes).map(([group, nodes]) => (
<TabPane key={group} title={groupNames[group] || group}>
{/* 只有在当前 tab 激活时才渲染内容 */}
{activeTab === group && (

Loading…
Cancel
Save