创作中心模块包含首页展示、个人中心、帖子审核。

“首页展示”支持广告轮播展示、推广帖子优先展示、分页显示所有帖子、导航栏便捷标签筛选帖子、全局标题模糊搜索帖子、点击帖子“查看更多”进入帖子详情页。帖子详情页展示帖子封面图片、作者时间、详细内容(可以插入种子链接对种子进行介绍与推广)等基本信息、对帖子点赞收藏举报评论回复、查看相关推荐帖子。相关推荐会推荐当前帖子作者的其他帖子(最多推荐5篇),还会推荐具有相似标签的其他帖子,两者总共最多推荐9篇帖子。

“个人中心”包含“我的中心”和“我的收藏”。
“我的中心”中可以管理已经成功发布的帖子(编辑、删除帖子),还可以发布新帖子。发布新帖子时除了填写帖子基本信息以外,帖子标签支持下拉多项选择,用户还可以选择帖子推广项目并进行支付。设置了多种推广项目,包含广告轮播推广、帖子置顶展示、限时优先展示、分类页首条展示。系统后台执行自动定时任务,每小时对帖子的推广时效性进行检查,如超出推广时限,则取消帖子的推广显示特权。用户点击发布帖子后帖子处于待审核状态,需要管理员审核通过才能正常发布在首页展示页面。编辑帖子时用户可以追加帖子推广,但如果帖子处于推广状态,则禁止修改推广项目。
“我的收藏”中可以便捷查看所有已收藏的帖子。

“帖子审核”包含“帖子发布管理”和“帖子举报管理”。“帖子审核”板块具有权限管理,只有管理员界面能够进入。
“帖子发布管理”对所有待审核帖子进行处理,支持预览待审核帖子详细内容,批准通过和拒绝通过选项。
“帖子举报管理”对所有用户的举报请求进行人工审核,如果举报内容属实,则将帖子下架处理,如果举报内容不属实,驳回举报请求。所有举报请求的处理结果均留存显示,方便后续再次审查。

