From 4b79152fa67ddaecbbade7dc559d3ef7f15ad81f Mon Sep 17 00:00:00 2001 From: mtvpls Date: Thu, 28 May 2026 21:56:46 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A8=E6=BC=AB=E5=A4=87=E7=94=A8=E6=BA=90?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E6=97=B6=E6=B8=85=E9=99=A4=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E5=A4=87=E7=94=A8=E6=BA=90=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ProxyImage.tsx | 6 +++++ src/components/VideoCard.tsx | 9 +++++++ src/lib/utils.ts | 45 +++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+) diff --git a/src/components/ProxyImage.tsx b/src/components/ProxyImage.tsx index 7f9e2fa..e8a16d2 100644 --- a/src/components/ProxyImage.tsx +++ b/src/components/ProxyImage.tsx @@ -3,6 +3,7 @@ import React, { useEffect, useMemo, useRef, useState } from 'react'; import { + clearBangumiImageFallbackCacheIfFailed, processImageUrl, tryApplyBangumiImageFallback, tryApplyDoubanImageFallback, @@ -65,6 +66,11 @@ const ProxyImage: React.FC = ({ return; } + if (clearBangumiImageFallbackCacheIfFailed(img, originalSrc)) { + setCurrentSrc(processImageUrl(originalSrc)); + return; + } + if (retryOnError && !img.dataset.retried) { img.dataset.retried = 'true'; window.setTimeout(() => { diff --git a/src/components/VideoCard.tsx b/src/components/VideoCard.tsx index f55b7dd..2bf72f8 100644 --- a/src/components/VideoCard.tsx +++ b/src/components/VideoCard.tsx @@ -35,6 +35,7 @@ import { import { isNetdiskSource } from '@/lib/netdisk/source'; import { base58Decode, + clearBangumiImageFallbackCacheIfFailed, getBangumiImageFallbackUrl, getDoubanImageFallbackUrl, markBangumiImageFallbackActive, @@ -981,6 +982,14 @@ const VideoCard = forwardRef( return; } + if ( + clearBangumiImageFallbackCacheIfFailed(img, actualPoster) + ) { + clearBangumiImageTimeout(); + setDisplayPoster(processedPoster); + return; + } + // 图片加载失败时的重试机制 if (!img.dataset.retried) { img.dataset.retried = 'true'; diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 85db5d2..3396eda 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -233,6 +233,47 @@ export function markBangumiImageFallbackActive(): void { ); } +function normalizeComparableUrl(url: string): string { + if (typeof window === 'undefined') return url; + + try { + return new URL(url, window.location.href).href; + } catch { + return url; + } +} + +export function clearBangumiImageFallbackCacheIfFailed( + target: HTMLImageElement, + originalUrl: string +): boolean { + if (!originalUrl || !isBangumiImageUrl(originalUrl)) { + return false; + } + + const fallbackUrl = getBangumiImageFallbackUrl(originalUrl); + if (!fallbackUrl) { + return false; + } + + const normalizedFallbackUrl = normalizeComparableUrl(fallbackUrl); + const failedUrls = [target.currentSrc, target.src] + .filter(Boolean) + .map(normalizeComparableUrl); + const isFallbackFailure = + target.dataset.bangumiBackupTried === 'true' || + failedUrls.includes(normalizedFallbackUrl); + + if (!isFallbackFailure) { + return false; + } + + target.dataset.bangumiBackupFailed = 'true'; + delete target.dataset.bangumiBackupTried; + clearBangumiImageFallbackCache(); + return true; +} + function isBangumiImageFallbackActive(): boolean { if (typeof window === 'undefined') return false; @@ -329,6 +370,10 @@ export function tryApplyBangumiImageFallback( return false; } + if (target.dataset.bangumiBackupFailed === 'true') { + return false; + } + const fallbackUrl = getBangumiImageFallbackUrl(originalUrl); if ( !fallbackUrl ||