修复查看帖子、评论、回复评论、点赞、收藏,添加用户等级

Change-Id: Ida9590d7ccee08dcd787a36c7e5cb39a3e26cd0d
diff --git a/src/pages/Forum/posts-detail/PostDetailPage.jsx b/src/pages/Forum/posts-detail/PostDetailPage.jsx
index c58ed33..a505d88 100644
--- a/src/pages/Forum/posts-detail/PostDetailPage.jsx
+++ b/src/pages/Forum/posts-detail/PostDetailPage.jsx
@@ -1,284 +1,3 @@
-// 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'; // 注意路径
-// import Header from '../../../components/Header';
-
-// 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">
-//       <Header />
-//       {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-user">用户ID: {postDetail.user_id}</span>
-//             <span className="post-time">
-//             发布时间:{new Date(postDetail.postTime).toLocaleString()}
-//             </span>
-//           </div>
-//           <div className="post-content">
-//             <p>{postDetail.postContent}</p>
-//             {Array.isArray(postDetail.imgUrl) ? (
-//               <div className="post-images">
-//                 {postDetail.imgUrl.map((url, idx) => (
-//                   <img key={idx} src={url} alt={`图片${idx}`} />
-//                 ))}
-//               </div>
-//             ) : (
-//               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="20"
-//                 fill={isLiked ? '#f00' : '#ccc'} // 如果已点赞,显示红色
-//               />
-//               <span>{postDetail.postLikeNum}</span>
-//             </button>
-//             <button
-//               className="icon-btn"
-//               onClick={toggleCollect} // 收藏操作
-//             >
-//               <Star
-//                 theme="outline"
-//                 size="20"
-//                 fill={isCollected ? '#ffd700' : '#ccc'} // 如果已收藏,显示金色
-//               />
-//               <span>{postDetail.postCollectNum}</span>
-//             </button>
-//           </div>
-          
-//           <hr className="divider" />
-//           {/* 评论部分 */}
-//           <h3>评论区</h3>
-//           <div className="comments-section">
-//             {comments.length ? (
-//               comments.map((comment) => (
-//                 <div key={comment.commentId} className="comment">
-//                   <div className="comment-header">
-//                     <span className="comment-user">用户 ID: {comment.userId}</span>
-//                     <button className="reply-btn" onClick={() => handleReply(comment.commentId)}>回复</button>
-//                   </div>
-//                   <p className="comment-content">{comment.content}</p>
-//                   <div className="comment-time">
-//                     {new Date(comment.commentTime).toLocaleString()}
-//                   </div>
-
-//                   {/* 回复框,只有在当前评论是正在回复的评论时显示 */}
-//                   {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;
-
 import React, { useEffect, useState } from 'react';
 import { useParams } from 'wouter';
 import { GoodTwo, Star } from '@icon-park/react';
@@ -298,6 +17,7 @@
   const [isLiked, setIsLiked] = useState(false); // 是否已点赞
   const [isCollected, setIsCollected] = useState(false); // 是否已收藏
   const [replyToCommentId, setReplyToCommentId] = useState(null); // 回复的评论ID
+  const [replyToUsername, setReplyToUsername] = useState(null);
 
   // 获取当前用户ID(假设从上下文中获取)
   const { user } = useUser(); // 你需要从用户上下文获取用户 ID
@@ -402,41 +122,61 @@
 };
 
   // 添加评论
