2026-03-12 20:04:27 +08:00
|
|
|
|
import React, { useCallback, useEffect, useState } from 'react';
|
2026-03-11 16:28:04 +08:00
|
|
|
|
import { useParams } from 'react-router-dom';
|
|
|
|
|
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
|
|
|
|
import {
|
|
|
|
|
|
Card,
|
|
|
|
|
|
Button,
|
|
|
|
|
|
Space,
|
|
|
|
|
|
Typography,
|
|
|
|
|
|
Row,
|
|
|
|
|
|
Col,
|
|
|
|
|
|
Statistic,
|
|
|
|
|
|
Table,
|
|
|
|
|
|
Tag,
|
|
|
|
|
|
Divider,
|
|
|
|
|
|
Descriptions,
|
|
|
|
|
|
Checkbox,
|
|
|
|
|
|
message,
|
|
|
|
|
|
Result,
|
|
|
|
|
|
} from 'antd';
|
|
|
|
|
|
import {
|
|
|
|
|
|
FileTextOutlined,
|
|
|
|
|
|
FileExcelOutlined,
|
|
|
|
|
|
FilePdfOutlined,
|
|
|
|
|
|
FileWordOutlined,
|
|
|
|
|
|
DownloadOutlined,
|
|
|
|
|
|
PrinterOutlined,
|
|
|
|
|
|
HistoryOutlined,
|
|
|
|
|
|
CheckCircleOutlined,
|
|
|
|
|
|
} from '@ant-design/icons';
|
|
|
|
|
|
import type { ColumnsType } from 'antd/es/table';
|
|
|
|
|
|
import { fetchCase, fetchAssessments, fetchReports, generateReport, getReportDownloadUrl } from '../../services/api';
|
|
|
|
|
|
|
2026-03-12 20:04:27 +08:00
|
|
|
|
type ContentKeys =
|
|
|
|
|
|
| 'include_summary'
|
|
|
|
|
|
| 'include_transactions'
|
|
|
|
|
|
| 'include_flow_chart'
|
|
|
|
|
|
| 'include_timeline'
|
|
|
|
|
|
| 'include_reasons'
|
|
|
|
|
|
| 'include_inquiry'
|
|
|
|
|
|
| 'include_screenshots';
|
|
|
|
|
|
|
|
|
|
|
|
const contentOptions: Array<{ key: ContentKeys; label: string; defaultOn: boolean }> = [
|
|
|
|
|
|
{ key: 'include_summary', label: '被骗金额汇总表', defaultOn: true },
|
|
|
|
|
|
{ key: 'include_transactions', label: '交易明细清单(含证据索引)', defaultOn: true },
|
|
|
|
|
|
{ key: 'include_flow_chart', label: '资金流转路径图', defaultOn: true },
|
|
|
|
|
|
{ key: 'include_timeline', label: '交易时间轴', defaultOn: true },
|
|
|
|
|
|
{ key: 'include_reasons', label: '认定理由与排除说明', defaultOn: true },
|
|
|
|
|
|
{ key: 'include_inquiry', label: '笔录辅助问询建议', defaultOn: false },
|
|
|
|
|
|
{ key: 'include_screenshots', label: '原始截图附件', defaultOn: false },
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
const STORAGE_PREFIX = 'report-content-';
|
|
|
|
|
|
|
|
|
|
|
|
const loadContentSelection = (caseId: string): Record<ContentKeys, boolean> => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const raw = localStorage.getItem(`${STORAGE_PREFIX}${caseId}`);
|
|
|
|
|
|
if (raw) return JSON.parse(raw);
|
|
|
|
|
|
} catch { /* ignore */ }
|
|
|
|
|
|
const defaults: Record<string, boolean> = {};
|
|
|
|
|
|
contentOptions.forEach((o) => { defaults[o.key] = o.defaultOn; });
|
|
|
|
|
|
return defaults as Record<ContentKeys, boolean>;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const saveContentSelection = (caseId: string, sel: Record<ContentKeys, boolean>) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
localStorage.setItem(`${STORAGE_PREFIX}${caseId}`, JSON.stringify(sel));
|
|
|
|
|
|
} catch { /* ignore */ }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-03-11 16:28:04 +08:00
|
|
|
|
const Reports: React.FC = () => {
|
|
|
|
|
|
const { id = '1' } = useParams();
|
|
|
|
|
|
const qc = useQueryClient();
|
|
|
|
|
|
const [generated, setGenerated] = useState(false);
|
2026-03-12 20:04:27 +08:00
|
|
|
|
const [selectedFormats, setSelectedFormats] = useState<Array<'excel' | 'pdf' | 'word'>>([
|
|
|
|
|
|
'excel',
|
|
|
|
|
|
'pdf',
|
|
|
|
|
|
]);
|
|
|
|
|
|
const [contentSel, setContentSel] = useState<Record<ContentKeys, boolean>>(() => loadContentSelection(id));
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
setContentSel(loadContentSelection(id));
|
|
|
|
|
|
}, [id]);
|
|
|
|
|
|
|
|
|
|
|
|
const toggleContent = useCallback((key: ContentKeys, checked: boolean) => {
|
|
|
|
|
|
setContentSel((prev) => {
|
|
|
|
|
|
const next = { ...prev, [key]: checked };
|
|
|
|
|
|
saveContentSelection(id, next);
|
|
|
|
|
|
return next;
|
|
|
|
|
|
});
|
|
|
|
|
|
}, [id]);
|
2026-03-11 16:28:04 +08:00
|
|
|
|
|
|
|
|
|
|
const { data: currentCase } = useQuery({ queryKey: ['case', id], queryFn: () => fetchCase(id) });
|
|
|
|
|
|
const { data: assessData } = useQuery({ queryKey: ['assessments', id], queryFn: () => fetchAssessments(id) });
|
|
|
|
|
|
const { data: reportsData } = useQuery({ queryKey: ['reports', id], queryFn: () => fetchReports(id) });
|
|
|
|
|
|
|
|
|
|
|
|
const allAssessments = assessData?.items ?? [];
|
|
|
|
|
|
const reportsList = reportsData?.items ?? [];
|
|
|
|
|
|
|
|
|
|
|
|
const confirmedAssessments = allAssessments.filter(
|
|
|
|
|
|
(a) => a.reviewStatus === 'confirmed' && a.assessedAmount > 0,
|
|
|
|
|
|
);
|
|
|
|
|
|
const totalConfirmed = confirmedAssessments.reduce(
|
|
|
|
|
|
(s, a) => s + a.assessedAmount,
|
|
|
|
|
|
0,
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const genMutation = useMutation({
|
2026-03-12 20:04:27 +08:00
|
|
|
|
mutationFn: async (reportTypes: Array<'excel' | 'pdf' | 'word'>) => {
|
|
|
|
|
|
const result = await Promise.all(
|
|
|
|
|
|
reportTypes.map((reportType) =>
|
|
|
|
|
|
generateReport(id, { report_type: reportType, ...contentSel }),
|
|
|
|
|
|
),
|
|
|
|
|
|
);
|
|
|
|
|
|
return result;
|
|
|
|
|
|
},
|
|
|
|
|
|
onSuccess: (_res, vars) => {
|
2026-03-11 16:28:04 +08:00
|
|
|
|
setGenerated(true);
|
|
|
|
|
|
qc.invalidateQueries({ queryKey: ['reports', id] });
|
2026-03-12 20:04:27 +08:00
|
|
|
|
message.success(`报告生成成功:${vars.map((v) => v.toUpperCase()).join(' / ')}`);
|
|
|
|
|
|
},
|
|
|
|
|
|
onError: () => {
|
|
|
|
|
|
message.error('报告生成失败');
|
2026-03-11 16:28:04 +08:00
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (!currentCase) return null;
|
|
|
|
|
|
|
2026-03-12 20:04:27 +08:00
|
|
|
|
const latestReportByType = reportsList.reduce<Record<string, (typeof reportsList)[0]>>((acc, report) => {
|
|
|
|
|
|
if (!acc[report.reportType]) {
|
|
|
|
|
|
acc[report.reportType] = report;
|
|
|
|
|
|
}
|
|
|
|
|
|
return acc;
|
|
|
|
|
|
}, {});
|
|
|
|
|
|
|
|
|
|
|
|
const historyColumns: ColumnsType<(typeof reportsList)[0]> = [
|
2026-03-11 16:28:04 +08:00
|
|
|
|
{
|
|
|
|
|
|
title: '类型',
|
2026-03-12 20:04:27 +08:00
|
|
|
|
dataIndex: 'reportType',
|
2026-03-11 16:28:04 +08:00
|
|
|
|
width: 100,
|
|
|
|
|
|
render: (t: string) => {
|
|
|
|
|
|
const map: Record<string, { icon: React.ReactNode; label: string; color: string }> = {
|
|
|
|
|
|
pdf: { icon: <FilePdfOutlined />, label: 'PDF', color: 'red' },
|
|
|
|
|
|
excel: { icon: <FileExcelOutlined />, label: 'Excel', color: 'green' },
|
|
|
|
|
|
word: { icon: <FileWordOutlined />, label: 'Word', color: 'blue' },
|
|
|
|
|
|
};
|
|
|
|
|
|
const cfg = map[t] || map.pdf;
|
|
|
|
|
|
return <Tag icon={cfg.icon} color={cfg.color}>{cfg.label}</Tag>;
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
title: '版本',
|
|
|
|
|
|
dataIndex: 'version',
|
|
|
|
|
|
width: 80,
|
|
|
|
|
|
render: (v: number) => `v${v}`,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
title: '生成时间',
|
|
|
|
|
|
dataIndex: 'createdAt',
|
|
|
|
|
|
width: 180,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
title: '操作',
|
|
|
|
|
|
width: 120,
|
2026-03-12 20:04:27 +08:00
|
|
|
|
render: (_, report) => (
|
2026-03-11 16:28:04 +08:00
|
|
|
|
<Space>
|
2026-03-12 20:04:27 +08:00
|
|
|
|
<Button
|
|
|
|
|
|
type="link"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
icon={<DownloadOutlined />}
|
|
|
|
|
|
href={getReportDownloadUrl(report.id)}
|
|
|
|
|
|
target="_blank"
|
|
|
|
|
|
>
|
2026-03-11 16:28:04 +08:00
|
|
|
|
下载
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
</Space>
|
|
|
|
|
|
),
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<Row gutter={16} style={{ marginBottom: 24 }}>
|
|
|
|
|
|
<Col span={8}>
|
|
|
|
|
|
<Card variant="borderless">
|
|
|
|
|
|
<Statistic
|
|
|
|
|
|
title="已确认被骗金额"
|
|
|
|
|
|
value={totalConfirmed}
|
|
|
|
|
|
precision={2}
|
|
|
|
|
|
prefix="¥"
|
|
|
|
|
|
valueStyle={{ color: '#cf1322', fontSize: 24 }}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</Card>
|
|
|
|
|
|
</Col>
|
|
|
|
|
|
<Col span={8}>
|
|
|
|
|
|
<Card variant="borderless">
|
|
|
|
|
|
<Statistic
|
|
|
|
|
|
title="已确认交易笔数"
|
|
|
|
|
|
value={confirmedAssessments.length}
|
|
|
|
|
|
suffix="笔"
|
|
|
|
|
|
prefix={<CheckCircleOutlined />}
|
|
|
|
|
|
valueStyle={{ color: '#52c41a' }}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</Card>
|
|
|
|
|
|
</Col>
|
|
|
|
|
|
<Col span={8}>
|
|
|
|
|
|
<Card variant="borderless">
|
|
|
|
|
|
<Statistic
|
|
|
|
|
|
title="历史报告"
|
|
|
|
|
|
value={reportsList.length}
|
|
|
|
|
|
suffix="份"
|
|
|
|
|
|
prefix={<HistoryOutlined />}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</Card>
|
|
|
|
|
|
</Col>
|
|
|
|
|
|
</Row>
|
|
|
|
|
|
|
|
|
|
|
|
<Row gutter={24}>
|
|
|
|
|
|
<Col span={14}>
|
|
|
|
|
|
<Card
|
|
|
|
|
|
title={
|
|
|
|
|
|
<Space>
|
|
|
|
|
|
<FileTextOutlined />
|
|
|
|
|
|
<span>生成报告</span>
|
|
|
|
|
|
</Space>
|
|
|
|
|
|
}
|
|
|
|
|
|
style={{ marginBottom: 24 }}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Descriptions column={2} size="small" style={{ marginBottom: 24 }}>
|
|
|
|
|
|
<Descriptions.Item label="案件编号">
|
|
|
|
|
|
{currentCase.caseNo}
|
|
|
|
|
|
</Descriptions.Item>
|
|
|
|
|
|
<Descriptions.Item label="案件名称">
|
|
|
|
|
|
{currentCase.title}
|
|
|
|
|
|
</Descriptions.Item>
|
|
|
|
|
|
<Descriptions.Item label="受害人">
|
|
|
|
|
|
{currentCase.victimName}
|
|
|
|
|
|
</Descriptions.Item>
|
|
|
|
|
|
<Descriptions.Item label="承办人">
|
|
|
|
|
|
{currentCase.handler}
|
|
|
|
|
|
</Descriptions.Item>
|
|
|
|
|
|
<Descriptions.Item label="已确认金额">
|
|
|
|
|
|
<Typography.Text strong style={{ color: '#cf1322' }}>
|
|
|
|
|
|
¥{totalConfirmed.toLocaleString('zh-CN', { minimumFractionDigits: 2 })}
|
|
|
|
|
|
</Typography.Text>
|
|
|
|
|
|
</Descriptions.Item>
|
|
|
|
|
|
<Descriptions.Item label="确认笔数">
|
|
|
|
|
|
{confirmedAssessments.length} 笔
|
|
|
|
|
|
</Descriptions.Item>
|
|
|
|
|
|
</Descriptions>
|
|
|
|
|
|
|
|
|
|
|
|
<Divider />
|
|
|
|
|
|
|
|
|
|
|
|
<Typography.Text strong>导出格式:</Typography.Text>
|
|
|
|
|
|
<div style={{ margin: '12px 0 24px' }}>
|
|
|
|
|
|
<Space size={16}>
|
|
|
|
|
|
<Card
|
|
|
|
|
|
hoverable
|
|
|
|
|
|
style={{ width: 140, textAlign: 'center' }}
|
|
|
|
|
|
styles={{ body: { padding: 16 } }}
|
|
|
|
|
|
>
|
|
|
|
|
|
<FileExcelOutlined style={{ fontSize: 32, color: '#52c41a' }} />
|
|
|
|
|
|
<div style={{ marginTop: 8 }}>
|
|
|
|
|
|
<Typography.Text>Excel 汇总表</Typography.Text>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div>
|
2026-03-12 20:04:27 +08:00
|
|
|
|
<Checkbox
|
|
|
|
|
|
checked={selectedFormats.includes('excel')}
|
|
|
|
|
|
onChange={(e) => {
|
|
|
|
|
|
setSelectedFormats((prev) =>
|
|
|
|
|
|
e.target.checked
|
|
|
|
|
|
? Array.from(new Set([...prev, 'excel']))
|
|
|
|
|
|
: prev.filter((x) => x !== 'excel'),
|
|
|
|
|
|
);
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
选择
|
|
|
|
|
|
</Checkbox>
|
2026-03-11 16:28:04 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</Card>
|
|
|
|
|
|
<Card
|
|
|
|
|
|
hoverable
|
|
|
|
|
|
style={{ width: 140, textAlign: 'center' }}
|
|
|
|
|
|
styles={{ body: { padding: 16 } }}
|
|
|
|
|
|
>
|
|
|
|
|
|
<FilePdfOutlined style={{ fontSize: 32, color: '#cf1322' }} />
|
|
|
|
|
|
<div style={{ marginTop: 8 }}>
|
|
|
|
|
|
<Typography.Text>PDF 报告</Typography.Text>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div>
|
2026-03-12 20:04:27 +08:00
|
|
|
|
<Checkbox
|
|
|
|
|
|
checked={selectedFormats.includes('pdf')}
|
|
|
|
|
|
onChange={(e) => {
|
|
|
|
|
|
setSelectedFormats((prev) =>
|
|
|
|
|
|
e.target.checked
|
|
|
|
|
|
? Array.from(new Set([...prev, 'pdf']))
|
|
|
|
|
|
: prev.filter((x) => x !== 'pdf'),
|
|
|
|
|
|
);
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
选择
|
|
|
|
|
|
</Checkbox>
|
2026-03-11 16:28:04 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</Card>
|
|
|
|
|
|
<Card
|
|
|
|
|
|
hoverable
|
|
|
|
|
|
style={{ width: 140, textAlign: 'center' }}
|
|
|
|
|
|
styles={{ body: { padding: 16 } }}
|
|
|
|
|
|
>
|
|
|
|
|
|
<FileWordOutlined style={{ fontSize: 32, color: '#1677ff' }} />
|
|
|
|
|
|
<div style={{ marginTop: 8 }}>
|
|
|
|
|
|
<Typography.Text>Word 文书</Typography.Text>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div>
|
2026-03-12 20:04:27 +08:00
|
|
|
|
<Checkbox
|
|
|
|
|
|
checked={selectedFormats.includes('word')}
|
|
|
|
|
|
onChange={(e) => {
|
|
|
|
|
|
setSelectedFormats((prev) =>
|
|
|
|
|
|
e.target.checked
|
|
|
|
|
|
? Array.from(new Set([...prev, 'word']))
|
|
|
|
|
|
: prev.filter((x) => x !== 'word'),
|
|
|
|
|
|
);
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
选择
|
|
|
|
|
|
</Checkbox>
|
2026-03-11 16:28:04 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</Card>
|
|
|
|
|
|
</Space>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<Typography.Text strong>报告内容:</Typography.Text>
|
|
|
|
|
|
<div style={{ margin: '12px 0 24px' }}>
|
|
|
|
|
|
<Space direction="vertical">
|
2026-03-12 20:04:27 +08:00
|
|
|
|
{contentOptions.map((opt) => (
|
|
|
|
|
|
<Checkbox
|
|
|
|
|
|
key={opt.key}
|
|
|
|
|
|
checked={contentSel[opt.key]}
|
|
|
|
|
|
onChange={(e) => toggleContent(opt.key, e.target.checked)}
|
|
|
|
|
|
>
|
|
|
|
|
|
{opt.label}
|
|
|
|
|
|
</Checkbox>
|
|
|
|
|
|
))}
|
2026-03-11 16:28:04 +08:00
|
|
|
|
</Space>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{!generated ? (
|
|
|
|
|
|
<Button
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
size="large"
|
|
|
|
|
|
icon={<FileTextOutlined />}
|
|
|
|
|
|
loading={genMutation.isPending}
|
2026-03-12 20:04:27 +08:00
|
|
|
|
onClick={() => {
|
|
|
|
|
|
if (selectedFormats.length === 0) {
|
|
|
|
|
|
message.warning('请至少选择一种导出格式');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
genMutation.mutate(selectedFormats);
|
|
|
|
|
|
}}
|
2026-03-11 16:28:04 +08:00
|
|
|
|
block
|
|
|
|
|
|
>
|
|
|
|
|
|
{genMutation.isPending ? '正在生成报告...' : '生成报告'}
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
) : (
|
|
|
|
|
|
<Result
|
|
|
|
|
|
status="success"
|
|
|
|
|
|
title="报告已生成"
|
|
|
|
|
|
subTitle="您可以下载或打印以下报告文件"
|
|
|
|
|
|
extra={[
|
|
|
|
|
|
<Button
|
|
|
|
|
|
key="excel"
|
|
|
|
|
|
icon={<DownloadOutlined />}
|
2026-03-12 20:04:27 +08:00
|
|
|
|
href={latestReportByType.excel ? getReportDownloadUrl(latestReportByType.excel.id) : undefined}
|
|
|
|
|
|
target="_blank"
|
|
|
|
|
|
disabled={!latestReportByType.excel}
|
2026-03-11 16:28:04 +08:00
|
|
|
|
>
|
|
|
|
|
|
下载 Excel
|
|
|
|
|
|
</Button>,
|
|
|
|
|
|
<Button
|
|
|
|
|
|
key="pdf"
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
icon={<DownloadOutlined />}
|
2026-03-12 20:04:27 +08:00
|
|
|
|
href={latestReportByType.pdf ? getReportDownloadUrl(latestReportByType.pdf.id) : undefined}
|
|
|
|
|
|
target="_blank"
|
|
|
|
|
|
disabled={!latestReportByType.pdf}
|
2026-03-11 16:28:04 +08:00
|
|
|
|
>
|
|
|
|
|
|
下载 PDF
|
|
|
|
|
|
</Button>,
|
2026-03-12 20:04:27 +08:00
|
|
|
|
<Button
|
|
|
|
|
|
key="word"
|
|
|
|
|
|
icon={<DownloadOutlined />}
|
|
|
|
|
|
href={latestReportByType.word ? getReportDownloadUrl(latestReportByType.word.id) : undefined}
|
|
|
|
|
|
target="_blank"
|
|
|
|
|
|
disabled={!latestReportByType.word}
|
|
|
|
|
|
>
|
|
|
|
|
|
下载 Word
|
|
|
|
|
|
</Button>,
|
2026-03-11 16:28:04 +08:00
|
|
|
|
<Button
|
|
|
|
|
|
key="print"
|
|
|
|
|
|
icon={<PrinterOutlined />}
|
|
|
|
|
|
onClick={() => message.info('演示模式:打印')}
|
|
|
|
|
|
>
|
|
|
|
|
|
打印
|
|
|
|
|
|
</Button>,
|
|
|
|
|
|
]}
|
|
|
|
|
|
/>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</Card>
|
|
|
|
|
|
</Col>
|
|
|
|
|
|
|
|
|
|
|
|
<Col span={10}>
|
|
|
|
|
|
<Card
|
|
|
|
|
|
title={
|
|
|
|
|
|
<Space>
|
|
|
|
|
|
<HistoryOutlined />
|
|
|
|
|
|
<span>历史报告</span>
|
|
|
|
|
|
</Space>
|
|
|
|
|
|
}
|
|
|
|
|
|
style={{ marginBottom: 24 }}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Table
|
|
|
|
|
|
rowKey="id"
|
|
|
|
|
|
columns={historyColumns}
|
|
|
|
|
|
dataSource={reportsList}
|
|
|
|
|
|
pagination={false}
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</Card>
|
|
|
|
|
|
|
|
|
|
|
|
<Card title="报告预览" style={{ minHeight: 300 }}>
|
|
|
|
|
|
<div
|
|
|
|
|
|
style={{
|
|
|
|
|
|
background: '#fafafa',
|
|
|
|
|
|
border: '1px dashed #d9d9d9',
|
|
|
|
|
|
borderRadius: 8,
|
|
|
|
|
|
padding: 24,
|
|
|
|
|
|
textAlign: 'center',
|
|
|
|
|
|
minHeight: 240,
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
flexDirection: 'column',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
<FileTextOutlined style={{ fontSize: 48, color: '#bfbfbf' }} />
|
|
|
|
|
|
<Typography.Text type="secondary" style={{ marginTop: 12 }}>
|
|
|
|
|
|
{generated
|
|
|
|
|
|
? '点击左侧"下载"查看完整报告'
|
|
|
|
|
|
: '生成报告后可在此预览'}
|
|
|
|
|
|
</Typography.Text>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</Card>
|
|
|
|
|
|
</Col>
|
|
|
|
|
|
</Row>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export default Reports;
|