forked from wangziqi/gongxue-base
feat(frontend): add usePermission hook, PermissionButton, PermissionRoute, and 403 handling
This commit is contained in:
@@ -19,8 +19,13 @@ api.interceptors.response.use(
|
||||
if (err.response?.status === 401) {
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('user');
|
||||
localStorage.removeItem('permissions');
|
||||
window.location.href = '/login';
|
||||
}
|
||||
if (err.response?.status === 403) {
|
||||
const msg = err.response?.data?.message || '权限不足';
|
||||
console.warn('[403]', msg);
|
||||
}
|
||||
return Promise.reject(err.response?.data || err);
|
||||
},
|
||||
);
|
||||
|
||||
17
frontend/src/components/PermissionButton.tsx
Normal file
17
frontend/src/components/PermissionButton.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
import { Button } from 'antd';
|
||||
import type { ButtonProps } from 'antd';
|
||||
import { usePermission } from '../hooks/usePermission';
|
||||
|
||||
interface PermissionButtonProps extends ButtonProps {
|
||||
permission: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const PermissionButton: React.FC<PermissionButtonProps> = ({ permission, children, ...btnProps }) => {
|
||||
const { hasPermission } = usePermission();
|
||||
if (!hasPermission(permission)) return null;
|
||||
return <Button {...btnProps}>{children}</Button>;
|
||||
};
|
||||
|
||||
export default PermissionButton;
|
||||
24
frontend/src/components/PermissionRoute.tsx
Normal file
24
frontend/src/components/PermissionRoute.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import React from 'react';
|
||||
import { Result } from 'antd';
|
||||
import { usePermission } from '../hooks/usePermission';
|
||||
|
||||
interface PermissionRouteProps {
|
||||
permission: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const PermissionRoute: React.FC<PermissionRouteProps> = ({ permission, children }) => {
|
||||
const { hasPermission } = usePermission();
|
||||
if (!hasPermission(permission)) {
|
||||
return (
|
||||
<Result
|
||||
status="403"
|
||||
title="无权访问"
|
||||
subTitle="您没有访问此页面的权限"
|
||||
/>
|
||||
);
|
||||
}
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export default PermissionRoute;
|
||||
21
frontend/src/hooks/usePermission.ts
Normal file
21
frontend/src/hooks/usePermission.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export function usePermission() {
|
||||
const permissions: string[] = useMemo(() => {
|
||||
try {
|
||||
return JSON.parse(localStorage.getItem('permissions') || '[]');
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}, []);
|
||||
|
||||
const hasPermission = (code: string): boolean => permissions.includes(code);
|
||||
|
||||
const hasAnyPermission = (...codes: string[]): boolean =>
|
||||
codes.some(c => permissions.includes(c));
|
||||
|
||||
const hasAllPermissions = (...codes: string[]): boolean =>
|
||||
codes.every(c => permissions.includes(c));
|
||||
|
||||
return { permissions, hasPermission, hasAnyPermission, hasAllPermissions };
|
||||
}
|
||||
@@ -16,6 +16,7 @@ const LoginPage: React.FC = () => {
|
||||
const res: any = await api.post('/auth/login', values);
|
||||
localStorage.setItem('token', res.access_token);
|
||||
localStorage.setItem('user', JSON.stringify(res.user));
|
||||
localStorage.setItem('permissions', JSON.stringify(res.user.permissions || []));
|
||||
message.success('登录成功');
|
||||
navigate('/dashboard');
|
||||
} catch (err: any) {
|
||||
|
||||
Reference in New Issue
Block a user