/* eslint-disable react-hooks/exhaustive-deps, no-console */ 'use client'; import Image from 'next/image'; import { useSearchParams } from 'next/navigation'; import { Suspense, useEffect, useState } from 'react'; import type { VideoDetail } from '@/lib/types'; import PageLayout from '@/components/PageLayout'; interface SearchResult { id: string; title: string; poster: string; episodes?: number; source: string; source_name: string; } function AggregatePageClient() { const searchParams = useSearchParams(); const query = searchParams.get('q')?.trim() || ''; const [results, setResults] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [details, setDetails] = useState([]); const [detailLoading, setDetailLoading] = useState(false); useEffect(() => { if (!query) { setError('缺少搜索关键词'); setLoading(false); return; } const fetchData = async () => { try { const res = await fetch(`/api/search?q=${encodeURIComponent(query)}`); if (!res.ok) { throw new Error('搜索失败'); } const data = await res.json(); const all: SearchResult[] = data.results || []; const exact = all.filter((r) => r.title === query); setResults(exact); } catch (e) { setError(e instanceof Error ? e.message : '搜索失败'); } finally { setLoading(false); } }; fetchData(); }, [query]); useEffect(() => { if (results.length === 0) return; const fetchDetails = async () => { setDetailLoading(true); try { const promises = results.map(async (r) => { try { const res = await fetch( `/api/detail?source=${r.source}&id=${r.id}` ); if (!res.ok) throw new Error(''); const data: VideoDetail = await res.json(); return data; } catch { return null; } }); const dts = (await Promise.all(promises)).filter( (d): d is VideoDetail => d !== null ); setDetails(dts); } finally { setDetailLoading(false); } }; fetchDetails(); }, [results]); // 选出信息最完整的字段 const chooseString = (vals: (string | undefined)[]): string | undefined => { return vals.reduce((best, v) => { if (!v) return best; if (!best) return v; return v.length > best.length ? v : best; }, undefined); }; const aggregatedInfo = { title: query, cover: chooseString(details.map((d) => d.videoInfo.cover)), desc: chooseString(details.map((d) => d.videoInfo.desc)), type: chooseString(details.map((d) => d.videoInfo.type)), year: chooseString(details.map((d) => d.videoInfo.year)), remarks: chooseString(details.map((d) => d.videoInfo.remarks)), }; const infoReady = Boolean( aggregatedInfo.cover || aggregatedInfo.desc || aggregatedInfo.type || aggregatedInfo.year || aggregatedInfo.remarks ); const uniqueSources = Array.from( new Map(results.map((r) => [r.source, r])).values() ); // 详情映射,便于快速获取每个源的集数 const sourceDetailMap = new Map(details.map((d) => [d.videoInfo.source, d])); return (
{loading ? (
) : error ? (
加载失败
{error}
) : !infoReady && detailLoading ? (
) : !infoReady ? (
未找到匹配结果
) : (
{/* 主信息区:左图右文 */}
{/* 返回按钮 */} {/* 封面 */}
{aggregatedInfo.title}
{/* 右侧信息 */}

{aggregatedInfo.title}

{aggregatedInfo.remarks && ( {aggregatedInfo.remarks} )} {aggregatedInfo.year && {aggregatedInfo.year}} {aggregatedInfo.type && {aggregatedInfo.type}}
{aggregatedInfo.desc}
{/* 选播放源 */} {uniqueSources.length > 0 && (
选择播放源
共 {uniqueSources.length} 个
{uniqueSources.map((src) => { const d = sourceDetailMap.get(src.source); const epCount = d ? d.episodes.length : src.episodes; return ( {/* 名称 */} {src.source_name} {/* 集数徽标 */} {epCount && epCount > 1 ? ( {epCount}集 ) : null} ); })}
)}
)}
); } export default function AggregatePage() { return ( ); }