Files
ThriveX-Admin/src/pages/Comment/index.tsx

228 lines
8.3 KiB
TypeScript
Raw Normal View History

2024-08-07 17:07:14 +08:00
import { useState, useEffect } from 'react';
2024-10-12 14:25:13 +08:00
import { Card, message, Table, Popconfirm, Button, Modal, Form, Input, DatePicker } from 'antd';
2024-10-21 16:15:16 +08:00
import { addCommentDataAPI, getCommentListAPI } from '@/api/Comment';
2024-09-27 21:20:35 +08:00
import { delCommentDataAPI } from '@/api/Comment';
2024-08-07 17:07:14 +08:00
import { ColumnsType } from 'antd/es/table';
import { titleSty } from '@/styles/sty';
import Title from '@/components/Title';
2024-10-12 14:25:13 +08:00
import { Comment, FilterForm } from '@/types/app/comment'
2024-10-21 12:19:05 +08:00
2024-10-21 16:15:16 +08:00
import { useWebStore, useUserStore } from '@/stores'
2024-10-21 12:19:05 +08:00
2024-08-17 15:34:39 +08:00
import dayjs from 'dayjs';
2024-10-21 15:57:12 +08:00
import TextArea from 'antd/es/input/TextArea';
2024-10-21 16:37:11 +08:00
import { sendCommentEmailAPI } from '@/api/Email';
2024-08-06 23:21:42 +08:00
2024-08-07 18:43:07 +08:00
const CommentPage = () => {
2024-10-21 16:15:16 +08:00
const web = useWebStore(state => state.web)
const user = useUserStore(state => state.user)
2024-10-21 12:19:05 +08:00
2024-08-07 17:07:14 +08:00
const [loading, setLoading] = useState(false);
2024-10-21 16:37:11 +08:00
const [comment, setComment] = useState<Comment>({} as Comment);
2024-08-07 17:07:14 +08:00
const [list, setList] = useState<Comment[]>([]);
2024-08-06 23:21:42 +08:00
2024-10-21 15:57:12 +08:00
const [isCommentModalOpen, setIsCommentModalOpen] = useState(false);
2024-08-07 18:43:07 +08:00
2024-08-07 17:07:14 +08:00
const getCommentList = async () => {
const { data } = await getCommentListAPI();
2024-09-02 16:58:20 +08:00
setList(data)
2024-08-07 17:07:14 +08:00
setLoading(false)
}
2024-08-06 23:21:42 +08:00
2024-08-07 17:07:14 +08:00
const delCommentData = async (id: number) => {
setLoading(true)
await delCommentDataAPI(id);
2024-08-06 23:21:42 +08:00
getCommentList();
2024-08-07 17:07:14 +08:00
message.success('🎉 删除评论成功');
2024-08-06 23:21:42 +08:00
};
2024-08-07 17:07:14 +08:00
useEffect(() => {
setLoading(true)
getCommentList();
}, []);
const columns: ColumnsType = [
{
title: 'ID',
dataIndex: 'id',
key: 'id',
align: "center"
},
{
title: '名称',
dataIndex: 'name',
key: 'name',
fixed: 'left',
},
{
title: '内容',
dataIndex: 'content',
key: 'content',
2024-09-02 16:58:20 +08:00
width: 400,
render: (text: string, record) => <span className="hover:text-primary cursor-pointer line-clamp-2" onClick={() => {
2024-08-07 18:43:07 +08:00
setComment(record)
2024-10-21 15:57:12 +08:00
setIsCommentModalOpen(true)
2024-08-07 18:43:07 +08:00
}}>{text}</span>
2024-08-07 17:07:14 +08:00
},
2024-09-28 16:15:10 +08:00
{
title: '邮箱',
dataIndex: 'email',
key: 'email',
render: (text: string) => text ? text : '暂无邮箱',
},
2024-08-07 17:07:14 +08:00
{
title: '网站',
dataIndex: 'url',
key: 'url',
2024-10-21 12:19:05 +08:00
render: (url: string) => url ? <a href={url} target='_blank' className="hover:text-primary">{url}</a> : '无网站',
2024-08-07 17:07:14 +08:00
},
{
title: '所属文章',
dataIndex: 'articleTitle',
key: 'articleTitle',
2024-10-21 16:15:16 +08:00
render: (text: string, record: Comment) => (text ? <a href={`${web.url}/article/${record.articleId}`} target='_blank' className="hover:text-primary">{text}</a> : '该评论暂未绑定文章'),
2024-08-07 17:07:14 +08:00
},
{
title: '评论时间',
dataIndex: 'createTime',
key: 'createTime',
2024-09-02 16:58:20 +08:00
render: (date: string) => dayjs(+date).format('YYYY-MM-DD HH:mm:ss'),
2024-08-07 17:07:14 +08:00
},
{
title: '操作',
key: 'action',
fixed: 'right',
align: 'center',
2024-08-07 18:43:07 +08:00
render: (text: string, record: Comment) => (
2024-08-07 23:30:01 +08:00
<div className='flex justify-center space-x-2'>
2024-09-27 21:20:35 +08:00
<Button onClick={() => {
setComment(record)
2024-10-21 15:57:12 +08:00
setIsReplyModalOpen(true)
}}></Button>
2024-08-07 18:43:07 +08:00
2024-10-21 16:15:16 +08:00
<Popconfirm title="警告" description="你确定要删除吗" okText="确定" cancelText="取消" onConfirm={() => delCommentData(record.id!)}>
2024-08-07 17:07:14 +08:00
<Button type="primary" danger></Button>
</Popconfirm>
</div>
),
},
];
2024-08-07 13:02:59 +08:00
2024-09-02 16:58:20 +08:00
const { RangePicker } = DatePicker;
const onSubmit = async (values: FilterForm) => {
const query: FilterData = {
2024-10-12 14:25:13 +08:00
key: values?.title,
content: values?.content,
2024-10-12 14:29:38 +08:00
startDate: values.createTime && values.createTime[0].valueOf() + '',
endDate: values.createTime && values.createTime[1].valueOf() + ''
2024-09-02 16:58:20 +08:00
}
const { data } = await getCommentListAPI({ query });
2024-09-27 21:20:35 +08:00
setList(data)
2024-09-02 16:58:20 +08:00
}
2024-10-21 15:57:12 +08:00
// 回复内容
const [replyInfo, setReplyInfo] = useState("")
const [isReplyModalOpen, setIsReplyModalOpen] = useState(false);
2024-10-21 16:15:16 +08:00
const handleReply = async () => {
await addCommentDataAPI({
avatar: user.avatar,
url: web.url,
content: replyInfo,
commentId: comment?.id!,
auditStatus: 1,
email: user.email,
name: user.name,
articleId: comment?.articleId!,
createTime: new Date().getTime().toString(),
})
message.success('🎉 回复评论成功');
setIsReplyModalOpen(false)
setReplyInfo("")
2024-10-21 16:23:32 +08:00
getCommentList()
2024-10-21 16:37:11 +08:00
// 发送邮件通知
await sendCommentEmailAPI({
content: comment.content,
reviewers: comment.name,
subject: comment.articleTitle!,
title: comment.articleTitle!,
url: location.href,
time: dayjs(Date.now()).format('YYYY年MM月DD日 HH:mm'),
to: comment.id !== comment.articleId ? comment.email : undefined
})
2024-10-21 15:57:12 +08:00
}
2024-08-06 23:21:42 +08:00
return (
2024-08-07 17:07:14 +08:00
<>
<Title value='评论管理' />
2024-09-02 16:58:20 +08:00
<Card className='my-2 overflow-scroll'>
<Form layout="inline" onFinish={onSubmit} autoComplete="off" className='flex-nowrap'>
<Form.Item label="标题" name="title" className='w-2/12'>
2024-09-27 21:20:35 +08:00
<Input placeholder='请输入标题关键词' />
</Form.Item>
<Form.Item label="内容" name="content" className='w-2/12'>
<Input placeholder='请输入内容关键词' />
2024-09-02 16:58:20 +08:00
</Form.Item>
<Form.Item label="时间范围" name="createTime" className='w-3/12'>
<RangePicker placeholder={["选择起始时间", "选择结束时间"]} />
</Form.Item>
<Form.Item className='pr-6'>
<Button type="primary" htmlType="submit"></Button>
</Form.Item>
</Form>
</Card>
2024-08-07 17:07:14 +08:00
<Card className={`${titleSty} mt-2`}>
2024-09-02 16:58:20 +08:00
<Table
rowKey="id"
dataSource={list}
columns={columns}
loading={loading}
expandable={{ defaultExpandAllRows: true }}
scroll={{ x: 'max-content' }}
pagination={{
position: ['bottomCenter'],
defaultPageSize: 8,
}}
/>
2024-08-07 17:07:14 +08:00
</Card>
2024-08-07 18:43:07 +08:00
2024-10-21 15:57:12 +08:00
<Modal title='评论详情' open={isCommentModalOpen} onCancel={() => setIsCommentModalOpen(false)} footer={null}>
2024-08-07 18:43:07 +08:00
<div className='pt-2 space-y-2'>
<div><b></b> {comment?.articleTitle}</div>
<div><b></b> {dayjs(comment?.createTime).format("YYYY-MM-DD HH:mm:ss")}</div>
<div><b></b> {comment?.name}</div>
2024-09-27 21:20:35 +08:00
<div><b></b> {comment?.email ? comment?.email : "暂无邮箱"}</div>
2024-08-07 18:43:07 +08:00
<div><b></b> {comment?.url ? <a href={comment?.url} className="hover:text-primary">{comment?.url}</a> : '无网站'}</div>
<div><b></b> {comment?.content}</div>
</div>
</Modal>
2024-10-21 15:57:12 +08:00
<Modal title="回复评论" open={isReplyModalOpen} footer={null} onCancel={() => setIsReplyModalOpen(false)}>
<TextArea
value={replyInfo}
onChange={(e) => setReplyInfo(e.target.value)}
placeholder="请输入回复内容"
autoSize={{ minRows: 3, maxRows: 5 }}
/>
<div className="flex space-x-4">
<Button className="w-full mt-2" onClick={() => setIsReplyModalOpen(false)}></Button>
<Button type="primary" className="w-full mt-2" onClick={handleReply}></Button>
</div>
</Modal>
2024-08-07 17:07:14 +08:00
</>
2024-08-06 23:21:42 +08:00
);
};
2024-08-07 18:43:07 +08:00
export default CommentPage;