2
0

menu.tsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. import React from 'react';
  2. import { useNavigate } from 'react-router';
  3. import { useAuth } from './hooks/AuthProvider';
  4. import {
  5. Users,
  6. Settings,
  7. LogOut,
  8. File,
  9. MapPin,
  10. MessageSquare,
  11. Building,
  12. User,
  13. ClipboardList,
  14. Monitor,
  15. DollarSign,
  16. CreditCard,
  17. Search,
  18. } from 'lucide-react';
  19. export interface MenuItem {
  20. key: string;
  21. label: string;
  22. icon?: React.ReactNode;
  23. children?: MenuItem[];
  24. path?: string;
  25. permission?: string;
  26. onClick?: () => void;
  27. }
  28. /**
  29. * 菜单搜索 Hook
  30. * 封装菜单搜索相关逻辑
  31. */
  32. export const useMenuSearch = (menuItems: MenuItem[]) => {
  33. const [searchText, setSearchText] = React.useState('');
  34. // 过滤菜单项
  35. const filteredMenuItems = React.useMemo(() => {
  36. if (!searchText) return menuItems;
  37. const filterItems = (items: MenuItem[]): MenuItem[] => {
  38. return items
  39. .map(item => {
  40. // 克隆对象避免修改原数据
  41. const newItem = { ...item };
  42. if (newItem.children) {
  43. newItem.children = filterItems(newItem.children);
  44. }
  45. return newItem;
  46. })
  47. .filter(item => {
  48. // 保留匹配项或其子项匹配的项
  49. const match = item.label.toLowerCase().includes(searchText.toLowerCase());
  50. if (match) return true;
  51. if (item.children?.length) return true;
  52. return false;
  53. });
  54. };
  55. return filterItems(menuItems);
  56. }, [menuItems, searchText]);
  57. // 清除搜索
  58. const clearSearch = () => {
  59. setSearchText('');
  60. };
  61. return {
  62. searchText,
  63. setSearchText,
  64. filteredMenuItems,
  65. clearSearch
  66. };
  67. };
  68. export const useMenu = () => {
  69. const navigate = useNavigate();
  70. const { logout: handleLogout } = useAuth();
  71. const [collapsed, setCollapsed] = React.useState(false);
  72. // 基础菜单项配置
  73. const menuItems: MenuItem[] = [
  74. // {
  75. // key: 'dashboard',
  76. // label: '控制台',
  77. // icon: <LayoutDashboard className="h-4 w-4" />,
  78. // path: '/admin/dashboard'
  79. // },
  80. {
  81. key: 'users',
  82. label: '用户管理',
  83. icon: <Users className="h-4 w-4" />,
  84. path: '/admin/users',
  85. permission: 'user:manage'
  86. },
  87. {
  88. key: 'files',
  89. label: '文件管理',
  90. icon: <File className="h-4 w-4" />,
  91. path: '/admin/files',
  92. permission: 'file:manage'
  93. },
  94. // {
  95. // key: 'analytics',
  96. // label: '数据分析',
  97. // icon: <BarChart3 className="h-4 w-4" />,
  98. // path: '/admin/analytics',
  99. // permission: 'analytics:view'
  100. // },
  101. // {
  102. // key: 'agents',
  103. // label: '代理商管理',
  104. // icon: <UserCheck className="h-4 w-4" />,
  105. // path: '/admin/agents',
  106. // permission: 'agent:manage'
  107. // },
  108. {
  109. key: 'areas',
  110. label: '区域管理',
  111. icon: <MapPin className="h-4 w-4" />,
  112. path: '/admin/areas',
  113. permission: 'area:manage'
  114. },
  115. {
  116. key: 'bank-names',
  117. label: '银行名称管理',
  118. icon: <CreditCard className="h-4 w-4" />,
  119. path: '/admin/bank-names',
  120. permission: 'bank-name:manage'
  121. },
  122. {
  123. key: 'channels',
  124. label: '渠道管理',
  125. icon: <MessageSquare className="h-4 w-4" />,
  126. path: '/admin/channels',
  127. permission: 'channel:manage'
  128. },
  129. {
  130. key: 'companies',
  131. label: '公司管理',
  132. icon: <Building className="h-4 w-4" />,
  133. path: '/admin/companies',
  134. permission: 'company:manage'
  135. },
  136. {
  137. key: 'disabilities',
  138. label: '残疾人管理',
  139. icon: <User className="h-4 w-4" />,
  140. path: '/admin/disabilities',
  141. permission: 'disability:manage'
  142. },
  143. {
  144. key: 'disability-company-query',
  145. label: '残疾人企业查询',
  146. icon: <Search className="h-4 w-4" />,
  147. path: '/admin/disability-person-company-query',
  148. permission: 'disability:manage'
  149. },
  150. {
  151. key: 'orders',
  152. label: '订单管理',
  153. icon: <ClipboardList className="h-4 w-4" />,
  154. path: '/admin/orders',
  155. permission: 'order:manage'
  156. },
  157. {
  158. key: 'platforms',
  159. label: '平台管理',
  160. icon: <Monitor className="h-4 w-4" />,
  161. path: '/admin/platforms',
  162. permission: 'platform:manage'
  163. },
  164. {
  165. key: 'salaries',
  166. label: '薪资管理',
  167. icon: <DollarSign className="h-4 w-4" />,
  168. path: '/admin/salaries',
  169. permission: 'salary:manage'
  170. },
  171. // {
  172. // key: 'cards',
  173. // label: '卡券管理',
  174. // icon: <CreditCard className="h-4 w-4" />,
  175. // permission: 'card:manage',
  176. // children: [
  177. // {
  178. // key: 'user-cards',
  179. // label: '用户卡管理',
  180. // path: '/admin/user-cards',
  181. // permission: 'card:manage'
  182. // },
  183. // {
  184. // key: 'user-card-balance-records',
  185. // label: '余额记录',
  186. // path: '/admin/user-card-balance-records',
  187. // permission: 'card:manage'
  188. // }
  189. // ]
  190. // },
  191. ];
  192. // 用户菜单项
  193. const userMenuItems = [
  194. // {
  195. // key: 'profile',
  196. // label: '个人资料',
  197. // icon: <User className="mr-2 h-4 w-4" />,
  198. // onClick: () => navigate('/admin/profile')
  199. // },
  200. // {
  201. // key: 'settings',
  202. // label: '账户设置',
  203. // icon: <Settings className="mr-2 h-4 w-4" />,
  204. // onClick: () => navigate('/admin/account-settings')
  205. // },
  206. // {
  207. // type: 'separator',
  208. // key: 'divider',
  209. // },
  210. {
  211. key: 'logout',
  212. label: '退出登录',
  213. icon: <LogOut className="mr-2 h-4 w-4" />,
  214. onClick: () => handleLogout()
  215. }
  216. ];
  217. // 处理菜单点击
  218. const handleMenuClick = (item: MenuItem) => {
  219. if (item.path) {
  220. navigate(item.path);
  221. }
  222. if (item.onClick) {
  223. item.onClick();
  224. }
  225. };
  226. return {
  227. menuItems,
  228. userMenuItems,
  229. collapsed,
  230. setCollapsed,
  231. handleMenuClick,
  232. };
  233. };