效果
核心源码
type MenuItem = {
label: string;
key: string | number;
icon?: React.ReactNode;
children?: MenuItem[];
type?: 'group';
}
function filterTreeData(tree: MenuItem[], keyword: string): MenuItem[] {
return tree.filter((node: MenuItem) => {
if (node.label.includes(keyword)) {
return true;
}
if (Array.isArray(node.children)) {
node.children = filterTreeData(node.children, keyword);
return !!node.children?.length;
}
return false;
});
}
源码
import React, {useState} from 'react';
import {
BarChartOutlined, CompassOutlined, DatabaseOutlined, DeploymentUnitOutlined, DesktopOutlined, SettingOutlined,
FundProjectionScreenOutlined, FundViewOutlined, HomeOutlined, MenuFoldOutlined, MenuUnfoldOutlined, MessageOutlined,
TrophyOutlined, VerifiedOutlined,
} from '@ant-design/icons';
import {Flex, Button, Menu as AntdMenu} from 'antd';
import Search from "antd/es/input/Search";
import {SearchProps} from "antd/lib/input";
type MenuItem = {
label: string;
key: string | number;
icon?: React.ReactNode;
children?: MenuItem[];
type?: 'group';
}
function getItem(label: React.ReactNode, key: React.Key, icon?: React.ReactNode, children?: MenuItem[], type?: 'group',): MenuItem {
return {key, icon, children, label, type,} as MenuItem;
}
function filterTreeData(tree: MenuItem[], keyword: string): MenuItem[] {
return tree.filter((node: MenuItem) => {
if (node.label.includes(keyword)) {
return true;
}
if (Array.isArray(node.children)) {
node.children = filterTreeData(node.children, keyword);
return !!node.children?.length;
}
return false;
});
}
const Menu: React.FC = () => {
const menuItems: MenuItem[] = [
getItem('首页', '1', <HomeOutlined/>),
getItem('平台管理', '2', <DesktopOutlined/>, [
getItem('学生管理', '2-1'),
getItem('教师管理', '2-2'),
getItem('班级管理', '2-3'),
getItem('任务管理', '2-4', null, [
getItem('课程管理', '2-4-1'),
getItem('发布任务', '2-4-2'),
]),
getItem('作业管理', '2-5'),
getItem('答卷管理', '2-6', null, [
getItem('批卷列表', '2-6-1'),
getItem('批卷结果', '2-6-2'),
]),
]),
getItem('平台资源', '3', <DatabaseOutlined/>),
getItem('教学实训', '4', <MessageOutlined/>),
getItem('培训认证', '5', <VerifiedOutlined/>),
getItem('技能竞赛', '6', <TrophyOutlined/>),
getItem('科研实验', '7', <DeploymentUnitOutlined/>),
getItem('数据平台', '8', <BarChartOutlined/>),
getItem('算法平台', '9', <FundProjectionScreenOutlined/>),
getItem('系統管理', '10', <CompassOutlined/>),
getItem('系统监控', '11', <FundViewOutlined/>),
getItem('系統工具', '12', <SettingOutlined/>),
];
const [items, setItems] = useState<MenuItem[]>(menuItems);
const [collapsed, setCollapsed] = useState(false);
const toggleCollapsed = () => {
setCollapsed(!collapsed);
};
const onSearch: SearchProps['onSearch'] = (value, _e, _info) => {
setItems(filterTreeData(menuItems, value));
};
return (
<>
<div className="menu-tool">
<Flex gap={10}>
{collapsed ? '' : (<Search placeholder="在此输入关键词..." onSearch={onSearch}/>)}
<Button block={collapsed} type="primary" onClick={toggleCollapsed} icon={collapsed ? <MenuUnfoldOutlined/> : <MenuFoldOutlined/>}/>
</Flex>
</div>
<AntdMenu defaultSelectedKeys={['1']} mode="inline" inlineCollapsed={collapsed} items={items}/>
</>
);
};
export default Menu;