个人中心全部,模糊乱序搜索,类型筛选

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">