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) {
|
if (err.response?.status === 401) {
|
||||||
localStorage.removeItem('token');
|
localStorage.removeItem('token');
|
||||||
localStorage.removeItem('user');
|
localStorage.removeItem('user');
|
||||||
|
localStorage.removeItem('permissions');
|
||||||
window.location.href = '/login';
|
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);
|
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);
|
const res: any = await api.post('/auth/login', values);
|
||||||
localStorage.setItem('token', res.access_token);
|
localStorage.setItem('token', res.access_token);
|
||||||
localStorage.setItem('user', JSON.stringify(res.user));
|
localStorage.setItem('user', JSON.stringify(res.user));
|
||||||
|
localStorage.setItem('permissions', JSON.stringify(res.user.permissions || []));
|
||||||
message.success('登录成功');
|
message.success('登录成功');
|
||||||
navigate('/dashboard');
|
navigate('/dashboard');
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
|
|||||||
Reference in New Issue
Block a user