feat: 平台管理员端 — SUPER_ADMIN 角色 + 企业租户管理 + 用户管理 + 数据总览
This commit is contained in:
@@ -37,6 +37,13 @@ const HealthCheck = lazy(() => import('./pages/tools/HealthCheck'))
|
||||
const AnnualValueReport = lazy(() => import('./pages/tools/AnnualValueReport'))
|
||||
const CalendarPage = lazy(() => import('./pages/Calendar'))
|
||||
|
||||
// 平台管理端
|
||||
const PlatformLogin = lazy(() => import('./pages/platform/PlatformLogin'))
|
||||
const PlatformDashboard = lazy(() => import('./pages/platform/PlatformDashboard'))
|
||||
const PlatformOrgs = lazy(() => import('./pages/platform/PlatformOrgs'))
|
||||
const PlatformUsers = lazy(() => import('./pages/platform/PlatformUsers'))
|
||||
const PlatformSidebar = lazy(() => import('./components/layout/PlatformSidebar'))
|
||||
|
||||
function ProtectedRoute({ children }: { children: React.ReactNode }) {
|
||||
const isAuthenticated = useAuthStore((s) => s.isAuthenticated)
|
||||
if (!isAuthenticated) return <Navigate to="/login" replace />
|
||||
@@ -67,6 +74,40 @@ function AdminLayout({ children }: { children: React.ReactNode }) {
|
||||
)
|
||||
}
|
||||
|
||||
function PlatformRoute({ children }: { children: React.ReactNode }) {
|
||||
const user = useAuthStore((s) => s.user)
|
||||
const isAuthenticated = useAuthStore((s) => s.isAuthenticated)
|
||||
if (!isAuthenticated || user?.role !== 'SUPER_ADMIN') return <Navigate to="/platform/login" replace />
|
||||
return <>{children}</>
|
||||
}
|
||||
|
||||
function PlatformLayout({ children }: { children: React.ReactNode }) {
|
||||
const [sidebarOpen, setSidebarOpen] = useState(false)
|
||||
return (
|
||||
<div className="flex min-h-screen bg-slate-100">
|
||||
<PlatformSidebar mobileOpen={sidebarOpen} onClose={() => setSidebarOpen(false)} />
|
||||
<div className="flex-1 flex flex-col min-w-0">
|
||||
<header className="h-14 bg-slate-950 border-b border-slate-800 flex items-center px-4 shrink-0">
|
||||
<button
|
||||
className="md:hidden mr-3 text-slate-400"
|
||||
onClick={() => setSidebarOpen(true)}
|
||||
aria-label="打开菜单"
|
||||
>
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
|
||||
</button>
|
||||
<span className="text-sm text-slate-400">平台管理后台</span>
|
||||
<span className="ml-2 px-2 py-0.5 rounded text-[10px] font-bold bg-amber-400 text-slate-950">ADMIN</span>
|
||||
</header>
|
||||
<main className="flex-1 py-6 px-4 md:px-6">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<Suspense fallback={<SkeletonPage />}>{children}</Suspense>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function PortalLayoutWrapper({ children, showNav = true }: { children: React.ReactNode; showNav?: boolean }) {
|
||||
if (!showNav) {
|
||||
return (
|
||||
@@ -112,6 +153,12 @@ export default function App() {
|
||||
<Route path="/tools/health-check" element={<ProtectedRoute><AdminLayout><HealthCheck /></AdminLayout></ProtectedRoute>} />
|
||||
<Route path="/tools/annual-value" element={<ProtectedRoute><AdminLayout><AnnualValueReport /></AdminLayout></ProtectedRoute>} />
|
||||
|
||||
{/* 平台管理端 */}
|
||||
<Route path="/platform/login" element={<Suspense fallback={<SkeletonPage />}><PlatformLogin /></Suspense>} />
|
||||
<Route path="/platform/dashboard" element={<PlatformRoute><PlatformLayout><PlatformDashboard /></PlatformLayout></PlatformRoute>} />
|
||||
<Route path="/platform/orgs" element={<PlatformRoute><PlatformLayout><PlatformOrgs /></PlatformLayout></PlatformRoute>} />
|
||||
<Route path="/platform/users" element={<PlatformRoute><PlatformLayout><PlatformUsers /></PlatformLayout></PlatformRoute>} />
|
||||
|
||||
{/* 员工端 */}
|
||||
<Route path="/portal/login" element={<PortalLayoutWrapper showNav={false}><PortalLogin /></PortalLayoutWrapper>} />
|
||||
<Route path="/portal/payslip" element={<PortalLayoutWrapper><Payslip /></PortalLayoutWrapper>} />
|
||||
|
||||
Reference in New Issue
Block a user