-  const handleAddComment = async () => {
-    if (!newComment.trim()) {
-      alert('评论内容不能为空');
-      return;
-    }
+const handleAddComment = async () => {
+  if (!newComment.trim()) {
+    alert('评论内容不能为空');
+    return;
+  }
 
-    try {
-      // 调用 API 添加评论,若为回复评论则传递父评论ID(com_comment_id)
-      const commentData = await addCommentToPost(postId, user.id, newComment, 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('评论失败,请稍后再试');
-    }
-  };
+  try {
+    const commentPayload = {
+      content: newComment,
+      userId: user.id,
+      isAnonymous: false,
+      com_comment_id: replyToCommentId || null,
+    };
+
+    const commentData = await addCommentToPost(postId, commentPayload);
+
+    setComments((prev) => [
+      ...prev,
+      {
+        commentId: (commentData && commentData.commentId) || Date.now(),
+        post_id: postId,
+        userId: user.id,
+        content: newComment,
+        commentTime: new Date().toISOString(),
+        comCommentId: replyToCommentId,
+      },
+    ]);
+
+    setNewComment('');
+    setReplyToCommentId(null);
+  } catch (err) {
+    console.error('评论添加失败:', err);
+    alert('评论失败,请稍后再试');
+  }
+};
+
+
 
   // 回复评论
   const handleReply = (commentId) => {
-    setReplyToCommentId(commentId); // 设置父评论ID为当前评论的ID
-  };
+  setReplyToCommentId(commentId);
+  const comment = comments.find(c => c.commentId === commentId);
+  if (comment) {
+    // 这里用用户名或者用户ID
+    setReplyToUsername(comment.username || comment.userId);
+  } else {
+    setReplyToUsername(null);
+  }
+};
+
+const findUsernameByCommentId = (id) => {
+  const comment = comments.find(c => c.commentId === id);
+  return comment ? (comment.username || comment.userId) : '未知用户';
+};
+
 
   return (
     <div className="post-detail-page">
@@ -499,7 +239,7 @@
           <hr className="divider" />
           {/* 评论部分 */}
           <h3>评论区</h3>
-          <div className="comments-section">
+          <div className="comments-section">      
             {comments.length ? (
               comments.map((comment) => (
                 <div key={comment.commentId} className="comment">
@@ -507,28 +247,34 @@
                     <span className="comment-user">用户 ID: {comment.userId}</span>
                     <button className="reply-btn" onClick={() => handleReply(comment.commentId)}>回复</button>
                   </div>
-                  <p className="comment-content">{comment.content}</p>
+
+                  <p className="comment-content">
+                    {comment.comCommentId ? (
+                      <>
+                        <span className="reply-to">回复 {findUsernameByCommentId(comment.comCommentId)}:</span>
+                        {comment.content}
+                      </>
+                    ) : (
+                      comment.content
+                    )}
+                  </p>
+
                   <div className="comment-time">
                     {new Date(comment.commentTime).toLocaleString()}
                   </div>
 
-                  {/* 回复框,只有在当前评论是正在回复的评论时显示 */}
+                  {/* 回复框 */}
                   {replyToCommentId === comment.commentId && (
                     <div className="reply-form">
+                      <div className="replying-to">
+                        回复 <strong>{replyToUsername}</strong>:
+                      </div>
                       <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>
@@ -539,6 +285,7 @@
               <p>暂无评论</p>
             )}
 
+
             {/* 添加评论表单 */}
             <div className="add-comment-form">
               <textarea
diff --git a/src/pages/Forum/posts-detail/api.js b/src/pages/Forum/posts-detail/api.js
index 27c3a18..53dbfd3 100644
--- a/src/pages/Forum/posts-detail/api.js
+++ b/src/pages/Forum/posts-detail/api.js
@@ -1,46 +1,60 @@
 import axios from 'axios';
 
-const API_BASE = process.env.REACT_APP_API_BASE;
+
 
 
 // 获取帖子详情
 export const getPostDetail = async (post_id) => {
-    const response = await axios.get(`${API_BASE}/echo/forum/posts/${post_id}/getPost`);
+    const response = await axios.get(`/echo/forum/posts/${post_id}/getPost`);
     return response.data;
 };
 
 // 获取帖子评论
 export const getPostComments = async (post_id) => {
-    const response = await axios.get(`${API_BASE}/echo/forum/posts/${post_id}/getAllComments`);
+    const response = await axios.get(`/echo/forum/posts/${post_id}/getAllComments`);
+    return response.data;
+};
+
+// 添加评论
+export const addCommentToPost = async (postId, commentPayload) => {
+  const res = await fetch(`/echo/forum/posts/${postId}/comments`, {
+    method: 'POST',
+    headers: { 'Content-Type': 'application/json' },
+    body: JSON.stringify(commentPayload),
+  });
+
+  if (!res.ok) {
+    throw new Error('请求失败,状态码:' + res.status);
+  }
+
+  // 试着解析 JSON,如果失败则返回 null(可能是空响应)
+  try {
+    const data = await res.json();
+    return data;
+  } catch {
+    return null;
+  }
+};
+
+
+
+// 点赞评论
+export const likeComment = async (commentId) => {
+    const response = await axios.post(`/echo/forum/comments/${commentId}/like`);
+    return response.data;
+};
+
+// 取消点赞评论
+export const unlikeComment = async (commentId) => {
+    const response = await axios.delete(`/echo/forum/comments/${commentId}/unlike`);
     return response.data;
 };
 
 // 点赞帖子
 export const likePost = async (post_id, userId) => {
     try {
-        const response = await axios.post(`${API_BASE}/echo/forum/posts/${post_id}/like`, {
-            user_id: userId,  // 用户 ID
-        });
-        return response.data;
-    } catch (error) {
-        return handleApiError(error);
-    }
-};
-
-// 取消点赞帖子
-export const unlikePost = async (post_id) => {
-    const response = await axios.delete(`${API_BASE}/echo/forum/posts/${post_id}/unlike`);
-    return response.data;
-};
-
-// 添加评论
-export const addCommentToPost = async (post_id, userId, content, isAnonymous, comCommentId = null) => {
-    try {
-        const response = await axios.post(`${API_BASE}/echo/forum/posts/${post_id}/comments`, {
-            content,
+        const response = await axios.post(`/echo/forum/posts/${post_id}/like`, {
             user_id: userId,
-            is_anonymous: isAnonymous,
-            com_comment_id: comCommentId, // 如果是回复评论,传递 com_comment_id
         });
         return response.data;
     } catch (error) {
@@ -48,24 +62,23 @@
     }
 };
 
-// 点赞评论
-export const likeComment = async (commentId) => {
-    const response = await axios.post(`${API_BASE}/echo/forum/comments/${commentId}/like`);
-    return response.data;
-};
-
-// 取消点赞评论
-export const unlikeComment = async (commentId) => {
-    const response = await axios.delete(`${API_BASE}/echo/forum/comments/${commentId}/unlike`);
-    return response.data;
+// 取消点赞帖子(改为 POST 请求,携带 user_id)
+export const unlikePost = async (post_id, userId) => {
+    try {
+        const response = await axios.post(`/echo/forum/posts/${post_id}/unlike`, {
+            user_id: userId,
+        });
+        return response.data;
+    } catch (error) {
+        return handleApiError(error);
+    }
 };
 
 // 收藏帖子
-export const collectPost = async (post_id, userId, action) => {
+export const collectPost = async (post_id, userId) => {
     try {
-        const response = await axios.post(`${API_BASE}/echo/forum/posts/${post_id}/collect`, {
+        const response = await axios.post(`/echo/forum/posts/${post_id}/collect`, {
             user_id: userId,
-            action: action,  // "collect" 或 "cancel"
         });
         return response.data;
     } catch (error) {
@@ -73,17 +86,21 @@
     }
 };
 
-// // 取消收藏帖子
-// export const uncollectPost = async (post_id, userId) => {
-//     const response = await axios.post(`${API_BASE}/echo/forum/posts/${post_id}/uncollect`, {
-//         user_id: userId,  // 用户 ID
-//     });
-//     return response.data;
-// };
+// 取消收藏帖子(使用 POST 请求)
+export const uncollectPost = async (post_id, userId) => {
+    try {
+        const response = await axios.post(`/echo/forum/posts/${post_id}/uncollect`, {
+            user_id: userId,
+        });
+        return response.data;
+    } catch (error) {
+        return handleApiError(error);
+    }
+};
 
-// 获取用户信息
+
 export const getUserInfo = async (userId) => {
-    const response = await axios.get(`${API_BASE}/user/${userId}/info`);
+    const response = await axios.get(`/user/${userId}/info`);
     return response.data;
 };