| import React, { useEffect, useState } from 'react'; |
| import axios from 'axios'; |
| import { useParams } from 'wouter'; |
| import Header from '../../../components/Header'; |
| import './SeedDetail.css'; |
| import { useUser } from '../../../context/UserContext'; |
| import SeedRating from './SeedRating'; |
| import AuthButton from '../../../components/AuthButton'; |
| |
| const SeedDetail = () => { |
| const params = useParams(); |
| const seed_id = params.id; |
| |
| const [seed, setSeed] = useState(null); |
| const [coverImage, setCoverImage] = useState(null); |
| const [error, setError] = useState(null); |
| const [comments, setComments] = useState([]); |
| const [newComment, setNewComment] = useState(''); |
| |
| const { user } = useUser(); |
| |
| const formatImageUrl = (url) => { |
| if (!url) return ''; |
| const filename = url.split('/').pop(); |
| return `http://localhost:5011/uploads/torrents/${filename}`; |
| }; |
| |
| useEffect(() => { |
| if (!seed_id) { |
| setError('无效的种子ID'); |
| return; |
| } |
| |
| const fetchSeedDetail = async () => { |
| try { |
| const res = await axios.post(`/seeds/info/${seed_id}`); |
| if (res.data.code === 0) { |
| const seedData = res.data.data; |
| let cover = seedData.imageUrl; |
| if (!cover && seedData.imgUrl) { |
| const imgs = seedData.imgUrl |
| .split(',') |
| .map((i) => i.trim()) |
| .filter(Boolean); |
| cover = imgs.length > 0 ? formatImageUrl(imgs[0]) : null; |
| } |
| setCoverImage(cover); |
| setSeed(seedData); |
| setError(null); |
| } else { |
| setError('未能获取种子信息'); |
| } |
| } catch (err) { |
| console.error('请求种子详情出错:', err); |
| setError('获取种子详情失败'); |
| } |
| }; |
| |
| const fetchComments = async () => { |
| try { |
| const res = await axios.get(`/seeds/${seed_id}/comments`); |
| if (res.data.code === 0) { |
| setComments(res.data.data || []); |
| } else { |
| setComments([]); |
| } |
| } catch { |
| setComments([]); |
| } |
| }; |
| |
| fetchSeedDetail(); |
| fetchComments(); |
| }, [seed_id]); |
| |
| const handleDownload = async (seedId) => { |
| if (!user || !user.userId) { |
| alert('请先登录再下载种子文件'); |
| return; |
| } |
| |
| try { |
| const response = await axios.get(`/seeds/${seedId}/download`, { |
| params: { passkey: user.userId }, |
| responseType: 'blob', |
| }); |
| |
| const blob = new Blob([response.data], { type: 'application/x-bittorrent' }); |
| const downloadUrl = URL.createObjectURL(blob); |
| const a = document.createElement('a'); |
| a.href = downloadUrl; |
| a.download = `${seedId}.torrent`; |
| a.click(); |
| URL.revokeObjectURL(downloadUrl); |
| } catch (error) { |
| console.error('下载失败:', error); |
| alert('下载失败,请稍后再试。'); |
| } |
| }; |
| |
| const handleCollect = async () => { |
| if (!user || !user.userId) { |
| alert('请先登录再收藏'); |
| return; |
| } |
| |
| try { |
| const res = await axios.post(`/seeds/${seed.id}/favorite-toggle`, null, { |
| params: { user_id: user.userId }, |
| }); |
| |
| if (res.data.code === 0) { |
| alert('操作成功'); |
| } else { |
| alert(res.data.msg || '操作失败'); |
| } |
| } catch (err) { |
| console.error('收藏失败:', err); |
| alert('收藏失败,请稍后再试。'); |
| } |
| }; |
| |
| const handleAddComment = async () => { |
| if (!user || !user.userId) { |
| alert('请登录后发表评论'); |
| return; |
| } |
| |
| if (newComment.trim()) { |
| try { |
| const res = await axios.post(`/seeds/${seed_id}/comments`, { |
| user_id: user.userId, |
| content: newComment, |
| }); |
| |
| if (res.data.code === 0) { |
| setComments([...comments, { content: newComment, user: user.username || '匿名用户' }]); |
| setNewComment(''); |
| } else { |
| alert(res.data.msg || '评论失败'); |
| } |
| } catch (err) { |
| console.error('评论提交失败:', err); |
| alert('评论失败,请稍后重试'); |
| } |
| } |
| }; |
| |
| if (error) { |
| return ( |
| <div className="seed-detail-page"> |
| <Header /> |
| <div className="seed-detail"> |
| <p className="error-text">{error}</p> |
| </div> |
| </div> |
| ); |
| } |
| |
| if (!seed) { |
| return ( |
| <div className="seed-detail-page"> |
| <Header /> |
| <div className="seed-detail"> |
| <p>加载中...</p> |
| </div> |
| </div> |
| ); |
| } |
| |
| const tags = Array.isArray(seed.tags) |
| ? seed.tags |
| : typeof seed.tags === 'string' |
| ? seed.tags.split(',').map((t) => t.trim()) |
| : []; |
| |
| const actors = Array.isArray(seed.actors) |
| ? seed.actors |
| : typeof seed.actors === 'string' |
| ? seed.actors.split(',').map((a) => a.trim()) |
| : []; |
| |
| return ( |
| <div className="seed-detail-page"> |
| <Header /> |
| <div className="seed-detail"> |
| <h1>{seed.title}</h1> |
| <div className="seed-header-container"> |
| <div className="seed-info"> |
| <div className="seed-basic-info"> |
| <p><strong>分类:</strong>{seed.category || '未知'}</p> |
| <p><strong>发布时间:</strong>{seed.upload_time ? new Date(seed.upload_time).toLocaleString() : '未知'}</p> |
| <p><strong>标签:</strong>{tags.join(' / ')}</p> |
| <p><strong>简介:</strong>{seed.description || '无'}</p> |
| <p><strong>大小:</strong>{seed.size || '未知'}</p> |
| <p><strong>分辨率:</strong>{seed.resolution || '未知'}</p> |
| <p><strong>片长:</strong>{seed.duration || '未知'}</p> |
| <p><strong>地区:</strong>{seed.region || '未知'}</p> |
| <p><strong>下载次数:</strong>{seed.downloads ?? 0}</p> |
| </div> |
| {(seed.category === '电影' || seed.category === '电视剧') && ( |
| <div className="seed-media-info"> |
| <p><strong>导演:</strong>{seed.director || '未知'}</p> |
| <p><strong>编剧:</strong>{seed.writer || '未知'}</p> |
| <p><strong>主演:</strong>{actors.join(' / ')}</p> |
| </div> |
| )} |
| </div> |
| <img |
| src={coverImage || '/default-cover.png'} |
| alt={seed.title} |
| className="cover-image" |
| /> |
| </div> |
| |
| <div className="action-buttons"> |
| <AuthButton roles={["cookie", "chocolate", "ice-cream"]} onClick={() => handleDownload(seed.id)}> |
| 下载 |
| </AuthButton> |
| <AuthButton roles={["cookie", "chocolate", "ice-cream"]} onClick={handleCollect}> |
| 收藏 |
| </AuthButton> |
| <SeedRating seedId={seed.id} /> |
| </div> |
| |
| |
| <hr className="divider" /> |
| <h3>评论区</h3> |
| <div className="comments-section"> |
| <div className="comments-list"> |
| {comments.length === 0 ? ( |
| <p className="no-comments">暂无评论</p> |
| ) : ( |
| comments.map((comment, index) => ( |
| <div key={index} className="comment"> |
| <p className="comment-user">{comment.user}</p> |
| <p className="comment-content">{comment.content}</p> |
| </div> |
| )) |
| )} |
| </div> |
| <div className="add-comment-form"> |
| <textarea |
| placeholder="输入你的评论..." |
| value={newComment} |
| onChange={(e) => setNewComment(e.target.value)} |
| /> |
| <div className="comment-options"> |
| <button className="btn" onClick={handleAddComment}>发布评论</button> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| ); |
| }; |
| |
| export default SeedDetail; |