Connect React workspace to backend data

This commit is contained in:
2026-07-20 13:02:26 +08:00
parent 215268e836
commit 875b326ddc
28 changed files with 1017 additions and 257 deletions

View File

@@ -0,0 +1,57 @@
export type ApiSession = {
baseUrl: string
token: string
}
type RequestOptions = {
method?: string
body?: unknown
token?: string
}
let configuredBaseUrl = normalizeBaseUrl(import.meta.env.VITE_API_BASE_URL ?? 'http://127.0.0.1:18080')
export function setApiBaseUrl(baseUrl: string) {
configuredBaseUrl = normalizeBaseUrl(baseUrl)
}
export function getApiBaseUrl() {
return configuredBaseUrl
}
export async function login(email: string, password: string): Promise<ApiSession> {
const response = await apiRequest<{ token: string }>('/api/auth/login', {
method: 'POST',
body: { email, password },
})
return { baseUrl: configuredBaseUrl, token: response.token }
}
export async function apiRequest<T>(path: string, options: RequestOptions = {}): Promise<T> {
const response = await fetch(`${configuredBaseUrl}${path}`, {
method: options.method ?? 'GET',
headers: {
'Content-Type': 'application/json',
...(options.token ? { Authorization: `Bearer ${options.token}` } : {}),
},
body: options.body === undefined ? undefined : JSON.stringify(options.body),
})
if (!response.ok) {
let message = `请求失败:${response.status}`
try {
const payload = await response.json()
if (typeof payload.error === 'string') message = payload.error
} catch {
// Keep the status-based message when the server does not return JSON.
}
throw new Error(message)
}
return response.json() as Promise<T>
}
function normalizeBaseUrl(value: string) {
const trimmed = value.trim()
return trimmed.endsWith('/') ? trimmed.slice(0, -1) : trimmed
}