blob: 5b59e68fcccd8ce096032cf467f5ad34c530e384 [file] [log] [blame]
ybtbac75f22025-06-08 22:31:15 +08001import React, {
2 createContext,
3 useContext,
4 useState,
5 useEffect,
6 useCallback,
7} from "react";
ybt0d010e52025-06-09 00:29:36 +08008import { userLogin, registerUser, logoutUser, adminLogin as adminLoginAPI } from "@/api/auth";
ybt3ec62e42025-06-11 22:46:22 +08009import { getUserInfo } from "@/api/user";
ybtbac75f22025-06-08 22:31:15 +080010import { message } from "antd";
11import { useNavigate } from "react-router-dom"; // 导入 useNavigate
ybtda5978b2025-05-31 15:58:05 +080012
13const AuthContext = createContext(null);
14
15export const AuthProvider = ({ children }) => {
16 const [user, setUser] = useState(null);
17 const [loading, setLoading] = useState(true); // 初始加载状态
18 const [isAuthenticated, setIsAuthenticated] = useState(false);
19 const navigate = useNavigate();
20
21 const loadAuthData = useCallback(() => {
22 setLoading(true);
23 try {
ybtbac75f22025-06-08 22:31:15 +080024 const storedToken = localStorage.getItem("token");
25 const storedUser = localStorage.getItem("user");
26
27 console.log("Loading auth data - token:", !!storedToken, "user:", !!storedUser);
ybtda5978b2025-05-31 15:58:05 +080028
29 if (storedToken && storedUser) {
ybtbac75f22025-06-08 22:31:15 +080030 try {
31 const userData = JSON.parse(storedUser);
32 // console.log("Parsed user data:", userData);
33 setUser(userData);
34 setIsAuthenticated(true);
35 } catch (parseError) {
36 console.error("Failed to parse stored user data:", parseError);
37 // 如果解析失败,清除损坏的数据
38 localStorage.removeItem("token");
39 localStorage.removeItem("user");
40 setIsAuthenticated(false);
41 setUser(null);
42 }
ybtda5978b2025-05-31 15:58:05 +080043 } else {
ybtbac75f22025-06-08 22:31:15 +080044 console.log("No stored auth data found");
ybtda5978b2025-05-31 15:58:05 +080045 setIsAuthenticated(false);
46 setUser(null);
47 }
48 } catch (error) {
49 console.error("Failed to load auth data from storage", error);
50 setIsAuthenticated(false);
51 setUser(null);
52 } finally {
53 setLoading(false);
54 }
55 }, []);
56
57 useEffect(() => {
58 loadAuthData();
59 }, [loadAuthData]);
60
ybtbac75f22025-06-08 22:31:15 +080061 const login = async (params) => {
ybtda5978b2025-05-31 15:58:05 +080062 setLoading(true);
63 try {
ybtbac75f22025-06-08 22:31:15 +080064 const response = await userLogin(params);
65 // 检查响应是否成功
66 if (response && response.data) {
67 const token = response.data.token;
68 const userData = response.data;
69
70 console.log("Saving token:", token);
71 console.log("Saving user data:", userData);
72
73 localStorage.setItem("token", token);
74 localStorage.setItem("user", JSON.stringify(userData));
75
76 setUser(userData);
77 setIsAuthenticated(true);
78
79 message.success(response?.message || "登录成功");
80 return userData;
81 }
ybtda5978b2025-05-31 15:58:05 +080082 } catch (error) {
ybtbac75f22025-06-08 22:31:15 +080083 console.log("login error", error);
ybtda5978b2025-05-31 15:58:05 +080084 setIsAuthenticated(false);
85 setUser(null);
ybtbac75f22025-06-08 22:31:15 +080086 message.error(error.message || "登录失败,请检查用户名和密码");
ybtda5978b2025-05-31 15:58:05 +080087 } finally {
88 setLoading(false);
89 }
90 };
91
ybt0d010e52025-06-09 00:29:36 +080092 const adminLogin = async (params) => {
93 setLoading(true);
94 try {
95 const response = await adminLoginAPI(params);
96
97 if (response && response.data) {
98 const token = response.data.token;
99 const adminData = response.data;
100
101 console.log("Saving user data:", adminData);
102
103 localStorage.setItem("token", token);
104 localStorage.setItem("user", JSON.stringify(adminData));
105
106 setUser(adminData);
107 setIsAuthenticated(true);
108
109 message.success(response?.message || "登录成功");
110 return adminData;
111 }
112 } catch (error) {
113 console.log("admin login error", error);
114 setIsAuthenticated(false);
115 setUser(null);
116 message.error(error.message || "管理员登录失败,请检查用户名和密码");
117 } finally {
118 setLoading(false);
119 }
120 };
121
ybtda5978b2025-05-31 15:58:05 +0800122 const register = async (userData) => {
123 setLoading(true);
124 try {
125 const response = await registerUser(userData);
ybtda5978b2025-05-31 15:58:05 +0800126
ybtbac75f22025-06-08 22:31:15 +0800127 // 检查响应是否成功
128 if (response.data && response.data.success) {
129 const { token, user: newUser } = response.data.data;
130
131 localStorage.setItem("token", token);
132 localStorage.setItem("user", JSON.stringify(newUser));
133 setUser(newUser);
134 setIsAuthenticated(true);
135 message.success("注册成功");
136 return newUser;
137 } else {
138 throw new Error(response.data?.message || "注册失败");
139 }
ybtda5978b2025-05-31 15:58:05 +0800140 } catch (error) {
141 console.error("Registration failed", error);
ybtbac75f22025-06-08 22:31:15 +0800142 message.error(error.message || "注册失败,请稍后再试");
ybtda5978b2025-05-31 15:58:05 +0800143 } finally {
144 setLoading(false);
145 }
146 };
147
148 const logout = async () => {
149 try {
150 await logoutUser();
ybtbac75f22025-06-08 22:31:15 +0800151 localStorage.removeItem("token");
152 localStorage.removeItem("user");
153 localStorage.removeItem("permissions"); // 移除旧的权限存储
ybtda5978b2025-05-31 15:58:05 +0800154 setUser(null);
155 setIsAuthenticated(false);
ybtbac75f22025-06-08 22:31:15 +0800156 message.success("已成功退出登录");
157 navigate("/login");
ybtda5978b2025-05-31 15:58:05 +0800158 return true;
159 } catch (error) {
160 console.error("登出失败", error);
ybtbac75f22025-06-08 22:31:15 +0800161 message.error("登出失败");
ybtda5978b2025-05-31 15:58:05 +0800162 return false;
163 }
164 };
165
ybtbac75f22025-06-08 22:31:15 +0800166 const hasRole = useCallback(
167 (roleName) => {
ybt0d010e52025-06-09 00:29:36 +0800168 if (user?.uid.includes('admin')) {
169 return true;
170 } else {
171 return user?.role === roleName;
172 }
ybtbac75f22025-06-08 22:31:15 +0800173 },
174 [user]
175 );
ybtda5978b2025-05-31 15:58:05 +0800176
ybt3ec62e42025-06-11 22:46:22 +0800177 // 更新用户信息的方法
178 const updateUserInfo = useCallback(async (username) => {
179 try {
180 const response = await getUserInfo(username || user?.username);
181
182 if (response && response.data) {
183 const updatedUserData = {
184 ...user,
185 ...response.data
186 };
187
188 // 更新localStorage和state
189 localStorage.setItem("user", JSON.stringify(updatedUserData));
190 setUser(updatedUserData);
191
192 console.log('用户信息已更新:', updatedUserData);
193 return updatedUserData;
194 } else {
195 console.error('获取用户信息失败:响应数据格式错误');
196 return null;
197 }
198 } catch (error) {
199 console.error('更新用户信息失败:', error);
200 message.error('更新用户信息失败: ' + (error.message || '网络错误'));
201 return null;
202 }
203 }, [user]);
204
ybtda5978b2025-05-31 15:58:05 +0800205 const value = {
206 user,
207 isAuthenticated,
208 loading,
209 login,
ybt0d010e52025-06-09 00:29:36 +0800210 adminLogin,
ybtda5978b2025-05-31 15:58:05 +0800211 register,
212 logout,
213 hasRole,
ybtbac75f22025-06-08 22:31:15 +0800214 reloadAuthData: loadAuthData, // 暴露一个重新加载数据的方法
ybt3ec62e42025-06-11 22:46:22 +0800215 updateUserInfo, // 暴露更新用户信息的方法
ybtda5978b2025-05-31 15:58:05 +0800216 };
217
218 return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
219};
220
221export const useAuth = () => {
222 const context = useContext(AuthContext);
ybtbac75f22025-06-08 22:31:15 +0800223 if (context === undefined || context === null) {
224 // 增加了对 null 的检查
225 throw new Error("useAuth must be used within an AuthProvider");
ybtda5978b2025-05-31 15:58:05 +0800226 }
227 return context;
ybtbac75f22025-06-08 22:31:15 +0800228};