效果
核心源码
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;