blob: 2f3b8d7bb769b67ca768a45eeb62f9c35bbe12f9 [file] [log] [blame]
ybtbac75f22025-06-08 22:31:15 +08001import React, { useState, useEffect } from "react";
2import { Link } from "react-router-dom";
3import {
4 List,
5 Avatar,
6 Space,
7 Tag,
8 Typography,
9 Button,
10 message,
11 Modal,
12 Form,
13 Input,
14 Spin,
15} from "antd";
ybt0d010e52025-06-09 00:29:36 +080016import { DeleteOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
17import { getPosts, createPost, deletePost } from "@/api/forum";
ybtbac75f22025-06-08 22:31:15 +080018import { useAuth } from "@/features/auth/contexts/AuthContext";
ybtda5978b2025-05-31 15:58:05 +080019
20const { Title, Paragraph, Text } = Typography;
21const { TextArea } = Input;
22
23const ForumPage = () => {
24 const [posts, setPosts] = useState([]);
25 const [loading, setLoading] = useState(true);
26 const [isModalOpen, setIsModalOpen] = useState(false);
27 const [form] = Form.useForm();
ybtbac75f22025-06-08 22:31:15 +080028
29 // 使用 AuthProvider 获取用户信息
ybt0d010e52025-06-09 00:29:36 +080030 const { user, isAuthenticated, hasRole } = useAuth();
31
32 // 判断是否为管理员
33 const isAdmin = hasRole('admin') || (user && user.uid && user.uid.includes('admin'));
ybtbac75f22025-06-08 22:31:15 +080034
ybtda5978b2025-05-31 15:58:05 +080035 // 加载帖子数据
36 useEffect(() => {
ybtbac75f22025-06-08 22:31:15 +080037 // 只有在用户已认证且有用户信息时才获取帖子
38 if (isAuthenticated && user?.username) {
39 fetchPosts();
40 }
41 }, [isAuthenticated, user]);
42
ybtda5978b2025-05-31 15:58:05 +080043 // 获取帖子列表
44 const fetchPosts = async () => {
45 try {
46 setLoading(true);
ybtbac75f22025-06-08 22:31:15 +080047 console.log("正在获取帖子列表,用户名:", user.username);
ybtda5978b2025-05-31 15:58:05 +080048 const response = await getPosts({ username: user.username });
ybtbac75f22025-06-08 22:31:15 +080049 console.log("获取帖子列表响应:", response);
50
51 if (response) {
52 const posts = response.data?.posts || [];
53 console.log("获取到的帖子数量:", posts.length);
54 console.log("帖子数据结构:", posts[0]); // 查看第一个帖子的数据结构
55 setPosts(posts);
56 } else {
57 console.error("获取帖子列表失败:", response.data);
58 message.error(response.data?.message || "获取帖子列表失败");
ybtda5978b2025-05-31 15:58:05 +080059 }
60 } catch (error) {
ybtbac75f22025-06-08 22:31:15 +080061 message.error(error.message || "获取帖子列表失败");
ybtda5978b2025-05-31 15:58:05 +080062 } finally {
63 setLoading(false);
64 }
65 };
ybtbac75f22025-06-08 22:31:15 +080066
ybtda5978b2025-05-31 15:58:05 +080067 // 显示新建帖子对话框
68 const showModal = () => {
69 setIsModalOpen(true);
70 };
ybtbac75f22025-06-08 22:31:15 +080071
ybtda5978b2025-05-31 15:58:05 +080072 // 关闭对话框
73 const handleCancel = () => {
74 setIsModalOpen(false);
75 form.resetFields();
76 };
ybtbac75f22025-06-08 22:31:15 +080077
ybtda5978b2025-05-31 15:58:05 +080078 // 提交新帖子
79 const handleSubmit = async () => {
80 try {
ybtbac75f22025-06-08 22:31:15 +080081 const params = await form.validateFields();
82
ybtda5978b2025-05-31 15:58:05 +080083 // 添加作者信息
ybtbac75f22025-06-08 22:31:15 +080084 params.author = user.username;
85 console.log("提交的帖子数据:", params);
86
87 const response = await createPost(params);
88 if (response.message === "Post created successfully") {
89 message.success("帖子发布成功");
ybtda5978b2025-05-31 15:58:05 +080090 setIsModalOpen(false);
91 form.resetFields();
92 fetchPosts(); // 重新加载帖子列表
ybtbac75f22025-06-08 22:31:15 +080093 } else {
94 message.error(response.message || "发布帖子失败");
ybtda5978b2025-05-31 15:58:05 +080095 }
96 } catch (error) {
ybtbac75f22025-06-08 22:31:15 +080097 console.error("发布帖子失败:", error);
98 message.error(error.message || "发布帖子失败");
ybtda5978b2025-05-31 15:58:05 +080099 }
100 };
101
ybt0d010e52025-06-09 00:29:36 +0800102 // 删除帖子(管理员功能)
103 const handleDeletePost = (post) => {
104 Modal.confirm({
105 title: '确认删除帖子',
106 icon: <ExclamationCircleOutlined />,
107 content: (
108 <div>
109 <p>您确定要删除这篇帖子吗?</p>
110 <p><strong>标题:</strong>{post.title}</p>
111 <p><strong>作者:</strong>{post.author}</p>
112 <p className="text-red-500 mt-2">此操作不可撤销!</p>
113 </div>
114 ),
115 okText: '确认删除',
116 okType: 'danger',
117 cancelText: '取消',
118 async onOk() {
119 try {
120 const params = {
121 username: user.username,
122 pid: post.pid,
123 };
124 const response = await deletePost(params);
125 if (response.message) {
126 message.success(response.message || '帖子删除成功');
127 fetchPosts(); // 重新加载帖子列表
128 } else {
129 message.error(response.message || '删除帖子失败');
130 }
131 } catch (error) {
132 console.error('删除帖子失败:', error);
133 message.error(error.message || '删除帖子失败');
134 }
135 },
136 });
137 };
138
ybtbac75f22025-06-08 22:31:15 +0800139 // 如果用户未认证,显示提示信息
140 if (!isAuthenticated) {
141 return (
142 <div className="text-center py-8">
143 <Title level={3}>请先登录</Title>
144 <Paragraph>您需要登录后才能查看论坛内容</Paragraph>
145 </div>
146 );
147 }
148
ybtda5978b2025-05-31 15:58:05 +0800149 return (
150 <div className="space-y-6">
151 <Title level={2}>社区论坛</Title>
152 <Paragraph className="text-slate-500">
153 欢迎来到我们的社区论坛,这里是会员交流分享的地方。
154 </Paragraph>
ybtbac75f22025-06-08 22:31:15 +0800155 <div className="text-center mt-4">
156 <Button type="primary" onClick={showModal}>
157 发布新主题
158 </Button>
159 </div>
160
161 {/* 新建帖子对话框 */}
162 <Modal
163 title="发布新主题"
164 open={isModalOpen}
165 onOk={handleSubmit}
166 onCancel={handleCancel}
167 okText="发布"
168 cancelText="取消"
169 >
170 <Form form={form} layout="vertical">
171 <Form.Item
172 name="title"
173 label="标题"
174 rules={[{ required: true, message: "请输入标题" }]}
175 >
176 <Input placeholder="请输入标题" />
177 </Form.Item>
178 <Form.Item
179 name="content"
180 label="内容"
181 rules={[{ required: true, message: "请输入帖子内容" }]}
182 >
183 <TextArea rows={6} placeholder="请输入帖子内容" />
184 </Form.Item>
185 </Form>
186 </Modal>
ybtda5978b2025-05-31 15:58:05 +0800187 {loading ? (
188 <div className="flex justify-center py-8">
189 <Spin size="large" tip="加载中..." />
190 </div>
191 ) : (
192 <List
193 itemLayout="vertical"
194 size="large"
195 dataSource={posts}
196 renderItem={(item) => (
197 <List.Item
198 key={item.id}
199 extra={
200 <Space>
ybtbac75f22025-06-08 22:31:15 +0800201 <Text type="secondary">{item.publishDate}</Text>
ybt0d010e52025-06-09 00:29:36 +0800202 {isAdmin && (
203 <Button
204 type="text"
205 danger
206 icon={<DeleteOutlined />}
207 onClick={() => handleDeletePost(item)}
208 title="删除帖子(管理员)"
209 size="small"
210 >
211 删除
212 </Button>
213 )}
ybtda5978b2025-05-31 15:58:05 +0800214 </Space>
215 }
216 >
217 <List.Item.Meta
ybtbac75f22025-06-08 22:31:15 +0800218 avatar={
219 <Avatar
220 src={`https://api.dicebear.com/7.x/avataaars/svg?seed=${item.author}`}
221 />
222 }
223 title={
224 <Link
225 to={`/post/${item.pid}`}
226 className="text-blue-600 hover:text-blue-800 hover:underline"
227 >
228 {item.title}
229 </Link>
230 }
ybtda5978b2025-05-31 15:58:05 +0800231 description={<Text type="secondary">作者: {item.author}</Text>}
232 />
233 <Paragraph ellipsis={{ rows: 2 }}>{item.content}</Paragraph>
234 </List.Item>
235 )}
236 />
237 )}
ybtda5978b2025-05-31 15:58:05 +0800238 </div>
239 );
240};
241
ybtbac75f22025-06-08 22:31:15 +0800242export default ForumPage;