22301014 | 3d96630 | 2025-06-07 22:54:40 +0800 | [diff] [blame] | 1 | import React, { useState, useEffect } from 'react'; |
| 2 | import { List, Button, Form, Input, message, Avatar, Typography, Modal, Pagination } from 'antd'; |
| 3 | import { LikeOutlined, MessageOutlined } from '@ant-design/icons'; |
| 4 | import CommentAPI from '../api/commentApi'; |
| 5 | import type { Comment } from '../api/otherType'; |
| 6 | |
| 7 | const { Text } = Typography; |
| 8 | const { TextArea } = Input; |
| 9 | |
| 10 | interface DiscussionSectionProps { |
| 11 | workId: number; |
| 12 | } |
| 13 | |
| 14 | const DiscussionSection: React.FC<DiscussionSectionProps> = ({ workId }) => { |
| 15 | const [comments, setComments] = useState<Comment[]>([]); |
| 16 | const [loading, setLoading] = useState(false); |
| 17 | const [modalVisible, setModalVisible] = useState(false); |
| 18 | const [form] = Form.useForm(); |
| 19 | const [currentPage, setCurrentPage] = useState(1); |
| 20 | const [pageSize, setPageSize] = useState(5); // 每页显示5条 |
| 21 | |
| 22 | // 加载评论 |
| 23 | useEffect(() => { |
| 24 | const loadComments = async () => { |
| 25 | try { |
| 26 | setLoading(true); |
| 27 | const commentList = await CommentAPI.getCommentsByPostId(workId); |
| 28 | setComments(commentList); |
| 29 | } catch (error) { |
| 30 | message.error('加载评论失败'); |
| 31 | } finally { |
| 32 | setLoading(false); |
| 33 | } |
| 34 | }; |
| 35 | |
| 36 | loadComments(); |
| 37 | }, [workId]); |
| 38 | |
| 39 | // 获取当前页的评论数据 |
| 40 | const getCurrentPageComments = () => { |
| 41 | const startIndex = (currentPage - 1) * pageSize; |
| 42 | const endIndex = startIndex + pageSize; |
| 43 | return comments.slice(startIndex, endIndex); |
| 44 | }; |
| 45 | |
| 46 | // 提交新评论 |
| 47 | const handleSubmit = async (values: { title: string; content: string }) => { |
| 48 | try { |
| 49 | await CommentAPI.addComment({ |
| 50 | postId: workId, |
| 51 | content: values.content |
| 52 | }); |
| 53 | message.success('评论添加成功'); |
| 54 | form.resetFields(); |
| 55 | setModalVisible(false); |
| 56 | // 重新加载评论 |
| 57 | const commentList = await CommentAPI.getCommentsByPostId(workId); |
| 58 | setComments(commentList); |
| 59 | // 重置到第一页 |
| 60 | setCurrentPage(1); |
| 61 | } catch (error) { |
| 62 | message.error('评论添加失败'); |
| 63 | } |
| 64 | }; |
| 65 | |
| 66 | // 点赞评论 |
| 67 | const handleLikeComment = async (commentId: number) => { |
| 68 | try { |
| 69 | await CommentAPI.likeComment(commentId); |
| 70 | setComments(prev => prev.map(comment => |
| 71 | comment.id === commentId |
| 72 | ? { ...comment, likes: (comment.likes || 0) + 1 } |
| 73 | : comment |
| 74 | )); |
| 75 | } catch (error) { |
| 76 | message.error('点赞失败'); |
| 77 | } |
| 78 | }; |
| 79 | |
| 80 | return ( |
| 81 | <div className="discussion-section"> |
| 82 | <Button |
| 83 | type="primary" |
| 84 | icon={<MessageOutlined />} |
| 85 | onClick={() => setModalVisible(true)} |
| 86 | style={{ marginBottom: 16 }} |
| 87 | > |
| 88 | 新建讨论 |
| 89 | </Button> |
| 90 | |
| 91 | <List |
| 92 | dataSource={getCurrentPageComments()} |
| 93 | loading={loading} |
| 94 | renderItem={comment => ( |
| 95 | <List.Item className="comment-item"> |
| 96 | <div className="comment-content"> |
| 97 | <div className="comment-header"> |
| 98 | <Avatar size="small"> |
| 99 | {comment.author?.charAt(0) || '?'} |
| 100 | </Avatar> |
| 101 | <Text strong>{comment.author || '匿名用户'}</Text> |
| 102 | <Text type="secondary"> |
| 103 | {comment.createTime ? new Date(comment.createTime).toLocaleString() : '未知时间'} |
| 104 | </Text> |
| 105 | </div> |
| 106 | <div className="comment-body"> |
| 107 | <Text>{comment.content}</Text> |
| 108 | </div> |
| 109 | <div className="comment-actions"> |
| 110 | <Button |
| 111 | type="text" |
| 112 | icon={<LikeOutlined />} |
| 113 | onClick={() => handleLikeComment(comment.id)} |
| 114 | > |
| 115 | {comment.likes || 0} |
| 116 | </Button> |
| 117 | </div> |
| 118 | </div> |
| 119 | </List.Item> |
| 120 | )} |
| 121 | /> |
| 122 | |
| 123 | <div style={{ textAlign: 'right', marginTop: 16 }}> |
| 124 | <Pagination |
| 125 | current={currentPage} |
| 126 | pageSize={pageSize} |
| 127 | total={comments.length} |
| 128 | onChange={(page, size) => { |
| 129 | setCurrentPage(page); |
| 130 | setPageSize(size); |
| 131 | }} |
| 132 | showSizeChanger |
| 133 | showQuickJumper |
| 134 | showTotal={total => `共 ${total} 条`} |
| 135 | /> |
| 136 | </div> |
| 137 | |
| 138 | <Modal |
| 139 | title={ |
| 140 | <span> |
| 141 | <MessageOutlined style={{ marginRight: 8 }} /> |
| 142 | 新建讨论 |
| 143 | </span> |
| 144 | } |
| 145 | visible={modalVisible} |
| 146 | onCancel={() => setModalVisible(false)} |
| 147 | footer={[ |
| 148 | <Button key="cancel" onClick={() => setModalVisible(false)}> |
| 149 | 取消 |
| 150 | </Button>, |
| 151 | <Button |
| 152 | key="submit" |
| 153 | type="primary" |
| 154 | onClick={() => { |
| 155 | form.validateFields() |
| 156 | .then(values => handleSubmit(values)) |
| 157 | .catch(() => message.error('请填写完整信息')); |
| 158 | }} |
| 159 | > |
| 160 | 创建讨论 |
| 161 | </Button>, |
| 162 | ]} |
| 163 | > |
| 164 | <Form form={form} layout="vertical"> |
| 165 | <Form.Item |
| 166 | name="title" |
| 167 | label="讨论主题" |
| 168 | rules={[{ required: true, message: '请输入讨论主题' }]} |
| 169 | > |
| 170 | <Input placeholder="输入讨论主题" /> |
| 171 | </Form.Item> |
| 172 | |
| 173 | <Form.Item |
| 174 | name="content" |
| 175 | label="讨论内容" |
| 176 | rules={[{ required: true, message: '请输入讨论内容' }]} |
| 177 | > |
| 178 | <TextArea |
| 179 | rows={6} |
| 180 | placeholder="详细描述你想讨论的内容..." |
| 181 | /> |
| 182 | </Form.Item> |
| 183 | </Form> |
| 184 | </Modal> |
| 185 | </div> |
| 186 | ); |
| 187 | }; |
| 188 | |
| 189 | |
| 190 | export default DiscussionSection; |