修复查看帖子、评论、回复评论、点赞、收藏,添加用户等级
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;
};