个人中心全部,模糊乱序搜索,类型筛选
Change-Id: Id635654fccccaea80bfbf4d1480abd55f7d12046
diff --git a/src/components/Dashboard.jsx b/src/components/Dashboard.jsx
index 836daa7..f8f5dd3 100644
--- a/src/components/Dashboard.jsx
+++ b/src/components/Dashboard.jsx
@@ -1,9 +1,10 @@
import React, {useEffect, useState} from 'react';
-import {useNavigate, useLocation, useParams} from 'react-router-dom';
-// import { getUserInfo } from '../api/auth';
-import {createTorrent, getTorrents} from '../api/torrent';
+import {useNavigate, useLocation, useParams} from 'react-router-dom';
+import {createTorrent, getTorrents, searchTorrents} from '../api/torrent';
import './Dashboard.css';
-import {createPost, getPosts, getPostDetail} from '../api/helpPost';
+import {createPost, getPosts, getPostDetail, searchPosts} from '../api/helpPost';
+import { getUserInfo, isAdmin } from '../api/auth';
+import { api } from '../api/auth';
const Dashboard = ({onLogout}) => {
@@ -45,6 +46,12 @@
const [filteredResources, setFilteredResources] = useState(torrentPosts);
const [isAdmin, setIsAdmin] = useState(false);
+ // 新增搜索状态
+ const [announcementSearch, setAnnouncementSearch] = useState('');
+ const [shareSearch, setShareSearch] = useState('');
+ const [requestSearch, setRequestSearch] = useState('');
+ const [helpSearch, setHelpSearch] = useState('');
+
const activeTab = tab || 'announcement'; // 如果没有tab参数,则默认为announcement
// 从location.state中初始化状态
@@ -118,6 +125,90 @@
// 其他公告...
]);
+ // 公告区搜索处理
+ const handleSearchAnnouncement = (e) => {
+ setAnnouncementSearch(e.target.value);
+ };
+
+ // 修改后的搜索函数
+ const handleSearchShare = async () => {
+ try {
+ setTorrentLoading(true);
+ const response = await searchTorrents(shareSearch, 1);
+ if (response.data.code === 200) {
+ setTorrentPosts(response.data.data.records);
+ const total = response.data.data.total;
+ setTotalPages(Math.ceil(total / 5));
+ setCurrentPage(1);
+ } else {
+ setTorrentError(response.data.message || '搜索失败');
+ }
+ } catch (err) {
+ setTorrentError(err.message || '搜索失败');
+ } finally {
+ setTorrentLoading(false);
+ }
+ };
+
+ const handleResetShareSearch = async () => {
+ setShareSearch('');
+ setSelectedFilters(
+ Object.keys(filterCategories).reduce((acc, category) => {
+ acc[category] = 'all';
+ return acc;
+ }, {})
+ );
+ await fetchTorrentPosts(1, true);
+ };
+
+ // 求种区搜索处理
+ const handleSearchRequest = (e) => {
+ setRequestSearch(e.target.value);
+ };
+
+ // 添加搜索函数
+ const handleSearchHelp = async () => {
+ try {
+ setHelpLoading(true);
+ const response = await searchPosts(helpSearch, currentPage);
+ if (response.data.code === 200) {
+ const postsWithCounts = await Promise.all(
+ response.data.data.records.map(async (post) => {
+ try {
+ const detailResponse = await getPostDetail(post.id);
+ if (detailResponse.data.code === 200) {
+ return {
+ ...post,
+ replyCount: detailResponse.data.data.post.replyCount || 0,
+ isLiked: false
+ };
+ }
+ return post;
+ } catch (err) {
+ console.error(`获取帖子${post.id}详情失败:`, err);
+ return post;
+ }
+ })
+ );
+ setHelpPosts(postsWithCounts);
+ setTotalPages(Math.ceil(response.data.data.total / 5));
+ } else {
+ setHelpError(response.data.message || '搜索失败');
+ }
+ } catch (err) {
+ setHelpError(err.message || '搜索失败');
+ } finally {
+ setHelpLoading(false);
+ }
+ };
+
+ // 添加重置搜索函数
+ const handleResetHelpSearch = async () => {
+ setHelpSearch('');
+ await fetchHelpPosts(1); // 重置到第一页
+ };
+
+
const handleAnnouncementClick = (announcement, e) => {
if (!e.target.closest('.exclude-click')) {
@@ -205,20 +296,41 @@
}
};
- // 获取Torrent帖子列表
- const fetchTorrentPosts = async (page = 1) => {
- setTorrentLoading(true);
- try {
- const response = await getTorrents(page);
- setTorrentPosts(response.data.data.records);
- setTotalPages(Math.ceil(response.data.data.total / 5)); // 假设每页5条
- setCurrentPage(page);
- } catch (err) {
- setTorrentError(err.message);
- } finally {
- setTorrentLoading(false);
+
+const fetchTorrentPosts = async (page = 1, isReset = false) => {
+ setTorrentLoading(true);
+ try {
+ const params = {
+ page,
+ size: 5
+ };
+
+ // 如果有筛选条件且不是重置操作
+ if (!isReset && Object.values(selectedFilters).some(v => v !== 'all')) {
+ if (selectedFilters.type !== 'all') params.category = selectedFilters.type;
+ if (selectedFilters.subtitle !== 'all') params.subtitle = selectedFilters.subtitle;
+ if (selectedFilters.region !== 'all') params.region = selectedFilters.region;
+ if (selectedFilters.resolution !== 'all') params.resolution = selectedFilters.resolution;
}
- };
+
+ const response = (shareSearch && !isReset)
+ ? await searchTorrents(shareSearch, page)
+ : await api.get('http://localhost:8088/torrent', { params });
+
+ if (response.data.code === 200) {
+ setTorrentPosts(response.data.data.records);
+ const total = response.data.data.total;
+ setTotalPages(Math.ceil(total / 5));
+ setCurrentPage(page);
+ } else {
+ setTorrentError(response.data.message);
+ }
+ } catch (err) {
+ setTorrentError(err.message);
+ } finally {
+ setTorrentLoading(false);
+ }
+};
// 在useEffect中调用
useEffect(() => {
@@ -276,7 +388,7 @@
}, [activeTab, currentPage]); // 添加 currentPage 作为依赖
- // 分类维度配置
+ // 分类维度配置
const filterCategories = {
type: {
label: '类型',
@@ -285,28 +397,50 @@
'电影': '电影',
'电视剧': '电视剧',
'动漫': '动漫',
- '综艺': '综艺'
+ '综艺': '综艺',
+ '音乐': '音乐',
+ '其他': '其他'
}
},
subtitle: {
label: '字幕',
options: {
'all': '全部',
- 'yes': '有字幕',
- 'no': '无字幕'
+ '无需字幕': '无需字幕',
+ '暂无字幕': '暂无字幕',
+ '自带中文字幕': '自带中文字幕',
+ '自带双语字幕(含中文)': '自带双语字幕(含中文)',
+ '附件中文字幕': '附件中文字幕',
+ '附件双语字幕': '附件双语字幕'
}
},
region: {
label: '地区',
options: {
'all': '全部',
- 'cn': '大陆',
- 'us': '欧美',
- 'jp': '日本'
+ '中国': '中国',
+ '英国': '英国',
+ '美国': '美国',
+ '日本': '日本',
+ '韩国': '韩国',
+ '其他': '其他'
+ }
+ },
+ resolution: {
+ label: '分辨率',
+ options: {
+ 'all': '全部',
+ '4K': '4K',
+ '2K': '2K',
+ '1080P': '1080P',
+ '720P': '720P',
+ 'SD': 'SD',
+ '无损音源': '无损音源',
+ '杜比全景声': '杜比全景声',
+ '其他': '其他'
}
}
};
-
const [selectedFilters, setSelectedFilters] = useState(
location.state?.savedFilters ||
Object.keys(filterCategories).reduce((acc, category) => {
@@ -315,27 +449,54 @@
}, {})
);
-
-// 处理筛选条件变更
+ // 处理筛选条件变更
const handleFilterSelect = (category, value) => {
setSelectedFilters(prev => ({
...prev,
- [category]: prev[category] === value ? null : value // 点击已选中的则取消
+ [category]: prev[category] === value ? 'all' : value
}));
};
-//应用筛选条件
- const applyFilters = () => {
- const result = torrentPosts.filter(resource => {
- return Object.entries(selectedFilters).every(([category, selectedValue]) => {
- if (selectedValue === 'all') return true;
- if (category === 'subtitle') {
- return resource.subtitle === (selectedValue === 'yes');
- }
- return resource[category] === selectedValue;
- });
- });
- setFilteredResources(result);
+ // 应用筛选条件
+ const applyFilters = async () => {
+ try {
+ setTorrentLoading(true);
+
+ // 构建查询参数
+ const params = {
+ page: 1, // 从第一页开始
+ size: 5
+ };
+
+ // 添加筛选条件
+ if (selectedFilters.type !== 'all') {
+ params.category = selectedFilters.type;
+ }
+ if (selectedFilters.subtitle !== 'all') {
+ params.subtitle = selectedFilters.subtitle;
+ }
+ if (selectedFilters.region !== 'all') {
+ params.region = selectedFilters.region;
+ }
+ if (selectedFilters.resolution !== 'all') {
+ params.resolution = selectedFilters.resolution;
+ }
+
+ // 调用API获取筛选结果
+ const response = await api.get('http://localhost:8088/torrent', { params });
+
+ if (response.data.code === 200) {
+ setTorrentPosts(response.data.data.records);
+ setTotalPages(Math.ceil(response.data.data.total / 5));
+ setCurrentPage(1);
+ } else {
+ setTorrentError(response.data.message || '筛选失败');
+ }
+ } catch (err) {
+ setTorrentError(err.message || '筛选失败');
+ } finally {
+ setTorrentLoading(false);
+ }
};
@@ -346,43 +507,37 @@
}
}, [location.state]);
-
- useEffect(() => {
- const token = localStorage.getItem('token');
- if (!token) {
- navigate('/login');
- return;
- }
-
- /* 保留但注释掉实际的用户信息获取
- const fetchUserInfo = async () => {
- try {
- const response = await getUserInfo(token);
- if (response.data.code === 200) {
- setUserInfo(response.data.data);
- } else {
- setError('获取用户信息失败');
- }
- } catch (err) {
- setError('获取用户信息失败');
- } finally {
- setLoading(false);
- }
- };
-
- fetchUserInfo();
- */
-
- // 模拟用户信息
- setUserInfo({
- name: localStorage.getItem('username') || '演示用户', // 确保这里读取的是最新值
+ // 在Dashboard.jsx中修改useEffect
+useEffect(() => {
+ const token = localStorage.getItem('token');
+ if (!token) {
+ navigate('/login');
+ return;
+ }
+
+ const fetchUserInfo = async () => {
+ try {
+ setLoading(true);
+ const backendData = await getUserInfo(); // 调用修改后的方法
+ console.log('后端返回的用户数据:', backendData); // 调试用
+
+ setUserInfo({
+ name: backendData.username || '演示用户',
avatar: 'https://via.placeholder.com/40',
- isAdmin: true
- });
- setLoading(false);
- }, [navigate]);
+ isAdmin: backendData.authority === 'ADMIN' // 检查 authority 是否为 "ADMIN"
+ });
+ } catch (error) {
+ console.error('获取用户信息失败:', error);
+ setError('获取用户信息失败');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ fetchUserInfo();
+}, [navigate]);
- // 轮播图自动切换效果
+
useEffect(() => {
if (activeTab === 'announcement') {
const timer = setInterval(() => {
@@ -403,6 +558,22 @@
case 'announcement':
return (
<div className="content-area" data-testid="announcement-section">
+ <div className="section-search-container">
+ <input
+ type="text"
+ placeholder="搜索公告..."
+ value={announcementSearch}
+ onChange={(e) => setAnnouncementSearch(e.target.value)}
+ className="section-search-input"
+ onKeyPress={(e) => e.key === 'Enter' && handleSearchAnnouncement()}
+ />
+ <button
+ className="search-button"
+ onClick={handleSearchAnnouncement}
+ >
+ 搜索
+ </button>
+ </div>
{/* 轮播图区域 */}
<div className="carousel-container">
<div className={`carousel-slide ${currentSlide === 0 ? 'active' : ''}`}>
@@ -443,6 +614,31 @@
case 'share':
return (
<div className="content-area" data-testid="share-section">
+ {/* 分享区搜索框 */}
+ <div className="section-search-container">
+ <input
+ type="text"
+ placeholder="搜索资源..."
+ value={shareSearch}
+ onChange={(e) => setShareSearch(e.target.value)}
+ className="section-search-input"
+ onKeyPress={(e) => e.key === 'Enter' && handleSearchShare()}
+ />
+ <button
+ className="search-button"
+ onClick={handleSearchShare}
+ >
+ 搜索
+ </button>
+ <button
+ className="reset-button"
+ onClick={handleResetShareSearch} // 使用新的重置函数
+ style={{marginLeft: '10px'}}
+ >
+ 重置
+ </button>
+ </div>
+
{/* 上传按钮 - 添加在筛选区上方 */}
<div className="upload-header">
<button
@@ -517,19 +713,26 @@
<option value="动漫">动漫</option>
<option value="综艺">综艺</option>
<option value="音乐">音乐</option>
+ <option value="其他">其他</option>
</select>
</div>
- {/* 新增地区输入框 */}
+ {/* 修改后的地区下拉框 */}
<div className="form-group">
<label>地区</label>
- <input
- type="text"
+ <select
value={uploadData.region || ''}
onChange={(e) => setUploadData({...uploadData, region: e.target.value})}
- placeholder="例如: 美国, 中国, 日本等"
required
- />
+ >
+ <option value="">请选择</option>
+ <option value="中国">中国</option>
+ <option value="英国">英国</option>
+ <option value="美国">美国</option>
+ <option value="日本">日本</option>
+ <option value="韩国">韩国</option>
+ <option value="其他">其他</option>
+ </select>
</div>
{/* 添加分辨率下拉框 */}
@@ -637,7 +840,7 @@
<p className="resource-subtitle">字幕: {torrent.subtitle}</p>
</div>
<div className="resource-stats">
- <span className="stat">{torrent.size}</span>
+ <span className="stat">{torrent.size}</span>
<span className="stat">发布者: {torrent.username}</span>
</div>
<button
@@ -653,7 +856,7 @@
))}
</div>
- {/* 分页控件 */}
+ {totalPages > 1 && (
<div className="pagination">
<button
onClick={() => fetchTorrentPosts(currentPage - 1)}
@@ -679,12 +882,30 @@
下一页
</button>
</div>
+ )}
</div>
);
// 在Dashboard.jsx的renderContent函数中修改case 'request'部分
case 'request':
return (
<div className="content-area" data-testid="request-section">
+ {/* 求种区搜索框 */}
+ <div className="section-search-container">
+ <input
+ type="text"
+ placeholder="搜索求种..."
+ value={requestSearch}
+ onChange={(e) => setRequestSearch(e.target.value)}
+ className="section-search-input"
+ onKeyPress={(e) => e.key === 'Enter' && handleSearchRequest()}
+ />
+ <button
+ className="search-button"
+ onClick={handleSearchRequest}
+ >
+ 搜索
+ </button>
+ </div>
{/* 求种区帖子列表 */}
<div className="request-list">
{[
@@ -734,6 +955,31 @@
case 'help':
return (
<div className="content-area" data-testid="help-section">
+ {/* 求助区搜索框 */}
+ <div className="section-search-container">
+ <input
+ type="text"
+ placeholder="搜索求助..."
+ value={helpSearch}
+ onChange={(e) => setHelpSearch(e.target.value)}
+ className="section-search-input"
+ onKeyPress={(e) => e.key === 'Enter' && handleSearchHelp()}
+ />
+ <button
+ className="search-button"
+ onClick={handleSearchHelp}
+ >
+ 搜索
+ </button>
+ <button
+ className="reset-button"
+ onClick={handleResetHelpSearch}
+ style={{marginLeft: '10px'}}
+ >
+ 重置
+ </button>
+ </div>
+
{/* 新增发帖按钮 */}
<div className="post-header">
<button
@@ -891,14 +1137,9 @@
<div className="dashboard-container" data-testid="dashboard-container">
{/* 顶部栏 */}
<div className="top-bar" data-testid="top-bar">
- {/* 搜索框 */}
- <div className="search-container">
- <input
- type="text"
- placeholder="搜索种子、用户..."
- className="search-input"
- />
- <button className="search-button">搜索</button>
+ {/* 平台名称替换搜索框 */}
+ <div className="platform-name">
+ <h2>PT资源站</h2>
</div>
<div className="user-actions">