## 修复内容 ### 依赖修复 - 安装缺失的 `prettier-plugin-organize-imports` 插件 - 修复 CI/CD 中的 "Cannot find package" 错误 - 更新 package.json 和 bun.lockb ### 代码格式化 - 对所有源文件运行 Prettier 自动格式化 - 统一 import 语句排序和组织 - 修复 49 个文件的代码风格问题 - 确保所有文件符合项目代码规范 ### 格式化改进 - Import 语句自动排序和分组 - 统一缩进和空格规范 - 标准化引号和分号使用 - 优化对象和数组格式 ## 验证结果 ✅ `bun run format` 通过 - 所有文件格式正确 ✅ `prettier-plugin-organize-imports` 正常工作 ✅ CI/CD 格式检查将通过 ## 技术细节 - 添加 prettier-plugin-organize-imports@^4.1.0 - 保持现有 .prettierrc 配置不变 - 格式化涉及 TS/TSX/JS/JSX/JSON/CSS/MD 文件 - 代码功能完全不受影响,仅调整格式
82 lines
2.5 KiB
TypeScript
82 lines
2.5 KiB
TypeScript
import { Button } from '@/components/ui/button'
|
||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
||
import { useAuthStore } from '@/stores/authStore'
|
||
import { Home, Shield } from 'lucide-react'
|
||
import { ReactNode } from '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
|