menu.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import React from 'react';
  2. import { useNavigate } from 'react-router';
  3. import type { MenuProps } from 'antd';
  4. import {
  5. UserOutlined,
  6. DashboardOutlined,
  7. TeamOutlined,
  8. InfoCircleOutlined,
  9. } from '@ant-design/icons';
  10. export interface MenuItem {
  11. key: string;
  12. label: string;
  13. icon?: React.ReactNode;
  14. children?: MenuItem[];
  15. path?: string;
  16. permission?: string;
  17. }
  18. /**
  19. * 菜单搜索 Hook
  20. * 封装菜单搜索相关逻辑
  21. */
  22. export const useMenuSearch = (menuItems: MenuItem[]) => {
  23. const [searchText, setSearchText] = React.useState('');
  24. // 过滤菜单项
  25. const filteredMenuItems = React.useMemo(() => {
  26. if (!searchText) return menuItems;
  27. const filterItems = (items: MenuItem[]): MenuItem[] => {
  28. return items
  29. .map(item => {
  30. // 克隆对象避免修改原数据
  31. const newItem = { ...item };
  32. if (newItem.children) {
  33. newItem.children = filterItems(newItem.children);
  34. }
  35. return newItem;
  36. })
  37. .filter(item => {
  38. // 保留匹配项或其子项匹配的项
  39. const match = item.label.toLowerCase().includes(searchText.toLowerCase());
  40. if (match) return true;
  41. if (item.children?.length) return true;
  42. return false;
  43. });
  44. };
  45. return filterItems(menuItems);
  46. }, [menuItems, searchText]);
  47. // 清除搜索
  48. const clearSearch = () => {
  49. setSearchText('');
  50. };
  51. return {
  52. searchText,
  53. setSearchText,
  54. filteredMenuItems,
  55. clearSearch
  56. };
  57. };
  58. export const useMenu = () => {
  59. const navigate = useNavigate();
  60. const [collapsed, setCollapsed] = React.useState(false);
  61. const [openKeys, setOpenKeys] = React.useState<string[]>([]);
  62. // 基础菜单项配置
  63. const menuItems: MenuItem[] = [
  64. {
  65. key: 'dashboard',
  66. label: '控制台',
  67. icon: <DashboardOutlined />,
  68. path: '/admin/dashboard'
  69. },
  70. {
  71. key: 'users',
  72. label: '用户管理',
  73. icon: <TeamOutlined />,
  74. path: '/admin/users',
  75. permission: 'user:manage'
  76. },
  77. ];
  78. // 用户菜单项
  79. const userMenuItems: MenuProps['items'] = [
  80. {
  81. key: 'profile',
  82. label: '个人资料',
  83. icon: <UserOutlined />
  84. },
  85. {
  86. key: 'logout',
  87. label: '退出登录',
  88. icon: <InfoCircleOutlined />,
  89. danger: true
  90. }
  91. ];
  92. // 处理菜单点击
  93. const handleMenuClick = (item: MenuItem) => {
  94. if (item.path) {
  95. navigate(item.path);
  96. }
  97. };
  98. // 处理菜单展开变化
  99. const onOpenChange = (keys: string[]) => {
  100. const latestOpenKey = keys.find(key => openKeys.indexOf(key) === -1);
  101. setOpenKeys(latestOpenKey ? [latestOpenKey] : []);
  102. };
  103. return {
  104. menuItems,
  105. userMenuItems,
  106. openKeys,
  107. collapsed,
  108. setCollapsed,
  109. handleMenuClick,
  110. onOpenChange
  111. };
  112. };