feat(frontend): 构建前端 MVP,实现完整 UI 框架与 mock 数据层
- 安装 zustand + react-router-dom 依赖 - 修复 Vite 代理配置,添加 /auth 路由转发 - 实现 API 封装层(client.ts 统一 fetch、auth.ts 真实调用) - 实现 mock 数据层(mock.ts 模拟 WebSocket 管线进度) - 实现 4 个 zustand stores(auth/project/task/generation) - 实现 5 个组件(StyleSelector/PromptEditor/GenerateForm/ProgressBar/AssetPreview) - 实现 5 个页面(Login/Register/Project/Generate/Result) - 实现路由含 ProtectedRoute 守卫 - 添加暗色主题全局样式 - 更新前端文档与 API 文档
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
import type { ApiResponse } from './types'
|
||||
|
||||
const TOKEN_KEY = 'gen2d_token'
|
||||
|
||||
export function getToken(): string | null {
|
||||
return localStorage.getItem(TOKEN_KEY)
|
||||
}
|
||||
|
||||
export function setToken(token: string): void {
|
||||
localStorage.setItem(TOKEN_KEY, token)
|
||||
}
|
||||
|
||||
export function clearToken(): void {
|
||||
localStorage.removeItem(TOKEN_KEY)
|
||||
}
|
||||
|
||||
export class ApiError extends Error {
|
||||
code: number
|
||||
constructor(code: number, message: string) {
|
||||
super(message)
|
||||
this.code = code
|
||||
}
|
||||
}
|
||||
|
||||
async function request<T>(url: string, options: RequestInit = {}): Promise<T> {
|
||||
const token = getToken()
|
||||
const headers: Record<string, string> = {
|
||||
'Content-Type': 'application/json',
|
||||
...(options.headers as Record<string, string>),
|
||||
}
|
||||
if (token) {
|
||||
headers['Authorization'] = `Bearer ${token}`
|
||||
}
|
||||
|
||||
const res = await fetch(url, {
|
||||
...options,
|
||||
headers,
|
||||
credentials: 'include',
|
||||
})
|
||||
|
||||
const json: ApiResponse<T> = await res.json()
|
||||
|
||||
if (json.code !== 0) {
|
||||
if (json.code === 401) {
|
||||
clearToken()
|
||||
window.location.href = '/login'
|
||||
}
|
||||
throw new ApiError(json.code, json.message)
|
||||
}
|
||||
|
||||
return json.data
|
||||
}
|
||||
|
||||
export function get<T>(url: string): Promise<T> {
|
||||
return request<T>(url)
|
||||
}
|
||||
|
||||
export function post<T>(url: string, body?: unknown): Promise<T> {
|
||||
return request<T>(url, {
|
||||
method: 'POST',
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
}
|
||||
|
||||
export function put<T>(url: string, body?: unknown): Promise<T> {
|
||||
return request<T>(url, {
|
||||
method: 'PUT',
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user