create-seed-detail

Change-Id: I7dcce81a7510b6fa97781d3ce509a8dc2ac229d4
diff --git a/src/pages/SeedList/SeedList.jsx b/src/pages/SeedList/SeedList.jsx
index 3519f17..f32224e 100644
--- a/src/pages/SeedList/SeedList.jsx
+++ b/src/pages/SeedList/SeedList.jsx
@@ -1,246 +1,3 @@
-// import React, { useState, useEffect } from 'react';
-// import { Link } from 'wouter';
-// import axios from 'axios';
-// import logo from '../../assets/logo.png';
-// import Recommend from './Recommend/Recommend';
-// import './SeedList.css';
-
-// const API_BASE = process.env.REACT_APP_API_BASE;
-
-// const SeedList = () => {
-//     const [seeds, setSeeds] = useState([]);
-//     const [filteredSeeds, setFilteredSeeds] = useState([]);
-//     const [loading, setLoading] = useState(true);
-//     const [searchTerm, setSearchTerm] = useState('');
-//     const [sortOption, setSortOption] = useState('最新');
-//     const [activeTab, setActiveTab] = useState('种子列表');
-
-//     const [filters, setFilters] = useState({});
-//     const [selectedFilters, setSelectedFilters] = useState({});
-
-//     const TAGS = ['猜你喜欢', '电影', '电视剧', '动漫', '音乐', '游戏', '综艺', '软件', '体育', '学习', '纪录片', '其他'];
-
-//     const CATEGORY_MAP = {
-//         '电影': 'movie',
-//         '电视剧': 'tv',
-//         '动漫': 'anime',
-//         '音乐': 'music',
-//         '游戏': 'game',
-//         '综艺': 'variety',
-//         '软件': 'software',
-//         '体育': 'sports',
-//         '学习': 'study',
-//         '纪录片': 'documentary',
-//         '其他': 'other'
-//     };
-
-//     const buildQueryParams = () => {
-//         const category = CATEGORY_MAP[activeTab];
-
-//         const params = {
-//             category,
-//             sort_by: sortOption === '最新' ? 'newest'
-//                     : sortOption === '最热' ? 'downloads'
-//                     : undefined,
-//             page: 1,
-//             limit: 20,
-//         };
-
-//         const tags = Object.entries(selectedFilters)
-//             .filter(([_, value]) => value !== '不限')
-//             .map(([_, value]) => value);
-
-//         if (tags.length > 0) params.tags = tags.join(',');
-
-//         return params;
-//     };
-
-//     const fetchSeeds = async () => {
-//         setLoading(true);
-//         try {
-//             const params = buildQueryParams();
-//             const queryString = new URLSearchParams(params).toString();
-//             const response = await fetch(`${API_BASE}/echo/seeds?${queryString}`);
-//             const data = await response.json();
-//             const seeds = data?.seeds || [];
-//             setSeeds(seeds);
-//             setFilteredSeeds(seeds);
-//         } catch (error) {
-//             console.error('获取种子列表失败:', error);
-//         } finally {
-//             setLoading(false);
-//         }
-//     };
-
-//     const fetchFilterOptions = async () => {
-//         if (activeTab === '猜你喜欢') return;
-//         const category = CATEGORY_MAP[activeTab];
-//         try {
-//             const res = await axios.get(`${API_BASE}/echo/seed-filters?category=${category}`);
-//             setFilters(res.data || {});
-//             const defaultSelections = {};
-//             for (const key in res.data) {
-//                 defaultSelections[key] = '不限';
-//             }
-//             setSelectedFilters(defaultSelections);
-//         } catch (err) {
-//             console.error('获取筛选项失败:', err);
-//             setFilters({});
-//             setSelectedFilters({});
-//         }
-//     };
-
-//     useEffect(() => {
-//         if (activeTab !== '猜你喜欢') {
-//             fetchFilterOptions();
-//         }
-//     }, [activeTab]);
-
-//     useEffect(() => {
-//         if (activeTab !== '猜你喜欢') {
-//             fetchSeeds();
-//         }
-//     }, [activeTab, sortOption, selectedFilters]);
-
-//     const handleDownload = async (seedId) => {
-//         const peer_id = 'echo-' + Math.random().toString(36).substring(2, 10);
-//         const ip = '127.0.0.1';
-//         const port = 6881;
-//         const uploaded = 0;
-//         const downloaded = 0;
-//         const left = 0;
-
-//         try {
-//             const response = await axios.get(`${API_BASE}/echo/seeds/${seedId}/download`, {
-//                 params: {
-//                     peer_id,
-//                     ip,
-//                     port,
-//                     uploaded,
-//                     downloaded,
-//                     left,
-//                 },
-//                 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('下载失败,请稍后再试。');
-//         }
-//     };
-
-//     return (
-//         <div className="main-page">
-//             <header className="header">
-//                 <div className="logo-and-name">
-//                     <img src={logo} alt="网站logo" className="logo" />
-//                     <span className="site-name">Echo</span>
-//                 </div>
-//                 <div className="user-and-message">
-//                     <img src="user-avatar.png" alt="用户头像" className="user-avatar" />
-//                     <span className="message-center">消息</span>
-//                 </div>
-//             </header>
-
-//             <nav className="nav">
-//                 <Link to="/friend-moments" className="nav-item">好友动态</Link>
-//                 <Link to="/forum" className="nav-item">论坛</Link>
-//                 <Link to="/interest-groups" className="nav-item">兴趣小组</Link>
-//                 <Link to="/seed-list" className="nav-item active">种子列表</Link>
-//                 <Link to="/publish-seed" className="nav-item">发布种子</Link>
-//             </nav>
-
-//             <div className="controls">
-//                 <input
-//                     type="text"
-//                     placeholder="搜索种子..."
-//                     value={searchTerm}
-//                     onChange={(e) => setSearchTerm(e.target.value)}
-//                     className="search-input"
-//                 />
-//                 <select value={sortOption} onChange={(e) => setSortOption(e.target.value)} className="sort-select">
-//                     <option value="最新">最新</option>
-//                     <option value="最热">最热</option>
-//                 </select>
-//             </div>
-
-//             <div className="tag-filters">
-//                 {TAGS.map((tag) => (
-//                     <button
-//                         key={tag}
-//                         className={`tag-button ${activeTab === tag ? 'active-tag' : ''}`}
-//                         onClick={() => {
-//                             setActiveTab(tag);
-//                             setFilters({});
-//                             setSelectedFilters({});
-//                         }}
-//                     >
-//                         {tag}
-//                     </button>
-//                 ))}
-//             </div>
-
-//             {activeTab !== '猜你喜欢' && Object.keys(filters).length > 0 && (
-//                 <div className="filter-bar">
-//                     {Object.entries(filters).map(([key, options]) => (
-//                         <div className="filter-group" key={key}>
-//                             <label>{key}:</label>
-//                             <select
-//                                 value={selectedFilters[key]}
-//                                 onChange={(e) =>
-//                                     setSelectedFilters({ ...selectedFilters, [key]: e.target.value })
-//                                 }
-//                             >
-//                                 {options.map((opt) => (
-//                                     <option key={opt} value={opt}>{opt}</option>
-//                                 ))}
-//                             </select>
-//                         </div>
-//                     ))}
-//                 </div>
-//             )}
-
-//             <div className="seed-list-content">
-//                 {activeTab === '猜你喜欢' ? (
-//                     <Recommend />
-//                 ) : loading ? (
-//                     <p>加载中...</p>
-//                 ) : filteredSeeds.length === 0 ? (
-//                     <p>未找到符合条件的种子。</p>
-//                 ) : (
-//                     <div className="seed-cards">
-//                         {filteredSeeds.map((seed, index) => (
-//                             <div key={index} className="seed-card">
-//                                 <div className="seed-card-header">
-//                                     <h3>{seed.title}</h3>
-//                                 </div>
-//                                 <div className="seed-card-body">
-//                                     <p><strong>大小:</strong> {seed.size || '未知'} GB</p>
-//                                     <p><strong>时间:</strong> {seed.upload_time?.split('T')[0] || '未知'}</p>
-//                                     <p><strong>下载数:</strong> {seed.downloads ?? 0}</p>
-//                                 </div>
-//                                 <div className="seed-card-actions">
-//                                     <button className="btn-primary" onClick={() => handleDownload(seed.seed_id)}>下载</button>
-//                                     <Link href={`/seed/${seed.seed_id}`} className="btn-secondary">详情</Link>
-//                                     <button className="btn-outline">收藏</button>
-//                                 </div>
-//                             </div>
-//                         ))}
-//                     </div>
-//                 )}
-//             </div>
-//         </div>
-//     );
-// };
-
-// export default SeedList;
 import React, { useState, useEffect } from 'react';
 import { Link } from 'wouter';
 import axios from 'axios';
