diff --git a/src/app/search/page.tsx b/src/app/search/page.tsx index 7b2bbca..962c156 100644 --- a/src/app/search/page.tsx +++ b/src/app/search/page.tsx @@ -67,7 +67,23 @@ function SearchPageClient() { return res; })(); const source_names = Array.from(new Set(group.map((g) => g.source_name).filter(Boolean))) as string[]; - return { episodes, source_names }; + + const douban_id = (() => { + const countMap = new Map(); + group.forEach((g) => { + if (g.douban_id && g.douban_id > 0) { + countMap.set(g.douban_id, (countMap.get(g.douban_id) || 0) + 1); + } + }); + let max = 0; + let res: number | undefined; + countMap.forEach((v, k) => { + if (v > max) { max = v; res = k; } + }); + return res; + })(); + + return { episodes, source_names, douban_id }; }; // 过滤器:非聚合与聚合 const [filterAll, setFilterAll] = useState<{ source: string; title: string; year: string; yearOrder: 'none' | 'asc' | 'desc' }>({ @@ -183,6 +199,9 @@ function SearchPageClient() { if (prevNames !== nextNames) { ref.current.setSourceNames(stats.source_names); } + if (prev.douban_id !== stats.douban_id) { + ref.current.setDoubanId(stats.douban_id); + } groupStatsRef.current.set(mapKey, stats); } }); @@ -748,12 +767,12 @@ function SearchPageClient() { const title = group[0]?.title || ''; const poster = group[0]?.poster || ''; const year = group[0]?.year || 'unknown'; - const { episodes, source_names } = computeGroupStats(group); + const { episodes, source_names, douban_id } = computeGroupStats(group); const type = episodes === 1 ? 'movie' : 'tv'; // 如果该聚合第一次出现,写入初始统计 if (!groupStatsRef.current.has(mapKey)) { - groupStatsRef.current.set(mapKey, { episodes, source_names }); + groupStatsRef.current.set(mapKey, { episodes, source_names, douban_id }); } return ( @@ -767,6 +786,7 @@ function SearchPageClient() { year={year} episodes={episodes} source_names={source_names} + douban_id={douban_id} query={ searchQuery.trim() !== title ? searchQuery.trim() diff --git a/src/components/VideoCard.tsx b/src/components/VideoCard.tsx index d3dece8..84d9fe5 100644 --- a/src/components/VideoCard.tsx +++ b/src/components/VideoCard.tsx @@ -51,6 +51,7 @@ export interface VideoCardProps { export type VideoCardHandle = { setEpisodes: (episodes?: number) => void; setSourceNames: (names?: string[]) => void; + setDoubanId: (id?: number) => void; }; const VideoCard = forwardRef(function VideoCard( @@ -89,6 +90,9 @@ const VideoCard = forwardRef(function VideoCard const [dynamicSourceNames, setDynamicSourceNames] = useState( source_names ); + const [dynamicDoubanId, setDynamicDoubanId] = useState( + douban_id + ); useEffect(() => { setDynamicEpisodes(episodes); @@ -98,16 +102,21 @@ const VideoCard = forwardRef(function VideoCard setDynamicSourceNames(source_names); }, [source_names]); + useEffect(() => { + setDynamicDoubanId(douban_id); + }, [douban_id]); + useImperativeHandle(ref, () => ({ setEpisodes: (eps?: number) => setDynamicEpisodes(eps), setSourceNames: (names?: string[]) => setDynamicSourceNames(names), + setDoubanId: (id?: number) => setDynamicDoubanId(id), })); const actualTitle = title; const actualPoster = poster; const actualSource = source; const actualId = id; - const actualDoubanId = douban_id; + const actualDoubanId = dynamicDoubanId; const actualEpisodes = dynamicEpisodes; const actualYear = year; const actualQuery = query || ''; @@ -321,7 +330,7 @@ const VideoCard = forwardRef(function VideoCard showPlayButton: true, showHeart: true, // 移动端菜单中需要显示收藏选项 showCheckCircle: false, - showDoubanLink: false, + showDoubanLink: true, // 移动端菜单中显示豆瓣链接 showRating: false, showYear: true, }, @@ -663,10 +672,7 @@ const VideoCard = forwardRef(function VideoCard {/* 年份徽章 */} {config.showYear && actualYear && actualYear !== 'unknown' && actualYear.trim() !== '' && (