blob: 3c53c9c1209b860c95828b3d728f2889ee1c8a13 [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";
ybtbac75f22025-06-08 22:31:15 +08009import { message } from "antd";
10import { useNavigate } from "react-router-dom"; // 导入 useNavigate
ybtda5978b2025-05-31 15:58:05 +080011
12const AuthContext = createContext(null);
13
14export const AuthProvider = ({ children }) => {
15 const [user, setUser] = useState(null);
16 const [loading, setLoading] = useState(true); // 初始加载状态
17 const [isAuthenticated, setIsAuthenticated] = useState(false);
18 const navigate = useNavigate();
19
20 const loadAuthData = useCallback(() => {
21 setLoading(true);
22 try {
ybtbac75f22025-06-08 22:31:15 +080023 const storedToken = localStorage.getItem("token");
24 const storedUser = localStorage.getItem("user");
25
26 console.log("Loading auth data - token:", !!storedToken, "user:", !!storedUser);
ybtda5978b2025-05-31 15:58:05 +080027
28 if (storedToken && storedUser) {
ybtbac75f22025-06-08 22:31:15 +080029 try {
30 const userData = JSON.parse(storedUser);
31 // console.log("Parsed user data:", userData);
32 setUser(userData);
33 setIsAuthenticated(true);
34 } catch (parseError) {
35 console.error("Failed to parse stored user data:", parseError);
36 // 如果解析失败,清除损坏的数据
37 localStorage.removeItem("token");
38 localStorage.removeItem("user");
39 setIsAuthenticated(false);
40 setUser(null);
41 }
ybtda5978b2025-05-31 15:58:05 +080042 } else {
ybtbac75f22025-06-08 22:31:15 +080043 console.log("No stored auth data found");
ybtda5978b2025-05-31 15:58:05 +080044 setIsAuthenticated(false);
45 setUser(null);
46 }
47 } catch (error) {
48 console.error("Failed to load auth data from storage", error);
49 setIsAuthenticated(false);
50 setUser(null);
51 } finally {
52 setLoading(false);
53 }
54 }, []);
55
56 useEffect(() => {
57 loadAuthData();
58 }, [loadAuthData]);
59
ybtbac75f22025-06-08 22:31:15 +080060 const login = async (params) => {
ybtda5978b2025-05-31 15:58:05 +080061 setLoading(true);
62 try {
ybtbac75f22025-06-08 22:31:15 +080063 const response = await userLogin(params);
64 // 检查响应是否成功
65 if (response && response.data) {
66 const token = response.data.token;
67 const userData = response.data;
68
69 console.log("Saving token:", token);
70 console.log("Saving user data:", userData);
71
72 localStorage.setItem("token", token);
73 localStorage.setItem("user", JSON.stringify(userData));
74
75 setUser(userData);
76 setIsAuthenticated(true);
77
78 message.success(response?.message || "登录成功");
79 return userData;
80 }
ybtda5978b2025-05-31 15:58:05 +080081 } catch (error) {
ybtbac75f22025-06-08 22:31:15 +080082 console.log("login error", error);
ybtda5978b2025-05-31 15:58:05 +080083 setIsAuthenticated(false);
84 setUser(null);
ybtbac75f22025-06-08 22:31:15 +080085 message.error(error.message || "登录失败,请检查用户名和密码");
ybtda5978b2025-05-31 15:58:05 +080086 } finally {
87 setLoading(false);
88 }
89 };
90
ybt0d010e52025-06-09 00:29:36 +080091 const adminLogin = async (params) => {
92 setLoading(true);
93 try {
94 const response = await adminLoginAPI(params);
95
96 if (response && response.data) {
97 const token = response.data.token;
98 const adminData = response.data;
99
100 console.log("Saving user data:", adminData);
101
102 localStorage.setItem("token", token);
103 localStorage.setItem("user", JSON.stringify(adminData));
104
105 setUser(adminData);
106 setIsAuthenticated(true);
107
108 message.success(response?.message || "登录成功");
109 return adminData;
110 }
111 } catch (error) {
112 console.log("admin login error", error);
113 setIsAuthenticated(false);
114 setUser(null);
115 message.error(error.message || "管理员登录失败,请检查用户名和密码");
116 } finally {
117 setLoading(false);
118 }
119 };
120
ybtda5978b2025-05-31 15:58:05 +0800121 const register = async (userData) => {
122 setLoading(true);
123 try {
124 const response = await registerUser(userData);
ybtda5978b2025-05-31 15:58:05 +0800125
ybtbac75f22025-06-08 22:31:15 +0800126 // 检查响应是否成功
127 if (response.data && response.data.success) {
128 const { token, user: newUser } = response.data.data;
129
130 localStorage.setItem("token", token);
131 localStorage.setItem("user", JSON.stringify(newUser));
132 setUser(newUser);
133 setIsAuthenticated(true);
134 message.success("注册成功");
135 return newUser;
136 } else {
137 throw new Error(response.data?.message || "注册失败");
138 }
ybtda5978b2025-05-31 15:58:05 +0800139 } catch (error) {
140 console.error("Registration failed", error);
ybtbac75f22025-06-08 22:31:15 +0800141 message.error(error.message || "注册失败,请稍后再试");
ybtda5978b2025-05-31 15:58:05 +0800142 } finally {
143 setLoading(false);
144 }
145 };
146
147 const logout = async () => {
148 try {
149 await logoutUser();
ybtbac75f22025-06-08 22:31:15 +0800150 localStorage.removeItem("token");
151 localStorage.removeItem("user");
152 localStorage.removeItem("permissions"); // 移除旧的权限存储
ybtda5978b2025-05-31 15:58:05 +0800153 setUser(null);
154 setIsAuthenticated(false);
ybtbac75f22025-06-08 22:31:15 +0800155 message.success("已成功退出登录");
156 navigate("/login");
ybtda5978b2025-05-31 15:58:05 +0800157 return true;
158 } catch (error) {
159 console.error("登出失败", error);
ybtbac75f22025-06-08 22:31:15 +0800160 message.error("登出失败");
ybtda5978b2025-05-31 15:58:05 +0800161 return false;
162 }
163 };
164
ybtbac75f22025-06-08 22:31:15 +0800165 const hasRole = useCallback(
166 (roleName) => {
ybt0d010e52025-06-09 00:29:36 +0800167 if (user?.uid.includes('admin')) {
168 return true;
169 } else {
170 return user?.role === roleName;
171 }
ybtbac75f22025-06-08 22:31:15 +0800172 },
173 [user]
174 );
ybtda5978b2025-05-31 15:58:05 +0800175
176 const value = {
177 user,
178 isAuthenticated,
179 loading,
180 login,
ybt0d010e52025-06-09 00:29:36 +0800181 adminLogin,
ybtda5978b2025-05-31 15:58:05 +0800182 register,
183 logout,
184 hasRole,
ybtbac75f22025-06-08 22:31:15 +0800185 reloadAuthData: loadAuthData, // 暴露一个重新加载数据的方法
ybtda5978b2025-05-31 15:58:05 +0800186 };
187
188 return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
189};
190
191export const useAuth = () => {
192 const context = useContext(AuthContext);
ybtbac75f22025-06-08 22:31:15 +0800193 if (context === undefined || context === null) {
194 // 增加了对 null 的检查
195 throw new Error("useAuth must be used within an AuthProvider");
ybtda5978b2025-05-31 15:58:05 +0800196 }
197 return context;
ybtbac75f22025-06-08 22:31:15 +0800198};