AdminLayout.tsx 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import {
  2. BookOpen,
  3. Clock3,
  4. LayoutDashboard,
  5. LogOut,
  6. Megaphone,
  7. ShieldCheck,
  8. Users
  9. } from 'lucide-react'
  10. import { NavLink, Navigate, Outlet, useNavigate } from 'react-router-dom'
  11. import { Brand } from '../../components/Brand'
  12. import { Footer } from '../../components/Footer'
  13. import { useAuth } from '../../AuthContext'
  14. export function AdminLayout() {
  15. const { user, loading, logout } = useAuth()
  16. const navigate = useNavigate()
  17. if (loading) return <div className="center-loading">正在加载管理后台…</div>
  18. // 未登录或非管理员,统一拦截跳转至管理员专属登录页 /admin/login
  19. if (!user || user.role !== 'ADMIN') {
  20. return <Navigate to="/admin/login" replace />
  21. }
  22. const handleAdminLogout = async () => {
  23. await logout()
  24. navigate('/admin/login', { replace: true })
  25. }
  26. return (
  27. <div className="admin-shell">
  28. <header className="admin-topbar">
  29. <div className="admin-brand-wrap">
  30. <NavLink to="/admin" className="logo-link">
  31. <Brand />
  32. </NavLink>
  33. <div className="admin-badge">
  34. <ShieldCheck size={14} />
  35. <span>管理后台</span>
  36. </div>
  37. </div>
  38. <nav className="admin-nav admin-nav-grouped" aria-label="平台管理">
  39. <NavLink to="/admin" end className={({ isActive }) => (isActive ? 'active' : '')}><LayoutDashboard size={16} /><span>待办概览</span></NavLink>
  40. <details className="admin-nav-group"><summary><Clock3 size={16} />课程制作</summary><div>
  41. <NavLink to="/admin/production-queue">制作队列</NavLink>
  42. <NavLink to="/admin/courses"><BookOpen size={15} />全部课程</NavLink>
  43. <NavLink to="/admin/digital-instructors">数字讲师</NavLink>
  44. </div></details>
  45. <details className="admin-nav-group"><summary><Users size={16} />人员与组织</summary><div>
  46. <NavLink to="/admin/users">用户管理</NavLink>
  47. <NavLink to="/admin/organizations">组织管理</NavLink>
  48. </div></details>
  49. <details className="admin-nav-group"><summary><Megaphone size={16} />运营</summary><div>
  50. <NavLink to="/admin/leads">落地页线索</NavLink>
  51. </div></details>
  52. </nav>
  53. <div className="admin-top-actions">
  54. <div className="admin-user-info">
  55. <strong>{user.contactName || '系统管理员'}</strong>
  56. <small>{user.phone}</small>
  57. </div>
  58. <button className="icon-button" title="退出管理员登录" onClick={handleAdminLogout}>
  59. <LogOut size={18} />
  60. </button>
  61. </div>
  62. </header>
  63. <main className="admin-main">
  64. <Outlet />
  65. </main>
  66. <Footer />
  67. </div>
  68. )
  69. }