| import { getTorrentInfo, downloadTorrent } from "@/api/torrents"; |
| import { useState, useEffect } from "react"; |
| import { useParams, useLocation } from "react-router-dom"; |
| import { useAuth } from "../../auth/contexts/AuthContext"; |
| import { message } from "antd"; |
| |
| const TorrentInfo = () => { |
| const { id } = useParams(); |
| const location = useLocation(); |
| const [torrentData, setTorrentData] = useState(null); |
| const [loading, setLoading] = useState(true); |
| const [error, setError] = useState(null); |
| const { user } = useAuth(); |
| |
| // 从路由状态或其他方式获取username |
| const username = user?.username; |
| |
| useEffect(() => { |
| const fetchTorrentInfo = async () => { |
| if (!id || !username) { |
| setError('缺少必要参数:ID或用户名'); |
| setLoading(false); |
| return; |
| } |
| |
| try { |
| setLoading(true); |
| setError(null); |
| |
| const response = await getTorrentInfo({ id, username }); |
| |
| if (response && response.data) { |
| setTorrentData(response.data); |
| } else { |
| setError('未找到种子信息'); |
| } |
| } catch (err) { |
| console.error('获取种子信息失败:', err); |
| setError(err.message || '获取种子信息失败'); |
| } finally { |
| setLoading(false); |
| } |
| }; |
| |
| fetchTorrentInfo(); |
| }, [id, username]); |
| |
| // 处理种子下载 |
| const handleDownload = async () => { |
| try { |
| const resourceId = torrentData.resourceId || id; |
| if (!resourceId) { |
| message.error('无法获取资源ID'); |
| return; |
| } |
| |
| message.loading('正在准备下载...', 1); |
| |
| // 调用下载API |
| const response = await downloadTorrent(resourceId, username); |
| |
| // 创建下载链接 |
| const blob = new Blob([response], { type: 'application/x-bittorrent' }); |
| const url = window.URL.createObjectURL(blob); |
| |
| // 创建临时链接并触发下载 |
| const link = document.createElement('a'); |
| link.href = url; |
| link.download = `${torrentData.name || 'torrent'}.torrent`; |
| document.body.appendChild(link); |
| link.click(); |
| |
| // 清理 |
| document.body.removeChild(link); |
| window.URL.revokeObjectURL(url); |
| |
| message.success('种子文件下载成功!'); |
| } catch (error) { |
| console.error('下载种子文件时出错:', error); |
| if (error.response) { |
| const status = error.response.status; |
| const errorMessage = error.response.data?.message || '未知错误'; |
| message.error(`下载失败 (${status}): ${errorMessage}`); |
| } else { |
| message.error('下载失败:' + (error.message || '网络错误,请重试')); |
| } |
| } |
| }; |
| |
| const formatDate = (dateString) => { |
| try { |
| const date = new Date(dateString); |
| return date.toLocaleString('zh-CN', { |
| year: 'numeric', |
| month: '2-digit', |
| day: '2-digit', |
| hour: '2-digit', |
| minute: '2-digit', |
| second: '2-digit' |
| }); |
| } catch { |
| return dateString; |
| } |
| }; |
| |
| if (loading) { |
| return ( |
| <div className="flex justify-center items-center min-h-screen"> |
| <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500"></div> |
| <span className="ml-3 text-gray-600">加载中...</span> |
| </div> |
| ); |
| } |
| |
| if (error) { |
| return ( |
| <div className="max-w-4xl mx-auto p-6"> |
| <div className="bg-red-50 border border-red-200 rounded-lg p-6"> |
| <div className="flex items-center"> |
| <div className="flex-shrink-0"> |
| <svg className="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor"> |
| <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" /> |
| </svg> |
| </div> |
| <div className="ml-3"> |
| <h3 className="text-sm font-medium text-red-800">错误</h3> |
| <div className="mt-2 text-sm text-red-700">{error}</div> |
| <div className="mt-2 text-sm text-red-600"> |
| <p>调试信息:</p> |
| <p>ID: {id}</p> |
| <p>用户名: {username}</p> |
| <p>路径: {location.pathname}</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| ); |
| } |
| |
| if (!torrentData) { |
| return ( |
| <div className="max-w-4xl mx-auto p-6"> |
| <div className="text-center text-gray-500"> |
| <p>未找到种子信息</p> |
| </div> |
| </div> |
| ); |
| } |
| |
| return ( |
| <div className="max-w-4xl mx-auto p-6"> |
| <div className="bg-white shadow-lg rounded-lg overflow-hidden"> |
| {/* 头部 */} |
| <div className="bg-gradient-to-r from-blue-500 to-purple-600 px-6 py-4"> |
| <h1 className="text-2xl font-bold text-white">种子详情</h1> |
| </div> |
| |
| {/* 内容 */} |
| <div className="p-6"> |
| <div className="grid grid-cols-1 md:grid-cols-2 gap-6"> |
| {/* 基本信息 */} |
| <div className="space-y-4"> |
| <div className="border-b border-gray-200 pb-4"> |
| <h2 className="text-lg font-semibold text-gray-800 mb-3">基本信息</h2> |
| |
| <div className="space-y-3"> |
| <div className="flex items-start"> |
| <span className="text-sm font-medium text-gray-500 w-20 flex-shrink-0">名称:</span> |
| <span className="text-sm text-gray-900 break-all">{torrentData.name}</span> |
| </div> |
| |
| <div className="flex items-start"> |
| <span className="text-sm font-medium text-gray-500 w-20 flex-shrink-0">作者:</span> |
| <span className="text-sm text-gray-900">{torrentData.author}</span> |
| </div> |
| |
| <div className="flex items-start"> |
| <span className="text-sm font-medium text-gray-500 w-20 flex-shrink-0">资源ID:</span> |
| <span className="text-sm text-gray-900">{torrentData.resourceId}</span> |
| </div> |
| |
| <div className="flex items-start"> |
| <span className="text-sm font-medium text-gray-500 w-20 flex-shrink-0">发布时间:</span> |
| <span className="text-sm text-gray-900">{formatDate(torrentData.publishTime)}</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| {/* 描述信息 */} |
| <div className="space-y-4"> |
| <div className="border-b border-gray-200 pb-4"> |
| <h2 className="text-lg font-semibold text-gray-800 mb-3">描述信息</h2> |
| <div className="bg-gray-50 rounded-lg p-4"> |
| <p className="text-sm text-gray-700 whitespace-pre-wrap"> |
| {torrentData.description || '暂无描述'} |
| </p> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| {/* 操作按钮 */} |
| <div className="mt-8 pt-6 border-t border-gray-200"> |
| <div className="flex flex-wrap gap-3"> |
| <button |
| onClick={handleDownload} |
| 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" |
| > |
| <svg className="w-4 h-4" fill="currentColor" viewBox="0 0 20 20"> |
| <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" /> |
| </svg> |
| 下载种子 |
| </button> |
| <button |
| onClick={() => window.history.back()} |
| className="px-4 py-2 bg-gray-500 text-white rounded-lg hover:bg-gray-600 transition-colors duration-200" |
| > |
| 返回 |
| </button> |
| <button |
| onClick={() => window.location.reload()} |
| className="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors duration-200" |
| > |
| 刷新 |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| ); |
| }; |
| |
| export default TorrentInfo; |