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