Add exam score import and management workflows
This commit is contained in:
1 parent
71ee21b063
commit
24d2a96144
26 files changed
+3865
No files matched your search
@@ -0,0 +1,87 @@
|
||||
import { lazy, Suspense, useEffect } from 'react'
|
||||
import { ConfigProvider, Skeleton } from 'antd'
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
import { BrowserRouter, Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom'
|
||||
import zhCN from 'antd/locale/zh_CN'
|
||||
import { useAuthStore } from '../stores/auth'
|
||||
|
||||
const LoginPage = lazy(() => import('../pages/LoginPage'))
|
||||
const DashboardPage = lazy(() => import('../pages/DashboardPage'))
|
||||
const MigrationPlaceholderPage = lazy(() => import('../pages/MigrationPlaceholderPage'))
|
||||
const AppShell = lazy(() => import('../layout/AppShell'))
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
staleTime: 30_000,
|
||||
retry: 1,
|
||||
refetchOnWindowFocus: false,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
function ProtectedRoute() {
|
||||
const token = useAuthStore((state) => state.token)
|
||||
const location = useLocation()
|
||||
if (!token) return <Navigate to={`/login?redirect=${encodeURIComponent(location.pathname + location.search)}`} replace />
|
||||
return <AppShell />
|
||||
}
|
||||
|
||||
function SessionExpiryBridge() {
|
||||
const navigate = useNavigate()
|
||||
useEffect(() => {
|
||||
const onExpired = () => navigate(`/login?redirect=${encodeURIComponent(location.pathname + location.search + location.hash)}`, { replace: true })
|
||||
window.addEventListener('mingxu-session-expired', onExpired)
|
||||
return () => window.removeEventListener('mingxu-session-expired', onExpired)
|
||||
}, [navigate])
|
||||
return null
|
||||
}
|
||||
|
||||
function AppRoutes() {
|
||||
return (
|
||||
<Suspense fallback={<div style={{ maxWidth: 1180, margin: '64px auto', padding: 24 }}><Skeleton active paragraph={{ rows: 8 }} /></div>}>
|
||||
<SessionExpiryBridge />
|
||||
<Routes>
|
||||
<Route path="/login" element={<LoginPage />} />
|
||||
<Route element={<ProtectedRoute />}>
|
||||
<Route path="/dashboard" element={<DashboardPage />} />
|
||||
<Route path="/account" element={<MigrationPlaceholderPage />} />
|
||||
<Route path="/users" element={<MigrationPlaceholderPage />} />
|
||||
<Route path="/" element={<Navigate to="/dashboard" replace />} />
|
||||
</Route>
|
||||
<Route path="*" element={<Navigate to="/dashboard" replace />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
)
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<ConfigProvider
|
||||
locale={zhCN}
|
||||
theme={{
|
||||
token: {
|
||||
colorPrimary: '#284583',
|
||||
colorSuccess: '#087f73',
|
||||
colorWarning: '#b8781d',
|
||||
colorError: '#b42318',
|
||||
colorInfo: '#476282',
|
||||
colorText: '#182033',
|
||||
colorBgLayout: '#f2f4f7',
|
||||
borderRadius: 7,
|
||||
fontFamily: '"Microsoft YaHei", "PingFang SC", "Noto Sans CJK SC", sans-serif',
|
||||
},
|
||||
components: {
|
||||
Button: { controlHeightLG: 44, fontWeight: 650 },
|
||||
Input: { controlHeightLG: 44 },
|
||||
Layout: { headerBg: '#ffffff', siderBg: '#162858' },
|
||||
Menu: { darkItemBg: '#162858', darkItemSelectedBg: '#284583', darkItemSelectedColor: '#ffffff' },
|
||||
},
|
||||
}}
|
||||
>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<BrowserRouter basename="/next"><AppRoutes /></BrowserRouter>
|
||||
</QueryClientProvider>
|
||||
</ConfigProvider>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user