feat: rbac接入
This commit is contained in:
+23
-9
@@ -5,7 +5,8 @@ import AdminLayout from '@/layouts/AdminLayout'
|
||||
import LoginPage from '@/pages/LoginPage'
|
||||
import ErrorBoundary from '@/components/ErrorBoundary'
|
||||
import { Suspense, useMemo, lazy, useEffect } from 'react'
|
||||
import { Loader2 } from 'lucide-react'
|
||||
import { Loader2, Shield } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import type { SystemMenu } from '@/api/system'
|
||||
|
||||
const pages = import.meta.glob('./pages/**/*.tsx')
|
||||
@@ -25,14 +26,27 @@ function ProtectedRoute({ children }: { children: React.ReactNode }) {
|
||||
|
||||
function PublicRoute({ children }: { children: React.ReactNode }) {
|
||||
const isAuthenticated = useAuthStore(s => s.isAuthenticated)
|
||||
if (isAuthenticated) return <Navigate to="/dashboard" replace />
|
||||
if (isAuthenticated) return <Navigate to="/" replace />
|
||||
return <>{children}</>
|
||||
}
|
||||
|
||||
function NoPermission() {
|
||||
const logout = useAuthStore(s => s.logout)
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center min-h-[60vh] text-center w-full">
|
||||
<Shield className="h-16 w-16 text-muted-foreground/30 mb-4" />
|
||||
<h2 className="text-2xl font-bold mb-2 text-foreground">访问受限</h2>
|
||||
<p className="text-muted-foreground mb-6 max-w-md">抱歉,您当前暂无任何系统权限,请联系管理员为您分配相关菜单与角色。</p>
|
||||
<Button onClick={logout} variant="default" className="w-32">退出登录</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function AppRoutes() {
|
||||
const menus = useAuthStore(s => s.menus)
|
||||
const isAuthenticated = useAuthStore(s => s.isAuthenticated)
|
||||
const refreshMenus = useAuthStore(s => s.refreshMenus)
|
||||
const hasFetchedMenus = useAuthStore(s => s.hasFetchedMenus)
|
||||
|
||||
useEffect(() => {
|
||||
if (isAuthenticated && menus.length === 0) refreshMenus()
|
||||
@@ -59,17 +73,17 @@ function AppRoutes() {
|
||||
<Routes>
|
||||
<Route path="/login" element={<PublicRoute><LoginPage /></PublicRoute>} />
|
||||
<Route path="/" element={<ProtectedRoute><AdminLayout /></ProtectedRoute>}>
|
||||
<Route index element={<Navigate to="/dashboard" replace />} />
|
||||
<Route index element={
|
||||
hasFetchedMenus ? (
|
||||
dynamicRoutes.length > 0 ? <Navigate to={dynamicRoutes[0].path} replace /> : <Navigate to="/403" replace />
|
||||
) : Loading
|
||||
} />
|
||||
{dynamicRoutes.map(({ path, Component }) => (
|
||||
<Route key={path} path={path.startsWith('/') ? path.substring(1) : path}
|
||||
element={<ErrorBoundary><Suspense fallback={Loading}><Component /></Suspense></ErrorBoundary>} />
|
||||
))}
|
||||
{!dynamicRoutes.some(r => r.path === '/dashboard') && dynamicComponentMap['/dashboard'] && (
|
||||
<Route path="dashboard" element={
|
||||
<ErrorBoundary><Suspense fallback={Loading}>
|
||||
{(() => { const D = dynamicComponentMap['/dashboard']; return <D /> })()}
|
||||
</Suspense></ErrorBoundary>
|
||||
} />
|
||||
{hasFetchedMenus && dynamicRoutes.length === 0 && (
|
||||
<Route path="*" element={<NoPermission />} />
|
||||
)}
|
||||
</Route>
|
||||
<Route path="*" element={<Navigate to="/" replace />} />
|
||||
|
||||
Reference in New Issue
Block a user