fix: 论坛页面优化 & 新增修改帖子
This commit is contained in:
parent
279e5d81f7
commit
9a7b889ada
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user