Files
lislgosms/src/components/ui/SystemLogExport.tsx
T

83 lines
2.9 KiB
TypeScript

import { useEffect, useState } from 'react';
import { Download, RotateCcw } from 'lucide-react';
import type { SystemLogExportResult } from '@/api/adminApi';
import { Button } from './Button';
type Filters = { keyword?: string; level?: string; module?: string; range?: string };
export function SystemLogExport({
portal,
filters,
exportLogs,
}: {
portal: 'admin' | 'client';
filters: Filters;
exportLogs: (filters: Filters) => Promise<SystemLogExportResult>;
}) {
const storageKey = `cmpp:${portal}:system-log-export-recovery`;
const [exporting, setExporting] = useState(false);
const [result, setResult] = useState<SystemLogExportResult | null>(null);
const [error, setError] = useState('');
const [retryFilters, setRetryFilters] = useState<Filters | null>(null);
useEffect(() => {
try {
const saved = sessionStorage.getItem(storageKey);
if (saved) {
setRetryFilters(JSON.parse(saved) as Filters);
setError('上次导出未完成,筛选条件已保留,可直接重试。');
}
} catch {
sessionStorage.removeItem(storageKey);
}
}, [storageKey]);
async function run(nextFilters: Filters) {
setExporting(true);
setError('');
setResult(null);
setRetryFilters(nextFilters);
sessionStorage.setItem(storageKey, JSON.stringify(nextFilters));
try {
const exported = await exportLogs(nextFilters);
setResult(exported);
setRetryFilters(null);
sessionStorage.removeItem(storageKey);
} catch (reason) {
setError(reason instanceof Error ? reason.message : '日志导出失败,请重试');
} finally {
setExporting(false);
}
}
function download() {
if (!result) return;
const url = URL.createObjectURL(new Blob([`\uFEFF${result.content}`], { type: 'text/csv;charset=utf-8' }));
const anchor = document.createElement('a');
anchor.href = url;
anchor.download = result.fileName;
anchor.click();
URL.revokeObjectURL(url);
}
return (
<div className="system-log-export">
<Button disabled={exporting} icon={<Download size={17} />} onClick={() => run(filters)} variant="secondary">
{exporting ? '导出中…' : '导出日志'}
</Button>
{result ? (
<div className="system-log-export__result" role="status">
<span>导出完成,共 {result.recordCount} {result.truncated ? '(已截取前 10000 条)' : ''},操作单号 {result.operationId}</span>
<Button icon={<Download size={15} />} onClick={download} size="sm" variant="ghost">下载文件</Button>
</div>
) : null}
{error ? (
<div className="system-log-export__error" role="alert">
<span>{error}</span>
<Button disabled={exporting} icon={<RotateCcw size={15} />} onClick={() => run(retryFilters ?? filters)} size="sm" variant="ghost">重试</Button>
</div>
) : null}
</div>
);
}