修改种子列表
Change-Id: I1f9d57092ca3ae2381da2b8dd137e2743782642d
diff --git a/src/pages/Forum/posts-main/components/PostList.jsx b/src/pages/Forum/posts-main/components/PostList.jsx
index 25b08a8..676ec45 100644
--- a/src/pages/Forum/posts-main/components/PostList.jsx
+++ b/src/pages/Forum/posts-main/components/PostList.jsx
@@ -163,171 +163,4 @@
);
};
-export default PostList;
-
-// import React, { useEffect, useState } from 'react';
-// import axios from 'axios';
-// import { Link } from 'wouter';
-// import { GoodTwo, Comment, Star } from '@icon-park/react';
-// import { likePost, unlikePost, collectPost } from '../../posts-detail/api';
-// import './PostList.css';
-
-// const API_BASE = process.env.REACT_APP_API_BASE;
-
-// const PostList = ({ search }) => {
-// const [posts, setPosts] = useState([]);
-// const [page, setPage] = useState(1);
-// const [total, setTotal] = useState(0);
-// const [loading, setLoading] = useState(true);
-// const [errorMsg, setErrorMsg] = useState('');
-
-// const size = 10; // 每页条数
-// const totalPages = Math.ceil(total / size);
-
-// useEffect(() => {
-// const fetchPosts = async () => {
-// setLoading(true);
-// setErrorMsg('');
-// try {
-// const res = await axios.get(`${API_BASE}/echo/forum/posts`, {
-// params: {
-// page: page,
-// pageSize: size,
-// sortBy: 'createdAt', // 按时间排序
-// order: 'desc' // 按降序排序
-// }
-// });
-
-// const postsData = res.data.posts || [];
-// const userIds = [...new Set(postsData.map(p => p.user_id))];
-
-// // 获取用户信息
-// const profiles = await Promise.all(userIds.map(async id => {
-// try {
-// const r = await axios.get(`${API_BASE}/echo/user/profile`, {
-// params: { user_id: id }
-// });
-// return { id, profile: r.data };
-// } catch {
-// return { id, profile: { nickname: '未知用户', avatar_url: 'default-avatar.png' } };
-// }
-// }));
-
-// const userMap = {};
-// profiles.forEach(({ id, profile }) => { userMap[id] = profile; });
-
-// // 更新帖子数据
-// const postsWithProfiles = postsData
-// .filter(post => post.title.includes(search))
-// .map(post => ({
-// ...post,
-// userProfile: userMap[post.user_id] || {}
-// }));
-
-// setPosts(postsWithProfiles);
-// setTotal(res.data.total || 0);
-// } catch (err) {
-// console.error('加载失败:', err);
-// setErrorMsg('加载失败,请稍后重试');
-// } finally {
-// setLoading(false);
-// }
-// };
-
-// fetchPosts();
-// }, [page, search]);
-
-// // 点赞/取消点赞操作
-// const toggleLike = async (postId, liked, userId) => {
-// try {
-// if (liked) {
-// await unlikePost(postId); // 取消点赞
-// } else {
-// await likePost(postId, userId); // 点赞
-// }
-
-// setPosts(posts =>
-// posts.map(post =>
-// post.id === postId
-// ? { ...post, liked: !liked, likeCount: liked ? post.likeCount - 1 : post.likeCount + 1 }
-// : post
-// )
-// );
-// } catch (err) {
-// console.error('点赞失败:', err);
-// }
-// };
-
-// // 收藏/取消收藏操作
-// const toggleCollect = async (postId, collected, userId) => {
-// try {
-// const action = collected ? 'cancel' : 'collect';
-// await collectPost(postId, userId, action);
-
-// setPosts(posts =>
-// posts.map(post =>
-// post.id === postId
-// ? { ...post, collected: !collected, collectCount: collected ? post.collectCount - 1 : post.collectCount + 1 }
-// : post
-// )
-// );
-// } catch (err) {
-// console.error('收藏失败:', err);
-// }
-// };
-// return (
-// <div className="post-list">
-// {loading ? <p>加载中...</p> :
-// errorMsg ? <p className="error-text">{errorMsg}</p> :
-// posts.length === 0 ? <p>暂无帖子。</p> :
-// posts.map(post => (
-// <Link
-// key={post.id}
-// href={`/forum/post/${post.id}`}
-// className="post-card"
-// style={{ backgroundColor: '#e9ded2' }}
-// >
-// <div className="user-info">
-// <img className="avatar" src={post.userProfile.avatar_url} alt="头像" />
-// <span className="nickname" style={ { color: '#755e50' } }>{post.userProfile.nickname}</span>
-// </div>
-// {post.cover_image_url && (
-// <img className="cover-image" src={post.cover_image_url} alt="封面" />
-// )}
-// <h3 style={ { color: '#000000' } }>{post.title}</h3>
-// <p className="post-meta">
-// 发布时间:{new Date(post.createdAt).toLocaleString()}
-// </p>
-// <div className="post-actions">
-// {/* 点赞按钮 */}
-// <button className="icon-btn" onClick={(e) => { e.stopPropagation(); toggleLike(post.id, post.liked, post.user_id); }}>
-// <GoodTwo theme="outline" size="24" fill={post.liked ? '#f00' : '#fff'} />
-// <span>{post.likeCount}</span>
-// </button>
-
-// {/* 收藏按钮 */}
-// <button className="icon-btn" onClick={(e) => { e.stopPropagation(); toggleCollect(post.id, post.collected, post.user_id); }}>
-// <Star theme="outline" size="24" fill={post.collected ? '#ffd700' : '#fff'} />
-// <span>{post.collectCount}</span>
-// </button>
-
-// <Link href={`/forum/post/${post.id}`} className="icon-btn" onClick={(e) => e.stopPropagation()}>
-// <Comment theme="outline" size="24" fill="#fff" />
-// <span>{post.commentCount}</span>
-// </Link>
-// </div>
-// </Link>
-// ))
-// }
-
-// <div className="pagination">
-// <button disabled={page === 1} onClick={() => setPage(page - 1)}>上一页</button>
-// <span>第 {page} 页 / 共 {totalPages} 页</span>
-// <button disabled={page === totalPages} onClick={() => setPage(page + 1)}>下一页</button>
-// </div>
-// </div>
-// );
-
-// };
-
-// export default PostList;
+export default PostList;
\ No newline at end of file
diff --git a/src/pages/ForumPage.css b/src/pages/ForumPage.css
deleted file mode 100644
index 72469e2..0000000
--- a/src/pages/ForumPage.css
+++ /dev/null
@@ -1,28 +0,0 @@
-/* .forum-container {
- padding: 20px;
- background-color: #c13a3a;
- }
-
- .forum-post {
- margin-bottom: 20px;
- padding: 15px;
- background-color: #06e7b6;
- border: 1px solid #a70dc2;
- border-radius: 5px;
- }
-
- .forum-post h2 {
- margin: 0 0 10px;
- }
-
- .forum-post img {
- max-width: 100%;
- height: auto;
- margin-top: 10px;
- }
-
- .forum-comment {
- padding: 10px;
- background-color: #9ae815;
- border-radius: 5px;
- } */
\ No newline at end of file
diff --git a/src/pages/ForumPage.jsx b/src/pages/ForumPage.jsx
deleted file mode 100644
index 4e63170..0000000
--- a/src/pages/ForumPage.jsx
+++ /dev/null
@@ -1,19 +0,0 @@
-// import React from 'react';
-// import './ForumPage.css';
-
-// const ForumPage = () => {
-// return (
-// <div className="forum-container">
-// <h1>论坛</h1>
-// <div className="forum-post">
-// <h2>示例帖子标题</h2>
-// <p>这是一个示例帖子内容,用于测试论坛页面的显示效果。</p>
-// </div>
-// <div className="forum-comment">
-// <p>示例评论内容:这是一条测试评论。</p>
-// </div>
-// </div>
-// );
-// };
-
-// export default ForumPage;
\ No newline at end of file
diff --git a/src/pages/SeedList/SeedList.css b/src/pages/SeedList/SeedList.css
index 028ef55..94c70aa 100644
--- a/src/pages/SeedList/SeedList.css
+++ b/src/pages/SeedList/SeedList.css
@@ -1,185 +1,239 @@
-.main-page {
- background-color: #5c3f31;
- color: white;
-}
+
+ .main-page {
+ background-color: #5c3f31;
+ color: white;
+ }
+
+ /* 搜索、排序控件 */
+ .controls {
+ display: flex;
+ justify-content: center;
+ gap: 16px;
+ padding: 10px 20px;
+ background-color: #5c3f31;
+ }
+
+ .search-input {
+ padding: 6px 10px;
+ border-radius: 6px;
+ border: none;
+ width: 200px;
+ }
+
+ .sort-select {
+ padding: 6px;
+ border-radius: 6px;
+ border: none;
+ }
+
+ /* 标签过滤 */
+ .tag-filters {
+ background-color: #5c3f31;
+ display: flex;
+ justify-content: center;
+ flex-wrap: wrap;
+ gap: 8px;
+ padding: 10px;
+ }
+
+ .tag-button {
+ background-color: #b38867;
+ color: white;
+ border: none;
+ border-radius: 20px;
+ padding: 6px 12px;
+ cursor: pointer;
+ }
+
+ .active-tag {
+ background-color: #d17c4f;
+ }
+
+ .clear-filter-btn {
+ background: transparent;
+ border: none;
+ color: #888;
+ font-size: 1rem;
+ cursor: pointer;
+ margin-left: 4px;
+ }
+
+ /* 去除 Link 组件默认的下划线和文字颜色变化 */
+ .seed-item-link {
+ text-decoration: none;
+ color: inherit;
+ display: block; /* 确保整个卡片可点击 */
+ }
+
+ .clear-filter-btn:hover {
+ color: red;
+ }
+
+ /* 卡片展示 */
+ .seed-list-content {
+ padding: 20px;
+ background-color: #5c3f31;
+ }
+
+ .seed-list-card {
+ background-color: #e9ded2;
+ color: #333;
+ border-radius: 8px;
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
+ overflow: hidden;
+ }
+
+ .seed-list-header {
+ display: grid;
+ grid-template-columns: 180px 2fr 1fr 1fr 1fr 1fr;
+ align-items: center;
+ justify-items: center; /* 新增:水平居中 */
+ padding: 12px 16px;
+ background-color: #BA929A;
+ font-weight: bold;
+ }
+
+ .seed-list-body {
+ display: flex;
+ flex-direction: column;
+ }
+
+ .seed-item {
+ display: grid;
+ grid-template-columns: 180px 2fr 1fr 1fr 1fr 1fr;
+ align-items: center;
+ justify-items: center; /* 新增:水平居中 */
+ padding: 12px 16px;
+ border-top: 1px solid #ccc;
+ }
+
+ .seed-item-cover {
+ margin-left: -50px;
+ width: 100px;
+ height: 140px;
+ object-fit: cover;
+ border-radius: 6px;
+ flex-shrink: 0;
+ }
+
+ .seed-item-title {
+ width: 100%;
+ margin-left: -100px;
+ text-align: center;
+ }
+
+ .seed-title-row {
+ display: flex;
+ flex-direction: column;
+ align-items: center; /* 新增:垂直居中 */
+ gap: 8px;
+ }
+
+ .seed-title {
+ font-size: 1.1rem;
+ margin: 0;
+ font-weight: bold;
+ }
+
+ .seed-tags {
+ margin-top: 4px;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 4px;
+ justify-content: center; /* 标签水平居中 */
+ max-width: 100%; /* 限制最大宽度以触发换行 */
+ word-break: break-word; /* 避免长标签溢出 */
+ }
+
+
+ .seed-item-actions {
+ display: flex;
+ flex-direction: row;
+ gap: 8px;
+ justify-content: center; /* 新增:操作按钮水平居中 */
+ }
+
+ .seed-header-cover {
+ width: 180px;
+ flex-shrink: 0;
+ text-align: center;
+ }
+
+ .seed-header-title {
+ margin-left: -100px;
+ }
-/* 搜索、排序控件 */
-.controls {
- display: flex;
- justify-content: center;
- gap: 16px;
- padding: 10px 20px;
- background-color: #704c3b;
-}
-
-.search-input {
- padding: 6px 10px;
- border-radius: 6px;
- border: none;
- width: 200px;
-}
-
-.sort-select {
- padding: 6px;
- border-radius: 6px;
- border: none;
-}
-
-/* 标签过滤 */
-.tag-filters {
- display: flex;
- justify-content: center;
- flex-wrap: wrap;
- gap: 8px;
- padding: 10px;
-}
-
-.tag-button {
- background-color: #b38867;
- color: white;
- border: none;
- border-radius: 20px;
- padding: 6px 12px;
- cursor: pointer;
-}
-
-.active-tag {
- background-color: #d17c4f;
-}
-
-.clear-filter-btn {
- background: transparent;
- border: none;
- color: #888;
- font-size: 1rem;
- cursor: pointer;
- margin-left: 4px;
-}
-
-.clear-filter-btn:hover {
- color: red;
-}
-
-/* 卡片展示 */
-.seed-list-content {
- padding: 20px;
-}
-
-.seed-cards {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
- gap: 20px;
- padding: 20px 0;
-}
-
-.seed-card {
- background-color: #fff;
- border-radius: 12px;
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
- padding: 16px;
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- color: #333;
- transition: transform 0.2s ease;
-}
-
-.seed-card:hover {
- transform: translateY(-5px);
-}
-
-.seed-card-header h3 {
- font-size: 1.2rem;
- margin-bottom: 10px;
- color: #333;
- word-break: break-word;
-}
-
-.seed-card-body {
- display: flex;
- flex-direction: column;
-}
-
-.seed-info {
- display: flex;
- justify-content: space-between;
- font-size: 0.9rem;
- color: #666;
- margin-bottom: 8px;
-}
-
-.seed-card-tags {
- display: flex;
- flex-wrap: wrap;
- gap: 6px;
- margin-top: 6px;
-}
-
-.tag-label {
- background-color: #f0f0f0;
- color: #555;
- padding: 4px 10px;
- font-size: 0.75rem;
- border-radius: 12px;
- white-space: nowrap;
-}
-
-.seed-card-actions {
- display: flex;
- justify-content: space-between;
- gap: 10px;
- margin-top: 12px;
-}
-
-.btn-primary,
-.btn-secondary,
-.btn-outline {
- padding: 6px 12px;
- border: none;
- border-radius: 6px;
- cursor: pointer;
- font-size: 0.9rem;
- text-align: center;
- white-space: nowrap;
- transition: background-color 0.2s ease;
-}
-
-.btn-primary {
- background-color: #007bff;
- color: white;
-}
-
-.btn-primary:hover {
- background-color: #0056b3;
-}
-
-.btn-secondary {
- background-color: #28a745;
- color: white;
-}
-
-.btn-secondary:hover {
- background-color: #218838;
-}
-
-.btn-outline {
- background-color: transparent;
- border: 1px solid #ccc;
- color: #333;
-}
-
-.btn-outline:hover {
- background-color: #f8f9fa;
-}
-.seed-cover {
- width: 100%;
- height: 180px;
- object-fit: cover;
- border-radius: 8px;
- margin-bottom: 12px;
-}
- .friend-moments {
- background-color: #5c3f31;
- color: white;
- }
-
+ .seed-header-size,
+ .seed-header-upload-time,
+ .seed-header-downloads,
+ .seed-header-actions {
+ text-align: center; /* 新增:文字居中 */
+ }
+
+ .seed-info {
+ display: flex;
+ justify-content: space-between;
+ font-size: 0.9rem;
+ color: #666;
+ margin-bottom: 8px;
+ }
+
+ .tag-label {
+ background-color: #eee;
+ border-radius: 4px;
+ padding: 2px 6px;
+ font-size: 12px;
+ }
+
+ .btn-primary,
+ .btn-secondary,
+ .btn-outline {
+ padding: 6px 12px;
+ border: none;
+ border-radius: 6px;
+ cursor: pointer;
+ font-size: 0.9rem;
+ text-align: center;
+ white-space: nowrap;
+ transition: background-color 0.2s ease;
+ }
+
+ .btn-primary {
+ background-color: #007bff;
+ color: white;
+ }
+
+ .btn-primary:hover {
+ background-color: #0056b3;
+ }
+
+ .btn-secondary {
+ background-color: #28a745;
+ color: white;
+ }
+
+ .btn-secondary:hover {
+ background-color: #218838;
+ }
+
+ .btn-outline {
+ background-color: transparent;
+ border: 1px solid #ccc;
+ color: #333;
+ }
+
+ .btn-outline:hover {
+ background-color: #f8f9fa;
+ }
+ .seed-cover {
+ width: 100%;
+ height: 180px;
+ object-fit: cover;
+ border-radius: 8px;
+ margin-bottom: 12px;
+ }
+ .friend-moments {
+ background-color: #5c3f31;
+ color: white;
+ }
+
\ No newline at end of file
diff --git a/src/pages/SeedList/SeedList.jsx b/src/pages/SeedList/SeedList.jsx
index 39a7615..2831434 100644
--- a/src/pages/SeedList/SeedList.jsx
+++ b/src/pages/SeedList/SeedList.jsx
@@ -1,4 +1,3 @@
-
import React, { useState, useEffect } from 'react';
import { Link } from 'wouter';
import axios from 'axios';
@@ -50,8 +49,8 @@
if (searchTerm.trim()) params.search = searchTerm.trim();
const tags = Object.entries(selectedFilters)
- .filter(([_, value]) => value !== '不限')
- .map(([_, value]) => value);
+ .filter(([_, value]) => value!== '不限')
+ .map(([_, value]) => value);
if (tags.length > 0) {
params.tags = tags.join(',');
@@ -70,7 +69,7 @@
const response = await fetch(`${API_BASE}/echo/seeds?${queryString}`);
const data = await response.json();
- if (data.status !== 'success') throw new Error(data.message || '获取失败');
+ if (data.status!== 'success') throw new Error(data.message || '获取失败');
const seeds = data.seeds || [];
setSeeds(seeds);
setFilteredSeeds(seeds);
@@ -105,13 +104,13 @@
};
useEffect(() => {
- if (activeTab !== '猜你喜欢') {
+ if (activeTab!== '猜你喜欢') {
fetchFilterOptions();
}
}, [activeTab]);
useEffect(() => {
- if (activeTab !== '猜你喜欢') {
+ if (activeTab!== '猜你喜欢') {
fetchSeeds();
}
}, [activeTab, sortOption, selectedFilters, tagMode, searchTerm]);
@@ -145,14 +144,14 @@
const handleFilterChange = (key, value) => {
setSelectedFilters((prev) => ({
- ...prev,
+ ...prev,
[key]: value
}));
};
const clearFilter = (key) => {
setSelectedFilters((prev) => ({
- ...prev,
+ ...prev,
[key]: '不限'
}));
};
@@ -183,7 +182,7 @@
{TAGS.map((tag) => (
<button
key={tag}
- className={`tag-button ${activeTab === tag ? 'active-tag' : ''}`}
+ className={`tag-button ${activeTab === tag? 'active-tag' : ''}`}
onClick={() => {
setActiveTab(tag);
setFilters({});
@@ -195,7 +194,7 @@
))}
</div>
- {activeTab !== '猜你喜欢' && Object.keys(filters).length > 0 && (
+ {activeTab!== '猜你喜欢' && Object.keys(filters).length > 0 && (
<div className="filter-bar">
{Object.entries(filters).map(([key, options]) => (
<div className="filter-group" key={key}>
@@ -208,7 +207,7 @@
<option key={opt} value={opt}>{opt}</option>
))}
</select>
- {selectedFilters[key] !== '不限' && (
+ {selectedFilters[key]!== '不限' && (
<button className="clear-filter-btn" onClick={() => clearFilter(key)}>✕</button>
)}
</div>
@@ -217,47 +216,73 @@
)}
<div className="seed-list-content">
- {activeTab === '猜你喜欢' ? (
+ {activeTab === '猜你喜欢'? (
<Recommend />
- ) : loading ? (
+ ) : loading? (
<p>加载中...</p>
- ) : errorMsg ? (
+ ) : errorMsg? (
<p className="error-text">{errorMsg}</p>
- ) : filteredSeeds.length === 0 ? (
+ ) : filteredSeeds.length === 0? (
<p>未找到符合条件的种子。</p>
) : (
- <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">
- <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 className="seed-list-card">
+ <div className="seed-list-header">
+ <div className="seed-header-cover"></div>
+ <div className="seed-header-title">种子名称</div>
+ <div className="seed-header-size">大小</div>
+ <div className="seed-header-upload-time">上传时间</div>
+ <div className="seed-header-downloads">下载次数</div>
+ <div className="seed-header-actions">操作</div>
+ </div>
+ <div className="seed-list-body">
+ {filteredSeeds.map((seed, index) => (
+ <Link href={`/seed/${seed.seed_id}`} key={index} className="seed-item-link">
+ <div className="seed-item">
+ {seed.image_url && (
+ <img src={seed.image_url} alt={seed.title} className="seed-item-cover" />
+ )}
+ <div className="seed-item-title">
+ <div className="seed-title-row">
+ <h3 className="seed-title">{seed.title}</h3>
+ <div className="seed-tags">
+ {seed.tags && seed.tags.map((tag, i) => (
+ <span key={i} className="tag-label">{tag}</span>
+ ))}
+ </div>
+ </div>
</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>
- <button className="btn-outline">收藏</button>
- </div>
- </div>
- ))}
+ <div className="seed-item-size">{seed.size || '未知'}</div>
+ <div className="seed-item-upload-time">{seed.upload_time?.split('T')[0] || '未知'}</div>
+ <div className="seed-item-downloads">{seed.downloads?? 0} 次下载</div>
+ <div
+ className="seed-item-actions"
+ onClick={(e) => e.stopPropagation()} // 阻止事件冒泡,避免跳转
+ >
+ <button
+ className="btn-primary"
+ onClick={(e) => {
+ e.preventDefault(); // 阻止跳转
+ e.stopPropagation();
+ handleDownload(seed.seed_id);
+ }}
+ >
+ 下载
+ </button>
+ <button
+ className="btn-outline"
+ onClick={(e) => {
+ e.preventDefault();
+ e.stopPropagation();
+ // TODO: 收藏操作
+ }}
+ >
+ 收藏
+ </button>
+ </div>
+ </div>
+ </Link>
+ ))}
+ </div>
</div>
)}
</div>
@@ -266,3 +291,4 @@
};
export default SeedList;
+