Files
Mycontent/soul-admin/src/api/client.ts

87 lines
2.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 统一 API 请求封装
* 规则API 路径与现网完全一致,仅通过 baseUrl 区分环境Next 或未来 Gin
* 鉴权:管理端使用 JWT自动带 Authorization: Bearer <token>token 存 localStorage
*/
import { getAdminToken } from './auth'
/** 未设置环境变量时使用的默认 API 地址(零配置部署) */
const DEFAULT_API_BASE = 'https://soulapi.quwanzhi.com'
const getBaseUrl = (): string => {
const url = import.meta.env.VITE_API_BASE_URL
if (typeof url === 'string' && url.length > 0) return url.replace(/\/$/, '')
return DEFAULT_API_BASE
}
/** 请求完整 URLbaseUrl + pathpath 必须与现网一致(如 /api/orders */
export function apiUrl(path: string): string {
const base = getBaseUrl()
const p = path.startsWith('/') ? path : `/${path}`
return base ? `${base}${p}` : p
}
export type RequestInitWithBody = RequestInit & { data?: unknown }
/**
* 发起请求。path 为与现网一致的 API 路径(如 /api/admin、/api/orders
* 若有 admin_tokenJWT则自动带 Authorization: Bearercredentials: 'include' 保留以兼容需 Cookie 的接口。
*/
export async function request<T = unknown>(
path: string,
options: RequestInitWithBody = {}
): Promise<T> {
const { data, ...init } = options
const url = apiUrl(path)
const headers = new Headers(init.headers as HeadersInit)
const token = getAdminToken()
if (token) {
headers.set('Authorization', `Bearer ${token}`)
}
if (data !== undefined && data !== null && !headers.has('Content-Type')) {
headers.set('Content-Type', 'application/json')
}
const body = data !== undefined && data !== null ? JSON.stringify(data) : init.body
const res = await fetch(url, {
...init,
headers,
body,
credentials: 'include',
})
const contentType = res.headers.get('Content-Type') || ''
const json: T = contentType.includes('application/json')
? ((await res.json()) as T)
: (res as unknown as T)
if (!res.ok) {
const err = new Error((json as { error?: string })?.error || `HTTP ${res.status}`) as Error & {
status: number
data: T
}
err.status = res.status
err.data = json
throw err
}
return json
}
/** GET */
export function get<T = unknown>(path: string, init?: RequestInit): Promise<T> {
return request<T>(path, { ...init, method: 'GET' })
}
/** POST */
export function post<T = unknown>(path: string, data?: unknown, init?: RequestInit): Promise<T> {
return request<T>(path, { ...init, method: 'POST', data })
}
/** PUT */
export function put<T = unknown>(path: string, data?: unknown, init?: RequestInit): Promise<T> {
return request<T>(path, { ...init, method: 'PUT', data })
}
/** DELETE */
export function del<T = unknown>(path: string, init?: RequestInit): Promise<T> {
return request<T>(path, { ...init, method: 'DELETE' })
}