132 lines
3.9 KiB
TypeScript
132 lines
3.9 KiB
TypeScript
import { lazy, Suspense } from 'react'
|
|
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'
|
|
import { Toaster } from 'sonner'
|
|
import { ThemeProvider } from '@/contexts/ThemeContext'
|
|
import { AuthProvider, useAuth } from '@/contexts/AuthContext'
|
|
import { UserPreferencesProvider } from '@/contexts/UserPreferencesContext'
|
|
import { AppProvider } from '@/contexts/AppContext'
|
|
import { JobProvider } from '@/contexts/JobContext'
|
|
import { HistoryProvider } from '@/contexts/HistoryContext'
|
|
import ErrorBoundary from '@/components/ErrorBoundary'
|
|
import LoadingScreen from '@/components/LoadingScreen'
|
|
import { SuperAdminRoute } from '@/components/SuperAdminRoute'
|
|
|
|
const Login = lazy(() => import('@/pages/Login'))
|
|
const Home = lazy(() => import('@/pages/Home'))
|
|
const Settings = lazy(() => import('@/pages/Settings'))
|
|
const UserManagement = lazy(() => import('@/pages/UserManagement'))
|
|
const VoiceManagement = lazy(() => import('@/pages/VoiceManagement'))
|
|
const Audiobook = lazy(() => import('@/pages/Audiobook'))
|
|
|
|
function ProtectedRoute({ children }: { children: React.ReactNode }) {
|
|
const { isAuthenticated, isLoading } = useAuth()
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<div className="min-h-screen flex items-center justify-center">
|
|
<div className="text-lg">加载中...</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
if (!isAuthenticated) {
|
|
return <Navigate to="/login" replace />
|
|
}
|
|
|
|
return <>{children}</>
|
|
}
|
|
|
|
function PublicRoute({ children }: { children: React.ReactNode }) {
|
|
const { isAuthenticated, isLoading } = useAuth()
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<div className="min-h-screen flex items-center justify-center">
|
|
<div className="text-lg">加载中...</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
if (isAuthenticated) {
|
|
return <Navigate to="/" replace />
|
|
}
|
|
|
|
return <>{children}</>
|
|
}
|
|
|
|
function App() {
|
|
return (
|
|
<ThemeProvider>
|
|
<ErrorBoundary>
|
|
<BrowserRouter>
|
|
<AuthProvider>
|
|
<UserPreferencesProvider>
|
|
<Toaster position="top-center" offset="16px" />
|
|
<Suspense fallback={<LoadingScreen />}>
|
|
<Routes>
|
|
<Route
|
|
path="/login"
|
|
element={
|
|
<PublicRoute>
|
|
<Login />
|
|
</PublicRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/"
|
|
element={
|
|
<ProtectedRoute>
|
|
<AppProvider>
|
|
<HistoryProvider>
|
|
<JobProvider>
|
|
<Home />
|
|
</JobProvider>
|
|
</HistoryProvider>
|
|
</AppProvider>
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/settings"
|
|
element={
|
|
<ProtectedRoute>
|
|
<Settings />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/users"
|
|
element={
|
|
<SuperAdminRoute>
|
|
<UserManagement />
|
|
</SuperAdminRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/voices"
|
|
element={
|
|
<ProtectedRoute>
|
|
<VoiceManagement />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/audiobook"
|
|
element={
|
|
<ProtectedRoute>
|
|
<Audiobook />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
</Routes>
|
|
</Suspense>
|
|
</UserPreferencesProvider>
|
|
</AuthProvider>
|
|
</BrowserRouter>
|
|
</ErrorBoundary>
|
|
</ThemeProvider>
|
|
)
|
|
}
|
|
|
|
export default App
|