bug处理

This commit is contained in:
truewhile
2026-10-02 13:14:29 +08:00
parent b8648f0049
commit 83ec494a36
4 changed files with 251 additions and 50 deletions
+44 -16
View File
@@ -16,29 +16,57 @@ interface ReaderComicProps {
onScrolled: () => void
}
function ComicImage({ src, theme }: { src: string; theme: { bg: string; text: string; accent: string } }) {
function ComicImage({
src,
theme,
fit = false,
}: {
src: string
theme: { bg: string; text: string; accent: string }
// fit:单页模式用。整页缩放至视口内,长图不再被 overflow-hidden 的容器裁掉。
fit?: boolean
}) {
const [state, setState] = useState<'loading' | 'ok' | 'error'>('loading')
// 换章后 src 变了要重新回到 loading:否则上一章加载失败的第 N 张会一直
// 显示「图片加载失败」,而 key 不变(滚动模式按序号做 key)不会重挂载。
useEffect(() => {
setState('loading')
}, [src])
// <img> 必须始终留在渲染树里(不能 display:none):浏览器不会去拉取
// display:none 的 loading="lazy" 图片,onLoad 就永远不会触发,于是更没机会
// 脱离 loading —— 之前用 hidden 藏图就死在这里,漫画只剩一个转圈。
// 改成图片正常参与布局,未加载时用 minHeight 占位,转圈/失败信息盖在上层。
return (
<div className="relative w-full">
<div
className={`relative flex w-full items-center justify-center ${fit ? 'h-full' : ''}`}
style={{ backgroundColor: theme.bg }}
>
<img
src={src}
loading="lazy"
alt=""
onLoad={() => setState('ok')}
onError={() => setState('error')}
className={fit ? 'block max-h-full w-auto max-w-full object-contain' : 'block w-full'}
style={state === 'ok' ? undefined : { minHeight: '10rem' }}
/>
{state === 'loading' && (
<div className="flex h-64 w-full items-center justify-center" style={{ color: theme.text }}>
<div
className="pointer-events-none absolute inset-0 flex items-center justify-center"
style={{ color: theme.text }}
>
<Loader2 className="animate-spin opacity-50" size={22} />
</div>
)}
{state === 'error' ? (
<div className="flex h-40 w-full items-center justify-center text-xs opacity-50" style={{ color: theme.text }}>
{state === 'error' && (
<div
className="pointer-events-none absolute inset-0 flex items-center justify-center text-xs opacity-60"
style={{ color: theme.text }}
>
图片加载失败
</div>
) : (
<img
src={src}
loading="lazy"
alt=""
onLoad={() => setState('ok')}
onError={() => setState('error')}
className={`block w-full ${state === 'loading' ? 'hidden' : ''}`}
style={{ backgroundColor: theme.bg }}
/>
)}
</div>
)
@@ -83,7 +111,7 @@ export function ReaderComic({ images, theme, mode, page, onZone, initialImage, o
const idx = Math.min(Math.max(page, 0), images.length - 1)
return (
<div className="flex h-full items-center justify-center">
<ComicImage key={images[idx]} src={images[idx]} theme={theme} />
<ComicImage key={images[idx]} src={images[idx]} theme={theme} fit />
</div>
)
}