blob: f5c0e99fd4806f26d7e27271a2397b339f2a3287 [file] [log] [blame] [edit]
import React, { useState, useEffect } from 'react';
import {
Card,
Table,
Button,
Modal,
Tag,
Space,
message,
Typography,
Input
} from 'antd';
import {
EyeOutlined,
CheckOutlined,
CloseOutlined
} from '@ant-design/icons';
import { getReportList, handleReport } from '@/services/post';
import styles from './index.module.css';
const { Title, Paragraph } = Typography;
const { TextArea } = Input;
interface ReportInfo {
reportId: number;
postId: number;
postTitle: string;
reportUserId: number;
reportUserName: string;
reportReason: string;
status: string;
handleResult?: string;
handleTime?: string;
handleBy?: string;
createTime: string;
}
const ReportManagement: React.FC = () => {
const [reports, setReports] = useState<ReportInfo[]>([]);
const [loading, setLoading] = useState(false);
const [detailModalVisible, setDetailModalVisible] = useState(false);
const [handleModalVisible, setHandleModalVisible] = useState(false);
const [currentReport, setCurrentReport] = useState<ReportInfo | null>(null);
const [currentAction, setCurrentAction] = useState<'approve' | 'reject' | null>(null);
const [handleReason, setHandleReason] = useState('');
useEffect(() => {
fetchReports();
}, []);
const fetchReports = async () => {
setLoading(true);
try {
const response = await getReportList({
pageNum: 1,
pageSize: 100
});
if (response.code === 200) {
setReports(response.rows || []);
} else {
message.error(response.msg || '获取举报列表失败');
}
} catch (error) {
message.error('获取举报列表失败');
} finally {
setLoading(false);
}
};
const handleReportAction = async (report: ReportInfo, action: 'approve' | 'reject') => {
setCurrentReport(report);
setCurrentAction(action);
setHandleReason('');
setHandleModalVisible(true);
};
const submitHandle = async () => {
if (!currentReport || !currentAction) return;
try {
const response = await handleReport(
currentReport.reportId,
currentAction,
currentReport.postId,
handleReason
);
if (response.code === 200) {
message.success(currentAction === 'approve' ? '举报处理成功,帖子已下架' : '举报已驳回');
fetchReports();
} else {
message.error(response.msg || '处理失败');
}
} catch (error) {
message.error('处理失败');
}
setHandleModalVisible(false);
setCurrentReport(null);
setCurrentAction(null);
setHandleReason('');
};
const showDetail = (report: ReportInfo) => {
setCurrentReport(report);
setDetailModalVisible(true);
};
const columns = [
{
title: '举报帖子',
dataIndex: 'postTitle',
key: 'postTitle',
width: 180,
render: (text: string, record: ReportInfo) => (
<a onClick={() => showDetail(record)} style={{ color: '#1890ff' }}>
{text}
</a>
),
},
{
title: '举报人',
dataIndex: 'reportUserName',
key: 'reportUserName',
width: 100,
},
{
title: '举报时间',
dataIndex: 'createTime',
key: 'createTime',
width: 140,
},
{
title: '举报理由',
dataIndex: 'reportReason',
key: 'reportReason',
width: 150,
ellipsis: true,
render: (text: string) => (
<span title={text}>{text}</span>
),
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
width: 80,
render: (status: string) => {
const statusMap: Record<string, { color: string; text: string }> = {
'0': { color: 'orange', text: '待处理' },
'1': { color: 'green', text: '已处理' },
'2': { color: 'red', text: '已驳回' }
};
const statusInfo = statusMap[status] || { color: 'gray', text: '未知' };
return <Tag color={statusInfo.color}>{statusInfo.text}</Tag>;
},
},
{
title: '操作',
key: 'action',
width: 300,
fixed: 'right' as const,
render: (text: any, record: ReportInfo) => (
<Space size="small">
<Button
type="link"
icon={<EyeOutlined />}
onClick={() => showDetail(record)}
size="small"
>
查看
</Button>
{record.status === '0' && (
<>
<Button
type="link"
icon={<CheckOutlined />}
style={{ color: 'green' }}
onClick={() => handleReportAction(record, 'approve')}
size="small"
>
确认下架
</Button>
<Button
type="link"
danger
icon={<CloseOutlined />}
onClick={() => handleReportAction(record, 'reject')}
size="small"
>
驳回举报
</Button>
</>
)}
</Space>
),
},
];
return (
<div className={styles.postReviewContainer}>
<Card title="帖子举报管理">
<Table
columns={columns}
dataSource={reports}
loading={loading}
rowKey="reportId"
scroll={{ x: 880 }}
pagination={{
pageSize: 10,
showTotal: (total) => `共 ${total} 条记录`,
showSizeChanger: true,
showQuickJumper: true,
}}
/>
</Card>
{/* 举报详情弹窗 */}
<Modal
title="举报详情"
open={detailModalVisible}
onCancel={() => {
setDetailModalVisible(false);
setCurrentReport(null);
}}
footer={null}
width={600}
>
{currentReport && (
<div>
<div style={{ marginBottom: 16 }}>
<strong>举报帖子:</strong>{currentReport.postTitle}
</div>
<div style={{ marginBottom: 16 }}>
<strong>举报人:</strong>{currentReport.reportUserName}
</div>
<div style={{ marginBottom: 16 }}>
<strong>举报时间:</strong>{currentReport.createTime}
</div>
<div style={{ marginBottom: 16 }}>
<strong>举报理由:</strong>
<Paragraph>{currentReport.reportReason}</Paragraph>
</div>
{currentReport.status !== '0' && (
<>
<div style={{ marginBottom: 16 }}>
<strong>处理结果:</strong>{currentReport.handleResult}
</div>
<div style={{ marginBottom: 16 }}>
<strong>处理时间:</strong>{currentReport.handleTime}
</div>
<div style={{ marginBottom: 16 }}>
<strong>处理人:</strong>{currentReport.handleBy}
</div>
</>
)}
{currentReport.status === '0' && (
<div style={{ marginTop: 16 }}>
<Space>
<Button
type="primary"
icon={<CheckOutlined />}
onClick={() => {
handleReportAction(currentReport, 'approve');
setDetailModalVisible(false);
}}
>
确认下架
</Button>
<Button
danger
icon={<CloseOutlined />}
onClick={() => {
handleReportAction(currentReport, 'reject');
setDetailModalVisible(false);
}}
>
驳回举报
</Button>
</Space>
</div>
)}
</div>
)}
</Modal>
{/* 处理举报弹窗 */}
<Modal
title={currentAction === 'approve' ? '确认下架帖子' : '驳回举报'}
open={handleModalVisible}
onOk={submitHandle}
onCancel={() => {
setHandleModalVisible(false);
setCurrentReport(null);
setCurrentAction(null);
setHandleReason('');
}}
okText="确定"
cancelText="取消"
>
<div style={{ marginBottom: 16 }}>
<strong>帖子:</strong>{currentReport?.postTitle}
</div>
<div>
<strong>
{currentAction === 'approve' ? '下架理由' : '驳回理由'}
(可选):
</strong>
<TextArea
value={handleReason}
onChange={(e) => setHandleReason(e.target.value)}
placeholder={
currentAction === 'approve' ? '请输入下架理由...' : '请输入驳回理由...'
}
rows={4}
style={{ marginTop: 8 }}
/>
</div>
</Modal>
</div>
);
};
export default ReportManagement;