blob: 2f3b8d7bb769b67ca768a45eeb62f9c35bbe12f9 [file] [log] [blame]
import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import {
List,
Avatar,
Space,
Tag,
Typography,
Button,
message,
Modal,
Form,
Input,
Spin,
} from "antd";
import { DeleteOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
import { getPosts, createPost, deletePost } from "@/api/forum";
import { useAuth } from "@/features/auth/contexts/AuthContext";
const { Title, Paragraph, Text } = Typography;
const { TextArea } = Input;
const ForumPage = () => {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
const [isModalOpen, setIsModalOpen] = useState(false);
const [form] = Form.useForm();
// 使用 AuthProvider 获取用户信息
const { user, isAuthenticated, hasRole } = useAuth();
// 判断是否为管理员
const isAdmin = hasRole('admin') || (user && user.uid && user.uid.includes('admin'));
// 加载帖子数据
useEffect(() => {
// 只有在用户已认证且有用户信息时才获取帖子
if (isAuthenticated && user?.username) {
fetchPosts();
}
}, [isAuthenticated, user]);
// 获取帖子列表
const fetchPosts = async () => {
try {
setLoading(true);
console.log("正在获取帖子列表,用户名:", user.username);
const response = await getPosts({ username: user.username });
console.log("获取帖子列表响应:", response);
if (response) {
const posts = response.data?.posts || [];
console.log("获取到的帖子数量:", posts.length);
console.log("帖子数据结构:", posts[0]); // 查看第一个帖子的数据结构
setPosts(posts);
} else {
console.error("获取帖子列表失败:", response.data);
message.error(response.data?.message || "获取帖子列表失败");
}
} catch (error) {
message.error(error.message || "获取帖子列表失败");
} finally {
setLoading(false);
}
};
// 显示新建帖子对话框
const showModal = () => {
setIsModalOpen(true);
};
// 关闭对话框
const handleCancel = () => {
setIsModalOpen(false);
form.resetFields();
};
// 提交新帖子
const handleSubmit = async () => {
try {
const params = await form.validateFields();
// 添加作者信息
params.author = user.username;
console.log("提交的帖子数据:", params);
const response = await createPost(params);
if (response.message === "Post created successfully") {
message.success("帖子发布成功");
setIsModalOpen(false);
form.resetFields();
fetchPosts(); // 重新加载帖子列表
} else {
message.error(response.message || "发布帖子失败");
}
} catch (error) {
console.error("发布帖子失败:", error);
message.error(error.message || "发布帖子失败");
}
};
// 删除帖子(管理员功能)
const handleDeletePost = (post) => {
Modal.confirm({
title: '确认删除帖子',
icon: <ExclamationCircleOutlined />,
content: (
<div>
<p>您确定要删除这篇帖子吗?</p>
<p><strong>标题:</strong>{post.title}</p>
<p><strong>作者:</strong>{post.author}</p>
<p className="text-red-500 mt-2">此操作不可撤销!</p>
</div>
),
okText: '确认删除',
okType: 'danger',
cancelText: '取消',
async onOk() {
try {
const params = {
username: user.username,
pid: post.pid,
};
const response = await deletePost(params);
if (response.message) {
message.success(response.message || '帖子删除成功');
fetchPosts(); // 重新加载帖子列表
} else {
message.error(response.message || '删除帖子失败');
}
} catch (error) {
console.error('删除帖子失败:', error);
message.error(error.message || '删除帖子失败');
}
},
});
};
// 如果用户未认证,显示提示信息
if (!isAuthenticated) {
return (
<div className="text-center py-8">
<Title level={3}>请先登录</Title>
<Paragraph>您需要登录后才能查看论坛内容</Paragraph>
</div>
);
}
return (
<div className="space-y-6">
<Title level={2}>社区论坛</Title>
<Paragraph className="text-slate-500">
欢迎来到我们的社区论坛,这里是会员交流分享的地方。
</Paragraph>
<div className="text-center mt-4">
<Button type="primary" onClick={showModal}>
发布新主题
</Button>
</div>
{/* 新建帖子对话框 */}
<Modal
title="发布新主题"
open={isModalOpen}
onOk={handleSubmit}
onCancel={handleCancel}
okText="发布"
cancelText="取消"
>
<Form form={form} layout="vertical">
<Form.Item
name="title"
label="标题"
rules={[{ required: true, message: "请输入标题" }]}
>
<Input placeholder="请输入标题" />
</Form.Item>
<Form.Item
name="content"
label="内容"
rules={[{ required: true, message: "请输入帖子内容" }]}
>
<TextArea rows={6} placeholder="请输入帖子内容" />
</Form.Item>
</Form>
</Modal>
{loading ? (
<div className="flex justify-center py-8">
<Spin size="large" tip="加载中..." />
</div>
) : (
<List
itemLayout="vertical"
size="large"
dataSource={posts}
renderItem={(item) => (
<List.Item
key={item.id}
extra={
<Space>
<Text type="secondary">{item.publishDate}</Text>
{isAdmin && (
<Button
type="text"
danger
icon={<DeleteOutlined />}
onClick={() => handleDeletePost(item)}
title="删除帖子(管理员)"
size="small"
>
删除
</Button>
)}
</Space>
}
>
<List.Item.Meta
avatar={
<Avatar
src={`https://api.dicebear.com/7.x/avataaars/svg?seed=${item.author}`}
/>
}
title={
<Link
to={`/post/${item.pid}`}
className="text-blue-600 hover:text-blue-800 hover:underline"
>
{item.title}
</Link>
}
description={<Text type="secondary">作者: {item.author}</Text>}
/>
<Paragraph ellipsis={{ rows: 2 }}>{item.content}</Paragraph>
</List.Item>
)}
/>
)}
</div>
);
};
export default ForumPage;