修复种子详情下载

Change-Id: I5673279933d639e1bf425fcaea3eabd447625bfc
diff --git a/src/pages/SeedList/SeedDetail/SeedDetail.css b/src/pages/SeedList/SeedDetail/SeedDetail.css
index 594cb8e..9e1a10e 100644
--- a/src/pages/SeedList/SeedDetail/SeedDetail.css
+++ b/src/pages/SeedList/SeedDetail/SeedDetail.css
@@ -1,29 +1,35 @@
 .seed-detail-page {
   background: #333;
+  min-height: 100vh;
+  padding-bottom: 40px;
   font-family: 'Helvetica Neue', sans-serif;
   color: #333;
 }
 
 .seed-detail {
-  background-color: #e9ded2;
+  background-color: #fff9f3;
   border-radius: 16px;
   max-width: 960px;
-  margin: 0 auto;
-  margin-top: 40px;
-  padding: 24px 32px;
+  margin: 40px auto 0;
+  padding: 32px;
+  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
 }
 
 .seed-detail h1 {
-  font-size: 24px;
-  font-weight: bold;
-  margin-bottom: 16px;
-  color: #4A3B34;
+  font-size: 28px;
+  font-weight: 700;
+  margin-bottom: 24px;
+  color: #3d2e2a;
+  border-left: 4px solid #ba929a;
+  padding-left: 12px;
 }
 
 .seed-header-container {
   display: flex;
   justify-content: space-between;
   align-items: flex-start;
+  gap: 32px;
+  flex-wrap: wrap;
 }
 
 .seed-info {
@@ -33,89 +39,86 @@
 .seed-basic-info p,
 .seed-media-info p {
   font-size: 16px;
+  line-height: 1.6;
   margin: 6px 0;
+  color: #4a3b34;
 }
 
-.cover-image {
-  width: 200px;
+/* .cover-image {
+  width: 240px;
   height: auto;
-  margin-left: 20px;
-  border-radius: 8px;
+  border-radius: 12px;
+  object-fit: cover;
+  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
+} */
+ .cover-image {
+  max-width: 100%;
+  width: 240px;
+  max-height: 320px;
+  height: auto;
+  border-radius: 12px;
+  object-fit: contain; /* 从 cover 改为 contain */
+  background-color: #f6eae3; /* 给 contain 留白背景 */
+  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
 }
 
-.comment-options {
-  margin-top: 8px;
-  display: flex;
-  justify-content: flex-end; /* 将 space-between 改为 flex-end */
-}
 
 .action-buttons {
-  justify-content: flex-end; /*靠右对齐*/
+  margin-top: 24px;
   display: flex;
-  gap: 10px;
-  margin-bottom: 20px;
+  justify-content: flex-end;
+  gap: 12px;
+}
+
+.btn, .btn-outline {
+  padding: 10px 18px;
+  font-size: 15px;
+  border-radius: 8px;
+  font-weight: 500;
+  cursor: pointer;
+  transition: all 0.2s ease-in-out;
 }
 
 .btn {
-  justify-content: flex-end; /*靠右对齐*/
-  padding: 6px 14px;
-  background-color: #BA929A;
-  color: #fff;
+  background-color: #ba929a;
+  color: white;
   border: none;
-  border-radius: 6px;
-  font-size: 14px;
-  cursor: pointer;
 }
 
 .btn:hover {
-  background-color: #5F4437;
+  background-color: #5f4437;
 }
 
-.comments-section {
-  margin-top: 20px;
+.btn-outline {
+  background-color: transparent;
+  color: #5f4437;
+  border: 2px solid #5f4437;
 }
 
-.comments-section h3 {
-  margin-bottom: 10px;
-  font-size: 20px;
-  color: #4A3B34;
-}
-
-.comments-list {
-  border-top: 1px solid #ccc;
-  padding-top: 10px;
-}
-
-.comment {
-  border-bottom: 1px solid #ccc;
-  padding: 10px 0;
-}
-
-.comment-user {
-  font-weight: bold;
-  margin-bottom: 5px;
-}
-
-.comment-content {
-  margin: 0;
-}
-
-.add-comment-form {
-  margin-top: 10px;
-}
-
-.add-comment-form textarea {
-  width: 100%;
-  padding: 10px;
-  resize: vertical;
-  min-height: 80px;
-  border: 1px solid #bbb;
-  border-radius: 6px;
-  margin-bottom: 10px;
+.btn-outline:hover {
+  background-color: #f6eae3;
 }
 
 .error-text {
-  color: #f00;
+  color: #e74c3c;
+  font-size: 18px;
   text-align: center;
+  margin-top: 60px;
 }
-  
\ No newline at end of file
+
+@media (max-width: 768px) {
+  .seed-header-container {
+    flex-direction: column;
+    align-items: center;
+  }
+
+  .cover-image {
+    width: 100%;
+    max-width: 320px;
+    margin-top: 20px;
+  }
+
+  .action-buttons {
+    justify-content: center;
+  }
+}
diff --git a/src/pages/SeedList/SeedDetail/SeedDetail.jsx b/src/pages/SeedList/SeedDetail/SeedDetail.jsx
index 16c6d01..0cb738c 100644
--- a/src/pages/SeedList/SeedDetail/SeedDetail.jsx
+++ b/src/pages/SeedList/SeedDetail/SeedDetail.jsx
@@ -5,7 +5,6 @@
 import './SeedDetail.css';
 import { useUser } from '../../../context/UserContext';
 
-
 const SeedDetail = () => {
   const params = useParams();
   const seed_id = params.id;
@@ -18,8 +17,6 @@
 
   const { user } = useUser();
 
-
-  // 格式化图片 URL
   const formatImageUrl = (url) => {
     if (!url) return '';
     const filename = url.split('/').pop();
@@ -37,8 +34,6 @@
         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
@@ -76,42 +71,76 @@
     fetchComments();
   }, [seed_id]);
 
- const handleDownload = async (seedId) => {
-        if (!user || !user.userId) {
-            alert('请先登录再下载种子文件');
-            return;
-        }
+  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'
-            });
+    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 = () => {
-    alert('已收藏');
+      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 handleAddComment = () => {
+  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()) {
-      setComments([...comments, { content: newComment, user: '用户' }]);
-      setNewComment('');
+      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('评论失败,请稍后重试');
+      }
     }
   };
 
@@ -137,20 +166,16 @@
     );
   }
 
