import { useState, useEffect, useMemo, useRef } from "react"; import { Search, FileText, Image, Video, Play, ChevronLeft, ChevronRight, Library, } from "lucide-react"; import { KIOSK_EVENT, loadKnowledgeEntries, type KnowledgeEntry } from "../kioskStorage"; import { PAGE_CONTENT_INSET } from "../pageContentInset"; /** 搜索框下方固定展示的关键词(顺序与文案一致) */ const QUICK_KEYWORDS = [ "天体物理", "教程", "日食", "星云", "暗物质", "望远镜", "深空摄影", ] as const; /** 每页条数(大屏约 5 列×2 行,共 10 条) */ const PAGE_SIZE = 10; function buildPageList(totalPages: number, currentPage: number): (number | "ellipsis")[] { if (totalPages <= 12) { return Array.from({ length: totalPages }, (_, i) => i + 1); } const set = new Set([1, totalPages, currentPage]); for (let p = currentPage - 2; p <= currentPage + 2; p++) { if (p >= 1 && p <= totalPages) set.add(p); } const sorted = [...set].sort((a, b) => a - b); const out: (number | "ellipsis")[] = []; for (let i = 0; i < sorted.length; i++) { const p = sorted[i]!; if (i > 0 && p - sorted[i - 1]! > 1) { out.push("ellipsis"); } out.push(p); } return out; } function matchesQuery(item: KnowledgeEntry, raw: string): boolean { const q = raw.trim(); if (q === "") return true; const lower = q.toLowerCase(); if (item.title.toLowerCase().includes(lower) || item.content.toLowerCase().includes(lower)) { return true; } return item.tags.some((t) => t.includes(q) || t.toLowerCase().includes(lower)); } export function SearchPage() { const [dbRev, setDbRev] = useState(0); const [searchQuery, setSearchQuery] = useState(""); const [page, setPage] = useState(1); const searchInputRef = useRef(null); useEffect(() => { const h = () => setDbRev((r) => r + 1); window.addEventListener(KIOSK_EVENT, h); window.addEventListener("storage", h); return () => { window.removeEventListener(KIOSK_EVENT, h); window.removeEventListener("storage", h); }; }, []); const searchResults = useMemo(() => loadKnowledgeEntries(), [dbRev]); const filteredResults = useMemo( () => searchResults.filter((item) => matchesQuery(item, searchQuery)), [searchResults, searchQuery] ); const totalPages = Math.max(1, Math.ceil(filteredResults.length / PAGE_SIZE)); useEffect(() => { setPage(1); }, [searchQuery, dbRev]); useEffect(() => { setPage((p) => Math.min(p, totalPages)); }, [totalPages]); const currentPage = Math.min(page, totalPages); const pageItems = filteredResults.slice( (currentPage - 1) * PAGE_SIZE, currentPage * PAGE_SIZE ); const toggleKeyword = (word: string) => { setSearchQuery((prev) => (prev.trim() === word ? "" : word)); }; const getTypeIcon = (type: string) => { switch (type) { case "文字": return FileText; case "图片": return Image; case "视频": return Video; default: return FileText; } }; const goPage = (p: number) => { setPage(Math.max(1, Math.min(p, totalPages))); }; return (
{/* 左:标题 · 右:搜索框,关键词仅在搜索框下方 */}
天文知识库
{ e.preventDefault(); searchInputRef.current?.blur(); }} >
setSearchQuery(e.target.value)} placeholder="搜索天文知识..." autoComplete="off" className="w-full rounded-lg border border-white/25 bg-transparent py-1.5 pl-8 pr-2.5 text-xs text-white placeholder-blue-300/80 transition-all focus:border-sky-400/80 focus:outline-none focus:ring-1 focus:ring-sky-400/30 sm:py-2 sm:pl-9 sm:text-sm" />
{QUICK_KEYWORDS.map((word) => { const active = searchQuery.trim() === word; return ( ); })}
{/* 搜索结果 + 分页 */}

找到 {filteredResults.length} 条结果

{filteredResults.length > 0 && ( <>
{pageItems.map((result) => { const Icon = getTypeIcon(result.type); return (
{result.image ? ( ) : (
)} {result.type === "视频" ? (
) : null} {result.type}

{result.title}

{result.content.trim() ? (

{result.content.trim()}

) : null}
{result.tags.length > 0 ? ( <> {result.tags.slice(0, 3).map((tag) => ( {tag} ))} {result.tags.length > 3 ? ( +{result.tags.length - 3} ) : null} ) : null}
); })}
)} {filteredResults.length === 0 && (

未找到匹配的结果

请尝试其他搜索词或点击上方关键词

)}
); }