blob: 54638fc92b6d9269cd0096c02fd1fb9e9eabdf77 [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";
16import { getPosts, createPost } from "@/api/forum";
17import { useAuth } from "@/features/auth/contexts/AuthContext";
ybtda5978b2025-05-31 15:58:05 +080018
19const { Title, Paragraph, Text } = Typography;
20const { TextArea } = Input;
21
22const ForumPage = () => {
23 const [posts, setPosts] = useState([]);
24 const [loading, setLoading] = useState(true);
25 const [isModalOpen, setIsModalOpen] = useState(false);
26 const [form] = Form.useForm();
ybtbac75f22025-06-08 22:31:15 +080027
28 // 使用 AuthProvider 获取用户信息
29 const { user, isAuthenticated } = useAuth();
30
ybtda5978b2025-05-31 15:58:05 +080031 // 加载帖子数据
32 useEffect(() => {
ybtbac75f22025-06-08 22:31:15 +080033 // 只有在用户已认证且有用户信息时才获取帖子
34 if (isAuthenticated && user?.username) {
35 fetchPosts();
36 }
37 }, [isAuthenticated, user]);
38
ybtda5978b2025-05-31 15:58:05 +080039 // 获取帖子列表
40 const fetchPosts = async () => {
41 try {
42 setLoading(true);
ybtbac75f22025-06-08 22:31:15 +080043 console.log("正在获取帖子列表,用户名:", user.username);
ybtda5978b2025-05-31 15:58:05 +080044 const response = await getPosts({ username: user.username });
ybtbac75f22025-06-08 22:31:15 +080045 console.log("获取帖子列表响应:", response);
46
47 if (response) {
48 const posts = response.data?.posts || [];
49 console.log("获取到的帖子数量:", posts.length);
50 console.log("帖子数据结构:", posts[0]); // 查看第一个帖子的数据结构
51 setPosts(posts);
52 } else {
53 console.error("获取帖子列表失败:", response.data);
54 message.error(response.data?.message || "获取帖子列表失败");
ybtda5978b2025-05-31 15:58:05 +080055 }
56 } catch (error) {
ybtbac75f22025-06-08 22:31:15 +080057 message.error(error.message || "获取帖子列表失败");
ybtda5978b2025-05-31 15:58:05 +080058 } finally {
59 setLoading(false);
60 }
61 };
ybtbac75f22025-06-08 22:31:15 +080062
ybtda5978b2025-05-31 15:58:05 +080063 // 显示新建帖子对话框
64 const showModal = () => {
65 setIsModalOpen(true);
66 };
ybtbac75f22025-06-08 22:31:15 +080067
ybtda5978b2025-05-31 15:58:05 +080068 // 关闭对话框
69 const handleCancel = () => {
70 setIsModalOpen(false);
71 form.resetFields();
72 };
ybtbac75f22025-06-08 22:31:15 +080073
ybtda5978b2025-05-31 15:58:05 +080074 // 提交新帖子
75 const handleSubmit = async () => {
76 try {
ybtbac75f22025-06-08 22:31:15 +080077 const params = await form.validateFields();
78
ybtda5978b2025-05-31 15:58:05 +080079 // 添加作者信息
ybtbac75f22025-06-08 22:31:15 +080080 params.author = user.username;
81 console.log("提交的帖子数据:", params);
82
83 const response = await createPost(params);
84 if (response.message === "Post created successfully") {
85 message.success("帖子发布成功");
ybtda5978b2025-05-31 15:58:05 +080086 setIsModalOpen(false);
87 form.resetFields();
88 fetchPosts(); // 重新加载帖子列表
ybtbac75f22025-06-08 22:31:15 +080089 } else {
90 message.error(response.message || "发布帖子失败");
ybtda5978b2025-05-31 15:58:05 +080091 }
92 } catch (error) {
ybtbac75f22025-06-08 22:31:15 +080093 console.error("发布帖子失败:", error);
94 message.error(error.message || "发布帖子失败");
ybtda5978b2025-05-31 15:58:05 +080095 }
96 };
97
ybtbac75f22025-06-08 22:31:15 +080098 // 如果用户未认证,显示提示信息
99 if (!isAuthenticated) {
100 return (
101 <div className="text-center py-8">
102 <Title level={3}>请先登录</Title>
103 <Paragraph>您需要登录后才能查看论坛内容</Paragraph>
104 </div>
105 );
106 }
107
ybtda5978b2025-05-31 15:58:05 +0800108 return (
109 <div className="space-y-6">
110 <Title level={2}>社区论坛</Title>
111 <Paragraph className="text-slate-500">
112 欢迎来到我们的社区论坛,这里是会员交流分享的地方。
113 </Paragraph>
ybtbac75f22025-06-08 22:31:15 +0800114 <div className="text-center mt-4">
115 <Button type="primary" onClick={showModal}>
116 发布新主题
117 </Button>
118 </div>
119
120 {/* 新建帖子对话框 */}
121 <Modal
122 title="发布新主题"
123 open={isModalOpen}
124 onOk={handleSubmit}
125 onCancel={handleCancel}
126 okText="发布"
127 cancelText="取消"
128 >
129 <Form form={form} layout="vertical">
130 <Form.Item
131 name="title"
132 label="标题"
133 rules={[{ required: true, message: "请输入标题" }]}
134 >
135 <Input placeholder="请输入标题" />
136 </Form.Item>
137 <Form.Item
138 name="content"
139 label="内容"
140 rules={[{ required: true, message: "请输入帖子内容" }]}
141 >
142 <TextArea rows={6} placeholder="请输入帖子内容" />
143 </Form.Item>
144 </Form>
145 </Modal>
ybtda5978b2025-05-31 15:58:05 +0800146 {loading ? (
147 <div className="flex justify-center py-8">
148 <Spin size="large" tip="加载中..." />
149 </div>
150 ) : (
151 <List
152 itemLayout="vertical"
153 size="large"
154 dataSource={posts}
155 renderItem={(item) => (
156 <List.Item
157 key={item.id}
158 extra={
159 <Space>
ybtbac75f22025-06-08 22:31:15 +0800160 <Text type="secondary">{item.publishDate}</Text>
ybtda5978b2025-05-31 15:58:05 +0800161 </Space>
162 }
163 >
164 <List.Item.Meta
ybtbac75f22025-06-08 22:31:15 +0800165 avatar={
166 <Avatar
167 src={`https://api.dicebear.com/7.x/avataaars/svg?seed=${item.author}`}
168 />
169 }
170 title={
171 <Link
172 to={`/post/${item.pid}`}
173 className="text-blue-600 hover:text-blue-800 hover:underline"
174 >
175 {item.title}
176 </Link>
177 }
ybtda5978b2025-05-31 15:58:05 +0800178 description={<Text type="secondary">作者: {item.author}</Text>}
179 />
180 <Paragraph ellipsis={{ rows: 2 }}>{item.content}</Paragraph>
181 </List.Item>
182 )}
183 />
184 )}
ybtda5978b2025-05-31 15:58:05 +0800185 </div>
186 );
187};
188
ybtbac75f22025-06-08 22:31:15 +0800189export default ForumPage;