| import React, { useEffect, useState } from 'react'; |
| import { useParams } from 'wouter'; |
| import { GoodTwo, Star } from '@icon-park/react'; |
| import { getPostDetail, getPostComments, likePost, unlikePost, addCommentToPost, collectPost } from './api'; // 引入你的 API 函数 |
| import './PostDetailPage.css'; |
| import { useUser } from '../../../context/UserContext'; // 注意路径 |
| |
| const PostDetailPage = () => { |
| const { postId } = useParams(); // 获取帖子ID |
| const [postDetail, setPostDetail] = useState(null); |
| const [comments, setComments] = useState([]); |
| const [loading, setLoading] = useState(true); |
| const [errorMsg, setErrorMsg] = useState(''); |
| const [newComment, setNewComment] = useState(''); // 新评论内容 |
| const [isAnonymous, setIsAnonymous] = useState(false); // 是否匿名 |
| const [isLiked, setIsLiked] = useState(false); // 是否已点赞 |
| const [isCollected, setIsCollected] = useState(false); // 是否已收藏 |
| const [replyToCommentId, setReplyToCommentId] = useState(null); // 回复的评论ID |
| |
| // 获取当前用户ID(假设从上下文中获取) |
| const { user } = useUser(); // 你需要从用户上下文获取用户 ID |
| |
| useEffect(() => { |
| const fetchPostDetail = async () => { |
| setLoading(true); |
| setErrorMsg(''); |
| try { |
| // 获取帖子详情 |
| const postData = await getPostDetail(postId); |
| setPostDetail(postData); |
| |
| // 获取帖子评论 |
| const commentsData = await getPostComments(postId); |
| setComments(commentsData); |
| |
| // 设置是否已经点赞 |
| if (postData.likedByUser) { |
| setIsLiked(true); |
| } else { |
| setIsLiked(false); |
| } |
| |
| // 设置是否已经收藏 |
| if (postData.collectedByUser) { |
| setIsCollected(true); |
| } else { |
| setIsCollected(false); |
| } |
| } catch (err) { |
| console.error('加载失败:', err); |
| setErrorMsg('加载失败,请稍后重试'); |
| } finally { |
| setLoading(false); |
| } |
| }; |
| |
| fetchPostDetail(); |
| }, [postId]); |
| |
| // 点赞功能 |
| const toggleLike = async () => { |
| if (!user) { |
| alert('请先登录'); |
| return; |
| } |
| |
| try { |
| if (isLiked) { |
| // 取消点赞 |
| await unlikePost(postId, user.id); |
| setIsLiked(false); |
| setPostDetail((prev) => ({ |
| ...prev, |
| postLikeNum: prev.postLikeNum - 1, |
| })); |
| } else { |
| // 点赞 |
| await likePost(postId, user.id); |
| setIsLiked(true); |
| setPostDetail((prev) => ({ |
| ...prev, |
| postLikeNum: prev.postLikeNum + 1, |
| })); |
| } |
| } catch (err) { |
| console.error('点赞失败:', err); |
| alert('点赞失败,请稍后再试'); |
| } |
| }; |
| |
| // 收藏功能 |
| const toggleCollect = async () => { |
| if (!user) { |
| alert('请先登录'); |
| return; |
| } |
| |
| try { |
| const action = isCollected ? 'cancel' : 'collect'; |
| // 调用收藏 API |
| await collectPost(postId, user.id, action); |
| setIsCollected(!isCollected); |
| setPostDetail((prev) => ({ |
| ...prev, |
| postCollectNum: isCollected ? prev.postCollectNum - 1 : prev.postCollectNum + 1, |
| })); |
| } catch (err) { |
| console.error('收藏失败:', err); |
| alert('收藏失败,请稍后再试'); |
| } |
| }; |
| |
| // 添加评论 |
| const handleAddComment = async () => { |
| if (!newComment.trim()) { |
| alert('评论内容不能为空'); |
| return; |
| } |
| |
| try { |
| // 调用 API 添加评论,若为回复评论则传递父评论ID(com_comment_id) |
| const commentData = await addCommentToPost(postId, user.id, newComment, isAnonymous, replyToCommentId); |
| // 更新评论列表 |
| setComments((prev) => [ |
| ...prev, |
| { |
| commentId: commentData.commentId, |
| post_id: postId, |
| userId: user.id, |
| content: newComment, |
| isAnonymous, |
| commentTime: new Date().toISOString(), |
| comCommentId: replyToCommentId, // 回复评论时传递父评论ID |
| }, |
| ]); |
| // 清空评论框和回复状态 |
| setNewComment(''); |
| setReplyToCommentId(null); |
| } catch (err) { |
| console.error('评论添加失败:', err); |
| alert('评论失败,请稍后再试'); |
| } |
| }; |
| |
| // 回复评论 |
| const handleReply = (commentId) => { |
| setReplyToCommentId(commentId); // 设置父评论ID为当前评论的ID |
| }; |
| |
| return ( |
| <div className="post-detail-page"> |
| {loading ? ( |
| <p>加载中...</p> |
| ) : errorMsg ? ( |
| <p className="error-text">{errorMsg}</p> |
| ) : postDetail ? ( |
| <div className="post-detail"> |
| <h1>{postDetail.title}</h1> |
| <div className="post-meta"> |
| <span className="post-time"> |
| {new Date(postDetail.postTime).toLocaleString()} |
| </span> |
| <span className="post-user">用户 ID: {postDetail.user_id}</span> |
| </div> |
| <div className="post-content"> |
| <p>{postDetail.postContent}</p> |
| {postDetail.imgUrl && ( |
| <img |
| className="post-image" |
| src={postDetail.imgUrl} |
| alt="帖子图片" |
| /> |
| )} |
| </div> |
| |
| {/* 点赞和收藏 */} |
| <div className="post-actions"> |
| <button |
| className="icon-btn" |
| onClick={toggleLike} // 点赞操作 |
| > |
| <GoodTwo |
| theme="outline" |
| size="24" |
| fill={isLiked ? '#f00' : '#ccc'} // 如果已点赞,显示红色 |
| /> |
| <span>{postDetail.postLikeNum}</span> |
| </button> |
| <button |
| className="icon-btn" |
| onClick={toggleCollect} // 收藏操作 |
| > |
| <Star |
| theme="outline" |
| size="24" |
| fill={isCollected ? '#ffd700' : '#ccc'} // 如果已收藏,显示金色 |
| /> |
| <span>{postDetail.postCollectNum}</span> |
| </button> |
| </div> |
| |
| {/* 评论部分 */} |
| <div className="comments-section"> |
| <h3>评论区</h3> |
| {comments.length ? ( |
| comments.map((comment) => ( |
| <div key={comment.commentId} className="comment"> |
| <p>{comment.content}</p> |
| <div className="comment-meta"> |
| <span className="comment-time"> |
| {new Date(comment.commentTime).toLocaleString()} |
| </span> |
| <span className="comment-user">用户 ID: {comment.userId}</span> |
| </div> |
| {/* 回复按钮 */} |
| <button onClick={() => handleReply(comment.commentId)}>回复</button> |
| |
| {/* 回复框,只有在当前评论是正在回复的评论时显示 */} |
| {replyToCommentId === comment.commentId && ( |
| <div className="reply-form"> |
| <textarea |
| placeholder="输入你的回复..." |
| value={newComment} |
| onChange={(e) => setNewComment(e.target.value)} |
| /> |
| <div className="comment-options"> |
| <label> |
| <input |
| type="checkbox" |
| checked={isAnonymous} |
| onChange={() => setIsAnonymous(!isAnonymous)} |
| /> |
| 匿名评论 |
| </label> |
| <button onClick={handleAddComment}>发布回复</button> |
| </div> |
| </div> |
| )} |
| </div> |
| )) |
| ) : ( |
| <p>暂无评论</p> |
| )} |
| |
| {/* 添加评论表单 */} |
| <div className="add-comment-form"> |
| <textarea |
| placeholder="输入你的评论..." |
| value={newComment} |
| onChange={(e) => setNewComment(e.target.value)} |
| /> |
| <div className="comment-options"> |
| <label> |
| <input |
| type="checkbox" |
| checked={isAnonymous} |
| onChange={() => setIsAnonymous(!isAnonymous)} |
| /> |
| 匿名评论 |
| </label> |
| <button onClick={handleAddComment}>发布评论</button> |
| </div> |
| </div> |
| </div> |
| </div> |
| ) : ( |
| <p>帖子不存在</p> |
| )} |
| </div> |
| ); |
| }; |
| |
| export default PostDetailPage; |