移动云盘在线播放
This commit is contained in:
+57
-39
@@ -8,8 +8,8 @@ import { Suspense, useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import { getAuthInfoFromBrowserCookie } from '@/lib/auth';
|
||||
import {
|
||||
convertDanmakuFormat,
|
||||
clearDanmakuCacheByTitle,
|
||||
convertDanmakuFormat,
|
||||
getDanmakuById,
|
||||
getDanmakuFromCache,
|
||||
getEpisodes,
|
||||
@@ -54,12 +54,13 @@ import {
|
||||
pruneLocalEpisodeProgressStorage,
|
||||
saveLocalEpisodeProgress,
|
||||
} from '@/lib/episode-progress';
|
||||
import { getTMDBImageUrl } from '@/lib/tmdb.search';
|
||||
import { isNetdiskSource, normalizeNetdiskSource } from '@/lib/netdisk/source';
|
||||
import {
|
||||
getRecommendationCache,
|
||||
recommendationCacheKeys,
|
||||
setRecommendationCache,
|
||||
} from '@/lib/recommendations/cache';
|
||||
import { getTMDBImageUrl } from '@/lib/tmdb.search';
|
||||
import { DanmakuFilterConfig, EpisodeFilterConfig, SearchResult } from '@/lib/types';
|
||||
import { base58Decode, getVideoResolutionFromM3u8, processImageUrl } from '@/lib/utils';
|
||||
import { useEnableAIComments } from '@/hooks/useEnableAIComments';
|
||||
@@ -605,27 +606,28 @@ function PlayPageClient() {
|
||||
|
||||
// 纠错后的描述信息(用于显示,不触发 detail 更新)
|
||||
const [correctedDesc, setCorrectedDesc] = useState<string>('');
|
||||
const [quarkTempTMDBMeta, setQuarkTempTMDBMeta] = useState<{
|
||||
const [netdiskTMDBMeta, setNetdiskTMDBMeta] = useState<{
|
||||
desc?: string;
|
||||
poster?: string;
|
||||
year?: string;
|
||||
tmdbId?: number;
|
||||
} | null>(null);
|
||||
const [pendingQuarkTempTMDBData, setPendingQuarkTempTMDBData] = useState<any | null>(null);
|
||||
const [pendingNetdiskTMDBData, setPendingNetdiskTMDBData] = useState<any | null>(null);
|
||||
|
||||
// 当前源和ID - source 直接存储完整格式(如 'emby_wumei' 或 'emby')
|
||||
const [currentSource, setCurrentSource] = useState(searchParams.get('source') || '');
|
||||
const [currentSource, setCurrentSource] = useState(normalizeNetdiskSource(searchParams.get('source')) || '');
|
||||
const [currentId, setCurrentId] = useState(searchParams.get('id') || '');
|
||||
const [fileName] = useState(searchParams.get('fileName') || ''); // 小雅源:用户点击的文件名
|
||||
const isDirectPlay = currentSource === 'directplay';
|
||||
|
||||
useEffect(() => {
|
||||
setQuarkTempTMDBMeta(null);
|
||||
setPendingQuarkTempTMDBData(null);
|
||||
setNetdiskTMDBMeta(null);
|
||||
setPendingNetdiskTMDBData(null);
|
||||
}, [currentSource, currentId]);
|
||||
|
||||
// 解析 source 参数以获取 embyKey(仅用于 API 调用)
|
||||
const parseSourceForApi = (source: string): { source: string; embyKey?: string } => {
|
||||
source = normalizeNetdiskSource(source);
|
||||
if (source.startsWith('emby_')) {
|
||||
const key = source.substring(5);
|
||||
return { source: 'emby', embyKey: key };
|
||||
@@ -1300,19 +1302,22 @@ function PlayPageClient() {
|
||||
|
||||
const populatePlayMetadataFromTMDB = (tmdbData: any) => {
|
||||
const currentDetail = detailRef.current;
|
||||
if (!currentDetail || currentDetail.source !== 'quark-temp') {
|
||||
setPendingQuarkTempTMDBData(tmdbData);
|
||||
if (!currentDetail || !isNetdiskSource(currentDetail.source)) {
|
||||
setPendingNetdiskTMDBData(tmdbData);
|
||||
return;
|
||||
}
|
||||
|
||||
const tmdbYear = tmdbData.releaseDate?.split('-')[0] || '';
|
||||
const shouldReplaceDesc = !currentDetail.desc || currentDetail.desc.startsWith('临时播放目录:');
|
||||
const shouldReplaceDesc =
|
||||
!currentDetail.desc ||
|
||||
currentDetail.desc.startsWith('临时播放目录:') ||
|
||||
currentDetail.desc.startsWith('移动云盘分享:');
|
||||
|
||||
const resolvedTmdbId = typeof tmdbData.tmdbId === 'string'
|
||||
? Number(String(tmdbData.tmdbId).split(':')[1] || 0)
|
||||
: tmdbData.tmdbId;
|
||||
|
||||
setQuarkTempTMDBMeta({
|
||||
setNetdiskTMDBMeta({
|
||||
desc: shouldReplaceDesc ? (tmdbData.overview || currentDetail.desc) : currentDetail.desc,
|
||||
poster: currentDetail.poster || tmdbData.poster || '',
|
||||
year: currentDetail.year || tmdbYear,
|
||||
@@ -1320,7 +1325,7 @@ function PlayPageClient() {
|
||||
});
|
||||
|
||||
setDetail((prev) => {
|
||||
if (!prev || prev.source !== 'quark-temp') {
|
||||
if (!prev || !isNetdiskSource(prev.source)) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
@@ -1381,25 +1386,32 @@ function PlayPageClient() {
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
pendingQuarkTempTMDBData &&
|
||||
detail?.source === 'quark-temp'
|
||||
pendingNetdiskTMDBData &&
|
||||
isNetdiskSource(detail?.source)
|
||||
) {
|
||||
const pending = pendingQuarkTempTMDBData;
|
||||
setPendingQuarkTempTMDBData(null);
|
||||
const currentDetail = detail;
|
||||
if (!currentDetail) {
|
||||
return;
|
||||
}
|
||||
const pending = pendingNetdiskTMDBData;
|
||||
setPendingNetdiskTMDBData(null);
|
||||
const tmdbYear = pending.releaseDate?.split('-')[0] || '';
|
||||
const shouldReplaceDesc = !detail.desc || detail.desc.startsWith('临时播放目录:');
|
||||
const shouldReplaceDesc =
|
||||
!currentDetail.desc ||
|
||||
currentDetail.desc.startsWith('临时播放目录:') ||
|
||||
currentDetail.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,
|
||||
setNetdiskTMDBMeta({
|
||||
desc: shouldReplaceDesc ? (pending.overview || currentDetail.desc) : currentDetail.desc,
|
||||
poster: currentDetail.poster || pending.poster || '',
|
||||
year: currentDetail.year || tmdbYear,
|
||||
tmdbId: currentDetail.tmdb_id || resolvedTmdbId,
|
||||
});
|
||||
|
||||
setDetail((prev) => prev && prev.source === 'quark-temp' ? {
|
||||
setDetail((prev) => prev && isNetdiskSource(prev.source) ? {
|
||||
...prev,
|
||||
poster: prev.poster || pending.poster || '',
|
||||
year: prev.year || tmdbYear,
|
||||
@@ -1407,17 +1419,17 @@ function PlayPageClient() {
|
||||
tmdb_id: prev.tmdb_id || resolvedTmdbId,
|
||||
} : prev);
|
||||
|
||||
if (pending.poster && !detail.poster) {
|
||||
if (pending.poster && !currentDetail.poster) {
|
||||
setVideoCover(processImageUrl(pending.poster));
|
||||
}
|
||||
if (tmdbYear && !detail.year) {
|
||||
if (tmdbYear && !currentDetail.year) {
|
||||
setVideoYear(tmdbYear);
|
||||
}
|
||||
if (pending.overview) {
|
||||
setCorrectedDesc(pending.overview);
|
||||
}
|
||||
}
|
||||
}, [pendingQuarkTempTMDBData, detail]);
|
||||
}, [pendingNetdiskTMDBData, detail]);
|
||||
|
||||
// 视频播放地址
|
||||
const [videoUrl, setVideoUrl] = useState('');
|
||||
@@ -1535,7 +1547,7 @@ function PlayPageClient() {
|
||||
!isM3u8LikeUrl(videoUrl) &&
|
||||
(
|
||||
detail.source === 'openlist' ||
|
||||
detail.source === 'quark-temp' ||
|
||||
isNetdiskSource(detail.source) ||
|
||||
detail.source === 'xiaoya' ||
|
||||
detail.source.startsWith('emby')
|
||||
)
|
||||
@@ -4165,7 +4177,7 @@ function PlayPageClient() {
|
||||
|
||||
// 监听 URL 参数变化,处理换源和换视频(用于房员跟随房主操作)
|
||||
useEffect(() => {
|
||||
const urlSource = searchParams.get('source');
|
||||
const urlSource = normalizeNetdiskSource(searchParams.get('source'));
|
||||
const urlId = searchParams.get('id');
|
||||
|
||||
// 只在URL参数存在且与当前状态不同时才处理
|
||||
@@ -9639,12 +9651,12 @@ function PlayPageClient() {
|
||||
</span>
|
||||
)}
|
||||
{/* 优先使用 doubanYear,如果没有则使用 detail.year 或 videoYear */}
|
||||
{(doubanYear || quarkTempTMDBMeta?.year || detail?.year || videoYear) && (
|
||||
<span>{doubanYear || quarkTempTMDBMeta?.year || detail?.year || videoYear}</span>
|
||||
{(doubanYear || netdiskTMDBMeta?.year || detail?.year || videoYear) && (
|
||||
<span>{doubanYear || netdiskTMDBMeta?.year || detail?.year || videoYear}</span>
|
||||
)}
|
||||
{detail?.source_name && (
|
||||
<span
|
||||
className={`relative group cursor-pointer border px-2 py-[1px] rounded ${detail.source === 'xiaoya' ? 'border-blue-500' : detail.source === 'quark-temp' ? 'border-purple-500' : detail.source === 'openlist' || detail.source === 'emby' || detail.source?.startsWith('emby_') ? 'border-yellow-500' : 'border-gray-500/60'
|
||||
className={`relative group cursor-pointer border px-2 py-[1px] rounded ${detail.source === 'xiaoya' ? 'border-blue-500' : isNetdiskSource(detail.source) ? 'border-purple-500' : detail.source === 'openlist' || detail.source === 'emby' || detail.source?.startsWith('emby_') ? 'border-yellow-500' : 'border-gray-500/60'
|
||||
}`}
|
||||
onClick={fetchCurrentSourceVideoInfo}
|
||||
>
|
||||
@@ -9664,7 +9676,7 @@ function PlayPageClient() {
|
||||
{detail?.type_name && <span>{detail.type_name}</span>}
|
||||
</div>
|
||||
{/* 剧情简介 */}
|
||||
{(doubanCardSubtitle || quarkTempTMDBMeta?.desc || correctedDesc || detail?.desc) && (
|
||||
{(doubanCardSubtitle || netdiskTMDBMeta?.desc || correctedDesc || detail?.desc) && (
|
||||
<div
|
||||
className={`mt-0 text-base leading-relaxed opacity-90 overflow-y-auto pr-2 flex-1 min-h-0 scrollbar-hide ${tmdbBackdrop ? 'text-white' : ''}`}
|
||||
style={{ whiteSpace: 'pre-line' }}
|
||||
@@ -9675,7 +9687,7 @@ function PlayPageClient() {
|
||||
{doubanCardSubtitle}
|
||||
</div>
|
||||
)}
|
||||
{quarkTempTMDBMeta?.desc || correctedDesc || detail?.desc}
|
||||
{netdiskTMDBMeta?.desc || correctedDesc || detail?.desc}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -9720,9 +9732,15 @@ function PlayPageClient() {
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<span className='text-gray-600 dark:text-gray-400'>
|
||||
封面图片
|
||||
</span>
|
||||
isNetdiskSource(detail?.source) ? (
|
||||
<div className='flex flex-col items-center justify-center text-gray-500 dark:text-gray-400'>
|
||||
<Cloud className='w-16 h-16 opacity-80' />
|
||||
</div>
|
||||
) : (
|
||||
<span className='text-gray-600 dark:text-gray-400'>
|
||||
封面图片
|
||||
</span>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -9929,7 +9947,7 @@ function PlayPageClient() {
|
||||
// 特殊源使用 tmdb,其他使用 cms(通过 doubanId)
|
||||
// 如果有豆瓣ID且不为0,传入doubanId
|
||||
detail.source === 'openlist' ||
|
||||
detail.source === 'quark-temp' ||
|
||||
isNetdiskSource(detail.source) ||
|
||||
detail.source?.startsWith('emby') ||
|
||||
detail.source === 'xiaoya'
|
||||
? undefined
|
||||
@@ -9940,7 +9958,7 @@ function PlayPageClient() {
|
||||
tmdbId={
|
||||
// 特殊源使用 tmdb
|
||||
detail.source === 'openlist' ||
|
||||
detail.source === 'quark-temp' ||
|
||||
isNetdiskSource(detail.source) ||
|
||||
detail.source?.startsWith('emby') ||
|
||||
detail.source === 'xiaoya'
|
||||
? detail.tmdb_id
|
||||
@@ -9952,7 +9970,7 @@ function PlayPageClient() {
|
||||
// 非特殊源使用 cms 数据
|
||||
// 但如果有豆瓣ID且不为0,则不传入cmsData,优先使用豆瓣数据
|
||||
detail.source !== 'openlist' &&
|
||||
detail.source !== 'quark-temp' &&
|
||||
!isNetdiskSource(detail.source) &&
|
||||
!detail.source?.startsWith('emby') &&
|
||||
detail.source !== 'xiaoya' &&
|
||||
!(detail.douban_id && detail.douban_id !== 0)
|
||||
|
||||
Reference in New Issue
Block a user