blob: 5f9b37e9c7a9b31a70ea36cd880ec5cfdef92054 [file] [log] [blame]
ybtda5978b2025-05-31 15:58:05 +08001import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
2import { loginUser, registerUser, getUserInfo, logoutUser } from '../services/authApi';
3import { message } from 'antd';
4import { useNavigate } from 'react-router-dom'; // 导入 useNavigate
5
6const AuthContext = createContext(null);
7
8export const AuthProvider = ({ children }) => {
9 const [user, setUser] = useState(null);
10 const [loading, setLoading] = useState(true); // 初始加载状态
11 const [isAuthenticated, setIsAuthenticated] = useState(false);
12 const navigate = useNavigate();
13
14 const loadAuthData = useCallback(() => {
15 setLoading(true);
16 try {
17 const storedToken = localStorage.getItem('authToken'); // 假设您使用token
18 const storedUser = localStorage.getItem('user');
19
20 if (storedToken && storedUser) {
21 setUser(JSON.parse(storedUser));
22 setIsAuthenticated(true);
23 // 调用API获取最新的用户信息
24 getUserInfo().then(response => {
25 if (response.data && response.data.user) {
26 setUser(response.data.user);
27 localStorage.setItem('user', JSON.stringify(response.data.user));
28 }
29 }).catch(error => {
30 console.error("获取用户信息失败", error);
31 });
32 } else {
33 setIsAuthenticated(false);
34 setUser(null);
35 }
36 } catch (error) {
37 console.error("Failed to load auth data from storage", error);
38 setIsAuthenticated(false);
39 setUser(null);
40 } finally {
41 setLoading(false);
42 }
43 }, []);
44
45 useEffect(() => {
46 loadAuthData();
47 }, [loadAuthData]);
48
49 const login = async (credentials) => {
50 setLoading(true);
51 try {
52 const response = await loginUser(credentials);
53 const { token, user: userData } = response.data;
54
55 localStorage.setItem('authToken', token);
56 localStorage.setItem('user', JSON.stringify(userData));
57 setUser(userData);
58 setIsAuthenticated(true);
59 message.success('登录成功');
60 return userData;
61 } catch (error) {
62 console.error("Login failed", error);
63 setIsAuthenticated(false);
64 setUser(null);
65 message.error(error.message || '登录失败,请检查用户名和密码');
66 } finally {
67 setLoading(false);
68 }
69 };
70
71 const register = async (userData) => {
72 setLoading(true);
73 try {
74 const response = await registerUser(userData);
75 const { token, user: newUser } = response.data;
76
77 localStorage.setItem('authToken', token);
78 localStorage.setItem('user', JSON.stringify(newUser));
79 setUser(newUser);
80 setIsAuthenticated(true);
81 message.success('注册成功');
82 return newUser;
83 } catch (error) {
84 console.error("Registration failed", error);
85 message.error(error.message || '注册失败,请稍后再试');
86 } finally {
87 setLoading(false);
88 }
89 };
90
91 const logout = async () => {
92 try {
93 await logoutUser();
94 localStorage.removeItem('authToken');
95 localStorage.removeItem('user');
96 localStorage.removeItem('permissions'); // 移除旧的权限存储
97 setUser(null);
98 setIsAuthenticated(false);
99 message.success('已成功退出登录');
100 navigate('/login');
101 return true;
102 } catch (error) {
103 console.error("登出失败", error);
104 message.error('登出失败');
105 return false;
106 }
107 };
108
109 const hasRole = useCallback((roleName) => {
110 return user?.role === roleName;
111 }, [user]);
112
113 const value = {
114 user,
115 isAuthenticated,
116 loading,
117 login,
118 register,
119 logout,
120 hasRole,
121 reloadAuthData: loadAuthData // 暴露一个重新加载数据的方法
122 };
123
124 return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
125};
126
127export const useAuth = () => {
128 const context = useContext(AuthContext);
129 if (context === undefined || context === null) { // 增加了对 null 的检查
130 throw new Error('useAuth must be used within an AuthProvider');
131 }
132 return context;
133};