Docker
Change-Id: I2aefd96a43bcf3a3c41c079ecfc04a3fee48bed6
diff --git a/src/views/search/search.tsx b/src/views/search/search.tsx
new file mode 100644
index 0000000..cd9db91
--- /dev/null
+++ b/src/views/search/search.tsx
@@ -0,0 +1,131 @@
+// search.tsx
+import React, { useState, useEffect } from 'react';
+import styles from './search.module.css';
+import { useLocation } from "react-router-dom";
+
+interface PostItem {
+ postId: number;
+ userId: number;
+ postTitle: string;
+ postContent: string;
+ createdAt: number;
+ postType: string;
+ viewCount: number;
+ hotScore: number;
+ lastCalculated: number;
+ tags?: number[];
+}
+
+const tagMap: Record<number, string> = {
+ 1: "搞笑",
+ 2: "悬疑",
+ 3: "教育",
+ 4: "动作",
+ 5: "剧情"
+};
+
+const SearchPage: React.FC = () => {
+ const [posts, setPosts] = useState<PostItem[]>([]);
+ const [filteredPosts, setFilteredPosts] = useState<PostItem[]>([]);
+ const [selectedPostType, setSelectedPostType] = useState<string>('all');
+ const [selectedRating, setSelectedRating] = useState<number | null>(null);
+ const [selectedTags, setSelectedTags] = useState<number[]>([]);
+
+ const location = useLocation();
+ const params = new URLSearchParams(location.search);
+ const keyword = params.get("keyword");
+
+ useEffect(() => {
+ fetch('/api/posts')
+ .then((res) => res.json())
+ .then((data) => {
+ setPosts(data);
+ setFilteredPosts(data);
+ });
+ }, []);
+
+ const applyFilters = () => {
+ let filtered = posts;
+
+ if (selectedPostType !== 'all') {
+ filtered = filtered.filter((post) => post.postType === selectedPostType);
+ }
+
+ if (selectedRating !== null) {
+ filtered = filtered.filter((post) => post.hotScore >= selectedRating);
+ }
+
+ if (selectedTags.length > 0) {
+ filtered = filtered.filter((post) =>
+ post.tags?.some((tag) => selectedTags.includes(tag))
+ );
+ }
+
+ setFilteredPosts(filtered);
+ };
+
+ return (
+ <div className={styles.secondaryHeader}>
+ <div className={styles.leftSection}>
+ <select
+ value={selectedPostType}
+ onChange={(e) => setSelectedPostType(e.target.value)}
+ className={styles.selectBox}
+ >
+ <option value="all">所有分区</option>
+ <option value="影视">影视</option>
+ <option value="音乐">音乐</option>
+ <option value="游戏">游戏</option>
+ <option value="软件">软件</option>
+ </select>
+
+ <select
+ value={selectedRating || ''}
+ onChange={(e) =>
+ setSelectedRating(e.target.value ? Number(e.target.value) : null)
+ }
+ className={styles.selectBox}
+ >
+ <option value="">所有评分</option>
+ <option value="1">1星及以上</option>
+ <option value="2">2星及以上</option>
+ <option value="3">3星及以上</option>
+ <option value="4">4星及以上</option>
+ <option value="5">5星</option>
+ </select>
+ </div>
+
+ <div className={styles.centerSection}>
+ <div className={styles.tagFilters}>
+ {Object.entries(tagMap).map(([tagId, tagName]) => (
+ <label key={tagId}>
+ <input
+ type="checkbox"
+ value={tagId}
+ checked={selectedTags.includes(Number(tagId))}
+ onChange={(e) => {
+ const value = Number(e.target.value);
+ setSelectedTags((prev) =>
+ prev.includes(value)
+ ? prev.filter((t) => t !== value)
+ : [...prev, value]
+ );
+ }}
+ />
+ {tagName}
+ </label>
+ ))}
+ </div>
+ </div>
+
+ <div className={styles.rightSection}>
+ <button className={styles.filterButton} onClick={applyFilters}>
+ 筛选
+ </button>
+ </div>
+ </div>
+
+ );
+};
+
+export default SearchPage;