返回 AiToEarn
commentList.tsx
根目录 / project / aitoearn-electron / src / views / reply / components / commentList.tsx
1 /*
2 * @Author: nevin
3 * @Date: 2025-03-18 21:02:38
4 * @LastEditTime: 2025-03-31 09:43:51
5 * @LastEditors: nevin
6 * @Description: 评论列表
7 */
8 import { CommentData, icpGetCommentList, WorkData } from '@/icp/reply';
9 import { Avatar, Button, Card, Col, Modal, Row, Tooltip, Space, Typography } from 'antd';
10 import { forwardRef, useImperativeHandle, useRef, useState } from 'react';
11 import Meta from 'antd/es/card/Meta';
12 import ReplyComment, { ReplyCommentRef } from './replyComment';
13 import { MessageOutlined } from '@ant-design/icons';
14
15 export interface CommentListRef {
16 init: (accountId: number, workData: WorkData) => Promise<void>;
17 }
18
19 const Com = forwardRef<CommentListRef>((props: any, ref) => {
20 const [commentList, setCommentList] = useState<CommentData[]>([]);
21 const [isModalOpen, setIsModalOpen] = useState(false);
22 const [accountId, setAccountId] = useState<number>(0);
23 const [workData, setWorkData] = useState<WorkData | null>(null);
24 const Ref_ReplyComment = useRef<ReplyCommentRef>(null);
25 const [pageInfo, setPageInfo] = useState<{
26 count: number;
27 hasMore: boolean;
28 pcursor?: string;
29 }>({
30 count: 0,
31 hasMore: false,
32 });
33
34 async function init(accountId: number, workData: WorkData) {
35 setCommentList([]);
36 setPageInfo({
37 count: 0,
38 hasMore: false,
39 });
40
41 setAccountId(accountId);
42 setWorkData(workData);
43 await getCommentList(accountId, workData);
44 setIsModalOpen(true);
45 }
46
47 useImperativeHandle(ref, () => ({
48 init: init,
49 }));
50
51 function handleCancel() {
52 setCommentList([]);
53 setPageInfo({
54 count: 0,
55 hasMore: false,
56 });
57 setIsModalOpen(false);
58 }
59
60 /**
61 * 获取评论列表
62 */
63 async function getCommentList(inAccountId: number, data: WorkData) {
64 const res = await icpGetCommentList(inAccountId, data, pageInfo.pcursor);
65 if (!res) return;
66
67 setPageInfo(res.pageInfo);
68 setCommentList([...commentList, ...res.list]);
69 }
70
71 /**
72 * 打开评论回复
73 * @param data
74 */
75 function openReplyComment(data: CommentData) {
76 Ref_ReplyComment.current?.init(accountId, data);
77 }
78
79 /**
80 *
81 * @param param0
82 * @returns
83 */
84 function WorkDataDom() {
85 if (!workData) return <div>数据有误</div>;
86
87 return (
88 <Card
89 style={{ width: 200 }}
90 cover={<img alt="example" src={workData.coverUrl} />}
91 >
92 <Meta title={workData.title} />
93 </Card>
94 );
95 }
96
97 return (
98 <>
99 <Modal
100 title="评论列表"
101 open={isModalOpen}
102 onCancel={handleCancel}
103 footer={null}
104 width={1200}
105 className="comment-list-modal"
106 >
107 <Row gutter={[24, 0]}>
108 <Col span={6}>
109 <div className="sticky top-4">
110 {WorkDataDom()}
111 </div>
112 </Col>
113 <Col span={18}>
114 <div className="space-y-4">
115 {commentList.map((item) => (
116 <Card
117 key={item.commentId}
118 className="comment-card"
119 bodyStyle={{ padding: '16px' }}
120 >
121 <div className="flex items-start gap-3">
122 <Avatar src={item.headUrl} size="large" />
123 <div className="flex-1">
124 <div className="flex items-center justify-between mb-2">
125 <Typography.Text strong>{item.nikeName}</Typography.Text>
126 <Tooltip title="回复">
127 <Button
128 type="text"
129 icon={<MessageOutlined />}
130 onClick={() => openReplyComment(item)}
131 className="text-gray-500 hover:text-blue-500"
132 />
133 </Tooltip>
134 </div>
135 <Typography.Paragraph className="mb-0">
136 {item.content}
137 </Typography.Paragraph>
138
139 {item.subCommentList.length > 0 && (
140 <div className="mt-4 space-y-3 pl-4 border-l-2 border-gray-100">
141 {item.subCommentList.map((subItem) => (
142 <div key={subItem.commentId} className="flex items-start gap-3">
143 <Avatar src={subItem.headUrl} size="small" />
144 <div>
145 <Typography.Text strong className="mr-2">
146 {subItem.nikeName}
147 </Typography.Text>
148 <Typography.Text>
149 {subItem.content}
150 </Typography.Text>
151 </div>
152 </div>
153 ))}
154 </div>
155 )}
156 </div>
157 </div>
158 </Card>
159 ))}
160
161 {commentList.length > 0 && (
162 <div className="text-center mt-4">
163 <Button
164 type="link"
165 onClick={() => getCommentList(accountId, workData!)}
166 className="text-blue-500 hover:text-blue-600"
167 >
168 加载更多
169 </Button>
170 </div>
171 )}
172 </div>
173 </Col>
174 </Row>
175 </Modal>
176
177 <ReplyComment ref={Ref_ReplyComment} />
178 </>
179 );
180 });
181 export default Com;
182
182 lines Plain Text