/** * 侧边栏导航组件 * 分组式菜单结构,支持折叠/展开,移动端抽屉模式 */ import { Link, useLocation } from 'react-router-dom' import { useState } from 'react' import { useQuery } from '@tanstack/react-query' import clsx from 'clsx' import { LayoutDashboard, Users, CalendarCheck, UserX, Calculator, Shield, BarChart3, ShieldAlert, FileSearch, FileText, Stethoscope, HeartPulse, Award, Bot, BookMarked, Bell, ScrollText, Settings, ChevronDown, ChevronRight, Building2, CalendarDays, ClipboardList, Heart, CalendarClock, Gift, PenTool, Umbrella, } from 'lucide-react' import Logo from '../ui/Logo' import { settingsApi } from '../../lib/api-services' interface NavItem { path: string label: string icon: typeof LayoutDashboard } interface NavGroup { title: string items: NavItem[] } const navGroups: NavGroup[] = [ { title: '首页', items: [ { path: '/', label: '工作台', icon: LayoutDashboard }, { path: '/calendar', label: '工作日历', icon: CalendarDays }, ], }, { title: '团队', items: [ { path: '/roster', label: '花名册', icon: Users }, { path: '/work-process', label: '用工办理', icon: ClipboardList }, { path: '/termination', label: '离职管理', icon: UserX }, { path: '/special-status', label: '特殊状态', icon: Heart }, { path: '/esign', label: '电子签署', icon: PenTool }, ], }, { title: '时间', items: [ { path: '/attendance', label: '考勤排班', icon: CalendarCheck }, { path: '/leave-approval', label: '休假审批', icon: CalendarClock }, ], }, { title: '薪酬', items: [ { path: '/money', label: '薪税管理', icon: Calculator }, { path: '/social', label: '社公商保', icon: Shield }, { path: '/salary-dashboard', label: '薪酬分析', icon: BarChart3 }, ], }, { title: '福利保障', items: [ { path: '/commercial-insurance', label: '商业保险', icon: Umbrella }, { path: '/benefits', label: '员工福利', icon: Gift }, ], }, { title: '合规', items: [ { path: '/risk-center', label: '风险中心', icon: ShieldAlert }, { path: '/evidence', label: '证据链条', icon: FileSearch }, { path: '/policies', label: '规章制度', icon: FileText }, { path: '/tools/health-check', label: '用工体检', icon: Stethoscope }, { path: '/tools/medical-period', label: '医疗期', icon: HeartPulse }, { path: '/tools/annual-value', label: '年度价值', icon: Award }, ], }, { title: '更多', items: [ { path: '/ai-assistant', label: 'AI顾问', icon: Bot }, { path: '/templates', label: '文本模板', icon: BookMarked }, { path: '/notifications', label: '通知管理', icon: Bell }, { path: '/audit', label: '操作日志', icon: ScrollText }, { path: '/company-files', label: '公司文件', icon: Building2 }, { path: '/settings', label: '系统设置', icon: Settings }, ], }, ] /** * 侧边栏导航 */ export default function SidebarNav({ mobileOpen, onClose }: { mobileOpen: boolean; onClose: () => void }) { const location = useLocation() const { data: orgData } = useQuery({ queryKey: ['org-settings'], queryFn: () => settingsApi.org(), staleTime: 300000, }) const isActive = (path: string) => { if (path === '/') return location.pathname === '/' return location.pathname.startsWith(path) } const activeGroup = navGroups.find(g => g.items.some(item => isActive(item.path))) const [expandedGroups, setExpandedGroups] = useState>( new Set(navGroups.map(g => g.title)) ) const toggleGroup = (title: string) => { setExpandedGroups(prev => { const next = new Set(prev) if (next.has(title)) next.delete(title) else next.add(title) return next }) } return ( <> {/* 移动端遮罩 */} {mobileOpen && (
)} ) }