blob: 704636ea861bc638eab68b3830f9bf77a26f2321 [file] [log] [blame]
import React, { useState, useEffect } from 'react';
import {
getCommentsByPostId,
createComment,
deleteComment,
likeComment,
unlikeComment,
} from '../api/comment';
import {
Card,
Button,
Input,
List,
Avatar,
Popconfirm,
message,
Space,
Tooltip
} from 'antd';
import {
LikeOutlined,
LikeFilled,
DeleteOutlined
} from '@ant-design/icons';
import axios from 'axios';
import './Comment.css';
const { TextArea } = Input;
const Comment = ({ postId, currentUser }) => {
const [comments, setComments] = useState([]);
const [newContent, setNewContent] = useState('');
const [loading, setLoading] = useState(false);
const [userInfoMap, setUserInfoMap] = useState({});
const [isCommenting, setIsCommenting] = useState(false);
useEffect(() => {
loadComments();
}, [postId, currentUser]);
const loadComments = async () => {
try {
if (!postId) return;
const commentList = await getCommentsByPostId(postId);
setComments(commentList);
// 修复1: 统一使用 userid 而不是 id
const userIds = [
...new Set(commentList.map(c => c.userid))
];
// 如果当前用户存在,添加其 userid
if (currentUser && currentUser.userid) {
userIds.push(currentUser.userid);
}
// 批量获取用户信息
const userInfoPromises = userIds.map(async (id) => {
try {
const res = await axios.get(`http://localhost:8080/user/getDecoration?userid=${id}`);
if (res.data?.success) {
return { id, data: res.data.data };
}
return { id, data: { username: `用户${id}`, image: '' } };
} catch (error) {
return { id, data: { username: `用户${id}`, image: '' } };
}
});
const userInfoResults = await Promise.all(userInfoPromises);
// 构建用户信息映射
const newUserInfoMap = {};
userInfoResults.forEach(({ id, data }) => {
newUserInfoMap[id] = data;
});
setUserInfoMap(newUserInfoMap);
} catch (error) {
console.error('加载评论失败:', error);
message.error('加载评论失败');
}
};
const handleCreate = async () => {
// 检查用户是否登录
if (!currentUser) {
message.error('请先登录后再评论');
return;
}
// 修复2: 确保当前用户有 userid 属性
if (!currentUser.userid) {
message.error('用户信息异常,请重新登录');
return;
}
if (!newContent.trim()) {
message.warning('评论内容不能为空');
return;
}
setIsCommenting(true);
setLoading(true);
// 修复3: 使用 currentUser.userid 而非 currentUser.id
const commentData = {
postid: postId,
userid: Number(currentUser.userid),
postCommentcontent: newContent,
commenttime: new Date().toISOString()
};
try {
await createComment(commentData);
setNewContent('');
await loadComments(); // 重新加载评论,确保新评论显示
message.success('评论发布成功');
} catch (error) {
console.error('发布评论失败:', error);
message.error('发布评论失败');
} finally {
setLoading(false);
setIsCommenting(false);
}
};
const handleDelete = async (commentid) => {
try {
await deleteComment(commentid);
message.success('删除成功');
loadComments();
} catch (error) {
console.error('删除评论失败:', error);
message.error('删除失败');
}
};
const handleLike = async (commentid) => {
try {
await likeComment(commentid);
loadComments();
} catch (error) {
console.error('点赞失败:', error);
message.error('操作失败');
}
};
const handleUnlike = async (commentid) => {
try {
await unlikeComment(commentid);
loadComments();
} catch (error) {
console.error('取消点赞失败:', error);
message.error('操作失败');
}
};
// 获取用户信息(包括当前登录用户)
const getUserInfo = (userId) => {
// 修复4: 使用 currentUser.userid 而非 currentUser.id
if (currentUser && currentUser.userid && userId === currentUser.userid) {
return {
username: currentUser.username || `用户${userId}`,
image: currentUser.image || '',
decoration: currentUser.decoration || ''
};
}
// 对于其他用户,从userInfoMap中获取
return userInfoMap[userId] || {
username: `用户${userId}`,
image: '',
decoration: ''
};
};
return (
<Card title="评论区" bordered={false} className="comment-card">
{/* 评论输入框 - 根据用户登录状态调整 */}
{currentUser ? (
<>
<TextArea
rows={3}
placeholder={`${currentUser.username},留下你的评论...`}
value={newContent}
onChange={(e) => setNewContent(e.target.value)}
className="comment-textarea"
disabled={loading}
/>
<div className="text-right mt-2">
<Button
type="primary"
onClick={handleCreate}
loading={loading || isCommenting}
disabled={isCommenting}
>
{isCommenting ? '发布中...' : '发布评论'}
</Button>
</div>
</>
) : (
<div className="login-prompt">
请<a href="/login" className="login-link">登录</a>后发表评论
</div>
)}
{/* 评论列表 */}
<List
itemLayout="vertical"
dataSource={comments}
locale={{ emptyText: '暂无评论' }}
className="mt-6"
renderItem={(item) => {
const user = getUserInfo(item.userid);
// 修复5: 使用 userid 而非 id 比较当前用户
const isCurrentUser = currentUser && currentUser.userid === item.userid;
return (
<List.Item
key={item.commentid}
className={isCurrentUser ? "current-user-comment" : ""}
actions={[
<Tooltip title="点赞" key="like">
<Space>
<Button
icon={<LikeOutlined />}
size="small"
onClick={() => handleLike(item.commentid)}
/>
{item.likes}
</Space>
</Tooltip>,
<Tooltip title="取消点赞" key="unlike">
<Button
icon={<LikeFilled style={{ color: '#fadb14' }} />}
size="small"
onClick={() => handleUnlike(item.commentid)}
/>
</Tooltip>,
isCurrentUser && (
<Popconfirm
title="确定要删除这条评论吗?"
onConfirm={() => handleDelete(item.commentid)}
okText="删除"
cancelText="取消"
key="delete"
>
<Button icon={<DeleteOutlined />} size="small" danger />
</Popconfirm>
)
]}
extra={
<div className="comment-time">
{new Date(item.commenttime).toLocaleString()}
</div>
}
>
<List.Item.Meta
avatar={
<Avatar
src={user.image || undefined}
alt={user.username}
className="comment-avatar"
>
{!user.image && user.username ? user.username.charAt(0).toUpperCase() : ''}
</Avatar>
}
title={
<span className="comment-username">
{user.username || `用户${item.userid}`}
{isCurrentUser && <span className="current-user-tag">(我)</span>}
</span>
}
description={<div className="comment-content">{item.postCommentcontent}</div>}
/>
</List.Item>
);
}}
/>
</Card>
);
};
export default Comment;