| 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; |