|
|
@@ -1,41 +1,75 @@
|
|
|
-import { showToast } from 'vant'
|
|
|
import { getStorage } from '@/utils/storage'
|
|
|
|
|
|
-// 当前使用 mock 模式
|
|
|
-const USE_MOCK = false
|
|
|
|
|
|
export interface ApiResponse<T = any> {
|
|
|
- code: number
|
|
|
- msg: string
|
|
|
- data: T
|
|
|
+ code: number
|
|
|
+ msg: string
|
|
|
+ data: T
|
|
|
+}
|
|
|
+
|
|
|
+function showError(msg: string): Promise<void> {
|
|
|
+ // 不使用 Vant showToast(在非组件上下文中不可靠),直接用 DOM 插入
|
|
|
+ const el = document.createElement('div')
|
|
|
+ el.textContent = msg
|
|
|
+ el.style.cssText =
|
|
|
+ 'position:fixed;z-index:99999;top:44%;left:50%;transform:translate(-50%,-50%);' +
|
|
|
+ 'background:rgba(0,0,0,.8);color:#fff;padding:12px 24px;border-radius:8px;' +
|
|
|
+ 'font-size:14px;max-width:70vw;text-align:center;white-space:pre-wrap;' +
|
|
|
+ 'box-shadow:0 4px 12px rgba(0,0,0,.15);'
|
|
|
+ document.body.appendChild(el)
|
|
|
+ setTimeout(() => el.remove(), 2500)
|
|
|
+ return new Promise((resolve) => setTimeout(resolve, 150))
|
|
|
}
|
|
|
|
|
|
export async function request<T = any>(url: string, options?: RequestInit): Promise<ApiResponse<T>> {
|
|
|
- if (USE_MOCK) {
|
|
|
- throw new Error('Mock mode — use mock services directly')
|
|
|
- }
|
|
|
|
|
|
- const token = getStorage('token')
|
|
|
- const headers: Record<string, string> = {
|
|
|
- 'Content-Type': 'application/json',
|
|
|
- ...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
|
- }
|
|
|
+ const token = getStorage('token')
|
|
|
+ const headers: Record<string, string> = {
|
|
|
+ 'Content-Type': 'application/json',
|
|
|
+ ...(token ? {Authorization: `Bearer ${token}`} : {}),
|
|
|
+ }
|
|
|
|
|
|
- try {
|
|
|
const baseUrl = import.meta.env.VITE_API_BASE || '/dgapi'
|
|
|
- const res = await fetch(`${baseUrl}${url}`, {
|
|
|
- ...options,
|
|
|
- headers: { ...headers, ...(options?.headers as Record<string, string> || {}) },
|
|
|
- })
|
|
|
- const json = await res.json()
|
|
|
+ let res: Response
|
|
|
+
|
|
|
+ try {
|
|
|
+ res = await fetch(`${baseUrl}${url}`, {
|
|
|
+ ...options,
|
|
|
+ headers: {...headers, ...(options?.headers as Record<string, string> || {})},
|
|
|
+ })
|
|
|
+ } catch {
|
|
|
+ await showError('网络连接失败,请检查网络')
|
|
|
+ throw new Error('网络连接失败')
|
|
|
+ }
|
|
|
+ // HTTP 状态码错误(500、404 等)
|
|
|
+ if (!res.ok) {
|
|
|
+ let errMsg = ''
|
|
|
+ try {
|
|
|
+ const body = await res.json()
|
|
|
+ errMsg = body.msg
|
|
|
+ } catch {
|
|
|
+ // 响应体不是 JSON(如 HTML 错误页)
|
|
|
+ }
|
|
|
+ if (!errMsg) {
|
|
|
+ errMsg = `服务器开小差了 (${res.status})`
|
|
|
+ }
|
|
|
+ await showError(errMsg)
|
|
|
+ throw new Error(errMsg)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 业务错误码
|
|
|
+ let json: ApiResponse
|
|
|
+ try {
|
|
|
+ json = await res.json()
|
|
|
+ } catch {
|
|
|
+ await showError('数据解析失败')
|
|
|
+ throw new Error('数据解析失败')
|
|
|
+ }
|
|
|
+
|
|
|
if (json.code !== 200) {
|
|
|
- const errMsg = json.msg || '请求失败'
|
|
|
- showToast(errMsg)
|
|
|
- throw new Error(errMsg)
|
|
|
+ const errMsg = json.msg || '请求失败'
|
|
|
+ await showError(errMsg)
|
|
|
+ throw new Error(errMsg)
|
|
|
}
|
|
|
return json
|
|
|
- } catch (err: any) {
|
|
|
- showToast(err.message || '网络错误')
|
|
|
- throw err
|
|
|
- }
|
|
|
}
|