From 80ae3e8c2178771693018a00c51e08af39a90a6e Mon Sep 17 00:00:00 2001 From: mtvpls Date: Tue, 7 Apr 2026 21:17:18 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BD=AC=E5=AD=98=E6=92=AD=E6=94=BE=E8=A1=A5?= =?UTF-8?q?=E5=85=85=E5=85=83=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/play/page.tsx | 181 ++++++++++++++++++++++------- src/components/EpisodeSelector.tsx | 2 +- src/components/VideoCard.tsx | 4 +- 3 files changed, 145 insertions(+), 42 deletions(-) diff --git a/src/app/play/page.tsx b/src/app/play/page.tsx index 11fd253..1394534 100644 --- a/src/app/play/page.tsx +++ b/src/app/play/page.tsx @@ -572,6 +572,13 @@ function PlayPageClient() { // 纠错后的描述信息(用于显示,不触发 detail 更新) const [correctedDesc, setCorrectedDesc] = useState(''); + const [quarkTempTMDBMeta, setQuarkTempTMDBMeta] = useState<{ + desc?: string; + poster?: string; + year?: string; + tmdbId?: number; + } | null>(null); + const [pendingQuarkTempTMDBData, setPendingQuarkTempTMDBData] = useState(null); // 当前源和ID - source 直接存储完整格式(如 'emby_wumei' 或 'emby') const [currentSource, setCurrentSource] = useState(searchParams.get('source') || ''); @@ -579,6 +586,11 @@ function PlayPageClient() { const [fileName] = useState(searchParams.get('fileName') || ''); // 小雅源:用户点击的文件名 const isDirectPlay = currentSource === 'directplay'; + useEffect(() => { + setQuarkTempTMDBMeta(null); + setPendingQuarkTempTMDBData(null); + }, [currentSource, currentId]); + // 解析 source 参数以获取 embyKey(仅用于 API 调用) const parseSourceForApi = (source: string): { source: string; embyKey?: string } => { if (source.startsWith('emby_')) { @@ -1187,14 +1199,18 @@ function PlayPageClient() { const detCacheAge = Date.now() - detTimestamp; const detCacheMaxAge = 24 * 60 * 60 * 1000; // 1天 - if (detCacheAge < detCacheMaxAge && data && data.backdrop) { - console.log('使用缓存的TMDB详情数据'); - setTmdbBackdrop(processImageUrl(data.backdrop)); + if (detCacheAge < detCacheMaxAge && data) { + if (data.backdrop) { + setTmdbBackdrop(processImageUrl(data.backdrop)); + } else { + setTmdbBackdrop(null); + } // 如果没有豆瓣ID,使用TMDb数据补充 if (!videoDoubanId || videoDoubanId === 0) { populateDoubanFieldsFromTMDB(data); } + populatePlayMetadataFromTMDB(data); return; } } catch (e) { @@ -1215,7 +1231,6 @@ function PlayPageClient() { const response = await fetch(url); if (!response.ok) { - console.log('获取TMDB详情失败'); setTmdbBackdrop(null); return; } @@ -1224,45 +1239,94 @@ function PlayPageClient() { if (result.backdrop) { setTmdbBackdrop(processImageUrl(result.backdrop)); - - // 如果没有豆瓣ID,使用TMDb数据补充 - if (!videoDoubanId || videoDoubanId === 0) { - populateDoubanFieldsFromTMDB(result); - } - - // 保存title到tmdbId的映射到localStorage(1个月) - if (result.tmdbId) { - try { - localStorage.setItem( - mappingCacheKey, - JSON.stringify({ - tmdbId: result.tmdbId, - timestamp: Date.now(), - }) - ); - - // 保存TMDB详情数据到localStorage(1天) - const detailsCacheKey = `tmdb_details_${result.tmdbId}`; - localStorage.setItem( - detailsCacheKey, - JSON.stringify({ - data: result, - timestamp: Date.now(), - }) - ); - } catch (e) { - console.error('保存缓存失败:', e); - } - } } else { setTmdbBackdrop(null); } + + // 如果没有豆瓣ID,使用TMDb数据补充 + if (!videoDoubanId || videoDoubanId === 0) { + populateDoubanFieldsFromTMDB(result); + } + populatePlayMetadataFromTMDB(result); + + // 保存title到tmdbId的映射到localStorage(1个月) + if (result.tmdbId) { + try { + localStorage.setItem( + mappingCacheKey, + JSON.stringify({ + tmdbId: result.tmdbId, + timestamp: Date.now(), + }) + ); + + // 保存TMDB详情数据到localStorage(1天) + const detailsCacheKey = `tmdb_details_${result.tmdbId}`; + localStorage.setItem( + detailsCacheKey, + JSON.stringify({ + data: result, + timestamp: Date.now(), + }) + ); + } catch (e) { + console.error('保存缓存失败:', e); + } + } } catch (error) { console.error('获取TMDB背景图失败:', error); setTmdbBackdrop(null); } }; + const populatePlayMetadataFromTMDB = (tmdbData: any) => { + const currentDetail = detailRef.current; + if (!currentDetail || currentDetail.source !== 'quark-temp') { + setPendingQuarkTempTMDBData(tmdbData); + return; + } + + const tmdbYear = tmdbData.releaseDate?.split('-')[0] || ''; + const shouldReplaceDesc = !currentDetail.desc || currentDetail.desc.startsWith('临时播放目录:'); + + const resolvedTmdbId = typeof tmdbData.tmdbId === 'string' + ? Number(String(tmdbData.tmdbId).split(':')[1] || 0) + : tmdbData.tmdbId; + + setQuarkTempTMDBMeta({ + desc: shouldReplaceDesc ? (tmdbData.overview || currentDetail.desc) : currentDetail.desc, + poster: currentDetail.poster || tmdbData.poster || '', + year: currentDetail.year || tmdbYear, + tmdbId: currentDetail.tmdb_id || resolvedTmdbId, + }); + + setDetail((prev) => { + if (!prev || prev.source !== 'quark-temp') { + return prev; + } + + return { + ...prev, + poster: prev.poster || tmdbData.poster || '', + year: prev.year || tmdbYear, + desc: shouldReplaceDesc ? (tmdbData.overview || prev.desc) : prev.desc, + tmdb_id: prev.tmdb_id || resolvedTmdbId, + }; + }); + + if (tmdbData.overview && (!correctedDesc || currentDetail.desc?.startsWith('临时播放目录:'))) { + setCorrectedDesc(tmdbData.overview); + } + + if (tmdbData.poster && !currentDetail.poster) { + setVideoCover(processImageUrl(tmdbData.poster)); + } + + if (tmdbYear && !currentDetail.year) { + setVideoYear(tmdbYear); + } + }; + // 辅助函数:使用TMDb数据填充豆瓣字段 const populateDoubanFieldsFromTMDB = (tmdbData: any) => { // 设置评分 @@ -1296,6 +1360,45 @@ function PlayPageClient() { fetchTMDBBackdrop(); }, [videoTitle, videoDoubanId, isDirectPlay]); + useEffect(() => { + if ( + pendingQuarkTempTMDBData && + detail?.source === 'quark-temp' + ) { + const pending = pendingQuarkTempTMDBData; + setPendingQuarkTempTMDBData(null); + const tmdbYear = pending.releaseDate?.split('-')[0] || ''; + const shouldReplaceDesc = !detail.desc || detail.desc.startsWith('临时播放目录:'); + const resolvedTmdbId = typeof pending.tmdbId === 'string' + ? Number(String(pending.tmdbId).split(':')[1] || 0) + : pending.tmdbId; + + setQuarkTempTMDBMeta({ + desc: shouldReplaceDesc ? (pending.overview || detail.desc) : detail.desc, + poster: detail.poster || pending.poster || '', + year: detail.year || tmdbYear, + tmdbId: detail.tmdb_id || resolvedTmdbId, + }); + + setDetail((prev) => prev && prev.source === 'quark-temp' ? { + ...prev, + poster: prev.poster || pending.poster || '', + year: prev.year || tmdbYear, + desc: shouldReplaceDesc ? (pending.overview || prev.desc) : prev.desc, + tmdb_id: prev.tmdb_id || resolvedTmdbId, + } : prev); + + if (pending.poster && !detail.poster) { + setVideoCover(processImageUrl(pending.poster)); + } + if (tmdbYear && !detail.year) { + setVideoYear(tmdbYear); + } + if (pending.overview) { + setCorrectedDesc(pending.overview); + } + } + }, [pendingQuarkTempTMDBData, detail]); // 视频播放地址 const [videoUrl, setVideoUrl] = useState(''); @@ -8872,12 +8975,12 @@ function PlayPageClient() { )} {/* 优先使用 doubanYear,如果没有则使用 detail.year 或 videoYear */} - {(doubanYear || detail?.year || videoYear) && ( - {doubanYear || detail?.year || videoYear} + {(doubanYear || quarkTempTMDBMeta?.year || detail?.year || videoYear) && ( + {doubanYear || quarkTempTMDBMeta?.year || detail?.year || videoYear} )} {detail?.source_name && ( @@ -8897,7 +9000,7 @@ function PlayPageClient() { {detail?.type_name && {detail.type_name}} {/* 剧情简介 */} - {(doubanCardSubtitle || correctedDesc || detail?.desc) && ( + {(doubanCardSubtitle || quarkTempTMDBMeta?.desc || correctedDesc || detail?.desc) && (
)} - {correctedDesc || detail?.desc} + {quarkTempTMDBMeta?.desc || correctedDesc || detail?.desc}
)} diff --git a/src/components/EpisodeSelector.tsx b/src/components/EpisodeSelector.tsx index 799bebc..933ba63 100644 --- a/src/components/EpisodeSelector.tsx +++ b/src/components/EpisodeSelector.tsx @@ -940,7 +940,7 @@ const EpisodeSelector: React.FC = ({ {/* 源名称和集数信息 - 垂直居中 */}
diff --git a/src/components/VideoCard.tsx b/src/components/VideoCard.tsx index 95ddcf7..87a3342 100644 --- a/src/components/VideoCard.tsx +++ b/src/components/VideoCard.tsx @@ -1043,7 +1043,7 @@ const VideoCard = forwardRef(function VideoCard > (function VideoCard {config.showSourceName && source_name && !cmsData && (