视频加载失败增加提示

This commit is contained in:
mtvpls
2025-12-18 20:33:18 +08:00
parent bac92c4abe
commit 6f780d66fe
+97 -29
View File
@@ -570,6 +570,7 @@ function PlayPageClient() {
const [videoLoadingStage, setVideoLoadingStage] = useState< const [videoLoadingStage, setVideoLoadingStage] = useState<
'initing' | 'sourceChanging' 'initing' | 'sourceChanging'
>('initing'); >('initing');
const [videoError, setVideoError] = useState<string | null>(null);
// 播放器就绪状态(用于触发 usePlaySync 的事件监听器设置) // 播放器就绪状态(用于触发 usePlaySync 的事件监听器设置)
const [playerReady, setPlayerReady] = useState(false); const [playerReady, setPlayerReady] = useState(false);
@@ -1939,6 +1940,7 @@ function PlayPageClient() {
// 显示换源加载状态 // 显示换源加载状态
setVideoLoadingStage('sourceChanging'); setVideoLoadingStage('sourceChanging');
setIsVideoLoading(true); setIsVideoLoading(true);
setVideoError(null);
// 记录当前播放进度(仅在同一集数切换时恢复) // 记录当前播放进度(仅在同一集数切换时恢复)
const currentPlayTime = artPlayerRef.current?.currentTime || 0; const currentPlayTime = artPlayerRef.current?.currentTime || 0;
@@ -2958,6 +2960,32 @@ function PlayPageClient() {
if (data.fatal) { if (data.fatal) {
switch (data.type) { switch (data.type) {
case Hls.ErrorTypes.NETWORK_ERROR: case Hls.ErrorTypes.NETWORK_ERROR:
// 检查是否是 manifest 加载错误(通常是 403/404/CORS 错误)
if (data.details === 'manifestLoadError') {
console.log('Manifest 加载失败:可能是 403/404 或 CORS 错误');
hls.destroy();
// 检查是否有响应码
const statusCode = data.response?.code || data.response?.status;
if (statusCode === 403) {
setVideoError('访问被拒绝 (403)');
} else if (statusCode === 404) {
setVideoError('视频不存在 (404)');
} else if (statusCode) {
setVideoError(`HTTP ${statusCode} 错误`);
} else {
// CORS 错误或其他网络错误
setVideoError('无法访问视频源(可能是跨域限制或访问被拒绝)');
}
return;
}
// 检查其他 HTTP 错误状态码
const statusCode = data.response?.code || data.response?.status;
if (statusCode && statusCode >= 400) {
console.log(`HTTP ${statusCode} 错误`);
hls.destroy();
setVideoError(`HTTP ${statusCode} 错误`);
return;
}
console.log('网络错误,尝试恢复...'); console.log('网络错误,尝试恢复...');
hls.startLoad(); hls.startLoad();
break; break;
@@ -2968,6 +2996,7 @@ function PlayPageClient() {
default: default:
console.log('无法恢复的错误'); console.log('无法恢复的错误');
hls.destroy(); hls.destroy();
setVideoError('视频加载错误');
break; break;
} }
} }
@@ -3813,6 +3842,7 @@ function PlayPageClient() {
// 隐藏换源加载状态 // 隐藏换源加载状态
setIsVideoLoading(false); setIsVideoLoading(false);
setVideoError(null);
}); });
// 监听视频时间更新事件,实现跳过片头片尾 // 监听视频时间更新事件,实现跳过片头片尾
@@ -4334,39 +4364,77 @@ function PlayPageClient() {
></div> ></div>
{/* 换源加载蒙层 */} {/* 换源加载蒙层 */}
{isVideoLoading && ( {(isVideoLoading || videoError) && (
<div className='absolute inset-0 bg-black/85 backdrop-blur-sm rounded-xl flex items-center justify-center z-[500] transition-all duration-300'> <div className='absolute inset-0 bg-black/85 backdrop-blur-sm rounded-xl flex items-center justify-center z-[500] transition-all duration-300'>
<div className='text-center max-w-md mx-auto px-6'> <div className='text-center max-w-md mx-auto px-6'>
{/* 动画影院图标 */} {videoError ? (
<div className='relative mb-8'> // 错误显示
<div className='relative mx-auto w-24 h-24 bg-gradient-to-r from-green-500 to-emerald-600 rounded-2xl shadow-2xl flex items-center justify-center transform hover:scale-105 transition-transform duration-300'> <>
<div className='text-white text-4xl'>🎬</div> {/* 错误图标 */}
{/* 旋转光环 */} <div className='relative mb-8'>
<div className='absolute -inset-2 bg-gradient-to-r from-green-500 to-emerald-600 rounded-2xl opacity-20 animate-spin'></div> <div className='relative mx-auto w-24 h-24 bg-gradient-to-r from-red-500 to-rose-600 rounded-2xl shadow-2xl flex items-center justify-center'>
</div> <div className='text-white text-4xl'></div>
</div>
</div>
{/* 浮动粒子效果 */} {/* 错误消息 */}
<div className='absolute top-0 left-0 w-full h-full pointer-events-none'> <div className='space-y-4'>
<div className='absolute top-2 left-2 w-2 h-2 bg-green-400 rounded-full animate-bounce'></div> <p className='text-xl font-semibold text-white'>
<div
className='absolute top-4 right-4 w-1.5 h-1.5 bg-emerald-400 rounded-full animate-bounce' </p>
style={{ animationDelay: '0.5s' }} <p className='text-base text-gray-300'>
></div> {videoError}
<div </p>
className='absolute bottom-3 left-6 w-1 h-1 bg-lime-400 rounded-full animate-bounce' <button
style={{ animationDelay: '1s' }} onClick={() => {
></div> setVideoError(null);
</div> setIsVideoLoading(true);
</div> // 重新加载视频
if (artPlayerRef.current) {
artPlayerRef.current.url = videoUrl;
}
}}
className='mt-4 px-6 py-2 bg-gradient-to-r from-green-500 to-emerald-600 text-white rounded-lg hover:from-green-600 hover:to-emerald-700 transition-all duration-200'
>
</button>
</div>
</>
) : (
// 加载显示
<>
{/* 动画影院图标 */}
<div className='relative mb-8'>
<div className='relative mx-auto w-24 h-24 bg-gradient-to-r from-green-500 to-emerald-600 rounded-2xl shadow-2xl flex items-center justify-center transform hover:scale-105 transition-transform duration-300'>
<div className='text-white text-4xl'>🎬</div>
{/* 旋转光环 */}
<div className='absolute -inset-2 bg-gradient-to-r from-green-500 to-emerald-600 rounded-2xl opacity-20 animate-spin'></div>
</div>
{/* 换源消息 */} {/* 浮动粒子效果 */}
<div className='space-y-2'> <div className='absolute top-0 left-0 w-full h-full pointer-events-none'>
<p className='text-xl font-semibold text-white animate-pulse'> <div className='absolute top-2 left-2 w-2 h-2 bg-green-400 rounded-full animate-bounce'></div>
{videoLoadingStage === 'sourceChanging' <div
? '🔄 切换播放源...' className='absolute top-4 right-4 w-1.5 h-1.5 bg-emerald-400 rounded-full animate-bounce'
: '🔄 视频加载中...'} style={{ animationDelay: '0.5s' }}
</p> ></div>
</div> <div
className='absolute bottom-3 left-6 w-1 h-1 bg-lime-400 rounded-full animate-bounce'
style={{ animationDelay: '1s' }}
></div>
</div>
</div>
{/* 换源消息 */}
<div className='space-y-2'>
<p className='text-xl font-semibold text-white animate-pulse'>
{videoLoadingStage === 'sourceChanging'
? '🔄 切换播放源...'
: '🔄 视频加载中...'}
</p>
</div>
</>
)}
</div> </div>
</div> </div>
)} )}