添加转换历史组件

- 实现转换历史记录展示
- 支持查看历史转换详情
This commit is contained in:
Leo 2025-10-20 14:06:32 +08:00
parent f14e62af66
commit 269c66d1ac

View File

@ -0,0 +1,333 @@
/**
* 转换历史记录组件
*/
import React, { useState, useEffect } from 'react';
import {
Table,
Button,
Tag,
Space,
Card,
message,
Modal,
Descriptions,
Alert,
Typography,
Tooltip,
} from 'antd';
import {
DownloadOutlined,
ReloadOutlined,
EyeOutlined,
ExclamationCircleOutlined,
} from '@ant-design/icons';
import { apiService } from '../services/api';
import {
formatFileSize,
formatDateTime,
formatConversionTime,
getStatusColor,
getStatusText,
downloadFile
} from '../utils/helpers';
import Pagination from './Pagination';
const { Text } = Typography;
const ConversionHistory = ({ refreshTrigger }) => {
const [loading, setLoading] = useState(false);
const [data, setData] = useState([]);
const [pagination, setPagination] = useState({
current: 1,
pageSize: 10,
total: 0,
});
const [detailModalVisible, setDetailModalVisible] = useState(false);
const [selectedRecord, setSelectedRecord] = useState(null);
// 加载历史记录
const loadHistory = async (page = 1, pageSize = 10) => {
setLoading(true);
try {
const response = await apiService.getHistory(page, pageSize);
if (response.data.status === 'success') {
setData(response.data.data.records);
setPagination(prev => ({
...prev,
current: page,
pageSize,
total: response.data.data.total,
}));
}
} catch (err) {
message.error('加载历史记录失败: ' + err.message);
} finally {
setLoading(false);
}
};
// 初始加载
useEffect(() => {
loadHistory();
}, []);
// 响应刷新触发器
useEffect(() => {
if (refreshTrigger) {
loadHistory(1);
}
}, [refreshTrigger]);
// 处理分页变化
const handlePaginationChange = (page, pageSize) => {
loadHistory(page, pageSize);
};
// 处理页面大小变化
const handlePageSizeChange = (current, size) => {
setPagination(prev => ({
...prev,
current: current,
pageSize: size,
}));
};
// 下载文件
const handleDownload = async (record) => {
if (record.conversion_status !== 'success') {
message.warning('只能下载转换成功的文件');
return;
}
try {
const response = await apiService.downloadFile(record.id);
const blob = new Blob([response.data], { type: 'text/plain' });
downloadFile(blob, record.converted_filename);
message.success('文件下载成功');
} catch (err) {
message.error('下载失败: ' + err.message);
}
};
// 查看详情
const handleViewDetails = async (record) => {
try {
const response = await apiService.getRecord(record.id);
if (response.data.status === 'success') {
setSelectedRecord(response.data.data);
setDetailModalVisible(true);
}
} catch (err) {
message.error('获取详情失败: ' + err.message);
}
};
// 表格列定义
const columns = [
{
title: '原始文件名',
dataIndex: 'original_filename',
key: 'original_filename',
ellipsis: {
showTitle: false,
},
render: (text) => (
<Tooltip title={text}>
<Text style={{ maxWidth: 200 }}>{text}</Text>
</Tooltip>
),
},
{
title: '文件大小',
dataIndex: 'file_size',
key: 'file_size',
width: 100,
render: (size) => formatFileSize(size),
},
{
title: '转换状态',
dataIndex: 'conversion_status',
key: 'conversion_status',
width: 100,
render: (status) => (
<Tag color={getStatusColor(status)}>
{getStatusText(status)}
</Tag>
),
},
{
title: '转换时间',
dataIndex: 'conversion_time',
key: 'conversion_time',
width: 100,
render: (time) => formatConversionTime(time),
},
{
title: '创建时间',
dataIndex: 'created_at',
key: 'created_at',
width: 160,
render: (time) => formatDateTime(time),
},
{
title: '操作',
key: 'actions',
width: 160,
render: (_, record) => (
<Space size="small">
<Tooltip title="查看详情">
<Button
type="text"
size="small"
icon={<EyeOutlined />}
onClick={() => handleViewDetails(record)}
/>
</Tooltip>
{record.conversion_status === 'success' && (
<Tooltip title="下载文件">
<Button
type="text"
size="small"
icon={<DownloadOutlined />}
onClick={() => handleDownload(record)}
/>
</Tooltip>
)}
</Space>
),
},
];
return (
<>
<Card
title="转换历史记录"
extra={
<Button
icon={<ReloadOutlined />}
onClick={() => loadHistory(pagination.current, pagination.pageSize)}
loading={loading}
>
刷新
</Button>
}
>
<Table
columns={columns}
dataSource={data}
rowKey="id"
loading={loading}
pagination={false}
size="middle"
scroll={{ x: 800 }}
/>
{/* 自定义分页组件 */}
<Pagination
current={pagination.current}
total={pagination.total}
pageSize={pagination.pageSize}
onChange={handlePaginationChange}
onShowSizeChange={handlePageSizeChange}
showSizeChanger={true}
showQuickJumper={true}
showTotal={true}
pageSizeOptions={['10', '20', '50', '100']}
/>
</Card>
{/* 详情模态框 */}
<Modal
title="转换记录详情"
open={detailModalVisible}
onCancel={() => {
setDetailModalVisible(false);
setSelectedRecord(null);
}}
footer={[
<Button key="close" onClick={() => setDetailModalVisible(false)}>
关闭
</Button>,
selectedRecord?.conversion_status === 'success' && (
<Button
key="download"
type="primary"
icon={<DownloadOutlined />}
onClick={() => handleDownload(selectedRecord)}
>
下载文件
</Button>
),
].filter(Boolean)}
width={800}
>
{selectedRecord && (
<div>
<Descriptions column={2} bordered size="small">
<Descriptions.Item label="记录ID">
{selectedRecord.id}
</Descriptions.Item>
<Descriptions.Item label="转换状态">
<Tag color={getStatusColor(selectedRecord.conversion_status)}>
{getStatusText(selectedRecord.conversion_status)}
</Tag>
</Descriptions.Item>
<Descriptions.Item label="原始文件名">
{selectedRecord.original_filename}
</Descriptions.Item>
<Descriptions.Item label="转换后文件名">
{selectedRecord.converted_filename || '-'}
</Descriptions.Item>
<Descriptions.Item label="文件大小">
{formatFileSize(selectedRecord.file_size)}
</Descriptions.Item>
<Descriptions.Item label="转换耗时">
{formatConversionTime(selectedRecord.conversion_time)}
</Descriptions.Item>
<Descriptions.Item label="创建时间">
{formatDateTime(selectedRecord.created_at)}
</Descriptions.Item>
<Descriptions.Item label="更新时间">
{formatDateTime(selectedRecord.updated_at)}
</Descriptions.Item>
</Descriptions>
{selectedRecord.original_minio_url && (
<div style={{ marginTop: 16 }}>
<Text strong>原始文件URL</Text>
<br />
<Text code copyable style={{ wordBreak: 'break-all' }}>
{selectedRecord.original_minio_url}
</Text>
</div>
)}
{selectedRecord.converted_minio_url && (
<div style={{ marginTop: 16 }}>
<Text strong>转换后文件URL</Text>
<br />
<Text code copyable style={{ wordBreak: 'break-all' }}>
{selectedRecord.converted_minio_url}
</Text>
</div>
)}
{selectedRecord.error_message && (
<div style={{ marginTop: 16 }}>
<Alert
message="错误信息"
description={selectedRecord.error_message}
type="error"
showIcon
icon={<ExclamationCircleOutlined />}
/>
</div>
)}
</div>
)}
</Modal>
</>
);
};
export default ConversionHistory;