管理后台
This commit is contained in:
91
admin/src/components/ProtectedRoute.tsx
Normal file
91
admin/src/components/ProtectedRoute.tsx
Normal file
@ -0,0 +1,91 @@
|
||||
import { ReactNode } from 'react'
|
||||
import { useAuthStore } from '@/stores/authStore'
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Shield, Home } from 'lucide-react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
|
||||
interface ProtectedRouteProps {
|
||||
children: ReactNode
|
||||
requiredRole?: 'admin' | 'editor' | 'user'
|
||||
fallback?: ReactNode
|
||||
}
|
||||
|
||||
export function ProtectedRoute({
|
||||
children,
|
||||
requiredRole,
|
||||
fallback
|
||||
}: ProtectedRouteProps) {
|
||||
const { user, isAuthenticated } = useAuthStore()
|
||||
const navigate = useNavigate()
|
||||
|
||||
// 如果未登录,这个检查应该在 App.tsx 层面处理
|
||||
if (!isAuthenticated || !user) {
|
||||
return null
|
||||
}
|
||||
|
||||
// 角色权限检查
|
||||
if (requiredRole) {
|
||||
const roleHierarchy = {
|
||||
'user': 0,
|
||||
'editor': 1,
|
||||
'admin': 2
|
||||
}
|
||||
|
||||
const userRoleLevel = roleHierarchy[user.role] || 0
|
||||
const requiredRoleLevel = roleHierarchy[requiredRole] || 0
|
||||
|
||||
if (userRoleLevel < requiredRoleLevel) {
|
||||
if (fallback) {
|
||||
return <>{fallback}</>
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-gray-50 p-4">
|
||||
<Card className="w-full max-w-md text-center">
|
||||
<CardHeader>
|
||||
<div className="flex justify-center mb-4">
|
||||
<Shield className="h-16 w-16 text-orange-400" />
|
||||
</div>
|
||||
<CardTitle className="text-xl">权限不足</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<p className="text-muted-foreground">
|
||||
抱歉,您没有访问此页面的权限。
|
||||
</p>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
当前角色: <span className="font-medium">{getRoleText(user.role)}</span><br />
|
||||
需要角色: <span className="font-medium">{getRoleText(requiredRole)}</span>
|
||||
</p>
|
||||
|
||||
<Button
|
||||
onClick={() => navigate('/dashboard')}
|
||||
className="w-full"
|
||||
>
|
||||
<Home className="h-4 w-4 mr-2" />
|
||||
返回首页
|
||||
</Button>
|
||||
|
||||
<div className="text-sm text-muted-foreground">
|
||||
错误代码: 403
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return <>{children}</>
|
||||
}
|
||||
|
||||
function getRoleText(role: string) {
|
||||
const roleTexts = {
|
||||
'admin': '管理员',
|
||||
'editor': '编辑者',
|
||||
'user': '用户'
|
||||
}
|
||||
return roleTexts[role as keyof typeof roleTexts] || role
|
||||
}
|
||||
|
||||
export default ProtectedRoute
|
||||
Reference in New Issue
Block a user