blob: 8019e4c92ffb5d520d0c9a6ed02ca50dc2ebd4a0 [file] [log] [blame]
刘嘉昕8a3c6ab2025-06-09 17:44:13 +08001import React, { useState, useEffect } from 'react';
2import { useParams, useNavigate, useLocation, useSearchParams } from 'react-router-dom'; // 添加 useLocation
3import {
4 Descriptions,
5 Table,
6 Button,
7 Modal,
8 Image,
9 message,
10 Spin,
11 Input,
12 Select,
13 Pagination,
14 Space,
15 Card
16} from 'antd';
17import { ExclamationCircleOutlined } from '@ant-design/icons';
18import axios from 'axios';
19
20const { confirm } = Modal;
21const { Option } = Select;
22
23//const { confirm } = Modal;
24
25const TorrentDetailhelp = () => {
26 // 从URL获取种子ID
27 const navigate = useNavigate(); // 用于返回上一页
28 const [torrent, setTorrent] = useState(null);
29 const [loading, setLoading] = useState(true);
30 const [error, setError] = useState(null);
31 const [isLoading, setIsLoading] = useState(false);
32 const [searchParams] = useSearchParams();
33 // 在组件状态中添加
34 // 获取参数并设置默认值
35 //const [manageId, setManageId] = useState(parseInt(searchParams.get('manageid')) || 1);
36 // const [rewardUserId, setRewardUserId] = useState(parseInt(searchParams.get('userid')) || 1);
37 // const [creditAmount, setCreditAmount] = useState(parseInt(searchParams.get('credit')) || 1);
38 const location = useLocation();
39
40 // 从路由state获取参数(可能为空)
41 const { loaduser, money, torrentid, helpedid } = location.state || {};
42
43 // 设置默认值
44 const [rewardUserId, setUserId] = useState(loaduser || null);
45 const [creditAmount, setCreditAmount] = useState(money || 1); // 默认1积分
46 const [torrentId, setTorrentId] = useState(torrentid); // 默认值为路由传递的torrentid
47 const [helpedId, setHelpedId] = useState(helpedid || null); // 新增的帮助者ID
48
49
50 const currentUserId = 1; // 示例,实际应从认证系统获取
51
52
53 // 格式化日期
54 const formatDate = (dateString) => {
55 if (!dateString) return '未知';
56 const date = new Date(dateString);
57 return date.toLocaleString('zh-CN', {
58 year: 'numeric',
59 month: '2-digit',
60 day: '2-digit',
61 hour: '2-digit',
62 minute: '2-digit'
63 });
64 };
65
66 console.log("Helped ID:", helpedId);
67
68 // 处理删除种子
69 const handleDeleteTorrent = async (torrentId) => {
70 if (!currentUserId) {
71 message.warning('请先登录');
72 return;
73 }
74
75 confirm({
76 title: '确认删除',
77 icon: <ExclamationCircleOutlined />,
78 content: '确定要删除这个种子吗?此操作不可恢复!',
79 onOk: async () => {
80 try {
81 await axios.delete(`http://localhost:8080/torrent/delete/${torrentId}`, {
82 params: { userid: currentUserId }
83 });
84 // 成功删除后,更新状态或返回上一页
85 setTorrent(null); // 清空当前种子详情
86 navigate(-1); // 返回上一页
87 message.success('种子删除成功');
88 } catch (err) {
89 console.error('删除种子失败', err);
90 if (err.response && err.response.status === 403) {
91 message.error('无权删除此种子');
92 } else {
93 message.error('删除种子失败');
94 }
95 }
96 }
97 });
98 };
99
100
101 const handleDownloadTorrent = async (torrentId) => {
102 if (!currentUserId) {
103 message.warning('请先登录');
104 return;
105 }
106
107 setIsLoading(true); // 开始加载
108 try {
109 // 使用axios发送带有参数的GET请求
110 // const response = await axios.get(`http://localhost:8080/torrent/download/${torrentId}`, {
111 // params: { userId: currentUserId }, // 正确添加请求参数
112 // responseType: 'blob' // 重要:指定响应类型为blob以处理文件下载
113 // });
114
115 // // 创建下载链接
116 // const url = window.URL.createObjectURL(new Blob([response.data]));
117 // const link = document.createElement('a');
118 // link.href = url;
119 // //link.setAttribute('download', 'torrent_file.torrent'); // 可以设置为动态文件名
120 // document.body.appendChild(link);
121 // link.click();
122 // document.body.removeChild(link);
123 // window.URL.revokeObjectURL(url);
124 open(`http://localhost:8080/torrent/download/${torrentId}?userId=${currentUserId}`, '_blank');
125
126 message.success('种子下载开始');
127 } catch (err) {
128 console.error('下载种子失败', err);
129 if (err.response?.status === 404) {
130 message.error('种子不存在');
131 } else {
132 message.error('下载失败: ' + (err.response?.data?.message || err.message));
133 }
134 } finally {
135 setIsLoading(false); // 结束加载
136 }
137 };
138
139
140 // 格式化文件大小
141 const formatFileSize = (bytes) => {
142 if (bytes === 0) return '0 Bytes';
143 const k = 1024;
144 const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
145 const i = Math.floor(Math.log(bytes) / Math.log(k));
146 return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
147 };
148
149 // 在组件函数内部添加这个函数
150 const getPromotionName = (promotionId) => {
151 const promotionMap = {
152 1: '上传加倍',
153 2: '下载减半',
154 3: '免费下载',
155 0: '无促销'
156 };
157
158 return promotionMap[promotionId] || '未知促销';
159 };
160
161 // 获取种子详情
162 useEffect(() => {
163 const fetchTorrentDetail = async () => {
164 try {
165 const response = await axios.get(`http://localhost:8080/torrent/${torrentid}`);
166 if (response.status === 200) {
167 setTorrent(response.data);
168 } else {
169 setError('获取种子详情失败');
170 }
171 } catch (err) {
172 console.error('获取种子详情失败:', err);
173 if (err.response) {
174 if (err.response.status === 404) {
175 setError('种子不存在');
176 } else {
177 setError('获取种子详情失败: ' + err.response.data);
178 }
179 } else {
180 setError('网络错误,请稍后重试');
181 }
182 } finally {
183 setLoading(false);
184 }
185 };
186
187 fetchTorrentDetail();
188 }, [torrentid]);
189
190 // 奖励保种积分处理函数(修正版)
191 const handleAddCredit = async (torrentId) => {
192 if (!currentUserId) { // 需要定义manageUserId
193 message.warning('缺少必要权限');
194 return;
195 }
196
197 setIsLoading(true);
198 try {
199 const params = new URLSearchParams();
200 params.append('manageid', currentUserId);
201 params.append('userid', rewardUserId);
202 params.append('credit', creditAmount);
203 params.append('helpedId', helpedId);
204
205 const response = await axios.post(`http://localhost:8080/torrent/addcredit`, params.toString(), {
206 headers: {
207 'Content-Type': 'application/x-www-form-urlencoded'
208 }
209 });
210
211 if (response.data.success !== false) {
212 message.success(`成功奖励 ${creditAmount} 保种积分`);
213 } else {
214 message.error(response.data.message || '奖励积分失败');
215 }
216 } catch (err) {
217 console.error('奖励积分失败', err);
218 if (err.response?.status === 500) {
219 message.error('服务器错误: ' + (err.response.data?.message || '未知错误'));
220 } else {
221 message.error('奖励积分失败: ' + (err.response?.data?.message || err.message));
222 }
223 } finally {
224 setIsLoading(false);
225 }
226 };
227
228 console.log('Torrent Detail:', torrent);
229
230 // 返回上一页
231 const handleBack = () => {
232 navigate(-1); // 返回上一页
233 };
234
235 // 如果正在加载
236 if (loading) {
237 return (
238 <div className="flex justify-center items-center h-96">
239 <Spin size="large" tip="加载中..." />
240 </div>
241 );
242 }
243
244 // 如果有错误
245 if (error) {
246 return (
247 <div className="p-6">
248 <Card>
249 <div className="text-center p-6">
250 <ExclamationCircleOutlined className="text-2xl text-red-500 mb-4" />
251 <h3 className="text-lg font-medium text-red-600 mb-2">错误</h3>
252 <p className="text-gray-600">{error}</p>
253 <Button type="primary" onClick={handleBack} className="mt-4">
254 返回
255 </Button>
256 </div>
257 </Card>
258 </div>
259 );
260 }
261
262 // 如果种子不存在
263 if (!torrent) {
264 return (
265 <div className="p-6">
266 <Card>
267 <div className="text-center p-6">
268 <ExclamationCircleOutlined className="text-2xl text-yellow-500 mb-4" />
269 <h3 className="text-lg font-medium text-yellow-600 mb-2">种子不存在</h3>
270 <p className="text-gray-600">抱歉,您查找的种子不存在或已被删除。</p>
271 <Button type="primary" onClick={handleBack} className="mt-4">
272 返回
273 </Button>
274 </div>
275 </Card>
276 </div>
277 );
278 }
279
280 // 渲染种子详情
281 return (
282 <div className="p-6">
283 <Card
284 title="种子详情"
285 extra={
286 <Button type="primary" onClick={handleBack}>
287 返回列表
288 </Button>
289 }
290 >
291 {/* 使用Descriptions组件展示详情 */}
292 <Descriptions bordered column={1}>
293 <Descriptions.Item label="ID">{torrent.torrentid}</Descriptions.Item>
294 {/* 新增的封面图片展示 */}
295 {torrent.coverImagePath && (
296 <Descriptions.Item label="封面图片">
297 <Image
298 src={torrent.coverImagePath}
299 alt="种子封面"
300 width={200} // 设置图片宽度
301 placeholder={
302 <div className="w-48 h-32 bg-gray-200 flex items-center justify-center">
303 加载中...
304 </div>
305 }
306 />
307 </Descriptions.Item>
308 )}
309 <Descriptions.Item label="文件名">{torrent.filename}</Descriptions.Item>
310 <Descriptions.Item label="大小">{formatFileSize(torrent.torrentSize)}</Descriptions.Item>
311 <Descriptions.Item label="上传者ID">{torrent.uploader_id}</Descriptions.Item>
312 <Descriptions.Item label="上传时间">{formatDate(torrent.uploadTime)}</Descriptions.Item>
313 <Descriptions.Item label="下载次数">{torrent.downloadCount}</Descriptions.Item>
314 <Descriptions.Item label="促销">
315 {getPromotionName(torrent.promotionid)}
316 </Descriptions.Item>
317 <Descriptions.Item label="描述">
318 {torrent.description || '无描述'}
319 </Descriptions.Item>
320 </Descriptions>
321
322
323 {/* 操作按钮区域 */}
324 <div className="mt-6 flex justify-end space-x-4">
325 <Button
326 danger
327 onClick={() => handleDeleteTorrent(torrent.torrentid)}
328 loading={isLoading}
329 >
330 删除
331 </Button>
332 <Button
333 type="primary"
334 onClick={() => handleDownloadTorrent(torrent.torrentid)}
335 loading={isLoading}
336 >
337 下载
338 </Button>
339 {/* 新增的奖励保种积分按钮 */}
340 <Button
341 type="default"
342 onClick={() => handleAddCredit(torrent.torrentid)}
343 loading={isLoading}
344 >
345 奖励保种积分
346 </Button>
347 </div>
348 </Card>
349 </div>
350 );
351};
352
353export default TorrentDetailhelp;