46 lines
1.3 KiB
TypeScript
46 lines
1.3 KiB
TypeScript
"use client";
|
|
|
|
import LockOutlinedIcon from "@mui/icons-material/LockOutlined";
|
|
import { Alert, Box, CircularProgress, Stack, Typography } from "@mui/material";
|
|
import { usePathname } from "next/navigation";
|
|
import type { ReactNode } from "react";
|
|
|
|
import { permissionForPath } from "@/lib/permissions";
|
|
import { useAccessStore } from "@/store/accessStore";
|
|
|
|
export const RoutePermissionGuard = ({
|
|
children,
|
|
}: {
|
|
children: ReactNode;
|
|
}) => {
|
|
const pathname = usePathname();
|
|
const permissions = useAccessStore((state) => state.permissions);
|
|
const loading = useAccessStore((state) => state.loading);
|
|
const requiredPermission = permissionForPath(pathname);
|
|
|
|
if (requiredPermission && loading) {
|
|
return (
|
|
<Box sx={{ minHeight: 320, display: "grid", placeItems: "center" }}>
|
|
<CircularProgress size={28} />
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
if (requiredPermission && !permissions.includes(requiredPermission)) {
|
|
return (
|
|
<Box sx={{ p: { xs: 2, md: 4 } }}>
|
|
<Alert severity="error" icon={<LockOutlinedIcon />}>
|
|
<Stack spacing={0.5}>
|
|
<Typography fontWeight={700}>无权访问此功能</Typography>
|
|
<Typography variant="body2">
|
|
当前项目角色缺少权限:{requiredPermission}
|
|
</Typography>
|
|
</Stack>
|
|
</Alert>
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
return children;
|
|
};
|