blob: b81efb0cd3cde1f6e3ddc9518e6bb109c175b944 [file] [log] [blame]
meisiyu1d4aade2025-06-02 20:10:36 +08001import React, { useEffect, useState } from 'react';
2import { Row, Col, Pagination, Input, Carousel, Menu, Card, message, Button } from 'antd';
3import { SearchOutlined, AuditOutlined } from '@ant-design/icons';
4import { getPostList, getPromotionPosts } from '@/services/post';
5import PostCard from '../PostCenter/PostCard';
6import styles from './index.module.css';
7import { Post } from '../PostCenter/types';
8import { useNavigate } from 'react-router-dom';
9import { useModel } from 'umi';
10
11const { Search } = Input;
12
13const PostCenter: React.FC = () => {
14 const [posts, setPosts] = useState<Post[]>([]);
15 const [promotionPosts, setPromotionPosts] = useState<Post[]>([]);
16 const [total, setTotal] = useState<number>(0);
17 const [page, setPage] = useState<number>(1);
18 const [loading, setLoading] = useState<boolean>(false);
19 const [selectedCategory, setSelectedCategory] = useState<string>('all');
20 const [searchKeyword, setSearchKeyword] = useState<string>('');
21 const pageSize = 12;
22 const navigate = useNavigate();
23 const { initialState } = useModel('@@initialState');
24
25 // 检查是否为管理员 - 用户名包含admin
26 const isAdmin = initialState?.currentUser?.userName?.toLowerCase().includes('admin') || false;
27
28 const fetchPosts = async (current: number = 1, category?: string, searchTitle?: string) => {
29 try {
30 setLoading(true);
31 const params: any = {
32 pageNum: current,
33 pageSize: pageSize,
34 status: '1', // 只查询正常状态的帖子
35 };
36
37 // 根据分类筛选
38 if (category && category !== 'all') {
39 params.tags = category;
40 }
41
42 // 搜索关键词
43 if (searchTitle) {
44 params.title = searchTitle;
45 }
46
47 const response = await getPostList(params);
48
49 if (response.code === 200) {
50 // 确保返回的数据符合 Post 类型
51 const formattedPosts = (response.rows || []).map((post: API.Post.PostInfo) => ({
52 ...post,
53 id: post.postId, // 确保id字段映射正确
54 tags: post.tags ? post.tags.split(',') : [],
55 views: post.views || 0,
56 comments: post.comments || 0,
57 favorites: post.favorites || 0,
58 likes: post.likes || 0,
59 coverImage: post.coverImage || '/images/404.png', // 使用本地默认图片
60 isPromoted: post.promotionPlanId != null && post.promotionPlanId > 0, // 添加推广标识
61 }));
62 setPosts(formattedPosts);
63 setTotal(response.total || 0);
64 } else {
65 message.error(response.msg || '获取帖子列表失败');
66 setPosts([]);
67 setTotal(0);
68 }
69 } catch (error) {
70 console.error('获取帖子失败:', error);
71 message.error('获取帖子列表失败,请稍后重试');
72 setPosts([]);
73 setTotal(0);
74 } finally {
75 setLoading(false);
76 }
77 };
78
79 const fetchPromotionPosts = async () => {
80 try {
81 const response = await getPromotionPosts();
82 if (response.code === 200) {
83 const formattedPosts = (response.data || []).map((post: API.Post.PostInfo) => ({
84 ...post,
85 id: post.postId,
86 tags: post.tags ? post.tags.split(',') : [],
87 views: post.views || 0,
88 comments: post.comments || 0,
89 favorites: post.favorites || 0,
90 likes: post.likes || 0,
91 coverImage: post.coverImage || '/images/404.png',
92 isPromoted: post.promotionPlanId != null && post.promotionPlanId > 0, // 添加推广标识
93 }));
94 setPromotionPosts(formattedPosts);
95 }
96 } catch (error) {
97 console.error('获取推广帖子失败:', error);
98 }
99 };
100
101 useEffect(() => {
102 fetchPosts(page, selectedCategory, searchKeyword);
103 fetchPromotionPosts();
104 }, [page, selectedCategory]);
105
106 const handleSearch = (value: string) => {
107 console.log('搜索:', value);
108 setSearchKeyword(value);
109 setPage(1); // 重置页码
110 fetchPosts(1, selectedCategory, value);
111 };
112
113 const handlePageChange = (newPage: number) => {
114 setPage(newPage);
115 fetchPosts(newPage, selectedCategory, searchKeyword);
116 };
117
118 const handleCategoryChange = (category: string) => {
119 setSelectedCategory(category);
120 setPage(1); // 重置页码
121 setSearchKeyword(''); // 清空搜索
122 fetchPosts(1, category, '');
123 };
124
125 return (
126 <div className={styles.postCenterContainer}>
127 {/* 顶部导航 */}
128 <div className={styles.headerNav}>
129 <div className={styles.categoryMenu}>
130 <Button
131 type={selectedCategory === 'all' ? 'primary' : 'text'}
132 onClick={() => handleCategoryChange('all')}
133 className={styles.categoryButton}
134 >
135 首页
136 </Button>
137 <Button
138 type={selectedCategory === '日剧' ? 'primary' : 'text'}
139 onClick={() => handleCategoryChange('日剧')}
140 className={styles.categoryButton}
141 >
142 日剧
143 </Button>
144 <Button
145 type={selectedCategory === '电影' ? 'primary' : 'text'}
146 onClick={() => handleCategoryChange('电影')}
147 className={styles.categoryButton}
148 >
149 电影
150 </Button>
151 <Button
152 type={selectedCategory === '音乐' ? 'primary' : 'text'}
153 onClick={() => handleCategoryChange('音乐')}
154 className={styles.categoryButton}
155 >
156 音乐
157 </Button>
158 <Button
159 type={selectedCategory === '合集' ? 'primary' : 'text'}
160 onClick={() => handleCategoryChange('合集')}
161 className={styles.categoryButton}
162 >
163 合集
164 </Button>
165 <Button
166 type={selectedCategory === '动漫' ? 'primary' : 'text'}
167 onClick={() => handleCategoryChange('动漫')}
168 className={styles.categoryButton}
169 >
170 动漫
171 </Button>
172 <Button
173 type={selectedCategory === '游戏' ? 'primary' : 'text'}
174 onClick={() => handleCategoryChange('游戏')}
175 className={styles.categoryButton}
176 >
177 游戏
178 </Button>
179 </div>
180
181 <div className={styles.searchContainer}>
182 <Search
183 placeholder="搜索帖子..."
184 onSearch={handleSearch}
185 style={{ width: 300 }}
186 enterButton={<SearchOutlined />}
187 value={searchKeyword}
188 onChange={(e) => setSearchKeyword(e.target.value)}
189 />
190 </div>
191
192 <div className={styles.userCenter}>
193 {isAdmin && (
194 <Button
195 icon={<AuditOutlined />}
196 onClick={() => navigate('/post-review')}
197 style={{ marginRight: 16 }}
198 >
199 帖子审核
200 </Button>
201 )}
202 <Button
203 type="primary"
204 onClick={() => navigate('/user-center')}
205 >
206 个人中心
207 </Button>
208 </div>
209 </div>
210
211 {/* 轮播推荐图 */}
212 <div className={styles.carouselContainer}>
213 <Carousel autoplay>
214 {promotionPosts.length > 0 ? (
215 promotionPosts.map((post) => (
216 <div key={post.id} onClick={() => navigate(`/post-detail/${post.id}`)}>
217 <div
218 className={styles.carouselSlide}
219 style={{
220 backgroundImage: `linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4)), url(${post.coverImage})`,
221 backgroundSize: 'cover',
222 backgroundPosition: 'center',
223 height: '300px',
224 position: 'relative',
225 cursor: 'pointer'
226 }}
227 >
228 <div className={styles.carouselOverlay}>
229 <h2 className={styles.carouselTitle}>{post.title}</h2>
230 <p className={styles.carouselSummary}>{post.summary}</p>
231 <div className={styles.carouselMeta}>
232 <span>作者: {post.author}</span>
233 <span>浏览: {post.views}</span>
234 <span>点赞: {post.likes}</span>
235 </div>
236 </div>
237 </div>
238 </div>
239 ))
240 ) : (
241 // 默认轮播图
242 <>
243 <div>
244 <div
245 className={styles.carouselSlide}
246 style={{
247 backgroundImage: `url(/images/flower.jpg)`,
248 backgroundSize: 'cover',
249 backgroundPosition: 'center',
250 height: '300px',
251 }}
252 >
253 <div className={styles.carouselOverlay}>
254 <h2 className={styles.carouselTitle}>欢迎来到ThunderHub</h2>
255 <p className={styles.carouselSummary}>发现精彩内容,分享美好时光</p>
256 </div>
257 </div>
258 </div>
259 </>
260 )}
261 </Carousel>
262 </div>
263
264 {/* 卡片帖子区 */}
265 <div className={styles.postsSection}>
266 {selectedCategory !== 'all' && (
267 <div className={styles.categoryTitle}>
268 <h2>{selectedCategory} 分类</h2>
269 <p>共找到 {total} 篇相关帖子</p>
270 </div>
271 )}
272
273 <Row gutter={[24, 24]} className={styles.postsRow}>
274 {posts.map((post) => (
275 <Col xs={24} sm={12} lg={8} xl={6} key={post.id} className={styles.postCol}>
276 <PostCard post={post} />
277 </Col>
278 ))}
279 </Row>
280
281 {posts.length === 0 && !loading && (
282 <div className={styles.emptyState}>
283 <p>暂无相关帖子</p>
284 </div>
285 )}
286
287 <div className={styles.paginationContainer}>
288 <Pagination
289 current={page}
290 pageSize={pageSize}
291 total={total}
292 onChange={handlePageChange}
293 showTotal={(total) => `共 ${total} 条帖子`}
294 />
295 </div>
296 </div>
297 </div>
298 );
299};
300
301export default PostCenter;