| import React, { useEffect, useState } from 'react'; |
| import { useParams } from 'react-router-dom'; |
| import styles from './PostDetail.module.css'; |
| import { Card, List, Typography, Button, Input, Spin, Empty } from 'antd'; |
| type CommentProps = { |
| children?: React.ReactNode; |
| }; |
| import { getPostDetail } from '@/api/post'; |
| import { getPostComments } from '@/api/comment'; |
| import { useSearchParams } from 'react-router-dom'; |
| import request from '@/utils/request'; |
| import { useApi } from '@/hooks/request'; |
| import Navbar from '@/components/navbar/navbar'; |
| |
| const { Title, Text, Paragraph } = Typography; |
| const { TextArea } = Input; |
| |
| export interface PostResponse { |
| createdAt?: number; |
| hotScore?: number; |
| lastCalculated?: number; |
| postContent?: string; |
| postId?: number; |
| postTitle?: string; |
| postType?: string; |
| userId?: number; |
| viewCount?: number; |
| [property: string]: any; |
| } |
| |
| export interface CommentResponse { |
| commentId?: number; |
| content?: string; |
| createdAt?: number; |
| parentCommentId?: number | null; |
| postId?: number; |
| replies?: CommentResponse[]; |
| userId?: number; |
| [property: string]: any; |
| } |
| |
| const PostDetail: React.FC = () => { |
| const [searchParams] = useSearchParams(); |
| const postId = searchParams.get('postId'); |
| const { refresh: getPostDetailRefresh } = useApi(() => request.get(getPostDetail + `/${postId}`), false); |
| const { refresh: getPostCommentsRefresh } = useApi(() => request.get(getPostComments + `/${postId}`), false); |
| const [post, setPost] = useState<PostResponse | null>(null); |
| const [comments, setComments] = useState<CommentResponse[]>([]); |
| const [newComment, setNewComment] = useState<string>(''); |
| const [loading, setLoading] = useState<boolean>(true); |
| |
| useEffect(() => { |
| console.log('postId', postId); |
| if (!postId) return; |
| const fetchData = async () => { |
| setLoading(true); |
| const res = await getPostDetailRefresh(); |
| if (res == null || (res as any).error) { |
| setLoading(false); |
| return; |
| } |
| setPost(res as PostResponse); |
| await getPostCommentsRefresh(); |
| setComments(res as CommentResponse[]); |
| setLoading(false); |
| }; |
| fetchData(); |
| }, [postId]); |
| |
| if (loading) return <div className={styles.center}><Spin /></div>; |
| if (!post) return <div className={styles.center}><Empty description="未找到帖子" /></div>; |
| |
| return ( |
| <div className={styles.container}> |
| <div className={styles.nav}> |
| <Navbar current={post.postType} /> |
| </div> |
| <div className={styles.content}> |
| <div className={styles.postDetail}> |
| |
| </div > |
| <Card title={post.postTitle} className={styles.card}> |
| <Paragraph>{post.postContent}</Paragraph> |
| <div className={styles.actions}> |
| <Button type="primary" onClick={() => setNewComment('')}>评论</Button> |
| </div> |
| </Card> |
| |
| <List |
| className={styles.commentList} |
| header={<Title level={4}>评论区</Title>} |
| dataSource={comments} |
| renderItem={(item) => ( |
| <List.Item key={item.commentId}> |
| <List.Item.Meta |
| title={<Text strong>{item.userId}</Text>} |
| description={<Text>{item.content}</Text>} |
| /> |
| </List.Item> |
| )} |
| /> |
| |
| <TextArea |
| rows={4} |
| value={newComment} |
| onChange={(e) => setNewComment(e.target.value)} |
| placeholder="写下你的评论..." |
| /> |
| </div> |
| </div> |
| ); |
| }; |
| |
| export default PostDetail; |