"use client"; import { useCallback, useEffect, useState } from "react"; import { useSearchParams, useRouter } from "next/navigation"; import Link from "next/link"; import { Search, ArrowLeft, X, MessageSquare } from "lucide-react"; // 匹配搜索结果类型(适配后端API) type SearchResultItem = { id: string; awemeId: string; type: 'video' | 'image'; rank: number; snippet: string; // 后端返回的高亮片段,已包含标签 video?: { aweme_id: string; desc: string; cover_url: string | null; video_url: string | null; duration_ms: number; author: { sec_uid: string; nickname: string; avatar_url: string | null; }; }; imagePost?: { aweme_id: string; desc: string; cover_url: string | null; author: { sec_uid: string; nickname: string; avatar_url: string | null; }; }; }; export default function SearchPage() { const searchParams = useSearchParams(); const router = useRouter(); const queryParam = searchParams.get("q") || ""; const [query, setQuery] = useState(queryParam); const [results, setResults] = useState([]); const [loading, setLoading] = useState(false); const [searched, setSearched] = useState(false); const performSearch = useCallback(async (q: string) => { if (!q.trim()) { setResults([]); setSearched(false); return; } setLoading(true); setSearched(true); try { const res = await fetch(`/api/search?q=${encodeURIComponent(q.trim())}&limit=60`); if (!res.ok) throw new Error("Search failed"); const data = await res.json(); setResults(data.results || []); } catch (err) { console.error("Search error:", err); setResults([]); } finally { setLoading(false); } }, []); // 初始查询 useEffect(() => { if (queryParam) { performSearch(queryParam); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const handleSearch = (e: React.FormEvent) => { e.preventDefault(); const trimmed = query.trim(); if (!trimmed) return; // 更新 URL router.push(`/search?q=${encodeURIComponent(trimmed)}`); performSearch(trimmed); }; const handleClear = () => { setQuery(""); setResults([]); setSearched(false); router.push("/search"); }; return (
{/* 顶部搜索栏 */}
setQuery(e.target.value)} placeholder="搜索视频、图文描述或语音内容..." className="w-full bg-white/5 border border-white/10 rounded-full px-5 py-3 pl-12 pr-12 text-white placeholder-white/40 focus:outline-none focus:ring-2 focus:ring-blue-500/50 focus:border-blue-500/50 transition-all" autoFocus /> {query && ( )}
{/* 结果区域 */}
{loading && (

正在搜索...

)} {!loading && searched && results.length === 0 && (

未找到相关内容

试试其他关键词

)} {!loading && !searched && !queryParam && (

输入关键词开始搜索

支持搜索视频描述、图文描述及语音转写内容

)} {!loading && results.length > 0 && (

找到 {results.length} 个结果

{/* 单列列表布局 */}
{results.map((item) => { const content = item.type === 'video' ? item.video : item.imagePost; if (!content) return null; return (
{/* 主内容区 */}
{/* 左侧:封面预览 */} {content.desc} {/* 右侧:信息区 */}
{/* 类型标签 */}
{item.type === 'video' ? '视频' : '图文'} 匹配度: {(item.rank * 100).toFixed(1)}%
{/* 描述 */}

{content.desc || "无描述"}

{/* 作者信息 */}
{content.author.nickname} {content.author.nickname}
{/* 匹配详情:展示后端返回的snippet(已包含标签) */}

匹配内容

); })}
)}
); }