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:
LAMCLOD
2026-03-08 18:00:28 +08:00
commit f6036cab66
36 changed files with 10579 additions and 0 deletions

52
src/store/authStore.ts Normal file
View File

@@ -0,0 +1,52 @@
import { create } from 'zustand'
interface UserInfo {
id: number
username: string
display_name: string
role: number
status: number
email: string
group: string
quota: number
used_quota: number
request_count: number
aff_code: string
inviter_id: number
}
interface SiteInfo {
id: number
name: string
url: string
}
interface AuthState {
sessionToken: string | null
userInfo: UserInfo | null
site: SiteInfo | null
isLoggedIn: boolean
loading: boolean
login: (sessionToken: string, userInfo: UserInfo, site: SiteInfo) => void
logout: () => void
updateUserInfo: (userInfo: UserInfo) => void
setLoading: (loading: boolean) => void
}
export const useAuthStore = create<AuthState>((set) => ({
sessionToken: localStorage.getItem('sessionToken'),
userInfo: null,
site: null,
isLoggedIn: !!localStorage.getItem('sessionToken'),
loading: true,
login: (sessionToken, userInfo, site) => {
localStorage.setItem('sessionToken', sessionToken)
set({ sessionToken, userInfo, site, isLoggedIn: true, loading: false })
},
logout: () => {
localStorage.removeItem('sessionToken')
set({ sessionToken: null, userInfo: null, site: null, isLoggedIn: false, loading: false })
},
updateUserInfo: (userInfo) => set({ userInfo }),
setLoading: (loading) => set({ loading }),
}))