fix legacy library scan and empty pages

This commit is contained in:
ShukeBta
2026-07-01 22:51:33 +08:00
parent e18f73ed3c
commit 0493823b99
17 changed files with 536 additions and 33 deletions
+15 -7
View File
@@ -28,13 +28,21 @@ class AppErrorBoundary extends Component<{ children: ReactNode }, { hasError: bo
<p className="mt-2 text-sm text-gray-500">
当前页面遇到异常,刷新后会重新加载资源和登录状态。
</p>
<button
type="button"
onClick={() => window.location.reload()}
className="mt-5 rounded-xl bg-gray-950 px-4 py-2 text-sm font-bold text-white hover:bg-gray-800"
>
刷新页面
</button>
<div className="mt-5 flex flex-wrap items-center gap-3">
<a
href="/"
className="rounded-xl bg-gray-950 px-4 py-2 text-sm font-bold text-white hover:bg-gray-800"
>
返回首页
</a>
<button
type="button"
onClick={() => window.location.reload()}
className="rounded-xl border border-gray-300 px-4 py-2 text-sm font-bold text-gray-700 hover:bg-gray-100"
>
刷新页面
</button>
</div>
</div>
</div>
)
+4 -1
View File
@@ -4,6 +4,7 @@ import clsx from 'clsx'
import { AppFooter } from './AppFooter'
import { LayoutSidebarContent, type LayoutSidebarContentProps } from './LayoutSidebarContent'
import { RouteErrorBoundary } from './RouteErrorBoundary'
import type { useLayoutSidebar } from './useLayoutSidebar'
type LayoutSidebarState = ReturnType<typeof useLayoutSidebar>
@@ -120,7 +121,9 @@ export function LayoutWorkspace({ routeKey }: LayoutWorkspaceProps) {
exit={{ opacity: 0, y: -6 }}
transition={{ duration: 0.25, ease: 'easeOut' }}
>
<Outlet />
<RouteErrorBoundary>
<Outlet />
</RouteErrorBoundary>
</motion.div>
</AnimatePresence>
</div>
+53
View File
@@ -0,0 +1,53 @@
import { Component, type ErrorInfo, type ReactNode } from 'react'
import { useNavigate } from 'react-router-dom'
/**
* 路由级错误边界:只包住当前路由内容(Outlet),崩溃时侧边栏 / 顶栏仍然保留,
* 用户可以点「返回首页」或直接用侧边栏切换到别的页面(切换 pathname 会让父层
* 的 keyed motion.div 重新挂载本边界,从而自动恢复),避免整页只剩一个刷新按钮
* 导致「无法返回」。
*/
function RouteErrorFallback() {
const navigate = useNavigate()
return (
<div className="flex flex-col items-center justify-center py-24 text-center">
<p className="text-lg font-bold text-ink-600">页面加载失败</p>
<p className="mt-2 max-w-md text-sm text-sand-500">
当前页面遇到异常。你可以返回首页继续使用,或刷新后重试;其他页面不受影响。
</p>
<div className="mt-5 flex flex-wrap items-center justify-center gap-3">
<button
type="button"
onClick={() => navigate('/')}
className="rounded-xl bg-gray-950 px-4 py-2 text-sm font-bold text-white hover:bg-gray-800"
>
返回首页
</button>
<button
type="button"
onClick={() => window.location.reload()}
className="rounded-xl border border-gray-300 px-4 py-2 text-sm font-bold text-ink-600 hover:bg-gray-100"
>
刷新页面
</button>
</div>
</div>
)
}
export class RouteErrorBoundary extends Component<{ children: ReactNode }, { hasError: boolean }> {
state = { hasError: false }
static getDerivedStateFromError() {
return { hasError: true }
}
componentDidCatch(error: Error, info: ErrorInfo) {
console.error('MediaStationGo route crashed', error, info)
}
render() {
if (this.state.hasError) return <RouteErrorFallback />
return this.props.children
}
}
+10 -6
View File
@@ -154,9 +154,11 @@ async function loadAllSeriesCards(
let collected: SeriesCard[] = []
for (;;) {
const data = await libraryAPI.listSeries(libraryID, page, pageSize)
collected = collected.concat(data.items)
onPage({ items: collected, total: data.total, firstPage: page === 1 })
if (collected.length >= data.total || data.items.length < pageSize) break
// 后端对空库可能返回 items: null(Go nil slice);不兜底会 concat 出 [null] 并崩溃。
const pageItems = data.items ?? []
collected = collected.concat(pageItems)
onPage({ items: collected, total: data.total ?? collected.length, firstPage: page === 1 })
if (collected.length >= (data.total ?? 0) || pageItems.length < pageSize) break
page += 1
}
return { items: collected }
@@ -171,9 +173,11 @@ async function loadAllMedia(
let collected: Media[] = []
for (;;) {
const data = await libraryAPI.listMedia(libraryID, page, pageSize)
collected = collected.concat(data.items)
onPage({ items: collected, total: data.total, firstPage: page === 1 })
if (collected.length >= data.total || data.items.length < pageSize) break
// 后端对空库可能返回 items: null(Go nil slice);不兜底会 concat 出 [null] 并崩溃。
const pageItems = data.items ?? []
collected = collected.concat(pageItems)
onPage({ items: collected, total: data.total ?? collected.length, firstPage: page === 1 })
if (collected.length >= (data.total ?? 0) || pageItems.length < pageSize) break
page += 1
}
return { items: collected }
+1
View File
@@ -74,6 +74,7 @@ function compactSeriesKey(raw: string): string {
}
export function isEpisodeLike(media: Media): boolean {
if (!media) return false
return (media.season_num ?? 0) > 0 || (media.episode_num ?? 0) > 0
}