blob: cd9db9169d1cbc089b88579f2f0601700202f986 [file] [log] [blame]
阳菜,放晴!7e1e3a52025-06-05 23:00:51 +08001// search.tsx
2import React, { useState, useEffect } from 'react';
3import styles from './search.module.css';
4import { useLocation } from "react-router-dom";
5
6interface PostItem {
7 postId: number;
8 userId: number;
9 postTitle: string;
10 postContent: string;
11 createdAt: number;
12 postType: string;
13 viewCount: number;
14 hotScore: number;
15 lastCalculated: number;
16 tags?: number[];
17}
18
19const tagMap: Record<number, string> = {
20 1: "搞笑",
21 2: "悬疑",
22 3: "教育",
23 4: "动作",
24 5: "剧情"
25};
26
27const SearchPage: React.FC = () => {
28 const [posts, setPosts] = useState<PostItem[]>([]);
29 const [filteredPosts, setFilteredPosts] = useState<PostItem[]>([]);
30 const [selectedPostType, setSelectedPostType] = useState<string>('all');
31 const [selectedRating, setSelectedRating] = useState<number | null>(null);
32 const [selectedTags, setSelectedTags] = useState<number[]>([]);
33
34 const location = useLocation();
35 const params = new URLSearchParams(location.search);
36 const keyword = params.get("keyword");
37
38 useEffect(() => {
39 fetch('/api/posts')
40 .then((res) => res.json())
41 .then((data) => {
42 setPosts(data);
43 setFilteredPosts(data);
44 });
45 }, []);
46
47 const applyFilters = () => {
48 let filtered = posts;
49
50 if (selectedPostType !== 'all') {
51 filtered = filtered.filter((post) => post.postType === selectedPostType);
52 }
53
54 if (selectedRating !== null) {
55 filtered = filtered.filter((post) => post.hotScore >= selectedRating);
56 }
57
58 if (selectedTags.length > 0) {
59 filtered = filtered.filter((post) =>
60 post.tags?.some((tag) => selectedTags.includes(tag))
61 );
62 }
63
64 setFilteredPosts(filtered);
65 };
66
67 return (
68 <div className={styles.secondaryHeader}>
69 <div className={styles.leftSection}>
70 <select
71 value={selectedPostType}
72 onChange={(e) => setSelectedPostType(e.target.value)}
73 className={styles.selectBox}
74 >
75 <option value="all">所有分区</option>
76 <option value="影视">影视</option>
77 <option value="音乐">音乐</option>
78 <option value="游戏">游戏</option>
79 <option value="软件">软件</option>
80 </select>
81
82 <select
83 value={selectedRating || ''}
84 onChange={(e) =>
85 setSelectedRating(e.target.value ? Number(e.target.value) : null)
86 }
87 className={styles.selectBox}
88 >
89 <option value="">所有评分</option>
90 <option value="1">1星及以上</option>
91 <option value="2">2星及以上</option>
92 <option value="3">3星及以上</option>
93 <option value="4">4星及以上</option>
94 <option value="5">5星</option>
95 </select>
96 </div>
97
98 <div className={styles.centerSection}>
99 <div className={styles.tagFilters}>
100 {Object.entries(tagMap).map(([tagId, tagName]) => (
101 <label key={tagId}>
102 <input
103 type="checkbox"
104 value={tagId}
105 checked={selectedTags.includes(Number(tagId))}
106 onChange={(e) => {
107 const value = Number(e.target.value);
108 setSelectedTags((prev) =>
109 prev.includes(value)
110 ? prev.filter((t) => t !== value)
111 : [...prev, value]
112 );
113 }}
114 />
115 {tagName}
116 </label>
117 ))}
118 </div>
119 </div>
120
121 <div className={styles.rightSection}>
122 <button className={styles.filterButton} onClick={applyFilters}>
123 筛选
124 </button>
125 </div>
126 </div>
127
128 );
129};
130
131export default SearchPage;