106 lines
2.5 KiB
TypeScript
106 lines
2.5 KiB
TypeScript
import { create } from 'zustand';
|
|
import { persist } from 'zustand/middleware';
|
|
import api from '../utils/api';
|
|
|
|
interface AdminInfo {
|
|
id: string;
|
|
username: string;
|
|
name: string;
|
|
role: string;
|
|
permissions: string[];
|
|
}
|
|
|
|
interface AuthState {
|
|
admin: AdminInfo | null;
|
|
token: string | null;
|
|
isAuthenticated: boolean;
|
|
login: (username: string, password: string) => Promise<void>;
|
|
logout: () => void;
|
|
checkAuth: () => Promise<boolean>;
|
|
hasPermission: (permission: string) => boolean;
|
|
}
|
|
|
|
export const useAuth = create<AuthState>()(
|
|
persist(
|
|
(set, get) => ({
|
|
admin: null,
|
|
token: null,
|
|
isAuthenticated: false,
|
|
|
|
login: async (username: string, password: string) => {
|
|
const response = await api.post('/admin/login', { username, password });
|
|
const { data } = response.data;
|
|
|
|
localStorage.setItem('admin_token', data.token);
|
|
|
|
set({
|
|
admin: data.admin,
|
|
token: data.token,
|
|
isAuthenticated: true,
|
|
});
|
|
},
|
|
|
|
logout: () => {
|
|
localStorage.removeItem('admin_token');
|
|
set({
|
|
admin: null,
|
|
token: null,
|
|
isAuthenticated: false,
|
|
});
|
|
},
|
|
|
|
checkAuth: async () => {
|
|
const token = localStorage.getItem('admin_token');
|
|
if (!token) {
|
|
set({ isAuthenticated: false, admin: null, token: null });
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
const response = await api.get('/admin/verify');
|
|
if (response.data.success) {
|
|
set({
|
|
admin: response.data.data,
|
|
token,
|
|
isAuthenticated: true,
|
|
});
|
|
return true;
|
|
}
|
|
} catch {
|
|
localStorage.removeItem('admin_token');
|
|
}
|
|
|
|
set({ isAuthenticated: false, admin: null, token: null });
|
|
return false;
|
|
},
|
|
|
|
hasPermission: (permission: string) => {
|
|
const { admin } = get();
|
|
if (!admin) return false;
|
|
|
|
const permissions = admin.permissions || [];
|
|
|
|
// 超管拥有所有权限
|
|
if (permissions.includes('*')) return true;
|
|
|
|
// 完全匹配
|
|
if (permissions.includes(permission)) return true;
|
|
|
|
// 通配符匹配
|
|
const [resource] = permission.split(':');
|
|
if (permissions.includes(`${resource}:*`)) return true;
|
|
|
|
return false;
|
|
},
|
|
}),
|
|
{
|
|
name: 'auth-storage',
|
|
partialize: (state) => ({
|
|
admin: state.admin,
|
|
token: state.token,
|
|
isAuthenticated: state.isAuthenticated,
|
|
}),
|
|
}
|
|
)
|
|
);
|