创作中心模块包含首页展示、个人中心、帖子审核。
“首页展示”支持广告轮播展示、推广帖子优先展示、分页显示所有帖子、导航栏便捷标签筛选帖子、全局标题模糊搜索帖子、点击帖子“查看更多”进入帖子详情页。帖子详情页展示帖子封面图片、作者时间、详细内容(可以插入种子链接对种子进行介绍与推广)等基本信息、对帖子点赞收藏举报评论回复、查看相关推荐帖子。相关推荐会推荐当前帖子作者的其他帖子(最多推荐5篇),还会推荐具有相似标签的其他帖子,两者总共最多推荐9篇帖子。
“个人中心”包含“我的中心”和“我的收藏”。
“我的中心”中可以管理已经成功发布的帖子(编辑、删除帖子),还可以发布新帖子。发布新帖子时除了填写帖子基本信息以外,帖子标签支持下拉多项选择,用户还可以选择帖子推广项目并进行支付。设置了多种推广项目,包含广告轮播推广、帖子置顶展示、限时优先展示、分类页首条展示。系统后台执行自动定时任务,每小时对帖子的推广时效性进行检查,如超出推广时限,则取消帖子的推广显示特权。用户点击发布帖子后帖子处于待审核状态,需要管理员审核通过才能正常发布在首页展示页面。编辑帖子时用户可以追加帖子推广,但如果帖子处于推广状态,则禁止修改推广项目。
“我的收藏”中可以便捷查看所有已收藏的帖子。
“帖子审核”包含“帖子发布管理”和“帖子举报管理”。“帖子审核”板块具有权限管理,只有管理员界面能够进入。
“帖子发布管理”对所有待审核帖子进行处理,支持预览待审核帖子详细内容,批准通过和拒绝通过选项。
“帖子举报管理”对所有用户的举报请求进行人工审核,如果举报内容属实,则将帖子下架处理,如果举报内容不属实,驳回举报请求。所有举报请求的处理结果均留存显示,方便后续再次审查。
Change-Id: If822351183e9d55a5a56ff5cf1e13b313fdbe231
diff --git a/mock/post.ts b/mock/post.ts
new file mode 100644
index 0000000..fdbb9f3
--- /dev/null
+++ b/mock/post.ts
@@ -0,0 +1,290 @@
+import { Request, Response } from 'express';
+
+// Mock数据
+const mockPosts = [
+ {
+ postId: 1,
+ title: '【日剧推荐】献给刚刚接触日剧的你',
+ content: `
+ <div class="post-content">
+ <p>在日本,并没有四大台柱的称谓,这一说法的由来是贴吧的一个投票。</p>
+ <h3>校园剧</h3>
+ <p>龙樱 - 校园青春励志剧,如果你还没参加高考,推荐你提前看看,相信你会有所收获。</p>
+ <p>野猪大改造 - 两个J家美少年和两个台柱,除第一集节奏稍慢外,无硬伤,有友情有效笑有泪水。</p>
+ <h3>职场剧</h3>
+ <p>麻辣教师 - 小栗旬还是个弱小男生。</p>
+ <p>极道鲜师 - 学生上课搞乱不听讲怎么办,小栗来教你。</p>
+ </div>
+ `,
+ summary: '这是一篇关于日剧推荐的帖子,包含了校园剧和职场剧的推荐。',
+ coverImage: '/images/flower.jpg',
+ authorId: 1,
+ author: 'Ryo',
+ views: 87951,
+ comments: 15,
+ favorites: 256,
+ likes: 1024,
+ status: '1',
+ publishTime: '2017年8月26日',
+ tags: '日剧,嘉宾专栏,作品合集',
+ promotionPlanId: 1,
+ createTime: '2017-08-26 10:30:00',
+ updateTime: '2017-08-26 10:30:00',
+ },
+ {
+ postId: 2,
+ title: '【2025年4月档】对岸的家务事 高清1080P 新番双语+中文字幕 百度网盘 更新07',
+ content: '<p>对岸的家务事是一部关于家庭生活的日剧。</p>',
+ summary: '对岸的家务事是一部关于家庭生活的日剧。',
+ coverImage: '/images/flower.jpg',
+ authorId: 2,
+ author: '日剧翻译组',
+ views: 3245,
+ comments: 156,
+ favorites: 89,
+ likes: 345,
+ status: '1',
+ publishTime: '2025-5-14',
+ tags: '日剧,2025,家务',
+ promotionPlanId: null,
+ createTime: '2025-05-14 10:30:00',
+ updateTime: '2025-05-14 10:30:00',
+ },
+ {
+ postId: 3,
+ title: '【2025年4月档】天久鹰央的推理历表 高清1080P 中文字幕 百度网盘 更新04',
+ content: '<p>天久鹰央的推理历表是一部推理题材的日剧。</p>',
+ summary: '天久鹰央的推理历表是一部推理题材的日剧。',
+ coverImage: '/images/flower.jpg',
+ authorId: 2,
+ author: '日剧翻译组',
+ views: 4589,
+ comments: 267,
+ favorites: 123,
+ likes: 567,
+ status: '1',
+ publishTime: '2025-5-14',
+ tags: '日剧,2025,推理',
+ promotionPlanId: null,
+ createTime: '2025-05-14 10:30:00',
+ updateTime: '2025-05-14 10:30:00',
+ }
+];
+
+const mockComments = [
+ {
+ commentId: 1,
+ postId: 1,
+ content: '早期的堀北真希真是太美了',
+ userId: 10,
+ userName: 'Inchou',
+ userAvatar: 'https://via.placeholder.com/40',
+ parentId: 0,
+ status: '1',
+ likes: 5,
+ createTime: '2025-05-15 05:19:00',
+ },
+ {
+ commentId: 2,
+ postId: 1,
+ content: '谢谢分享 😚',
+ userId: 11,
+ userName: '紫毛球',
+ userAvatar: 'https://via.placeholder.com/40',
+ parentId: 0,
+ status: '1',
+ likes: 3,
+ createTime: '2025-05-02 10:35:00',
+ },
+ {
+ commentId: 3,
+ postId: 1,
+ content: '感谢分享',
+ userId: 12,
+ userName: 'JJxMM666',
+ userAvatar: 'https://via.placeholder.com/40',
+ parentId: 0,
+ status: '1',
+ likes: 2,
+ createTime: '2025-05-01 18:54:00',
+ }
+];
+
+export default {
+ // 获取帖子列表
+ 'GET /api/post/list': (req: Request, res: Response) => {
+ const { pageNum = 1, pageSize = 10, title, status = '1' } = req.query;
+
+ let filteredPosts = mockPosts.filter(post => post.status === status);
+
+ if (title) {
+ filteredPosts = filteredPosts.filter(post =>
+ post.title.toLowerCase().includes((title as string).toLowerCase())
+ );
+ }
+
+ const startIndex = (Number(pageNum) - 1) * Number(pageSize);
+ const endIndex = startIndex + Number(pageSize);
+ const paginatedPosts = filteredPosts.slice(startIndex, endIndex);
+
+ res.json({
+ code: 200,
+ rows: paginatedPosts,
+ total: filteredPosts.length,
+ msg: '查询成功',
+ });
+ },
+
+ // 获取帖子详情
+ 'GET /api/post/:id': (req: Request, res: Response) => {
+ const { id } = req.params;
+ const post = mockPosts.find(p => p.postId === Number(id));
+
+ if (!post) {
+ return res.json({
+ code: 404,
+ msg: '帖子不存在',
+ });
+ }
+
+ const postComments = mockComments
+ .filter(c => c.postId === Number(id) && c.parentId === 0)
+ .map(comment => ({
+ comment,
+ replies: mockComments.filter(c => c.parentId === comment.commentId)
+ }));
+
+ const authorPosts = mockPosts
+ .filter(p => p.authorId === post.authorId && p.postId !== post.postId)
+ .slice(0, 3);
+
+ const similarPosts = mockPosts
+ .filter(p => {
+ if (p.postId === post.postId) return false;
+ const postTags = post.tags.split(',');
+ const pTags = p.tags.split(',');
+ return postTags.some(tag => pTags.includes(tag));
+ })
+ .slice(0, 3);
+
+ res.json({
+ code: 200,
+ data: {
+ post,
+ tags: post.tags.split(',').map((tag, index) => ({
+ tagId: index + 1,
+ tagName: tag,
+ tagColor: 'blue',
+ postCount: Math.floor(Math.random() * 100) + 1,
+ status: '0'
+ })),
+ comments: postComments,
+ authorPosts,
+ similarPosts,
+ favorited: false
+ },
+ msg: '查询成功',
+ });
+ },
+
+ // 添加评论
+ 'POST /api/post/comment': (req: Request, res: Response) => {
+ const { postId, content, parentId = 0 } = req.body;
+
+ if (!postId || !content) {
+ return res.json({
+ code: 400,
+ msg: '参数不完整',
+ });
+ }
+
+ const newComment = {
+ commentId: Date.now(),
+ postId: Number(postId),
+ content,
+ userId: 100,
+ userName: '当前用户',
+ userAvatar: 'https://via.placeholder.com/40',
+ parentId: Number(parentId),
+ status: '1',
+ likes: 0,
+ createTime: new Date().toLocaleString('zh-CN'),
+ };
+
+ mockComments.push(newComment);
+
+ // 更新帖子评论数
+ const post = mockPosts.find(p => p.postId === Number(postId));
+ if (post) {
+ post.comments += 1;
+ }
+
+ res.json({
+ code: 200,
+ data: newComment,
+ msg: '评论成功',
+ });
+ },
+
+ // 收藏/取消收藏帖子
+ 'POST /api/post/favorite/:id': (req: Request, res: Response) => {
+ const { id } = req.params;
+ const { favorite } = req.query;
+
+ const post = mockPosts.find(p => p.postId === Number(id));
+ if (!post) {
+ return res.json({
+ code: 404,
+ msg: '帖子不存在',
+ });
+ }
+
+ if (favorite === 'true') {
+ post.favorites += 1;
+ res.json({
+ code: 200,
+ msg: '收藏成功',
+ });
+ } else {
+ post.favorites = Math.max(0, post.favorites - 1);
+ res.json({
+ code: 200,
+ msg: '取消收藏成功',
+ });
+ }
+ },
+
+ // 获取热门标签
+ 'GET /api/post/tags/hot': (req: Request, res: Response) => {
+ const mockTags = [
+ { tagId: 1, tagName: '日剧', tagColor: 'blue', postCount: 150, status: '0' },
+ { tagId: 2, tagName: '电影', tagColor: 'green', postCount: 120, status: '0' },
+ { tagId: 3, tagName: '音乐', tagColor: 'orange', postCount: 80, status: '0' },
+ { tagId: 4, tagName: '推理', tagColor: 'purple', postCount: 65, status: '0' },
+ { tagId: 5, tagName: '爱情', tagColor: 'pink', postCount: 45, status: '0' },
+ ];
+
+ res.json({
+ code: 200,
+ data: mockTags,
+ msg: '查询成功',
+ });
+ },
+
+ // 根据标签获取帖子
+ 'GET /api/post/bytag/:tagId': (req: Request, res: Response) => {
+ const { tagId } = req.params;
+
+ // 简单的mock实现,实际应该根据tagId查询相关帖子
+ const filteredPosts = mockPosts.filter(post =>
+ post.tags.includes('日剧') // 假设查询日剧标签
+ );
+
+ res.json({
+ code: 200,
+ rows: filteredPosts,
+ total: filteredPosts.length,
+ msg: '查询成功',
+ });
+ },
+};
\ No newline at end of file