feat(api): 重构 API 调用并优化用户认证流程
- 新增 auth、forum 和 user API 文件夹,重新组织 API 调用结构
- 重构 AuthContext,使用新 API 进行用户认证和信息管理
- 更新 AdminPanel、ForumPage 等组件,使用新的 API 调用
- 删除旧的 authApi.js 文件,清理冗余代码
- 优化用户登录、注册和登出流程,改进错误处理和用户提示
Change-Id: If664193e1bf30036c197f164edc5b10df75f1331
diff --git a/src/features/auth/contexts/AuthContext.jsx b/src/features/auth/contexts/AuthContext.jsx
index 5f9b37e..b0afd8e 100644
--- a/src/features/auth/contexts/AuthContext.jsx
+++ b/src/features/auth/contexts/AuthContext.jsx
@@ -1,7 +1,13 @@
-import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
-import { loginUser, registerUser, getUserInfo, logoutUser } from '../services/authApi';
-import { message } from 'antd';
-import { useNavigate } from 'react-router-dom'; // 导入 useNavigate
+import React, {
+ createContext,
+ useContext,
+ useState,
+ useEffect,
+ useCallback,
+} from "react";
+import { userLogin, registerUser, logoutUser } from "@/api/auth";
+import { message } from "antd";
+import { useNavigate } from "react-router-dom"; // 导入 useNavigate
const AuthContext = createContext(null);
@@ -14,22 +20,27 @@
const loadAuthData = useCallback(() => {
setLoading(true);
try {
- const storedToken = localStorage.getItem('authToken'); // 假设您使用token
- const storedUser = localStorage.getItem('user');
+ const storedToken = localStorage.getItem("token");
+ const storedUser = localStorage.getItem("user");
+
+ console.log("Loading auth data - token:", !!storedToken, "user:", !!storedUser);
if (storedToken && storedUser) {
- setUser(JSON.parse(storedUser));
- setIsAuthenticated(true);
- // 调用API获取最新的用户信息
- getUserInfo().then(response => {
- if (response.data && response.data.user) {
- setUser(response.data.user);
- localStorage.setItem('user', JSON.stringify(response.data.user));
- }
- }).catch(error => {
- console.error("获取用户信息失败", error);
- });
+ try {
+ const userData = JSON.parse(storedUser);
+ // console.log("Parsed user data:", userData);
+ setUser(userData);
+ setIsAuthenticated(true);
+ } catch (parseError) {
+ console.error("Failed to parse stored user data:", parseError);
+ // 如果解析失败,清除损坏的数据
+ localStorage.removeItem("token");
+ localStorage.removeItem("user");
+ setIsAuthenticated(false);
+ setUser(null);
+ }
} else {
+ console.log("No stored auth data found");
setIsAuthenticated(false);
setUser(null);
}
@@ -46,23 +57,32 @@
loadAuthData();
}, [loadAuthData]);
- const login = async (credentials) => {
+ const login = async (params) => {
setLoading(true);
try {
- const response = await loginUser(credentials);
- const { token, user: userData } = response.data;
-
- localStorage.setItem('authToken', token);
- localStorage.setItem('user', JSON.stringify(userData));
- setUser(userData);
- setIsAuthenticated(true);
- message.success('登录成功');
- return userData;
+ const response = await userLogin(params);
+ // 检查响应是否成功
+ if (response && response.data) {
+ const token = response.data.token;
+ const userData = response.data;
+
+ console.log("Saving token:", token);
+ console.log("Saving user data:", userData);
+
+ localStorage.setItem("token", token);
+ localStorage.setItem("user", JSON.stringify(userData));
+
+ setUser(userData);
+ setIsAuthenticated(true);
+
+ message.success(response?.message || "登录成功");
+ return userData;
+ }
} catch (error) {
- console.error("Login failed", error);
+ console.log("login error", error);
setIsAuthenticated(false);
setUser(null);
- message.error(error.message || '登录失败,请检查用户名和密码');
+ message.error(error.message || "登录失败,请检查用户名和密码");
} finally {
setLoading(false);
}
@@ -72,17 +92,23 @@
setLoading(true);
try {
const response = await registerUser(userData);
- const { token, user: newUser } = response.data;
- localStorage.setItem('authToken', token);
- localStorage.setItem('user', JSON.stringify(newUser));
- setUser(newUser);
- setIsAuthenticated(true);
- message.success('注册成功');
- return newUser;
+ // 检查响应是否成功
+ if (response.data && response.data.success) {
+ const { token, user: newUser } = response.data.data;
+
+ localStorage.setItem("token", token);
+ localStorage.setItem("user", JSON.stringify(newUser));
+ setUser(newUser);
+ setIsAuthenticated(true);
+ message.success("注册成功");
+ return newUser;
+ } else {
+ throw new Error(response.data?.message || "注册失败");
+ }
} catch (error) {
console.error("Registration failed", error);
- message.error(error.message || '注册失败,请稍后再试');
+ message.error(error.message || "注册失败,请稍后再试");
} finally {
setLoading(false);
}
@@ -91,24 +117,27 @@
const logout = async () => {
try {
await logoutUser();
- localStorage.removeItem('authToken');
- localStorage.removeItem('user');
- localStorage.removeItem('permissions'); // 移除旧的权限存储
+ localStorage.removeItem("token");
+ localStorage.removeItem("user");
+ localStorage.removeItem("permissions"); // 移除旧的权限存储
setUser(null);
setIsAuthenticated(false);
- message.success('已成功退出登录');
- navigate('/login');
+ message.success("已成功退出登录");
+ navigate("/login");
return true;
} catch (error) {
console.error("登出失败", error);
- message.error('登出失败');
+ message.error("登出失败");
return false;
}
};
- const hasRole = useCallback((roleName) => {
- return user?.role === roleName;
- }, [user]);
+ const hasRole = useCallback(
+ (roleName) => {
+ return user?.role === roleName;
+ },
+ [user]
+ );
const value = {
user,
@@ -118,7 +147,7 @@
register,
logout,
hasRole,
- reloadAuthData: loadAuthData // 暴露一个重新加载数据的方法
+ reloadAuthData: loadAuthData, // 暴露一个重新加载数据的方法
};
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
@@ -126,8 +155,9 @@
export const useAuth = () => {
const context = useContext(AuthContext);
- if (context === undefined || context === null) { // 增加了对 null 的检查
- throw new Error('useAuth must be used within an AuthProvider');
+ if (context === undefined || context === null) {
+ // 增加了对 null 的检查
+ throw new Error("useAuth must be used within an AuthProvider");
}
return context;
-};
\ No newline at end of file
+};
diff --git a/src/features/auth/pages/LoginPage.jsx b/src/features/auth/pages/LoginPage.jsx
index 19434a4..3a8cdbc 100644
--- a/src/features/auth/pages/LoginPage.jsx
+++ b/src/features/auth/pages/LoginPage.jsx
@@ -14,7 +14,6 @@
} from "antd";
import { UserOutlined, LockOutlined } from "@ant-design/icons";
import { useAuth } from "../contexts/AuthContext"; // 使用新的 AuthContext
-// import { loginUser } from '../services/authApi'; // 如果不直接在 context 中调用 API
const { Title, Text } = Typography;
@@ -33,10 +32,18 @@
const onFinish = async (values) => {
setLoading(true);
try {
- await login({ username: values.username, password: values.password });
- // 登录成功后的导航由 AuthContext 内部或 ProtectedRoute 处理
- // AuthContext 已经包含成功提示,这里不再重复提示
- navigate("/"); // 或者根据用户角色导航到不同页面
+ const params = {
+ username: values.username,
+ password: values.password,
+ };
+ const userData = await login(params);
+
+ // 根据用户角色导航到不同页面
+ if (userData && userData.role === 'admin') {
+ navigate("/admin"); // 管理员导航到管理面板
+ } else {
+ navigate("/"); // 普通用户导航到首页
+ }
} catch (error) {
// 错误消息由 AuthContext 中的 login 方法或 request 拦截器处理
console.error("Login page error:", error);
diff --git a/src/features/auth/services/authApi.js b/src/features/auth/services/authApi.js
deleted file mode 100644
index dd40a80..0000000
--- a/src/features/auth/services/authApi.js
+++ /dev/null
@@ -1,165 +0,0 @@
-// src/features/auth/services/authApi.js
-import request from "../../../services/request";
-import { message } from "antd";
-
-// 使用API前缀
-const API_PREFIX = "/user";
-const ADMIN_PREFIX = "/admin";
-
-// 导出API函数
-export const loginUser = (credentials) => {
- return request.post(`${API_PREFIX}/login`, credentials).then((response) => {
- if (response.data && response.data.success) {
- // 保存token和用户信息到localStorage
- localStorage.setItem("token", response.data.data.token);
- localStorage.setItem("user", JSON.stringify(response.data.data.user));
- return response.data;
- } else {
- return Promise.reject(new Error(response.data.message || "登录失败"));
- }
- });
-};
-
-export const adminLogin = (credentials) => {
- return request.post(`${ADMIN_PREFIX}/login`, credentials).then((response) => {
- if (response.data && response.data.success) {
- // 保存token和用户信息到localStorage
- localStorage.setItem("token", response.data.data.token);
- localStorage.setItem("user", JSON.stringify(response.data.data.user));
- return response.data;
- } else {
- return Promise.reject(new Error(response.data.message || "管理员登录失败"));
- }
- });
-};
-
-export const registerUser = (userData) => {
- return request.post(`${API_PREFIX}/register`, userData).then((response) => {
- if (response.data && response.data.success) {
- return response.data;
- } else {
- return Promise.reject(new Error(response.data.message || "注册失败"));
- }
- });
-};
-
-export const updateUsername = (username, newUsername) => {
- const token = localStorage.getItem("token");
- return request
- .post(`${API_PREFIX}/update/username`,
- { username, newUsername },
- { headers: { token } })
- .then((response) => {
- if (response.data && response.data.success) {
- // 更新本地存储的用户信息
- const user = JSON.parse(localStorage.getItem("user") || "{}");
- user.username = newUsername;
- localStorage.setItem("user", JSON.stringify(user));
- return response.data;
- } else {
- return Promise.reject(
- new Error(response.data.message || "修改用户名失败")
- );
- }
- });
-};
-
-export const updatePassword = (username, newPassword) => {
- const token = localStorage.getItem("token");
- return request
- .post(`${API_PREFIX}/update/password`,
- { username, newPassword },
- { headers: { token } })
- .then((response) => {
- if (response.data && response.data.success) {
- return response.data;
- } else {
- return Promise.reject(
- new Error(response.data.message || "修改密码失败")
- );
- }
- });
-};
-
-export const updateEmail = (username, newEmail) => {
- const token = localStorage.getItem("token");
- return request
- .post(`${API_PREFIX}/update/email`,
- { username, newEmail },
- { headers: { token } })
- .then((response) => {
- if (response.data && response.data.success) {
- // 更新本地存储的用户信息
- const user = JSON.parse(localStorage.getItem("user") || "{}");
- user.email = newEmail;
- localStorage.setItem("user", JSON.stringify(user));
- return response.data;
- } else {
- return Promise.reject(
- new Error(response.data.message || "修改邮箱失败")
- );
- }
- });
-};
-
-export const getUserInfo = (username) => {
- const token = localStorage.getItem("token");
- return request
- .get(`${API_PREFIX}/get/info?username=${username}`,
- { headers: { token } })
- .then((response) => {
- if (response.data && response.data.success) {
- return response.data;
- } else {
- return Promise.reject(
- new Error(response.data.message || "获取用户信息失败")
- );
- }
- });
-};
-
-export const getUserList = (username) => {
- const token = localStorage.getItem("token");
- return request
- .get(`/user/list?username=${username}`,
- { headers: { token } })
- .then((response) => {
- if (response.data && response.data.success) {
- return response.data;
- } else {
- return Promise.reject(
- new Error(response.data.message || "获取用户列表失败")
- );
- }
- });
-};
-
-export const deleteUser = (username, targetUsername) => {
- const token = localStorage.getItem("token");
- return request
- .delete(`/user/delete`,
- {
- headers: { token },
- data: { username, targetUsername }
- })
- .then((response) => {
- if (response.data && response.data.success) {
- return response.data;
- } else {
- return Promise.reject(
- new Error(response.data.message || "删除用户失败")
- );
- }
- });
-};
-
-export const logoutUser = () => {
- // 清除本地存储
- localStorage.removeItem("token");
- localStorage.removeItem("user");
-
- return Promise.resolve({
- success: true,
- message: "注销成功"
- });
-};