2
0

menu.tsx 3.0 KB

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