feat: newapi-dashboard 全栈项目初始化
为 new-api (LLM API 网关) 构建独立前端管理面板: - React 18 + TypeScript + Vite + Ant Design 5 前端 - Node.js + Express + better-sqlite3 BFF 后端 - 登录页: 站点选择器 + UserID + AccessToken 认证 - 仪表盘: 用户信息、额度环形图、7天趋势图、模型饼图、令牌概览、日志时间线 - 账单页: 筛选日志表格、模型消耗柱状图、充值记录、CSV/PDF 导出(HMAC签名) - 管理员站点管理: 站点 CRUD - API 代理: 多站点切换,会话管理 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
70
src/App.tsx
Normal file
70
src/App.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import { useEffect } from 'react'
|
||||
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'
|
||||
import { ConfigProvider, App as AntApp, Spin } from 'antd'
|
||||
import zhCN from 'antd/locale/zh_CN'
|
||||
import { lightTheme } from '@/utils/theme'
|
||||
import { useAuthStore } from '@/store/authStore'
|
||||
import { authApi } from '@/api/auth'
|
||||
import Layout from '@/components/Layout'
|
||||
import Login from '@/pages/Login'
|
||||
import Dashboard from '@/pages/Dashboard'
|
||||
import Billing from '@/pages/Billing'
|
||||
import SiteManagement from '@/pages/admin/SiteManagement'
|
||||
|
||||
function ProtectedRoute({ children }: { children: React.ReactNode }) {
|
||||
const { isLoggedIn, loading } = useAuthStore()
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
|
||||
<Spin size="large" tip="Loading..." />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return isLoggedIn ? <>{children}</> : <Navigate to="/login" />
|
||||
}
|
||||
|
||||
function SessionRestore({ children }: { children: React.ReactNode }) {
|
||||
const { sessionToken, login, logout, setLoading } = useAuthStore()
|
||||
|
||||
useEffect(() => {
|
||||
if (sessionToken) {
|
||||
authApi.me()
|
||||
.then((res) => {
|
||||
if (res.data.success) {
|
||||
login(sessionToken, res.data.data.userInfo, res.data.data.site)
|
||||
} else {
|
||||
logout()
|
||||
}
|
||||
})
|
||||
.catch(() => logout())
|
||||
} else {
|
||||
setLoading(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return <>{children}</>
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<ConfigProvider locale={zhCN} theme={lightTheme}>
|
||||
<AntApp>
|
||||
<BrowserRouter>
|
||||
<SessionRestore>
|
||||
<Routes>
|
||||
<Route path="/login" element={<Login />} />
|
||||
<Route path="/" element={<ProtectedRoute><Layout /></ProtectedRoute>}>
|
||||
<Route index element={<Navigate to="/dashboard" />} />
|
||||
<Route path="dashboard" element={<Dashboard />} />
|
||||
<Route path="billing" element={<Billing />} />
|
||||
<Route path="admin/sites" element={<SiteManagement />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</SessionRestore>
|
||||
</BrowserRouter>
|
||||
</AntApp>
|
||||
</ConfigProvider>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user