perf(frontend,config): parallelize auth, virtualize logs, cache public configs

Frontend layout renders immediately; pages gate via RequireAuth and
useAuthRedirect. Login/register skip getUserInfo. Admin log panel uses
useVirtualizer to avoid 2000-row DOM. ListVisibleSystemConfigs caches
visibility=1 configs in Redis with invalidation on create/update.
PERFORMANCE.md marks completed optimizations.
This commit is contained in:
ryan
2026-06-17 11:41:24 +08:00
parent 6a8f9a7aea
commit ca21e0eca7
13 changed files with 427 additions and 165 deletions
+8 -25
View File
@@ -1,35 +1,18 @@
"use client"
import { AdminUsersProvider } from "@/contexts/admin-users-context"
import { useUser } from "@/contexts/user-context"
import { LoadingPage } from "@/components/layout/loading"
import { ErrorPage } from "@/components/layout/error"
import {AdminUsersProvider} from "@/contexts/admin-users-context"
import {RequireAdminAuth} from "@/components/auth/require-auth"
export default function AdminLayout({
children,
}: {
children: React.ReactNode
}) {
const { user, loading } = useUser()
/* 等待用户信息加载完成 */
if (loading) {
return <LoadingPage text="管理后台" badgeText="管理" />
}
/* 权限检查:只有管理员才能访问 */
if (!user?.is_admin) {
return (
<ErrorPage
title="访问被拒绝"
message="您没有权限访问此页面"
/>
)
}
return (
<AdminUsersProvider>
{children}
</AdminUsersProvider>
<RequireAdminAuth>
<AdminUsersProvider>
{children}
</AdminUsersProvider>
</RequireAdminAuth>
)
}
}
+3
View File
@@ -3,11 +3,13 @@
import * as React from "react"
import {motion} from "motion/react"
import {RequireAuth} from "@/components/auth/require-auth"
import {UserFileManager} from "@/components/common/user/file-manager"
import {FolderOpen} from "lucide-react"
export default function UserFilesPage() {
return (
<RequireAuth>
<motion.div
initial={{ opacity: 0, y: 15 }}
animate={{ opacity: 1, y: 0 }}
@@ -26,5 +28,6 @@ export default function UserFilesPage() {
<UserFileManager />
</motion.div>
</RequireAuth>
)
}
+5 -22
View File
@@ -1,13 +1,12 @@
"use client"
import {motion} from "motion/react"
import {usePathname, useRouter} from "next/navigation"
import {useEffect, useState} from "react"
import {usePathname} from "next/navigation"
import {useState} from "react"
import {AppSidebar} from "@/components/layout/sidebar"
import {SiteHeader} from "@/components/layout/header"
import {SidebarInset, SidebarProvider} from "@/components/ui/sidebar"
import {LoadingPage} from "@/components/layout/loading"
import {useUser} from "@/contexts/user-context"
import {useAuthRedirect} from "@/hooks/use-auth-redirect"
export default function MainLayout({
@@ -15,26 +14,10 @@ export default function MainLayout({
}: {
children: React.ReactNode
}) {
const router = useRouter()
const pathname = usePathname()
const {user, loading} = useUser()
const [isFullWidth, setIsFullWidth] = useState(false)
useEffect(() => {
if (loading || user) return
const queryString = window.location.search
const callbackUrl = queryString ? `${pathname}${queryString}` : pathname
const loginUrl = new URL("/login", window.location.origin)
loginUrl.searchParams.set("callbackUrl", callbackUrl)
sessionStorage.setItem("redirect_after_login", callbackUrl)
router.replace(loginUrl.toString())
}, [loading, pathname, router, user])
if (loading || !user) {
return <LoadingPage text="登录状态" badgeText="Auth" />
}
useAuthRedirect()
return (
<SidebarProvider
@@ -67,4 +50,4 @@ export default function MainLayout({
</SidebarInset>
</SidebarProvider>
)
}
}
+11
View File
@@ -0,0 +1,11 @@
"use client"
import {RequireAuth} from "@/components/auth/require-auth"
export default function SettingsLayout({
children,
}: {
children: React.ReactNode
}) {
return <RequireAuth>{children}</RequireAuth>
}