import { lazy, Suspense, useEffect, useState } from 'react' import type { ReactNode } from 'react' import { Navigate, Route, Routes } from 'react-router' import { App as AntdApp, ConfigProvider, Spin } from 'antd' import zhCN from 'antd/locale/zh_CN' import { useAuth } from './lib/auth' import { useTheme } from './lib/theme' import useShadcnTheme from './theme/shadcnTheme' import { BlogLayout, AdminLayout } from './components/Layout' import Home from './pages/Home' import TagPage from './pages/TagPage' import Login from './pages/Login' import AdminList from './pages/AdminList' import AdminTrash from './pages/AdminTrash' import AdminSettings from './pages/AdminSettings' import NotFound from './pages/NotFound' // 重依赖路由懒加载:Note 带 markdown 渲染管线,AdminEdit 额外带 CodeMirror, // 拆出主包以避免单 chunk 过大(vite 500kB 告警) const Note = lazy(() => import('./pages/Note')) const AdminEdit = lazy(() => import('./pages/AdminEdit')) // antd ConfigProvider:跟随应用三态主题切换 light/dark 算法(system 监听系统变化) function AntdProvider({ children }: { children: ReactNode }) { const { mode } = useTheme() const [systemDark, setSystemDark] = useState( () => window.matchMedia('(prefers-color-scheme: dark)').matches, ) useEffect(() => { const mq = window.matchMedia('(prefers-color-scheme: dark)') const onChange = (e: MediaQueryListEvent) => setSystemDark(e.matches) mq.addEventListener('change', onChange) return () => mq.removeEventListener('change', onChange) }, []) const dark = mode === 'dark' || (mode === 'system' && systemDark) const configProps = useShadcnTheme(dark) return ( {children} ) } // 登录守卫:401 统一跳转 /admin/login(§8.2) function RequireAuth({ children }: { children: ReactNode }) { const { authenticated, loading } = useAuth() if (loading) { return
} if (!authenticated) { return } return <>{children} } export default function App() { return ( }> }> } /> } /> } /> } /> } /> }> } /> } /> } /> } /> } /> } /> ) }