feat(auth): 实现登录注册功能并重构 App 组件

- 新增登录和注册页面组件
- 实现用户认证和权限管理逻辑
- 重构 App 组件,使用 Router 和 AuthProvider
- 添加管理员面板和论坛页面组件

Change-Id: Iaa4502616970e75e3268537f73c75dac8f60e24d
diff --git a/src/features/auth/contexts/AuthContext.jsx b/src/features/auth/contexts/AuthContext.jsx
new file mode 100644
index 0000000..5f9b37e
--- /dev/null
+++ b/src/features/auth/contexts/AuthContext.jsx
@@ -0,0 +1,133 @@
+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
+
+const AuthContext = createContext(null);
+
+export const AuthProvider = ({ children }) => {
+  const [user, setUser] = useState(null);
+  const [loading, setLoading] = useState(true); // 初始加载状态
+  const [isAuthenticated, setIsAuthenticated] = useState(false);
+  const navigate = useNavigate();
+
+  const loadAuthData = useCallback(() => {
+    setLoading(true);
+    try {
+      const storedToken = localStorage.getItem('authToken'); // 假设您使用token
+      const storedUser = localStorage.getItem('user');
+
+      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);
+        });
+      } else {
+        setIsAuthenticated(false);
+        setUser(null);
+      }
+    } catch (error) {
+      console.error("Failed to load auth data from storage", error);
+      setIsAuthenticated(false);
+      setUser(null);
+    } finally {
+      setLoading(false);
+    }
+  }, []);
+
+  useEffect(() => {
+    loadAuthData();
+  }, [loadAuthData]);
+
+  const login = async (credentials) => {
+    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;
+    } catch (error) {
+      console.error("Login failed", error);
+      setIsAuthenticated(false);
+      setUser(null);
+      message.error(error.message || '登录失败,请检查用户名和密码');
+    } finally {
+      setLoading(false);
+    }
+  };
+
+  const register = async (userData) => {
+    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;
+    } catch (error) {
+      console.error("Registration failed", error);
+      message.error(error.message || '注册失败,请稍后再试');
+    } finally {
+      setLoading(false);
+    }
+  };
+
+  const logout = async () => {
+    try {
+      await logoutUser();
+      localStorage.removeItem('authToken');
+      localStorage.removeItem('user');
+      localStorage.removeItem('permissions'); // 移除旧的权限存储
+      setUser(null);
+      setIsAuthenticated(false);
+      message.success('已成功退出登录');
+      navigate('/login');
+      return true;
+    } catch (error) {
+      console.error("登出失败", error);
+      message.error('登出失败');
+      return false;
+    }
+  };
+
+  const hasRole = useCallback((roleName) => {
+    return user?.role === roleName;
+  }, [user]);
+
+  const value = {
+    user,
+    isAuthenticated,
+    loading,
+    login,
+    register,
+    logout,
+    hasRole,
+    reloadAuthData: loadAuthData // 暴露一个重新加载数据的方法
+  };
+
+  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
+};
+
+export const useAuth = () => {
+  const context = useContext(AuthContext);
+  if (context === undefined || context === null) { // 增加了对 null 的检查
+    throw new Error('useAuth must be used within an AuthProvider');
+  }
+  return context;
+};
\ No newline at end of file