@@ -259,7 +16,7 @@
     const [activeTab, setActiveTab] = useState('种子列表');
     const [filters, setFilters] = useState({});
     const [selectedFilters, setSelectedFilters] = useState({});
-    const [tagMode, setTagMode] = useState('all'); // 支持 tag_mode 参数
+    const [tagMode, setTagMode] = useState('all');
     const [errorMsg, setErrorMsg] = useState('');
 
     const TAGS = ['猜你喜欢', '电影', '电视剧', '动漫', '音乐', '游戏', '综艺', '软件', '体育', '学习', '纪录片', '其他'];
@@ -285,12 +42,10 @@
             sort_by: sortOption === '最新' ? 'newest' : sortOption === '最热' ? 'downloads' : undefined,
             page: 1,
             limit: 20,
-            include_fields: 'seed_id,title,category,tags,size,upload_time,downloads',
+            include_fields: 'seed_id,title,category,tags,size,upload_time,downloads,image_url',
         };
 
-        if (searchTerm.trim()) {
-            params.search = searchTerm.trim();
-        }
+        if (searchTerm.trim()) params.search = searchTerm.trim();
 
         const tags = Object.entries(selectedFilters)
             .filter(([_, value]) => value !== '不限')
@@ -332,9 +87,11 @@
         const category = CATEGORY_MAP[activeTab];
         try {
             const res = await axios.get(`${API_BASE}/echo/seed-filters?category=${category}`);
-            setFilters(res.data || {});
+            const filterData = res.data || {};
+            setFilters(filterData);
+
             const defaultSelections = {};
-            for (const key in res.data) {
+            for (const key in filterData) {
                 defaultSelections[key] = '不限';
             }
             setSelectedFilters(defaultSelections);
@@ -384,6 +141,20 @@
         }
     };
 
