/** 管理端 API client:token 注入 + 统一信封解包 + 401 跳登录 */ const TOKEN_KEY = 'sundynix-admin-token' export function getToken(): string | null { return localStorage.getItem(TOKEN_KEY) } export function setToken(token: string) { localStorage.setItem(TOKEN_KEY, token) } export function clearToken() { localStorage.removeItem(TOKEN_KEY) } interface Envelope { code: number message: string data: T } export class ApiError extends Error { status: number code: number constructor(status: number, code: number, message: string) { super(message) this.status = status this.code = code } } export async function request( path: string, init: RequestInit = {}, ): Promise { const headers = new Headers(init.headers) headers.set('Content-Type', 'application/json') const token = getToken() if (token) headers.set('Authorization', `Bearer ${token}`) const res = await fetch(path, { ...init, headers }) if (res.status === 401) { clearToken() // basename=/admin,登录路由实际是 /admin/login if (!window.location.pathname.endsWith('/login')) { window.location.href = '/admin/login' } throw new ApiError(401, 40100, '登录已过期') } let body: Envelope | null = null try { body = (await res.json()) as Envelope } catch { // 非 JSON 响应 } if (!res.ok || !body || body.code !== 0) { throw new ApiError( res.status, body?.code ?? -1, body?.message ?? `请求失败(${res.status})`, ) } return body.data }