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