blob: 6d9048f108e023c1d7d61e4bf5a3669cf3c886ac [file] [log] [blame]
ybt3ec62e42025-06-11 22:46:22 +08001import { getTorrentInfo, downloadTorrent } from "@/api/torrents";
2import { useState, useEffect } from "react";
3import { useParams, useLocation } from "react-router-dom";
4import { useAuth } from "../../auth/contexts/AuthContext";
5import { message } from "antd";
6
7const TorrentInfo = () => {
8 const { id } = useParams();
9 const location = useLocation();
10 const [torrentData, setTorrentData] = useState(null);
11 const [loading, setLoading] = useState(true);
12 const [error, setError] = useState(null);
13 const { user } = useAuth();
14
15 // 从路由状态或其他方式获取username
16 const username = user?.username;
17
18 useEffect(() => {
19 const fetchTorrentInfo = async () => {
20 if (!id || !username) {
21 setError('缺少必要参数:ID或用户名');
22 setLoading(false);
23 return;
24 }
25
26 try {
27 setLoading(true);
28 setError(null);
29
30 const response = await getTorrentInfo({ id, username });
31
32 if (response && response.data) {
33 setTorrentData(response.data);
34 } else {
35 setError('未找到种子信息');
36 }
37 } catch (err) {
38 console.error('获取种子信息失败:', err);
39 setError(err.message || '获取种子信息失败');
40 } finally {
41 setLoading(false);
42 }
43 };
44
45 fetchTorrentInfo();
46 }, [id, username]);
47
48 // 处理种子下载
49 const handleDownload = async () => {
50 try {
51 const resourceId = torrentData.resourceId || id;
52 if (!resourceId) {
53 message.error('无法获取资源ID');
54 return;
55 }
56
57 message.loading('正在准备下载...', 1);
58
59 // 调用下载API
60 const response = await downloadTorrent(resourceId, username);
61
62 // 创建下载链接
63 const blob = new Blob([response], { type: 'application/x-bittorrent' });
64 const url = window.URL.createObjectURL(blob);
65
66 // 创建临时链接并触发下载
67 const link = document.createElement('a');
68 link.href = url;
69 link.download = `${torrentData.name || 'torrent'}.torrent`;
70 document.body.appendChild(link);
71 link.click();
72
73 // 清理
74 document.body.removeChild(link);
75 window.URL.revokeObjectURL(url);
76
77 message.success('种子文件下载成功!');
78 } catch (error) {
79 console.error('下载种子文件时出错:', error);
80 if (error.response) {
81 const status = error.response.status;
82 const errorMessage = error.response.data?.message || '未知错误';
83 message.error(`下载失败 (${status}): ${errorMessage}`);
84 } else {
85 message.error('下载失败:' + (error.message || '网络错误,请重试'));
86 }
87 }
88 };
89
90 const formatDate = (dateString) => {
91 try {
92 const date = new Date(dateString);
93 return date.toLocaleString('zh-CN', {
94 year: 'numeric',
95 month: '2-digit',
96 day: '2-digit',
97 hour: '2-digit',
98 minute: '2-digit',
99 second: '2-digit'
100 });
101 } catch {
102 return dateString;
103 }
104 };
105
106 if (loading) {
107 return (
108 <div className="flex justify-center items-center min-h-screen">
109 <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500"></div>
110 <span className="ml-3 text-gray-600">加载中...</span>
111 </div>
112 );
113 }
114
115 if (error) {
116 return (
117 <div className="max-w-4xl mx-auto p-6">
118 <div className="bg-red-50 border border-red-200 rounded-lg p-6">
119 <div className="flex items-center">
120 <div className="flex-shrink-0">
121 <svg className="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor">
122 <path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clipRule="evenodd" />
123 </svg>
124 </div>
125 <div className="ml-3">
126 <h3 className="text-sm font-medium text-red-800">错误</h3>
127 <div className="mt-2 text-sm text-red-700">{error}</div>
128 <div className="mt-2 text-sm text-red-600">
129 <p>调试信息:</p>
130 <p>ID: {id}</p>
131 <p>用户名: {username}</p>
132 <p>路径: {location.pathname}</p>
133 </div>
134 </div>
135 </div>
136 </div>
137 </div>
138 );
139 }
140
141 if (!torrentData) {
142 return (
143 <div className="max-w-4xl mx-auto p-6">
144 <div className="text-center text-gray-500">
145 <p>未找到种子信息</p>
146 </div>
147 </div>
148 );
149 }
150
151 return (
152 <div className="max-w-4xl mx-auto p-6">
153 <div className="bg-white shadow-lg rounded-lg overflow-hidden">
154 {/* 头部 */}
155 <div className="bg-gradient-to-r from-blue-500 to-purple-600 px-6 py-4">
156 <h1 className="text-2xl font-bold text-white">种子详情</h1>
157 </div>
158
159 {/* 内容 */}
160 <div className="p-6">
161 <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
162 {/* 基本信息 */}
163 <div className="space-y-4">
164 <div className="border-b border-gray-200 pb-4">
165 <h2 className="text-lg font-semibold text-gray-800 mb-3">基本信息</h2>
166
167 <div className="space-y-3">
168 <div className="flex items-start">
169 <span className="text-sm font-medium text-gray-500 w-20 flex-shrink-0">名称:</span>
170 <span className="text-sm text-gray-900 break-all">{torrentData.name}</span>
171 </div>
172
173 <div className="flex items-start">
174 <span className="text-sm font-medium text-gray-500 w-20 flex-shrink-0">作者:</span>
175 <span className="text-sm text-gray-900">{torrentData.author}</span>
176 </div>
177
178 <div className="flex items-start">
179 <span className="text-sm font-medium text-gray-500 w-20 flex-shrink-0">资源ID:</span>
180 <span className="text-sm text-gray-900">{torrentData.resourceId}</span>
181 </div>
182
183 <div className="flex items-start">
184 <span className="text-sm font-medium text-gray-500 w-20 flex-shrink-0">发布时间:</span>
185 <span className="text-sm text-gray-900">{formatDate(torrentData.publishTime)}</span>
186 </div>
187 </div>
188 </div>
189 </div>
190
191 {/* 描述信息 */}
192 <div className="space-y-4">
193 <div className="border-b border-gray-200 pb-4">
194 <h2 className="text-lg font-semibold text-gray-800 mb-3">描述信息</h2>
195 <div className="bg-gray-50 rounded-lg p-4">
196 <p className="text-sm text-gray-700 whitespace-pre-wrap">
197 {torrentData.description || '暂无描述'}
198 </p>
199 </div>
200 </div>
201 </div>
202 </div>
203
204 {/* 操作按钮 */}
205 <div className="mt-8 pt-6 border-t border-gray-200">
206 <div className="flex flex-wrap gap-3">
207 <button
208 onClick={handleDownload}
209 className="px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors duration-200 flex items-center gap-2"
210 >
211 <svg className="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
212 <path fillRule="evenodd" d="M3 17a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm3.293-7.707a1 1 0 011.414 0L9 10.586V3a1 1 0 112 0v7.586l1.293-1.293a1 1 0 111.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z" clipRule="evenodd" />
213 </svg>
214 下载种子
215 </button>
216 <button
217 onClick={() => window.history.back()}
218 className="px-4 py-2 bg-gray-500 text-white rounded-lg hover:bg-gray-600 transition-colors duration-200"
219 >
220 返回
221 </button>
222 <button
223 onClick={() => window.location.reload()}
224 className="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors duration-200"
225 >
226 刷新
227 </button>
228 </div>
229 </div>
230 </div>
231 </div>
232 </div>
233 );
234};
235
236export default TorrentInfo;