-  const tags = seed.tags
-    ? Array.isArray(seed.tags)
-      ? seed.tags
-      : typeof seed.tags === 'string'
-      ? seed.tags.split(',').map((t) => t.trim())
-      : []
+  const tags = Array.isArray(seed.tags)
+    ? seed.tags
+    : typeof seed.tags === 'string'
+    ? seed.tags.split(',').map((t) => t.trim())
     : [];
 
-  const actors = seed.actors
-    ? Array.isArray(seed.actors)
-      ? seed.actors
-      : typeof seed.actors === 'string'
-      ? seed.actors.split(',').map((a) => a.trim())
-      : []
+  const actors = Array.isArray(seed.actors)
+    ? seed.actors
+    : typeof seed.actors === 'string'
+    ? seed.actors.split(',').map((a) => a.trim())
     : [];
 
   return (
@@ -185,20 +210,26 @@
             className="cover-image"
           />
         </div>
+
         <div className="action-buttons">
           <button className="btn" onClick={() => handleDownload(seed.id)}>下载</button>
-          <button className="btn" onClick={handleCollect}>收藏</button>
+          <button className="btn-outline" onClick={handleCollect}>收藏</button>
         </div>
+
         <hr className="divider" />
         <h3>评论区</h3>
         <div className="comments-section">
           <div className="comments-list">
-            {comments.map((comment, index) => (
-              <div key={index} className="comment">
-                <p className="comment-user">{comment.user}</p>
-                <p className="comment-content">{comment.content}</p>
-              </div>
-            ))}
+            {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