Files
Jeff Gu bd76a89ba1 feat(auth): 新增系统设置功能
- 实现管理员登录和验证码验证功能
- 添加管理员登录流程,支持通过 Telegram 验证
- 实现登录挑战和会话管理,确保安全性
- 更新前端状态管理,处理登录和登出逻辑
- 增加系统配置管理,支持 Telegram 安全设置
- 新增数据库表以存储登录挑战和会话信息
2026-04-13 19:07:16 +08:00

166 lines
4.2 KiB
TypeScript

import { useEffect } from "react";
import { BrowserRouter as Router, Routes, Route, Navigate } from "react-router-dom";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { AppLayout } from "./components/layout/AppLayout";
import { Toaster } from "./components/ui/toaster";
import { useAuthStore } from "./store/auth";
import { Dashboard } from "./pages/Dashboard";
import { Analytics } from "./pages/Analytics";
import { UsageLogs } from "./pages/UsageLogs";
import { Channels } from "./pages/Channels";
import { Tokens } from "./pages/Tokens";
import { Pricing } from "./pages/Pricing";
import { ApiTest } from "./pages/ApiTest";
import { NotFound } from "./pages/NotFound";
import { SystemSettings } from "./pages/SystemSettings";
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: 1,
refetchOnWindowFocus: false,
},
},
});
function ProtectedRoute({ children }: { children: React.ReactNode }) {
const { isAuthenticated, isLoading } = useAuthStore();
if (isLoading) {
return null;
}
if (!isAuthenticated) {
return <Navigate to="/" replace />;
}
return <>{children}</>;
}
function HomeRoute() {
const { isAuthenticated, isLoading } = useAuthStore();
if (isLoading) {
return null;
}
if (isAuthenticated) {
return <Navigate to="/dashboard" replace />;
}
return <Dashboard />;
}
function App() {
const { checkAuth } = useAuthStore();
useEffect(() => {
checkAuth();
}, [checkAuth]);
return (
<QueryClientProvider client={queryClient}>
<Router>
<AppLayout>
<Routes>
<Route path="/" element={<HomeRoute />} />
<Route path="/analytics" element={<Navigate to="/dashboard" replace />} />
<Route
path="/api-test"
element={
<ProtectedRoute>
<ApiTest />
</ProtectedRoute>
}
/>
<Route
path="/dashboard"
element={
<ProtectedRoute>
<Analytics />
</ProtectedRoute>
}
/>
<Route
path="/usage-logs"
element={
<ProtectedRoute>
<UsageLogs />
</ProtectedRoute>
}
/>
<Route
path="/channels"
element={
<ProtectedRoute>
<Channels />
</ProtectedRoute>
}
/>
<Route
path="/channels/new"
element={
<ProtectedRoute>
<Channels createMode />
</ProtectedRoute>
}
/>
<Route
path="/channels/edit/:key"
element={
<ProtectedRoute>
<Channels editRoute />
</ProtectedRoute>
}
/>
<Route
path="/tokens"
element={
<ProtectedRoute>
<Tokens />
</ProtectedRoute>
}
/>
<Route
path="/tokens/new"
element={
<ProtectedRoute>
<Tokens createMode />
</ProtectedRoute>
}
/>
<Route
path="/tokens/edit/:key"
element={
<ProtectedRoute>
<Tokens editRoute />
</ProtectedRoute>
}
/>
<Route
path="/pricing"
element={
<ProtectedRoute>
<Pricing />
</ProtectedRoute>
}
/>
<Route
path="/settings"
element={
<ProtectedRoute>
<SystemSettings />
</ProtectedRoute>
}
/>
<Route path="*" element={<NotFound />} />
</Routes>
</AppLayout>
<Toaster />
</Router>
</QueryClientProvider>
);
}
export default App;