import { useEffect, useState } from 'react'; import { Layout, Menu, Avatar, Space, Typography, Button, Modal, Dropdown } from 'antd'; import { DashboardOutlined, UserOutlined, LogoutOutlined, CloudServerOutlined, TeamOutlined, ApiOutlined, KeyOutlined, MenuFoldOutlined, MenuUnfoldOutlined, SwapOutlined, SunOutlined, MoonOutlined, DesktopOutlined, FileTextOutlined, } from '@ant-design/icons'; import { useNavigate, useLocation, Outlet } from 'react-router-dom'; import { getUser, clearAuth, hasPerm, type AuthUser } from '../store/auth'; import { authApi } from '../api/modules'; import { useTheme, type ThemeMode } from '../store/theme'; const { Sider, Content } = Layout; const { Text } = Typography; const ROLE_LABELS: Record = { super_admin: '超级管理员', operation: '运营', support: '客服', }; const THEME_OPTIONS: { key: ThemeMode; label: string; icon: React.ReactNode }[] = [ { key: 'light', label: '亮色', icon: }, { key: 'dark', label: '暗色', icon: }, { key: 'system', label: '跟随系统', icon: }, ]; export default function MainLayout({ onLogout }: { onLogout?: () => void }) { const navigate = useNavigate(); const location = useLocation(); const [user] = useState(getUser()); const [collapsed, setCollapsed] = useState(false); const { mode, isDark, setMode } = useTheme(); useEffect(() => { if (!user) navigate('/login'); }, [user]); if (!user) return null; const menuItems: { key: string; label: string; icon: React.ReactNode }[] = []; // Dashboard - 所有人可见 menuItems.push({ key: '/', label: '概览', icon: }); // 账号管理 if (hasPerm(user, 'account:view_all') || hasPerm(user, 'account:view_assigned')) { menuItems.push({ key: '/accounts', label: '账号管理', icon: }); } // 分配管理 if (hasPerm(user, 'account:assign')) { menuItems.push({ key: '/assignments', label: '分配管理', icon: }); } // 登录任务 if (hasPerm(user, 'login:batch') || hasPerm(user, 'login:view_all')) { menuItems.push({ key: '/login-tasks', label: '登录任务', icon: }); } // Cookie 管理 if (hasPerm(user, 'cookie:view')) { menuItems.push({ key: '/cookies', label: 'Cookie 管理', icon: }); } // 代理配置 if (hasPerm(user, 'proxy:manage')) { menuItems.push({ key: '/proxy', label: '代理配置', icon: }); } // 请求日志(运营和管理员可见) if (hasPerm(user, 'audit:view') || hasPerm(user, 'login:batch')) { menuItems.push({ key: '/http-logs', label: '请求日志', icon: }); } // 用户管理 if (hasPerm(user, 'user:view')) { menuItems.push({ key: '/users', label: '用户管理', icon: }); } const handleLogout = () => { Modal.confirm({ title: '确认退出', content: '确定要退出登录吗?', okText: '退出', cancelText: '取消', okButtonProps: { type: 'primary' }, centered: true, onOk: async () => { try { await authApi.logout(); } catch {} clearAuth(); onLogout?.(); navigate('/login', { replace: true }); }, }); }; const siderTheme = isDark ? 'dark' : 'light'; const siderTextColor = isDark ? '#fff' : undefined; return (
{collapsed ? '鱼' : '斗鱼登录后台'}
navigate(key)} style={{ flex: 1, overflow: 'auto', marginTop: 8 }} />
} size="small" /> {!collapsed && ( <> {user.username} ({ROLE_LABELS[user.role] || user.role}) )} {collapsed ? ( ({ key: o.key, label: o.label, icon: o.icon, onClick: () => setMode(o.key) })) }} trigger={['click']} > )}
); }