From 897d475ad550c1ed36ca4737151c1d41579efee0 Mon Sep 17 00:00:00 2001 From: mtvpls Date: Sat, 18 Apr 2026 09:33:38 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E6=97=A5=E6=9C=9F=E6=9C=AA?= =?UTF-8?q?=E7=9F=A5=E5=92=8C=E4=BF=AE=E6=AD=A3=E9=A1=B5=E9=9D=A2=E5=AE=9A?= =?UTF-8?q?=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/layout.tsx | 2 ++ src/app/manga/detail/page.tsx | 11 +++++++---- src/app/manga/read/page.tsx | 18 ++++++++++++++++++ src/components/RouteScrollReset.tsx | 27 +++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 src/components/RouteScrollReset.tsx diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 71f2f16..c3ca802 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -16,6 +16,7 @@ import { SiteProvider } from '../components/SiteProvider'; import { ThemeProvider } from '../components/ThemeProvider'; import { TokenRefreshManager } from '../components/TokenRefreshManager'; import TopProgressBar from '../components/TopProgressBar'; +import RouteScrollReset from '../components/RouteScrollReset'; import ChatFloatingWindow from '../components/watch-room/ChatFloatingWindow'; import { WatchRoomProvider } from '../components/WatchRoomProvider'; import { DownloadProvider } from '../contexts/DownloadContext'; @@ -268,6 +269,7 @@ export default async function RootLayout({ disableTransitionOnChange > + diff --git a/src/app/manga/detail/page.tsx b/src/app/manga/detail/page.tsx index b032356..e934996 100644 --- a/src/app/manga/detail/page.tsx +++ b/src/app/manga/detail/page.tsx @@ -48,7 +48,7 @@ function MangaDetailSkeleton() { ); } -function formatChapterMeta(chapter: MangaChapter): string { +function formatChapterMeta(chapter: MangaChapter): string | null { if (typeof chapter.pageCount === 'number' && chapter.pageCount > 0) { return `${chapter.pageCount} 页`; } @@ -64,7 +64,7 @@ function formatChapterMeta(chapter: MangaChapter): string { } } - return '日期未知'; + return null; } export default function MangaDetailPage() { @@ -264,8 +264,11 @@ export default function MangaDetailPage() { )}
- {formatChapterMeta(chapter)} - {active && currentRecord ? ` · 上次看到第 ${currentRecord.pageIndex + 1} 页` : ''} + {(() => { + const meta = formatChapterMeta(chapter); + const progress = active && currentRecord ? `上次看到第 ${currentRecord.pageIndex + 1} 页` : null; + return [meta, progress].filter(Boolean).join(' · '); + })()}
); diff --git a/src/app/manga/read/page.tsx b/src/app/manga/read/page.tsx index af9495c..764d71d 100644 --- a/src/app/manga/read/page.tsx +++ b/src/app/manga/read/page.tsx @@ -102,6 +102,7 @@ export default function MangaReadPage() { const requestVerticalPageSyncRef = useRef<(() => void) | null>(null); const currentVerticalPageIndexRef = useRef(0); const preloadedImageUrlsRef = useRef>(new Set()); + const activeChapterRef = useRef(null); const getCurrentVerticalPageIndex = () => { if (!verticalPageRefs.current.length) return 0; @@ -642,6 +643,22 @@ export default function MangaReadPage() { [chapterList, chapterListDesc] ); + useEffect(() => { + if (!chapterListOpen) return; + + const rafId = window.requestAnimationFrame(() => { + activeChapterRef.current?.scrollIntoView({ + block: 'center', + inline: 'nearest', + behavior: 'auto', + }); + }); + + return () => { + window.cancelAnimationFrame(rafId); + }; + }, [chapterId, chapterListOpen, orderedChapterList]); + const pagedItems = useMemo(() => { if (readMode === 'single') { return pages[activePage] ? [pages[activePage]] : []; @@ -798,6 +815,7 @@ export default function MangaReadPage() { return ( { + if (typeof window === 'undefined' || !pathname?.startsWith('/manga') || pathname === '/manga/read') return; + + const reset = () => { + window.scrollTo({ top: 0, left: 0, behavior: 'auto' }); + document.documentElement.scrollTop = 0; + document.body.scrollTop = 0; + }; + + reset(); + const rafId = window.requestAnimationFrame(reset); + + return () => { + window.cancelAnimationFrame(rafId); + }; + }, [pathname]); + + return null; +}