| import React, { useState, useEffect } from 'react'; |
| import { useParams, useNavigate, useLocation, useSearchParams } from 'react-router-dom'; // 添加 useLocation |
| import { |
| Descriptions, |
| Table, |
| Button, |
| Modal, |
| Image, |
| message, |
| Spin, |
| Input, |
| Select, |
| Pagination, |
| Space, |
| Card |
| } from 'antd'; |
| import { ExclamationCircleOutlined } from '@ant-design/icons'; |
| import axios from 'axios'; |
| |
| const { confirm } = Modal; |
| const { Option } = Select; |
| |
| //const { confirm } = Modal; |
| |
| const TorrentDetailhelp = () => { |
| // 从URL获取种子ID |
| const navigate = useNavigate(); // 用于返回上一页 |
| const [torrent, setTorrent] = useState(null); |
| const [loading, setLoading] = useState(true); |
| const [error, setError] = useState(null); |
| const [isLoading, setIsLoading] = useState(false); |
| const [searchParams] = useSearchParams(); |
| // 在组件状态中添加 |
| // 获取参数并设置默认值 |
| //const [manageId, setManageId] = useState(parseInt(searchParams.get('manageid')) || 1); |
| // const [rewardUserId, setRewardUserId] = useState(parseInt(searchParams.get('userid')) || 1); |
| // const [creditAmount, setCreditAmount] = useState(parseInt(searchParams.get('credit')) || 1); |
| const location = useLocation(); |
| |
| // 从路由state获取参数(可能为空) |
| const { loaduser, money, torrentid, helpedid } = location.state || {}; |
| |
| // 设置默认值 |
| const [rewardUserId, setUserId] = useState(loaduser || null); |
| const [creditAmount, setCreditAmount] = useState(money || 1); // 默认1积分 |
| const [torrentId, setTorrentId] = useState(torrentid); // 默认值为路由传递的torrentid |
| const [helpedId, setHelpedId] = useState(helpedid || null); // 新增的帮助者ID |
| |
| |
| const currentUserId = 1; // 示例,实际应从认证系统获取 |
| |
| |
| // 格式化日期 |
| const formatDate = (dateString) => { |
| if (!dateString) return '未知'; |
| const date = new Date(dateString); |
| return date.toLocaleString('zh-CN', { |
| year: 'numeric', |
| month: '2-digit', |
| day: '2-digit', |
| hour: '2-digit', |
| minute: '2-digit' |
| }); |
| }; |
| |
| console.log("Helped ID:", helpedId); |
| |
| // 处理删除种子 |
| const handleDeleteTorrent = async (torrentId) => { |
| if (!currentUserId) { |
| message.warning('请先登录'); |
| return; |
| } |
| |
| confirm({ |
| title: '确认删除', |
| icon: <ExclamationCircleOutlined />, |
| content: '确定要删除这个种子吗?此操作不可恢复!', |
| onOk: async () => { |
| try { |
| await axios.delete(`http://localhost:8080/torrent/delete/${torrentId}`, { |
| params: { userid: currentUserId } |
| }); |
| // 成功删除后,更新状态或返回上一页 |
| setTorrent(null); // 清空当前种子详情 |
| navigate(-1); // 返回上一页 |
| message.success('种子删除成功'); |
| } catch (err) { |
| console.error('删除种子失败', err); |
| if (err.response && err.response.status === 403) { |
| message.error('无权删除此种子'); |
| } else { |
| message.error('删除种子失败'); |
| } |
| } |
| } |
| }); |
| }; |
| |
| |
| const handleDownloadTorrent = async (torrentId) => { |
| if (!currentUserId) { |
| message.warning('请先登录'); |
| return; |
| } |
| |
| setIsLoading(true); // 开始加载 |
| try { |
| // 使用axios发送带有参数的GET请求 |
| // const response = await axios.get(`http://localhost:8080/torrent/download/${torrentId}`, { |
| // params: { userId: currentUserId }, // 正确添加请求参数 |
| // responseType: 'blob' // 重要:指定响应类型为blob以处理文件下载 |
| // }); |
| |
| // // 创建下载链接 |
| // const url = window.URL.createObjectURL(new Blob([response.data])); |
| // const link = document.createElement('a'); |
| // link.href = url; |
| // //link.setAttribute('download', 'torrent_file.torrent'); // 可以设置为动态文件名 |
| // document.body.appendChild(link); |
| // link.click(); |
| // document.body.removeChild(link); |
| // window.URL.revokeObjectURL(url); |
| open(`http://localhost:8080/torrent/download/${torrentId}?userId=${currentUserId}`, '_blank'); |
| |
| message.success('种子下载开始'); |
| } catch (err) { |
| console.error('下载种子失败', err); |
| if (err.response?.status === 404) { |
| message.error('种子不存在'); |
| } else { |
| message.error('下载失败: ' + (err.response?.data?.message || err.message)); |
| } |
| } finally { |
| setIsLoading(false); // 结束加载 |
| } |
| }; |
| |
| |
| // 格式化文件大小 |
| const formatFileSize = (bytes) => { |
| if (bytes === 0) return '0 Bytes'; |
| const k = 1024; |
| const sizes = ['Bytes', '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 getPromotionName = (promotionId) => { |
| const promotionMap = { |
| 1: '上传加倍', |
| 2: '下载减半', |
| 3: '免费下载', |
| 0: '无促销' |
| }; |
| |
| return promotionMap[promotionId] || '未知促销'; |
| }; |
| |
| // 获取种子详情 |
| useEffect(() => { |
| const fetchTorrentDetail = async () => { |
| try { |
| const response = await axios.get(`http://localhost:8080/torrent/${torrentid}`); |
| if (response.status === 200) { |
| setTorrent(response.data); |
| } else { |
| setError('获取种子详情失败'); |
| } |
| } catch (err) { |
| console.error('获取种子详情失败:', err); |
| if (err.response) { |
| if (err.response.status === 404) { |
| setError('种子不存在'); |
| } else { |
| setError('获取种子详情失败: ' + err.response.data); |
| } |
| } else { |
| setError('网络错误,请稍后重试'); |
| } |
| } finally { |
| setLoading(false); |
| } |
| }; |
| |
| fetchTorrentDetail(); |
| }, [torrentid]); |
| |
| // 奖励保种积分处理函数(修正版) |
| const handleAddCredit = async (torrentId) => { |
| if (!currentUserId) { // 需要定义manageUserId |
| message.warning('缺少必要权限'); |
| return; |
| } |
| |
| setIsLoading(true); |
| try { |
| const params = new URLSearchParams(); |
| params.append('manageid', currentUserId); |
| params.append('userid', rewardUserId); |
| params.append('credit', creditAmount); |
| params.append('helpedId', helpedId); |
| |
| const response = await axios.post(`http://localhost:8080/torrent/addcredit`, params.toString(), { |
| headers: { |
| 'Content-Type': 'application/x-www-form-urlencoded' |
| } |
| }); |
| |
| if (response.data.success !== false) { |
| message.success(`成功奖励 ${creditAmount} 保种积分`); |
| } else { |
| message.error(response.data.message || '奖励积分失败'); |
| } |
| } catch (err) { |
| console.error('奖励积分失败', err); |
| if (err.response?.status === 500) { |
| message.error('服务器错误: ' + (err.response.data?.message || '未知错误')); |
| } else { |
| message.error('奖励积分失败: ' + (err.response?.data?.message || err.message)); |
| } |
| } finally { |
| setIsLoading(false); |
| } |
| }; |
| |
| console.log('Torrent Detail:', torrent); |
| |
| // 返回上一页 |
| const handleBack = () => { |
| navigate(-1); // 返回上一页 |
| }; |
| |
| // 如果正在加载 |
| if (loading) { |
| return ( |
| <div className="flex justify-center items-center h-96"> |
| <Spin size="large" tip="加载中..." /> |
| </div> |
| ); |
| } |
| |
| // 如果有错误 |
| if (error) { |
| return ( |
| <div className="p-6"> |
| <Card> |
| <div className="text-center p-6"> |
| <ExclamationCircleOutlined className="text-2xl text-red-500 mb-4" /> |
| <h3 className="text-lg font-medium text-red-600 mb-2">错误</h3> |
| <p className="text-gray-600">{error}</p> |
| <Button type="primary" onClick={handleBack} className="mt-4"> |
| 返回 |
| </Button> |
| </div> |
| </Card> |
| </div> |
| ); |
| } |
| |
| // 如果种子不存在 |
| if (!torrent) { |
| return ( |
| <div className="p-6"> |
| <Card> |
| <div className="text-center p-6"> |
| <ExclamationCircleOutlined className="text-2xl text-yellow-500 mb-4" /> |
| <h3 className="text-lg font-medium text-yellow-600 mb-2">种子不存在</h3> |
| <p className="text-gray-600">抱歉,您查找的种子不存在或已被删除。</p> |
| <Button type="primary" onClick={handleBack} className="mt-4"> |
| 返回 |
| </Button> |
| </div> |
| </Card> |
| </div> |
| ); |
| } |
| |
| // 渲染种子详情 |
| return ( |
| <div className="p-6"> |
| <Card |
| title="种子详情" |
| extra={ |
| <Button type="primary" onClick={handleBack}> |
| 返回列表 |
| </Button> |
| } |
| > |
| {/* 使用Descriptions组件展示详情 */} |
| <Descriptions bordered column={1}> |
| <Descriptions.Item label="ID">{torrent.torrentid}</Descriptions.Item> |
| {/* 新增的封面图片展示 */} |
| {torrent.coverImagePath && ( |
| <Descriptions.Item label="封面图片"> |
| <Image |
| src={torrent.coverImagePath} |
| alt="种子封面" |
| width={200} // 设置图片宽度 |
| placeholder={ |
| <div className="w-48 h-32 bg-gray-200 flex items-center justify-center"> |
| 加载中... |
| </div> |
| } |
| /> |
| </Descriptions.Item> |
| )} |
| <Descriptions.Item label="文件名">{torrent.filename}</Descriptions.Item> |
| <Descriptions.Item label="大小">{formatFileSize(torrent.torrentSize)}</Descriptions.Item> |
| <Descriptions.Item label="上传者ID">{torrent.uploader_id}</Descriptions.Item> |
| <Descriptions.Item label="上传时间">{formatDate(torrent.uploadTime)}</Descriptions.Item> |
| <Descriptions.Item label="下载次数">{torrent.downloadCount}</Descriptions.Item> |
| <Descriptions.Item label="促销"> |
| {getPromotionName(torrent.promotionid)} |
| </Descriptions.Item> |
| <Descriptions.Item label="描述"> |
| {torrent.description || '无描述'} |
| </Descriptions.Item> |
| </Descriptions> |
| |
| |
| {/* 操作按钮区域 */} |
| <div className="mt-6 flex justify-end space-x-4"> |
| <Button |
| danger |
| onClick={() => handleDeleteTorrent(torrent.torrentid)} |
| loading={isLoading} |
| > |
| 删除 |
| </Button> |
| <Button |
| type="primary" |
| onClick={() => handleDownloadTorrent(torrent.torrentid)} |
| loading={isLoading} |
| > |
| 下载 |
| </Button> |
| {/* 新增的奖励保种积分按钮 */} |
| <Button |
| type="default" |
| onClick={() => handleAddCredit(torrent.torrentid)} |
| loading={isLoading} |
| > |
| 奖励保种积分 |
| </Button> |
| </div> |
| </Card> |
| </div> |
| ); |
| }; |
| |
| export default TorrentDetailhelp; |