import { Outlet, useNavigate, useLocation } from 'react-router-dom' import { ProLayout } from '@ant-design/pro-components' import { Dropdown, Avatar, Tag, Space, message } from 'antd' import { LogoutOutlined, UserOutlined } from '@ant-design/icons' import { useAuth } from '@/contexts/AuthContext' import { filterMenuByRole, adminMenuItems } from '@/config/menu' import { ADMIN_ROLE_LABELS, ADMIN_ROLE_COLORS } from '@/constants/roles' import type { AdminRole } from '@/types/admin' const breadcrumbMap: Record = { '/': '总览', '/assistant': '任务助理', '/users': '用户管理', '/users/admins': '管理员', '/users/members': '普通用户', '/membership': '会员与额度', '/knowledge': '知识库管理', '/knowledge/bases': '知识库列表', '/knowledge/sources': '知识源列表', '/imports': '文档导入', '/files': '文件与 COS', '/settings': '系统配置', '/billing': 'API 用量', '/git': '代码仓库', '/servers': '服务器运维', '/audit': '审计日志', } export default function AdminLayout() { const navigate = useNavigate() const location = useLocation() const { adminUser, logout, hasPermission } = useAuth() const currentRole = adminUser?.role as AdminRole | undefined const handleLogout = async () => { await logout() message.success('已退出登录') navigate('/login', { replace: true }) } const userMenuItems = [ { key: 'info', label: (
{adminUser?.displayName}
{adminUser?.email}
{ADMIN_ROLE_LABELS[currentRole ?? 'READONLY']}
), disabled: true, }, { type: 'divider' as const }, { key: 'logout', icon: , label: '退出登录', onClick: handleLogout, }, ] const isDev = import.meta.env.DEV || import.meta.env.MODE !== 'production' return ( { const items = filterMenuByRole(adminMenuItems, currentRole) return items }} menuItemRender={(item, dom) => ( item.path && navigate(item.path)}>{dom} )} breadcrumbRender={(routers) => { return (routers ?? []).map((r) => { const path = (r as any).path ?? '' const label = breadcrumbMap[path] || (r as any).breadcrumbName || path return { ...r, breadcrumbName: label, title: label } as any }) }} rightContentRender={() => hasPermission('READONLY') ? ( {isDev && ( DEV )}
} /> {adminUser?.displayName || '管理员'}
) : null } siderWidth={220} token={{ header: { heightLayoutHeader: 48 }, pageContainer: { paddingBlockPageContainerContent: 24, paddingInlinePageContainerContent: 24 }, }} >
) }