blob: 16c6d01f358322e5d1e8e632c359253a19701d46 [file] [log] [blame]
223010095b28c672025-04-10 20:12:45 +08001import React, { useEffect, useState } from 'react';
2import axios from 'axios';
2230100980aaf0d2025-06-05 23:20:05 +08003import { useParams } from 'wouter';
223010095b28c672025-04-10 20:12:45 +08004import Header from '../../../components/Header';
5import './SeedDetail.css';
2230100980aaf0d2025-06-05 23:20:05 +08006import { useUser } from '../../../context/UserContext';
Krishya2283d882025-05-27 22:25:19 +08007
223010095b28c672025-04-10 20:12:45 +08008
9const SeedDetail = () => {
2230100980aaf0d2025-06-05 23:20:05 +080010 const params = useParams();
11 const seed_id = params.id;
223010095b28c672025-04-10 20:12:45 +080012
2230100980aaf0d2025-06-05 23:20:05 +080013 const [seed, setSeed] = useState(null);
14 const [coverImage, setCoverImage] = useState(null);
15 const [error, setError] = useState(null);
16 const [comments, setComments] = useState([]);
17 const [newComment, setNewComment] = useState('');
18
19 const { user } = useUser();
20
21
22 // 格式化图片 URL
23 const formatImageUrl = (url) => {
24 if (!url) return '';
25 const filename = url.split('/').pop();
223010094158f3a2025-06-06 19:59:10 +080026 return `http://localhost:5011/uploads/torrents/${filename}`;
2230100980aaf0d2025-06-05 23:20:05 +080027 };
28
29 useEffect(() => {
30 if (!seed_id) {
31 setError('无效的种子ID');
32 return;
33 }
34
35 const fetchSeedDetail = async () => {
36 try {
37 const res = await axios.post(`/seeds/info/${seed_id}`);
38 if (res.data.code === 0) {
39 const seedData = res.data.data;
40
41 // 处理封面图
42 let cover = seedData.imageUrl;
43 if (!cover && seedData.imgUrl) {
44 const imgs = seedData.imgUrl
45 .split(',')
46 .map((i) => i.trim())
47 .filter(Boolean);
48 cover = imgs.length > 0 ? formatImageUrl(imgs[0]) : null;
49 }
50 setCoverImage(cover);
51 setSeed(seedData);
52 setError(null);
53 } else {
54 setError('未能获取种子信息');
55 }
56 } catch (err) {
57 console.error('请求种子详情出错:', err);
58 setError('获取种子详情失败');
59 }
60 };
61
62 const fetchComments = async () => {
63 try {
64 const res = await axios.get(`/seeds/${seed_id}/comments`);
65 if (res.data.code === 0) {
66 setComments(res.data.data || []);
67 } else {
68 setComments([]);
69 }
70 } catch {
71 setComments([]);
72 }
73 };
74
75 fetchSeedDetail();
76 fetchComments();
77 }, [seed_id]);
78
79 const handleDownload = async (seedId) => {
80 if (!user || !user.userId) {
81 alert('请先登录再下载种子文件');
82 return;
83 }
84
85 try {
86 const response = await axios.get(`/seeds/${seedId}/download`, {
87 params: {
88 passkey: user.userId,
89 },
90 responseType: 'blob'
Krishyac0f7e9b2025-04-22 15:28:28 +080091 });
92
2230100980aaf0d2025-06-05 23:20:05 +080093 const blob = new Blob([response.data], { type: 'application/x-bittorrent' });
94 const downloadUrl = URL.createObjectURL(blob);
95 const a = document.createElement('a');
96 a.href = downloadUrl;
97 a.download = `${seedId}.torrent`;
98 a.click();
99 URL.revokeObjectURL(downloadUrl);
100 } catch (error) {
101 console.error('下载失败:', error);
102 alert('下载失败,请稍后再试。');
223010095b28c672025-04-10 20:12:45 +0800103 }
Krishyac0f7e9b2025-04-22 15:28:28 +0800104 };
223010095b28c672025-04-10 20:12:45 +0800105
Krishyac0f7e9b2025-04-22 15:28:28 +0800106
2230100980aaf0d2025-06-05 23:20:05 +0800107 const handleCollect = () => {
108 alert('已收藏');
109 };
Krishyac0f7e9b2025-04-22 15:28:28 +0800110
2230100980aaf0d2025-06-05 23:20:05 +0800111 const handleAddComment = () => {
112 if (newComment.trim()) {
113 setComments([...comments, { content: newComment, user: '用户' }]);
114 setNewComment('');
Krishyac0f7e9b2025-04-22 15:28:28 +0800115 }
2230100980aaf0d2025-06-05 23:20:05 +0800116 };
Krishyac0f7e9b2025-04-22 15:28:28 +0800117
2230100980aaf0d2025-06-05 23:20:05 +0800118 if (error) {
223010095b28c672025-04-10 20:12:45 +0800119 return (
2230100980aaf0d2025-06-05 23:20:05 +0800120 <div className="seed-detail-page">
121 <Header />
122 <div className="seed-detail">
123 <p className="error-text">{error}</p>
223010095b28c672025-04-10 20:12:45 +0800124 </div>
2230100980aaf0d2025-06-05 23:20:05 +0800125 </div>
223010095b28c672025-04-10 20:12:45 +0800126 );
2230100980aaf0d2025-06-05 23:20:05 +0800127 }
128
129 if (!seed) {
130 return (
131 <div className="seed-detail-page">
132 <Header />
133 <div className="seed-detail">
134 <p>加载中...</p>
135 </div>
136 </div>
137 );
138 }
139
140 const tags = seed.tags
141 ? Array.isArray(seed.tags)
142 ? seed.tags
143 : typeof seed.tags === 'string'
144 ? seed.tags.split(',').map((t) => t.trim())
145 : []
146 : [];
147
148 const actors = seed.actors
149 ? Array.isArray(seed.actors)
150 ? seed.actors
151 : typeof seed.actors === 'string'
152 ? seed.actors.split(',').map((a) => a.trim())
153 : []
154 : [];
155
156 return (
157 <div className="seed-detail-page">
158 <Header />
159 <div className="seed-detail">
160 <h1>{seed.title}</h1>
161 <div className="seed-header-container">
162 <div className="seed-info">
163 <div className="seed-basic-info">
164 <p><strong>分类:</strong>{seed.category || '未知'}</p>
165 <p><strong>发布时间:</strong>{seed.upload_time ? new Date(seed.upload_time).toLocaleString() : '未知'}</p>
166 <p><strong>标签:</strong>{tags.join(' / ')}</p>
167 <p><strong>简介:</strong>{seed.description || ''}</p>
168 <p><strong>大小:</strong>{seed.size || '未知'}</p>
169 <p><strong>分辨率:</strong>{seed.resolution || '未知'}</p>
170 <p><strong>片长:</strong>{seed.duration || '未知'}</p>
171 <p><strong>地区:</strong>{seed.region || '未知'}</p>
172 <p><strong>下载次数:</strong>{seed.downloads ?? 0}</p>
173 </div>
174 {(seed.category === '电影' || seed.category === '电视剧') && (
175 <div className="seed-media-info">
176 <p><strong>导演:</strong>{seed.director || '未知'}</p>
177 <p><strong>编剧:</strong>{seed.writer || '未知'}</p>
178 <p><strong>主演:</strong>{actors.join(' / ')}</p>
179 </div>
180 )}
181 </div>
182 <img
183 src={coverImage || '/default-cover.png'}
184 alt={seed.title}
185 className="cover-image"
186 />
187 </div>
188 <div className="action-buttons">
189 <button className="btn" onClick={() => handleDownload(seed.id)}>下载</button>
190 <button className="btn" onClick={handleCollect}>收藏</button>
191 </div>
192 <hr className="divider" />
193 <h3>评论区</h3>
194 <div className="comments-section">
195 <div className="comments-list">
196 {comments.map((comment, index) => (
197 <div key={index} className="comment">
198 <p className="comment-user">{comment.user}</p>
199 <p className="comment-content">{comment.content}</p>
200 </div>
201 ))}
202 </div>
203 <div className="add-comment-form">
204 <textarea
205 placeholder="输入你的评论..."
206 value={newComment}
207 onChange={(e) => setNewComment(e.target.value)}
208 />
209 <div className="comment-options">
210 <button className="btn" onClick={handleAddComment}>发布评论</button>
211 </div>
212 </div>
213 </div>
214 </div>
215 </div>
216 );
223010095b28c672025-04-10 20:12:45 +0800217};
218
219export default SeedDetail;