+    const handleFilterChange = (key, value) => {
+        setSelectedFilters((prev) => ({
+            ...prev,
+            [key]: value
+        }));
+    };
+
+    const clearFilter = (key) => {
+        setSelectedFilters((prev) => ({
+            ...prev,
+            [key]: '不限'
+        }));
+    };
+
     return (
         <div className="main-page">
             <header className="header">
@@ -446,14 +217,15 @@
                             <label>{key}:</label>
                             <select
                                 value={selectedFilters[key]}
-                                onChange={(e) =>
-                                    setSelectedFilters({ ...selectedFilters, [key]: e.target.value })
-                                }
+                                onChange={(e) => handleFilterChange(key, e.target.value)}
                             >
                                 {options.map((opt) => (
                                     <option key={opt} value={opt}>{opt}</option>
                                 ))}
                             </select>
+                            {selectedFilters[key] !== '不限' && (
+                                <button className="clear-filter-btn" onClick={() => clearFilter(key)}>✕</button>
+                            )}
                         </div>
                     ))}
                 </div>
@@ -472,14 +244,28 @@
                     <div className="seed-cards">
                         {filteredSeeds.map((seed, index) => (
                             <div key={index} className="seed-card">
+                                {seed.image_url && (
+                                    <img src={seed.image_url} alt={seed.title} className="seed-cover" />
+                                )}
                                 <div className="seed-card-header">
                                     <h3>{seed.title}</h3>
                                 </div>
+
                                 <div className="seed-card-body">
-                                    <p><strong>大小:</strong> {seed.size || '未知'} GB</p>
-                                    <p><strong>时间:</strong> {seed.upload_time?.split('T')[0] || '未知'}</p>
-                                    <p><strong>下载数:</strong> {seed.downloads ?? 0}</p>
+                                    <div className="seed-info">
+                                        <span>{seed.size || '未知'} GB</span>
+                                        <span>{seed.upload_time?.split('T')[0] || '未知'}</span>
+                                        <span>{seed.downloads ?? 0} 次下载</span>
+                                    </div>
+                                    {seed.tags && seed.tags.length > 0 && (
+                                        <div className="seed-card-tags">
+                                            {seed.tags.map((tag, i) => (
+                                                <span key={i} className="tag-label">{tag}</span>
+                                            ))}
+                                        </div>
+                                    )}
                                 </div>
+
                                 <div className="seed-card-actions">
                                     <button className="btn-primary" onClick={() => handleDownload(seed.seed_id)}>下载</button>
                                     <Link href={`/seed/${seed.seed_id}`} className="btn-secondary">详情</Link>