fix: 论坛页面优化 & 新增修改帖子

This commit is contained in:
Shu Guang 2025-05-16 02:17:53 +08:00
parent 279e5d81f7
commit 9a7b889ada
3 changed files with 169 additions and 60 deletions

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import { useParams } from '@umijs/max';
import {
Card,
@ -19,44 +19,90 @@ import {
StarFilled,
ShareAltOutlined,
} from '@ant-design/icons';
import { getPostVoByIdUsingGet } from '@/services/hebi/postController';
import { doThumbUsingPost } from '@/services/hebi/postThumbController';
import { doPostFavourUsingPost } from '@/services/hebi/postFavourController';
import dayjs from 'dayjs';
import MDEditor from '@uiw/react-md-editor';
import '@uiw/react-md-editor/markdown-editor.css';
import '@uiw/react-markdown-preview/markdown.css';
const { Title, Paragraph } = Typography;
const { Title } = Typography;
const { TextArea } = Input;
// Mock comment data
const mockComments = [
{
id: 1,
author: '张三',
avatar: 'https://joeschmoe.io/api/v1/random',
content: '这个帖子很有帮助,感谢分享!',
createTime: '2024-03-20 10:00',
likes: 5,
},
{
id: 2,
author: '李四',
avatar: 'https://joeschmoe.io/api/v1/random',
content: '我也有一些补充,大家可以参考一下...',
createTime: '2024-03-20 11:30',
likes: 3,
},
{
id: 3,
author: '王五',
avatar: 'https://joeschmoe.io/api/v1/random',
content: '学到了很多新知识,期待更多分享!',
createTime: '2024-03-20 14:15',
likes: 2,
},
];
import { useModel } from '@umijs/max'; // 新增
const ForumDetail: React.FC = () => {
const { initialState } = useModel('@@initialState'); // 获取当前登录用户信息
const currentUser = initialState?.currentUser;
const { id } = useParams();
const [liked, setLiked] = useState(false);
const [collected, setCollected] = useState(false);
const [comment, setComment] = useState('');
const [comments, setComments] = useState(mockComments);
// mock 评论数据
const [comments, setComments] = useState([
{
id: 1,
author: '小明',
avatar: 'https://joeschmoe.io/api/v1/1',
content: '很棒的分享,受益匪浅!',
createTime: '2025-05-15 10:00:00',
likes: 2,
},
{
id: 2,
author: 'AI助手',
avatar: 'https://joeschmoe.io/api/v1/2',
content: '请问有完整代码示例吗?',
createTime: '2025-05-15 11:20:00',
likes: 1,
},
{
id: 3,
author: '匿名用户',
avatar: 'https://joeschmoe.io/api/v1/random',
content: '期待更多相关内容!',
createTime: '2025-05-15 12:45:00',
likes: 0,
},
]);
// 帖子详情状态
const [post, setPost] = useState<any>(null);
const [loading, setLoading] = useState(true);
// 拉取帖子详情
useEffect(() => {
const fetchDetail = async () => {
setLoading(true);
const res = await getPostVoByIdUsingGet({ id });
console.log('res', res);
if (res && res.code === 0 && res.data) {
setPost(res.data);
setLiked(!!res.data.hasThumb);
setCollected(!!res.data.hasFavour);
}
setLoading(false);
};
if (id) fetchDetail();
}, [id]);
// 点赞处理
const handleLike = async () => {
try {
const res = await doThumbUsingPost({ postId: id }); // 直接传字符串 id
if (res && res.code === 0) {
setLiked(!liked);
message.success(liked ? '已取消点赞' : '点赞成功');
} else {
message.error(res?.message || '操作失败');
}
} catch (e) {
message.error('操作失败');
}
};
const handleSubmitComment = () => {
if (!comment.trim()) {
@ -77,46 +123,80 @@ const ForumDetail: React.FC = () => {
setComment('');
};
// 收藏处理
const handleFavour = async () => {
try {
const res = await doPostFavourUsingPost({ postId: id });
if (res && res.code === 0) {
setCollected(!collected);
message.success(collected ? '已取消收藏' : '收藏成功');
} else {
message.error(res?.message || '操作失败');
}
} catch (e) {
message.error('操作失败');
}
};
// 判断是否是当前用户的帖子
const isMyPost = currentUser?.id === post?.userId;
return (
<Card>
<Card loading={loading}>
<article>
<header style={{ marginBottom: 24 }}>
<Title level={2}></Title>
<Title level={2}>{post?.title || '帖子标题'}</Title>
<Space split={<Divider type="vertical" />}>
<Space>
<Avatar src="https://joeschmoe.io/api/v1/random" />
<span></span>
<Avatar src={post?.user?.userAvatar || 'https://joeschmoe.io/api/v1/random'} />
<span>{post?.user?.userName || '无'}</span>
</Space>
<span></span>
<Tag color="blue"></Tag>
<span> 1000</span>
<span>
{post?.createTime ? dayjs(post.createTime).format('YYYY-MM-DD HH:mm:ss') : '发布时间'}
</span>
{post?.tagList?.map((tag: string) => (
<Tag color="blue" key={tag}>{tag}</Tag>
))}
</Space>
</header>
<Paragraph>
</Paragraph>
{/* Markdown 渲染帖子内容 */}
<div data-color-mode="light" style={{ background: '#fff' }}>
<MDEditor.Markdown source={post?.content || '帖子内容'} />
</div>
<div style={{ marginTop: 24 }}>
<Space size="large">
<Button
icon={liked ? <LikeFilled /> : <LikeOutlined />}
onClick={() => setLiked(!liked)}
icon={liked ? <LikeFilled style={{ color: '#ff4d4f' }} /> : <LikeOutlined />}
onClick={handleLike}
style={liked ? { color: '#ff4d4f', borderColor: '#ff4d4f', background: '#fff0f0' } : {}}
>
{post?.thumbNum ?? 0}
</Button>
<Button
icon={collected ? <StarFilled /> : <StarOutlined />}
onClick={() => setCollected(!collected)}
icon={collected ? <StarFilled style={{ color: '#ff4d4f' }} /> : <StarOutlined />}
onClick={handleFavour}
style={collected ? { color: '#ff4d4f', borderColor: '#ff4d4f', background: '#fff0f0' } : {}}
>
{post?.favourNum ?? 0}
</Button>
{isMyPost && (
<Button
type="primary"
onClick={() => {
window.location.href = `/forum/publish?id=${id}`; // 使用 window.location.href 进行跳转
}}
>
</Button>
)}
<Button icon={<ShareAltOutlined />}>
</Button>
</Space>
</div>
<Divider />
<div>

View File

@ -99,9 +99,9 @@ const ForumList: React.FC = () => {
className={styles.postItem}
actions={[
<Space key={"actions"} className={styles.postStats}>
<span key="views" className={styles.statItem}>
{/* <span key="views" className={styles.statItem}>
<EyeOutlined /> {item.viewNum || 0}
</span>
</span> */}
<span key="comments" className={styles.statItem}>
<MessageOutlined /> {item.commentNum || 0}
</span>
@ -158,7 +158,13 @@ const ForumList: React.FC = () => {
</Space>
}
/>
<div className={styles.postContent}>
<div className={styles.postContent} style={{
display: '-webkit-box',
WebkitBoxOrient: 'vertical',
WebkitLineClamp: 5,
overflow: 'hidden',
textOverflow: 'ellipsis',
}}>
{item.content}
</div>
</List.Item>

View File

@ -1,43 +1,66 @@
import React, { useState } from 'react';
import React, { useState,useEffect } from 'react';
import { Card, Form, Input, Button, Select, message, Alert } from 'antd';
import { history } from '@umijs/max';
import styles from './index.less';
import MDEditor from '@uiw/react-md-editor'; // 直接引入,不用 next/dynamic
import '@uiw/react-md-editor/markdown-editor.css';
import '@uiw/react-markdown-preview/markdown.css';
import { addPostUsingPost } from '@/services/hebi/postController';
import { addPostUsingPost, updatePostUsingPost} from '@/services/hebi/postController';
import { useSearchParams } from '@umijs/max'; // 新增
import { getPostVoByIdUsingGet } from '@/services/hebi/postController'; // 新增
const { TextArea } = Input;
const ForumPublish: React.FC = () => {
const [searchParams] = useSearchParams();
const id = searchParams.get('id'); // 获取帖子 ID
const [form] = Form.useForm();
const [submitting, setSubmitting] = useState(false);
const [mdContent, setMdContent] = useState<string>(''); // 新增
const [mdContent, setMdContent] = useState<string>('');
// 如果是编辑模式,加载帖子内容
useEffect(() => {
const loadPost = async () => {
if (id) {
const res = await getPostVoByIdUsingGet({ id });
if (res?.code === 0 && res.data) {
form.setFieldsValue({
title: res.data.title,
tags: res.data.tagList,
});
setMdContent(res.data.content);
}
}
};
loadPost();
}, [id, form]);
const handleSubmit = async (values: any) => {
setSubmitting(true);
try {
const postAddRequest = {
id: id || undefined,
title: values.title,
content: mdContent, // 使用 Markdown 内容
content: mdContent,
tags: values.tags || [],
};
const res = await addPostUsingPost(postAddRequest);
const res = id ? await updatePostUsingPost(postAddRequest as any): await addPostUsingPost(postAddRequest);
if (res && res.code === 0) {
message.success('发布成功');
message.success(id ? '修改成功' : '发布成功');
history.push('/forum/list');
} else {
message.error(res?.message || '发布失败');
message.error(res?.message || (id ? '修改失败' : '发布失败'));
}
} catch (error) {
message.error('发布失败');
message.error(id ? '修改失败' : '发布失败');
}
setSubmitting(false);
};
return (
<div className={styles.publishContainer}>
<Card title="发布帖子" className={styles.publishCard}>
<Card title={id ? '修改帖子' : '发布帖子'} className={styles.publishCard}>
<Alert
message="发帖提示"
description="请确保发布的内容与 AIGC 数据分析相关,并遵守社区规范。"
@ -99,7 +122,7 @@ const ForumPublish: React.FC = () => {
</Button>
<Button type="primary" htmlType="submit" loading={submitting}>
{id ? '保存修改' : '发布帖子'}
</Button>
</div>
</Form>