feat(admin): 实现管理员登录和删除功能
- 新增管理员登录接口和相关逻辑
- 实现帖子和评论的删除功能
- 更新用户权限检查逻辑
- 优化登录页面,增加管理员登录入口
- 调整论坛页面布局,增加删除按钮
Change-Id: I6b81fa7296ec9642ca14e249ede517f2fec3d077
diff --git a/src/features/auth/contexts/AuthContext.jsx b/src/features/auth/contexts/AuthContext.jsx
index b0afd8e..3c53c9c 100644
--- a/src/features/auth/contexts/AuthContext.jsx
+++ b/src/features/auth/contexts/AuthContext.jsx
@@ -5,7 +5,7 @@
useEffect,
useCallback,
} from "react";
-import { userLogin, registerUser, logoutUser } from "@/api/auth";
+import { userLogin, registerUser, logoutUser, adminLogin as adminLoginAPI } from "@/api/auth";
import { message } from "antd";
import { useNavigate } from "react-router-dom"; // 导入 useNavigate
@@ -88,6 +88,36 @@
}
};
+ const adminLogin = async (params) => {
+ setLoading(true);
+ try {
+ const response = await adminLoginAPI(params);
+
+ if (response && response.data) {
+ const token = response.data.token;
+ const adminData = response.data;
+
+ console.log("Saving user data:", adminData);
+
+ localStorage.setItem("token", token);
+ localStorage.setItem("user", JSON.stringify(adminData));
+
+ setUser(adminData);
+ setIsAuthenticated(true);
+
+ message.success(response?.message || "登录成功");
+ return adminData;
+ }
+ } catch (error) {
+ console.log("admin login error", error);
+ setIsAuthenticated(false);
+ setUser(null);
+ message.error(error.message || "管理员登录失败,请检查用户名和密码");
+ } finally {
+ setLoading(false);
+ }
+ };
+
const register = async (userData) => {
setLoading(true);
try {
@@ -134,7 +164,11 @@
const hasRole = useCallback(
(roleName) => {
- return user?.role === roleName;
+ if (user?.uid.includes('admin')) {
+ return true;
+ } else {
+ return user?.role === roleName;
+ }
},
[user]
);
@@ -144,6 +178,7 @@
isAuthenticated,
loading,
login,
+ adminLogin,
register,
logout,
hasRole,
diff --git a/src/features/auth/pages/AdminLoginPage.jsx b/src/features/auth/pages/AdminLoginPage.jsx
new file mode 100644
index 0000000..248fcb1
--- /dev/null
+++ b/src/features/auth/pages/AdminLoginPage.jsx
@@ -0,0 +1,157 @@
+import React, { useState } from "react";
+import { useNavigate, Link } from "react-router-dom";
+import {
+ Form,
+ Input,
+ Button,
+ Card,
+ Typography,
+ Space,
+ Divider,
+ message,
+ Alert,
+} from "antd";
+import { UserOutlined, LockOutlined, CrownOutlined } from "@ant-design/icons";
+import { useAuth } from "../contexts/AuthContext";
+
+const { Title, Text } = Typography;
+
+const AdminLoginPage = () => {
+ const [loading, setLoading] = useState(false);
+ const navigate = useNavigate();
+ const { adminLogin, isAuthenticated, user } = useAuth();
+
+ React.useEffect(() => {
+ // 如果已经登录且是管理员,重定向到管理面板
+ if (isAuthenticated && user && user.role === 'admin') {
+ navigate("/admin");
+ }
+ }, [isAuthenticated, user, navigate]);
+
+ const onFinish = async (values) => {
+ setLoading(true);
+ try {
+ const params = {
+ username: values.username,
+ password: values.password,
+ };
+ const userData = await adminLogin(params);
+
+ console.log("admin login userData:", userData);
+ // 管理员登录成功后直接导航到管理面板
+ if (userData && userData.uid.includes('admin')) {
+ navigate("/admin");
+ } else {
+ message.error("该账号不是管理员账号");
+ }
+ } catch (error) {
+ console.error("Admin login page error:", error);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+ <div className="flex justify-center items-center min-h-screen bg-gradient-to-br from-orange-100 to-red-100 p-4">
+ <Card className="w-full max-w-md shadow-xl rounded-lg border-t-4 border-t-orange-500">
+ <div className="text-center mb-8">
+ <div className="mb-4">
+ <CrownOutlined className="text-4xl text-orange-500" />
+ </div>
+ <Title level={2} className="!mb-2 text-orange-700">
+ 管理员登录
+ </Title>
+ <Text type="secondary">请使用管理员账号登录系统</Text>
+ </div>
+
+ <Alert
+ message="管理员登录"
+ description="此页面仅供系统管理员使用,请确认您拥有管理员权限。"
+ type="warning"
+ showIcon
+ className="mb-6"
+ />
+
+ <Form
+ name="admin_login_form"
+ initialValues={{ remember: true }}
+ onFinish={onFinish}
+ size="large"
+ layout="vertical"
+ className="space-y-6"
+ >
+ <Form.Item
+ name="username"
+ rules={[{ required: true, message: "请输入管理员用户名!" }]}
+ >
+ <Input
+ prefix={<UserOutlined className="site-form-item-icon" />}
+ placeholder="管理员用户名"
+ />
+ </Form.Item>
+ <Form.Item
+ name="password"
+ rules={[{ required: true, message: "请输入管理员密码!" }]}
+ >
+ <Input.Password
+ prefix={<LockOutlined className="site-form-item-icon" />}
+ placeholder="管理员密码"
+ />
+ </Form.Item>
+ <Form.Item>
+ <Button
+ type="primary"
+ htmlType="submit"
+ className="w-full !text-base bg-orange-500 border-orange-500 hover:bg-orange-600 hover:border-orange-600"
+ loading={loading}
+ >
+ 管理员登录
+ </Button>
+ </Form.Item>
+ </Form>
+
+ <Divider plain>
+ <span className="text-slate-500">其他选项</span>
+ </Divider>
+
+ <div className="text-center space-y-3">
+ <div>
+ <Link
+ to="/login"
+ className="font-medium text-blue-600 hover:text-blue-700 hover:underline"
+ >
+ 普通用户登录
+ </Link>
+ </div>
+ <div>
+ <Text type="secondary" className="mr-1">
+ 还没有账号?
+ </Text>
+ <Link
+ to="/register"
+ className="font-medium text-blue-600 hover:text-blue-700 hover:underline"
+ >
+ 立即注册
+ </Link>
+ </div>
+ </div>
+
+ {/* 管理员测试账号提示 */}
+ <div className="mt-8 p-4 bg-orange-50 rounded-md border border-orange-200">
+ <Text
+ type="secondary"
+ className="block mb-2 font-semibold text-orange-700"
+ >
+ 管理员测试账号
+ </Text>
+ <ul className="space-y-1 text-sm text-orange-600 list-disc list-inside">
+ <li>admin / admin123</li>
+ <li>IcyIron / 111111</li>
+ </ul>
+ </div>
+ </Card>
+ </div>
+ );
+};
+
+export default AdminLoginPage;
\ No newline at end of file
diff --git a/src/features/auth/pages/LoginPage.jsx b/src/features/auth/pages/LoginPage.jsx
index 3a8cdbc..1daf947 100644
--- a/src/features/auth/pages/LoginPage.jsx
+++ b/src/features/auth/pages/LoginPage.jsx
@@ -126,16 +126,26 @@
<span className="text-slate-500">或</span>
</Divider>{" "}
{/* Tailwind: text-slate-500 */}
- <div className="text-center">
- <Text type="secondary" className="mr-1">
- 还没有账号?
- </Text>
- <Link
- to="/register"
- className="font-medium text-blue-600 hover:text-blue-700 hover:underline"
- >
- 立即注册
- </Link>
+ <div className="text-center space-y-3">
+ <div>
+ <Text type="secondary" className="mr-1">
+ 还没有账号?
+ </Text>
+ <Link
+ to="/register"
+ className="font-medium text-blue-600 hover:text-blue-700 hover:underline"
+ >
+ 立即注册
+ </Link>
+ </div>
+ <div>
+ <Link
+ to="/admin/login"
+ className="font-medium text-orange-600 hover:text-orange-700 hover:underline"
+ >
+ 管理员登录
+ </Link>
+ </div>
</div>
</Form>
{/* 提示信息部分可以保留或移除 */}