From 1490c0614b1af53e8c0eef23bb3aab164a98e833 Mon Sep 17 00:00:00 2001 From: shinya Date: Sun, 20 Jul 2025 18:06:14 +0800 Subject: [PATCH] feat: optimize search in play page --- src/app/douban/page.tsx | 1 + src/app/page.tsx | 2 ++ src/app/play/page.tsx | 50 ++++++++++++++++++----------- src/components/ContinueWatching.tsx | 1 + src/components/VideoCard.tsx | 8 +++-- 5 files changed, 40 insertions(+), 22 deletions(-) diff --git a/src/app/douban/page.tsx b/src/app/douban/page.tsx index be8d3c8..0663b33 100644 --- a/src/app/douban/page.tsx +++ b/src/app/douban/page.tsx @@ -295,6 +295,7 @@ function DoubanPageClient() { douban_id={item.id} rate={item.rate} year={item.year} + type={type === 'movie' ? 'movie' : ''} // 电影类型严格控制,tv 不控 /> ))} diff --git a/src/app/page.tsx b/src/app/page.tsx index ebc2be0..7a59668 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -190,6 +190,7 @@ function HomeClient() { query={item.search_title} {...item} from='favorite' + type={item.episodes > 1 ? 'tv' : ''} /> ))} @@ -247,6 +248,7 @@ function HomeClient() { douban_id={movie.id} rate={movie.rate} year={movie.year} + type='movie' /> ))} diff --git a/src/app/play/page.tsx b/src/app/play/page.tsx index 6b3d11f..bda1f96 100644 --- a/src/app/play/page.tsx +++ b/src/app/play/page.tsx @@ -465,6 +465,27 @@ function PlayPageClient() { // 进入页面时直接获取全部源信息 useEffect(() => { + const fetchSourceDetail = async ( + source: string, + id: string + ): Promise => { + try { + const detailResponse = await fetch( + `/api/detail?source=${source}&id=${id}` + ); + if (!detailResponse.ok) { + throw new Error('获取视频详情失败'); + } + const detailData = (await detailResponse.json()) as SearchResult; + setAvailableSources([detailData]); + return [detailData]; + } catch (err) { + console.error('获取视频详情失败:', err); + return []; + } finally { + setSourceSearchLoading(false); + } + }; const fetchSourcesData = async (query: string): Promise => { // 根据搜索词获取全部源信息 try { @@ -489,24 +510,6 @@ function PlayPageClient() { (searchType === 'movie' && result.episodes.length === 1) : true) ); - if (results.length !== 0) { - setAvailableSources(results); - return results; - } - - // 未获取到任何内容,fallback 使用 source + id - if (!currentSource || !currentId) { - return []; - } - - const detailResponse = await fetch( - `/api/detail?source=${currentSource}&id=${currentId}` - ); - if (!detailResponse.ok) { - throw new Error('获取视频详情失败'); - } - const detailData = (await detailResponse.json()) as SearchResult; - results.push(detailData); setAvailableSources(results); return results; } catch (err) { @@ -532,7 +535,16 @@ function PlayPageClient() { : '🔍 正在搜索播放源...' ); - const sourcesInfo = await fetchSourcesData(searchTitle || videoTitle); + let sourcesInfo = await fetchSourcesData(searchTitle || videoTitle); + if ( + currentSource && + currentId && + !sourcesInfo.some( + (source) => source.source === currentSource && source.id === currentId + ) + ) { + sourcesInfo = await fetchSourceDetail(currentSource, currentId); + } if (sourcesInfo.length === 0) { setError('未找到匹配结果'); setLoading(false); diff --git a/src/components/ContinueWatching.tsx b/src/components/ContinueWatching.tsx index 0adbc85..0a9d882 100644 --- a/src/components/ContinueWatching.tsx +++ b/src/components/ContinueWatching.tsx @@ -143,6 +143,7 @@ export default function ContinueWatching({ className }: ContinueWatchingProps) { prev.filter((r) => r.key !== record.key) ) } + type={record.total_episodes > 1 ? 'tv' : ''} /> ); diff --git a/src/components/VideoCard.tsx b/src/components/VideoCard.tsx index 7c7877b..5f429ac 100644 --- a/src/components/VideoCard.tsx +++ b/src/components/VideoCard.tsx @@ -34,6 +34,7 @@ interface VideoCardProps { onDelete?: () => void; rate?: string; items?: SearchResult[]; + type?: string; } export default function VideoCard({ @@ -52,6 +53,7 @@ export default function VideoCard({ onDelete, rate, items, + type = '', }: VideoCardProps) { const router = useRouter(); const [favorited, setFavorited] = useState(false); @@ -105,10 +107,10 @@ export default function VideoCard({ const actualYear = aggregateData?.first.year ?? year; const actualQuery = query || ''; const actualSearchType = isAggregate - ? aggregateData?.first.episodes.length === 1 + ? aggregateData?.first.episodes?.length === 1 ? 'movie' : 'tv' - : ''; + : type; // 获取收藏状态 useEffect(() => { @@ -198,7 +200,7 @@ export default function VideoCard({ router.push( `/play?title=${encodeURIComponent(actualTitle.trim())}${ actualYear ? `&year=${actualYear}` : '' - }` + }${actualSearchType ? `&stype=${actualSearchType}` : ''}` ); } else if (actualSource && actualId) { router.push(