Change-Id: If822351183e9d55a5a56ff5cf1e13b313fdbe231
diff --git a/src/pages/PostCenter/index.tsx b/src/pages/PostCenter/index.tsx
new file mode 100644
index 0000000..b81efb0
--- /dev/null
+++ b/src/pages/PostCenter/index.tsx
@@ -0,0 +1,301 @@
+import React, { useEffect, useState } from 'react';
+import { Row, Col, Pagination, Input, Carousel, Menu, Card, message, Button } from 'antd';
+import { SearchOutlined, AuditOutlined } from '@ant-design/icons';
+import { getPostList, getPromotionPosts } from '@/services/post';
+import PostCard from '../PostCenter/PostCard';
+import styles from './index.module.css';
+import { Post } from '../PostCenter/types';
+import { useNavigate } from 'react-router-dom';
+import { useModel } from 'umi';
+
+const { Search } = Input;
+
+const PostCenter: React.FC = () => {
+  const [posts, setPosts] = useState<Post[]>([]);
+  const [promotionPosts, setPromotionPosts] = useState<Post[]>([]);
+  const [total, setTotal] = useState<number>(0);
+  const [page, setPage] = useState<number>(1);
+  const [loading, setLoading] = useState<boolean>(false);
+  const [selectedCategory, setSelectedCategory] = useState<string>('all');
+  const [searchKeyword, setSearchKeyword] = useState<string>('');
+  const pageSize = 12;
+  const navigate = useNavigate();
+  const { initialState } = useModel('@@initialState');
+
+  // 检查是否为管理员 - 用户名包含admin
+  const isAdmin = initialState?.currentUser?.userName?.toLowerCase().includes('admin') || false;
+
+  const fetchPosts = async (current: number = 1, category?: string, searchTitle?: string) => {
+    try {
+      setLoading(true);
+      const params: any = {
+        pageNum: current,
+        pageSize: pageSize,
+        status: '1', // 只查询正常状态的帖子
+      };
+
+      // 根据分类筛选
+      if (category && category !== 'all') {
+        params.tags = category;
+      }
+
+      // 搜索关键词
+      if (searchTitle) {
+        params.title = searchTitle;
+      }
+
+      const response = await getPostList(params);
+      
+      if (response.code === 200) {
+        // 确保返回的数据符合 Post 类型
+        const formattedPosts = (response.rows || []).map((post: API.Post.PostInfo) => ({
+          ...post,
+          id: post.postId, // 确保id字段映射正确
+          tags: post.tags ? post.tags.split(',') : [],
+          views: post.views || 0,
+          comments: post.comments || 0,
+          favorites: post.favorites || 0,
+          likes: post.likes || 0,
+          coverImage: post.coverImage || '/images/404.png', // 使用本地默认图片
+          isPromoted: post.promotionPlanId != null && post.promotionPlanId > 0, // 添加推广标识
+        }));
+        setPosts(formattedPosts);
+        setTotal(response.total || 0);
+      } else {
+        message.error(response.msg || '获取帖子列表失败');
+        setPosts([]);
+        setTotal(0);
+      }
+    } catch (error) {
+      console.error('获取帖子失败:', error);
+      message.error('获取帖子列表失败,请稍后重试');
+      setPosts([]);
+      setTotal(0);
+    } finally {
+      setLoading(false);
+    }
+  };
+
+  const fetchPromotionPosts = async () => {
+    try {
+      const response = await getPromotionPosts();
+      if (response.code === 200) {
+        const formattedPosts = (response.data || []).map((post: API.Post.PostInfo) => ({
+          ...post,
+          id: post.postId,
+          tags: post.tags ? post.tags.split(',') : [],
+          views: post.views || 0,
+          comments: post.comments || 0,
+          favorites: post.favorites || 0,
+          likes: post.likes || 0,
+          coverImage: post.coverImage || '/images/404.png',
+          isPromoted: post.promotionPlanId != null && post.promotionPlanId > 0, // 添加推广标识
+        }));
+        setPromotionPosts(formattedPosts);
+      }
+    } catch (error) {
+      console.error('获取推广帖子失败:', error);
+    }
+  };
+
+  useEffect(() => {
+    fetchPosts(page, selectedCategory, searchKeyword);
+    fetchPromotionPosts();
+  }, [page, selectedCategory]);
+
+  const handleSearch = (value: string) => {
+    console.log('搜索:', value);
+    setSearchKeyword(value);
+    setPage(1); // 重置页码
+    fetchPosts(1, selectedCategory, value);
+  };
+
+  const handlePageChange = (newPage: number) => {
+    setPage(newPage);
+    fetchPosts(newPage, selectedCategory, searchKeyword);
+  };
+
+  const handleCategoryChange = (category: string) => {
+    setSelectedCategory(category);
+    setPage(1); // 重置页码
+    setSearchKeyword(''); // 清空搜索
+    fetchPosts(1, category, '');
+  };
+
+  return (
+    <div className={styles.postCenterContainer}>
+      {/* 顶部导航 */}
+      <div className={styles.headerNav}>
+        <div className={styles.categoryMenu}>
+          <Button 
+            type={selectedCategory === 'all' ? 'primary' : 'text'}
+            onClick={() => handleCategoryChange('all')}
+            className={styles.categoryButton}
+          >
+            首页
+          </Button>
+          <Button 
+            type={selectedCategory === '日剧' ? 'primary' : 'text'}
+            onClick={() => handleCategoryChange('日剧')}
+            className={styles.categoryButton}
+          >
+            日剧
+          </Button>
+          <Button 
+            type={selectedCategory === '电影' ? 'primary' : 'text'}
+            onClick={() => handleCategoryChange('电影')}
+            className={styles.categoryButton}
+          >
+            电影
+          </Button>
+          <Button 
+            type={selectedCategory === '音乐' ? 'primary' : 'text'}
+            onClick={() => handleCategoryChange('音乐')}
+            className={styles.categoryButton}
+          >
+            音乐
+          </Button>
+          <Button 
+            type={selectedCategory === '合集' ? 'primary' : 'text'}
+            onClick={() => handleCategoryChange('合集')}
+            className={styles.categoryButton}
+          >
+            合集
+          </Button>
+          <Button 
+            type={selectedCategory === '动漫' ? 'primary' : 'text'}
+            onClick={() => handleCategoryChange('动漫')}
+            className={styles.categoryButton}
+          >
+            动漫
+          </Button>
+          <Button 
+            type={selectedCategory === '游戏' ? 'primary' : 'text'}
+            onClick={() => handleCategoryChange('游戏')}
+            className={styles.categoryButton}
+          >
+            游戏
+          </Button>
+        </div>
+        
+        <div className={styles.searchContainer}>
+          <Search
+            placeholder="搜索帖子..."
+            onSearch={handleSearch}
+            style={{ width: 300 }}
+            enterButton={<SearchOutlined />}
+            value={searchKeyword}
+            onChange={(e) => setSearchKeyword(e.target.value)}
+          />
+        </div>
+        
+        <div className={styles.userCenter}>
+          {isAdmin && (
+            <Button 
+              icon={<AuditOutlined />}
+              onClick={() => navigate('/post-review')}
+              style={{ marginRight: 16 }}
+            >
+              帖子审核
+            </Button>
+          )}
+          <Button 
+            type="primary" 
+            onClick={() => navigate('/user-center')}
+          >
+            个人中心
+          </Button>
+        </div>
+      </div>
+
+      {/* 轮播推荐图 */}
+      <div className={styles.carouselContainer}>
+        <Carousel autoplay>
+          {promotionPosts.length > 0 ? (
+            promotionPosts.map((post) => (
+              <div key={post.id} onClick={() => navigate(`/post-detail/${post.id}`)}>
+                <div 
+                  className={styles.carouselSlide}
+                  style={{
+                    backgroundImage: `linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4)), url(${post.coverImage})`,
+                    backgroundSize: 'cover',
+                    backgroundPosition: 'center',
+                    height: '300px',
+                    position: 'relative',
+                    cursor: 'pointer'
+                  }}
+                >
+                  <div className={styles.carouselOverlay}>
+                    <h2 className={styles.carouselTitle}>{post.title}</h2>
+                    <p className={styles.carouselSummary}>{post.summary}</p>
+                    <div className={styles.carouselMeta}>
+                      <span>作者: {post.author}</span>
+                      <span>浏览: {post.views}</span>
+                      <span>点赞: {post.likes}</span>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            ))
+          ) : (
+            // 默认轮播图
+            <>
+              <div>
+                <div 
+                  className={styles.carouselSlide}
+                  style={{
+                    backgroundImage: `url(/images/flower.jpg)`,
+                    backgroundSize: 'cover',
+                    backgroundPosition: 'center',
+                    height: '300px',
+                  }}
+                >
+                  <div className={styles.carouselOverlay}>
+                    <h2 className={styles.carouselTitle}>欢迎来到ThunderHub</h2>
+                    <p className={styles.carouselSummary}>发现精彩内容,分享美好时光</p>
+                  </div>
+                </div>
+              </div>
+            </>
+          )}
+        </Carousel>
+      </div>
+
+      {/* 卡片帖子区 */}
+      <div className={styles.postsSection}>
+        {selectedCategory !== 'all' && (
+          <div className={styles.categoryTitle}>
+            <h2>{selectedCategory} 分类</h2>
+            <p>共找到 {total} 篇相关帖子</p>
+          </div>
+        )}
+        
+        <Row gutter={[24, 24]} className={styles.postsRow}>
+          {posts.map((post) => (
+            <Col xs={24} sm={12} lg={8} xl={6} key={post.id} className={styles.postCol}>
+              <PostCard post={post} />
+            </Col>
+          ))}
+        </Row>
+
+        {posts.length === 0 && !loading && (
+          <div className={styles.emptyState}>
+            <p>暂无相关帖子</p>
+          </div>
+        )}
+
+        <div className={styles.paginationContainer}>
+          <Pagination
+            current={page}
+            pageSize={pageSize}
+            total={total}
+            onChange={handlePageChange}
+            showTotal={(total) => `共 ${total} 条帖子`}
+          />
+        </div>
+      </div>
+    </div>
+  );
+};
+
+export default PostCenter;
\ No newline at end of file