154 lines
5.3 KiB
TypeScript
154 lines
5.3 KiB
TypeScript
import React, { useEffect, useState } from 'react'
|
|
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'
|
|
import { useAppStore } from './store'
|
|
import { ToastProvider } from './contexts/ToastContext'
|
|
import AuthService from './services/authService'
|
|
|
|
// 懒加载页面组件
|
|
const Login = React.lazy(() => import('./pages/Login'))
|
|
const Lottery = React.lazy(() => import('./pages/Lottery'))
|
|
const Home = React.lazy(() => import('./pages/Home'))
|
|
const Admin = React.lazy(() => import('./pages/Admin'))
|
|
|
|
const WinnerDetails = React.lazy(() => import('./pages/WinnerDetails'))
|
|
const ClearRecords = React.lazy(() => import('./pages/ClearRecords'))
|
|
const ConfettiDemo = React.lazy(() => import('./pages/ConfettiDemo'))
|
|
const CrudTest = React.lazy(() => import('./pages/CrudTest'))
|
|
const NetworkTest = React.lazy(() => import('./pages/NetworkTest'))
|
|
const SimpleNetworkTest = React.lazy(() => import('./pages/SimpleNetworkTest'))
|
|
|
|
function App() {
|
|
const { isAuthenticated, initializeApp, checkAuthStatus } = useAppStore()
|
|
const [isInitializing, setIsInitializing] = useState(true)
|
|
|
|
useEffect(() => {
|
|
const initApp = async () => {
|
|
try {
|
|
// 首先检查认证状态
|
|
checkAuthStatus()
|
|
|
|
// 然后初始化应用
|
|
await initializeApp()
|
|
} catch (error) {
|
|
console.error('应用初始化失败:', error)
|
|
} finally {
|
|
setIsInitializing(false)
|
|
}
|
|
}
|
|
|
|
initApp()
|
|
}, [initializeApp, checkAuthStatus])
|
|
|
|
// 监听页面可见性变化,恢复时检查认证状态
|
|
useEffect(() => {
|
|
const handleVisibilityChange = () => {
|
|
if (!document.hidden) {
|
|
checkAuthStatus()
|
|
}
|
|
}
|
|
|
|
document.addEventListener('visibilitychange', handleVisibilityChange)
|
|
|
|
return () => {
|
|
document.removeEventListener('visibilitychange', handleVisibilityChange)
|
|
}
|
|
}, [checkAuthStatus])
|
|
|
|
// 应用卸载时清理资源
|
|
useEffect(() => {
|
|
return () => {
|
|
const { cleanup } = useAppStore.getState()
|
|
cleanup()
|
|
}
|
|
}, [])
|
|
|
|
// 应用初始化中的加载状态
|
|
if (isInitializing) {
|
|
return (
|
|
<div className="min-h-screen bg-gradient-to-br from-purple-900 via-blue-900 to-indigo-900 flex items-center justify-center">
|
|
<div className="text-center">
|
|
<div className="w-16 h-16 border-4 border-white/30 border-t-white rounded-full animate-spin mx-auto mb-4"></div>
|
|
<p className="text-white text-lg">正在初始化应用...</p>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<ToastProvider>
|
|
<Router>
|
|
<div className="min-h-screen bg-gradient-to-br from-purple-900 via-blue-900 to-indigo-900">
|
|
|
|
|
|
{/* 背景装饰 */}
|
|
<div className="fixed inset-0 overflow-hidden pointer-events-none">
|
|
<div className="absolute top-1/4 left-1/4 w-96 h-96 bg-purple-500/10 rounded-full blur-3xl" />
|
|
<div className="absolute top-3/4 right-1/4 w-96 h-96 bg-blue-500/10 rounded-full blur-3xl" />
|
|
<div className="absolute bottom-1/4 left-1/2 w-96 h-96 bg-indigo-500/10 rounded-full blur-3xl" />
|
|
</div>
|
|
|
|
{/* 路由配置 */}
|
|
<React.Suspense fallback={
|
|
<div className="min-h-screen flex items-center justify-center">
|
|
<div className="text-center">
|
|
<div className="w-16 h-16 border-4 border-white/30 border-t-white rounded-full animate-spin mx-auto mb-4"></div>
|
|
<p className="text-white text-lg">正在加载页面...</p>
|
|
</div>
|
|
</div>
|
|
}>
|
|
<Routes>
|
|
<Route
|
|
path="/login"
|
|
element={isAuthenticated ? <Navigate to="/" replace /> : <Login />}
|
|
/>
|
|
<Route
|
|
path="/"
|
|
element={isAuthenticated ? <Lottery /> : <Navigate to="/login" replace />}
|
|
/>
|
|
<Route
|
|
path="/home"
|
|
element={isAuthenticated ? <Home /> : <Navigate to="/login" replace />}
|
|
/>
|
|
<Route
|
|
path="/admin"
|
|
element={isAuthenticated ? <Admin /> : <Navigate to="/login" replace />}
|
|
/>
|
|
|
|
<Route
|
|
path="/winners"
|
|
element={<WinnerDetails />}
|
|
/>
|
|
<Route
|
|
path="/clear-records"
|
|
element={isAuthenticated ? <ClearRecords /> : <Navigate to="/login" replace />}
|
|
/>
|
|
<Route
|
|
path="/confetti-demo"
|
|
element={isAuthenticated ? <ConfettiDemo /> : <Navigate to="/login" replace />}
|
|
/>
|
|
<Route
|
|
path="/crud-test"
|
|
element={<CrudTest />}
|
|
/>
|
|
<Route
|
|
path="/network-test"
|
|
element={<NetworkTest />}
|
|
/>
|
|
<Route
|
|
path="/simple-test"
|
|
element={<SimpleNetworkTest />}
|
|
/>
|
|
<Route
|
|
path="*"
|
|
element={<Navigate to={isAuthenticated ? "/" : "/login"} replace />}
|
|
/>
|
|
</Routes>
|
|
</React.Suspense>
|
|
</div>
|
|
</Router>
|
|
</ToastProvider>
|
|
)
|
|
}
|
|
|
|
export default App
|