blob: a955b7bdfe615cc8dcfb456abeb1def0b3740a56 [file] [log] [blame] [edit]
import React, { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom'; // 添加 useNavigate
import axios from 'axios';
import {
Row,
Col,
Card,
Descriptions,
Table,
Typography,
Spin,
Tag,
Button, // 添加 Button 组件
} from 'antd';
import { Image as AntdImage } from 'antd';
import '../TorrentDetail.css'; // 引入样式
const { Title, Text } = Typography;
const TorrentDetail = () => {
const { id } = useParams();
const navigate = useNavigate(); // 获取导航函数
const [torrent, setTorrent] = useState(null);
const [seeders, setSeeders] = useState([]);
const [loading, setLoading] = useState(true);
const [torrentLoading, setTorrentLoading] = useState(true);
const [seedersLoading, setSeedersLoading] = useState(false);
useEffect(() => {
const fetchTorrentDetails = async () => {
try {
setTorrentLoading(true);
const torrentRes = await axios.get(`http://localhost:8080/torrent/${id}`);
setTorrent(torrentRes.data);
setSeedersLoading(true);
const seedersRes = await axios.get(`http://localhost:8080/torrent/${torrentRes.data.infoHash}/seeders`);
setSeeders(seedersRes.data);
} catch (err) {
console.error('获取数据失败', err);
} finally {
setTorrentLoading(false);
setSeedersLoading(false);
setLoading(false);
}
};
fetchTorrentDetails();
}, [id]);
const formatSize = (bytes) => {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};
const formatSpeed = (bytesPerSec) => {
if (bytesPerSec < 1024) return bytesPerSec.toFixed(2) + ' B/s';
if (bytesPerSec < 1024 * 1024) return (bytesPerSec / 1024).toFixed(2) + ' KB/s';
return (bytesPerSec / (1024 * 1024)).toFixed(2) + ' MB/s';
};
const columns = [
{
title: '用户名',
dataIndex: 'username',
key: 'username',
align: 'center',
render: (text) => <Tag color="orange">{text}</Tag>,
},
{
title: '已上传',
dataIndex: 'uploaded',
key: 'uploaded',
align: 'center',
render: (text) => <Text>{formatSize(text)}</Text>,
},
{
title: '上传速度',
dataIndex: 'uploadSpeed',
key: 'uploadSpeed',
align: 'center',
render: (text) => <Text>{formatSpeed(text)}</Text>,
},
{
title: '已下载',
dataIndex: 'downloaded',
key: 'downloaded',
align: 'center',
render: (text) => <Text>{formatSize(text)}</Text>,
},
{
title: '下载速度',
dataIndex: 'downloadSpeed',
key: 'downloadSpeed',
align: 'center',
render: (text) => text > 0 ? <Text>{formatSpeed(text)}</Text> : <Text>-</Text>,
},
{
title: '客户端',
dataIndex: 'client',
key: 'client',
align: 'center',
},
{
title: '最后活动',
dataIndex: 'lastEvent',
key: 'lastEvent',
align: 'center',
},
];
if (loading) return <div className="page-wrapper"><Spin size="large" /></div>;
return (
<div className="page-wrapper">
{/* 添加返回按钮 */}
<div className="mb-4">
<Button
type="primary"
onClick={() => navigate(-1)} // 返回上一页
style={{ marginBottom: '16px' }}
>
返回列表
</Button>
</div>
<Row gutter={[16, 16]}>
<Col xs={24} md={8}>
<Card bordered={false} className="custom-card h-full">
{torrent.coverImagePath ? (
<AntdImage
src={torrent.coverImagePath}
alt="Torrent Cover"
className="w-full h-64 object-cover rounded"
placeholder={
<div className="w-full h-64 flex items-center justify-center bg-gray-100">
<Spin size="small" />
</div>
}
preview={false}
/>
) : (
<div className="w-full h-64 flex items-center justify-center bg-gray-100 rounded">
<Text type="secondary">无封面图片</Text>
</div>
)}
</Card>
</Col>
<Col xs={24} md={16}>
<Card className="info-card">
<Title level={1} className="info-title">
{torrent?.torrentTitle || '加载中...'}
</Title>
<Descriptions
bordered
column={{ xs: 1, sm: 2 }}
size="middle"
className="custom-descriptions"
labelStyle={{ fontWeight: 'bold', color: '#a15c00', fontSize: '16px' }}
contentStyle={{ fontSize: '15px' }}
>
<Descriptions.Item label="简介">{torrent.description || '暂无简介'}</Descriptions.Item>
<Descriptions.Item label="上传人">{torrent.uploader_id || '未知用户'}</Descriptions.Item>
<Descriptions.Item label="上传时间">{new Date(torrent.uploadTime).toLocaleString()}</Descriptions.Item>
<Descriptions.Item label="文件大小"><Text>{formatSize(torrent.torrentSize)}</Text></Descriptions.Item>
<Descriptions.Item label="下载数"><Text>{torrent.downloadCount || 0}</Text></Descriptions.Item>
<Descriptions.Item label="做种数"><Text>{seeders.length}</Text></Descriptions.Item>
<Descriptions.Item label="文件分辨率">{torrent.dpi || '未知'}</Descriptions.Item>
<Descriptions.Item label="文件字幕">{torrent.caption || '无'}</Descriptions.Item>
<Descriptions.Item label="最后做种时间">
{torrent.lastseed ? new Date(torrent.lastseed).toLocaleString() : '暂无'}
</Descriptions.Item>
</Descriptions>
</Card>
</Col>
</Row>
<Card className="custom-card mt-4">
<Title level={4} style={{ color: '#d46b08' }}>当前做种用户 ({seeders.length})</Title>
{seedersLoading ? (
<div className="p-4 text-center"><Spin size="small" /></div>
) : seeders.length > 0 ? (
<Table
columns={columns}
dataSource={seeders}
rowKey={(record, index) => index}
pagination={false}
size="small"
className="custom-table"
/>
) : (
<div className="p-4 text-center text-gray-500 bg-gray-50 rounded">
当前没有用户在做种
</div>
)}
</Card>
</div>
);
};
export default TorrentDetail;