blob: 6dba69c3a60245fe99248cc050b7e69d271f95d3 [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
阳菜,放晴!77743f42025-06-06 23:04:08 +080019const tagMap: Record<string, Record<number, string>> = {
20 Game: {
21 0: "android",
22 1: "mac",
23 2: "pc",
24 3: "ios",
25 4: "other",
26 5: "action",
27 6: "adventure",
28 7: "leisure",
29 8: "riddle",
30 9: "sport",
31 10: "strategy",
32 11: "table",
33 },
34 video: {
35 20: "视频标签1",
36 21: "视频标签2",
37 22: "视频标签3",
38 },
39 music: {
40 40: "音乐标签1",
41 41: "音乐标签2",
42 42: "音乐标签3",
43 },
44 software: {
45 60: "软件标签1",
46 61: "软件标签2",
47 62: "软件标签3",
48 },
阳菜,放晴!7e1e3a52025-06-05 23:00:51 +080049};
50
51const SearchPage: React.FC = () => {
52 const [posts, setPosts] = useState<PostItem[]>([]);
53 const [filteredPosts, setFilteredPosts] = useState<PostItem[]>([]);
54 const [selectedPostType, setSelectedPostType] = useState<string>('all');
55 const [selectedRating, setSelectedRating] = useState<number | null>(null);
56 const [selectedTags, setSelectedTags] = useState<number[]>([]);
57
58 const location = useLocation();
59 const params = new URLSearchParams(location.search);
60 const keyword = params.get("keyword");
61
阳菜,放晴!77743f42025-06-06 23:04:08 +080062 const getTagsForPostType = (postType: string) => {
63 return tagMap[postType] || {};
64 };
65
阳菜,放晴!7e1e3a52025-06-05 23:00:51 +080066 useEffect(() => {
67 fetch('/api/posts')
68 .then((res) => res.json())
69 .then((data) => {
70 setPosts(data);
71 setFilteredPosts(data);
72 });
73 }, []);
74
75 const applyFilters = () => {
76 let filtered = posts;
77
78 if (selectedPostType !== 'all') {
79 filtered = filtered.filter((post) => post.postType === selectedPostType);
80 }
81
82 if (selectedRating !== null) {
83 filtered = filtered.filter((post) => post.hotScore >= selectedRating);
84 }
85
86 if (selectedTags.length > 0) {
87 filtered = filtered.filter((post) =>
88 post.tags?.some((tag) => selectedTags.includes(tag))
89 );
90 }
91
92 setFilteredPosts(filtered);
阳菜,放晴!77743f42025-06-06 23:04:08 +080093
阳菜,放晴!7e1e3a52025-06-05 23:00:51 +080094 };
95
96 return (
97 <div className={styles.secondaryHeader}>
98 <div className={styles.leftSection}>
99 <select
100 value={selectedPostType}
101 onChange={(e) => setSelectedPostType(e.target.value)}
102 className={styles.selectBox}
103 >
104 <option value="all">所有分区</option>
阳菜,放晴!77743f42025-06-06 23:04:08 +0800105 <option value="video">影视</option>
106 <option value="music">音乐</option>
107 <option value="Game">游戏</option>
108 <option value="software">软件</option>
阳菜,放晴!7e1e3a52025-06-05 23:00:51 +0800109 </select>
110
111 <select
112 value={selectedRating || ''}
113 onChange={(e) =>
114 setSelectedRating(e.target.value ? Number(e.target.value) : null)
115 }
116 className={styles.selectBox}
117 >
118 <option value="">所有评分</option>
119 <option value="1">1星及以上</option>
120 <option value="2">2星及以上</option>
121 <option value="3">3星及以上</option>
122 <option value="4">4星及以上</option>
123 <option value="5">5星</option>
124 </select>
125 </div>
126
127 <div className={styles.centerSection}>
128 <div className={styles.tagFilters}>
阳菜,放晴!77743f42025-06-06 23:04:08 +0800129 {Object.entries(getTagsForPostType(selectedPostType)).map(([tagId, tagName]) => (
阳菜,放晴!7e1e3a52025-06-05 23:00:51 +0800130 <label key={tagId}>
131 <input
132 type="checkbox"
133 value={tagId}
134 checked={selectedTags.includes(Number(tagId))}
135 onChange={(e) => {
136 const value = Number(e.target.value);
137 setSelectedTags((prev) =>
138 prev.includes(value)
139 ? prev.filter((t) => t !== value)
140 : [...prev, value]
141 );
142 }}
143 />
144 {tagName}
145 </label>
146 ))}
147 </div>
148 </div>
149
150 <div className={styles.rightSection}>
151 <button className={styles.filterButton} onClick={applyFilters}>
152 筛选
153 </button>
154 </div>
155 </div>
156
157 );
158};
159
160export default SearchPage;