layout.tsx 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. 'use client';
  2. import { useEffect, useState } from 'react';
  3. import { useRouter } from 'next/navigation';
  4. import AdminSidebar from '@/components/admin/AdminSidebar';
  5. import { isAdmin, getCurrentUser } from '@/lib/auth';
  6. export default function AdminLayout({ children }: { children: React.ReactNode }) {
  7. const router = useRouter();
  8. const [isAuthorized, setIsAuthorized] = useState(false);
  9. const [user, setUser] = useState<any>(null);
  10. useEffect(() => {
  11. // 权限检查
  12. const token = localStorage.getItem('rsid');
  13. if (!token) {
  14. router.push('/login');
  15. return;
  16. }
  17. if (!isAdmin()) {
  18. alert("您没有权限访问管理后台");
  19. router.push('/dashboard');
  20. return;
  21. }
  22. setIsAuthorized(true);
  23. setUser(getCurrentUser());
  24. }, [router]);
  25. if (!isAuthorized) return null;
  26. return (
  27. <div className="min-h-screen bg-slate-50 flex flex-col md:flex-row font-sans text-slate-900">
  28. {/*
  29. 侧边栏组件
  30. - 内部自包含移动端 Header 和开关逻辑
  31. - 不需要传递 isOpen / onClose
  32. */}
  33. <AdminSidebar />
  34. {/*
  35. 主内容区域
  36. - flex-1: 占满剩余空间
  37. - pt-16: 移动端顶部留出 64px 给 Sidebar 的固定 Header
  38. - md:pt-0: 桌面端不需要留白(左右布局)
  39. - h-screen: 限制高度以便内部滚动 (可选,视需求而定)
  40. */}
  41. <main className="flex-1 flex flex-col min-w-0 pt-16 md:pt-0 h-screen overflow-hidden">
  42. {/*
  43. Desktop Header (右侧顶部栏)
  44. - 显示页面标题和用户信息
  45. - 移动端如果觉得太挤可以隐藏 (hidden md:flex),或者保留
  46. */}
  47. <header className="bg-white shadow-sm h-16 flex items-center justify-between px-6 flex-shrink-0 z-10 border-b border-slate-200">
  48. <h2 className="font-bold text-lg text-slate-800">管理控制台</h2>
  49. <div className="flex items-center gap-4">
  50. <div className="text-right hidden sm:block">
  51. <div className="text-sm font-medium text-slate-700">
  52. {user?.nickname || 'Administrator'}
  53. </div>
  54. <div className="text-xs text-slate-500">
  55. {user?.email}
  56. </div>
  57. </div>
  58. <div className="h-9 w-9 bg-blue-100 rounded-full flex items-center justify-center text-blue-600 font-bold text-sm border border-blue-200">
  59. AD
  60. </div>
  61. </div>
  62. </header>
  63. {/* 页面内容滚动区 */}
  64. <div className="flex-1 overflow-y-auto p-4 md:p-8 scroll-smooth">
  65. <div className="max-w-7xl mx-auto">
  66. {children}
  67. </div>
  68. </div>
  69. </main>
  70. </div>
  71. );
  72. }