添加转换历史组件
- 实现转换历史记录展示 - 支持查看历史转换详情
This commit is contained in:
parent
f14e62af66
commit
269c66d1ac
333
src/components/ConversionHistory.js
Normal file
333
src/components/ConversionHistory.js
Normal 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;
|
||||||
Loading…
Reference in New Issue
Block a user