blob: b0afd8e4af8ba25e5b76258b18793f65c0d89ab3 [file] [log] [blame]
ybtbac75f22025-06-08 22:31:15 +08001import React, {
2 createContext,
3 useContext,
4 useState,
5 useEffect,
6 useCallback,
7} from "react";
8import { userLogin, registerUser, logoutUser } from "@/api/auth";
9import { 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
91 const register = async (userData) => {
92 setLoading(true);
93 try {
94 const response = await registerUser(userData);
ybtda5978b2025-05-31 15:58:05 +080095
ybtbac75f22025-06-08 22:31:15 +080096 // 检查响应是否成功
97 if (response.data && response.data.success) {
98 const { token, user: newUser } = response.data.data;
99
100 localStorage.setItem("token", token);
101 localStorage.setItem("user", JSON.stringify(newUser));
102 setUser(newUser);
103 setIsAuthenticated(true);
104 message.success("注册成功");
105 return newUser;
106 } else {
107 throw new Error(response.data?.message || "注册失败");
108 }
ybtda5978b2025-05-31 15:58:05 +0800109 } catch (error) {
110 console.error("Registration failed", error);
ybtbac75f22025-06-08 22:31:15 +0800111 message.error(error.message || "注册失败,请稍后再试");
ybtda5978b2025-05-31 15:58:05 +0800112 } finally {
113 setLoading(false);
114 }
115 };
116
117 const logout = async () => {
118 try {
119 await logoutUser();
ybtbac75f22025-06-08 22:31:15 +0800120 localStorage.removeItem("token");
121 localStorage.removeItem("user");
122 localStorage.removeItem("permissions"); // 移除旧的权限存储
ybtda5978b2025-05-31 15:58:05 +0800123 setUser(null);
124 setIsAuthenticated(false);
ybtbac75f22025-06-08 22:31:15 +0800125 message.success("已成功退出登录");
126 navigate("/login");
ybtda5978b2025-05-31 15:58:05 +0800127 return true;
128 } catch (error) {
129 console.error("登出失败", error);
ybtbac75f22025-06-08 22:31:15 +0800130 message.error("登出失败");
ybtda5978b2025-05-31 15:58:05 +0800131 return false;
132 }
133 };
134
ybtbac75f22025-06-08 22:31:15 +0800135 const hasRole = useCallback(
136 (roleName) => {
137 return user?.role === roleName;
138 },
139 [user]
140 );
ybtda5978b2025-05-31 15:58:05 +0800141
142 const value = {
143 user,
144 isAuthenticated,
145 loading,
146 login,
147 register,
148 logout,
149 hasRole,
ybtbac75f22025-06-08 22:31:15 +0800150 reloadAuthData: loadAuthData, // 暴露一个重新加载数据的方法
ybtda5978b2025-05-31 15:58:05 +0800151 };
152
153 return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
154};
155
156export const useAuth = () => {
157 const context = useContext(AuthContext);
ybtbac75f22025-06-08 22:31:15 +0800158 if (context === undefined || context === null) {
159 // 增加了对 null 的检查
160 throw new Error("useAuth must be used within an AuthProvider");
ybtda5978b2025-05-31 15:58:05 +0800161 }
162 return context;
ybtbac75f22025-06-08 22:31:15 +0800163};