request.ts 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import { getStorage } from '@/utils/storage'
  2. export interface ApiResponse<T = any> {
  3. code: number
  4. msg: string
  5. data: T
  6. }
  7. function showError(msg: string): Promise<void> {
  8. // 不使用 Vant showToast(在非组件上下文中不可靠),直接用 DOM 插入
  9. const el = document.createElement('div')
  10. el.textContent = msg
  11. el.style.cssText =
  12. 'position:fixed;z-index:99999;top:44%;left:50%;transform:translate(-50%,-50%);' +
  13. 'background:rgba(0,0,0,.8);color:#fff;padding:12px 24px;border-radius:8px;' +
  14. 'font-size:14px;max-width:70vw;text-align:center;white-space:pre-wrap;' +
  15. 'box-shadow:0 4px 12px rgba(0,0,0,.15);'
  16. document.body.appendChild(el)
  17. setTimeout(() => el.remove(), 2500)
  18. return new Promise((resolve) => setTimeout(resolve, 150))
  19. }
  20. export async function request<T = any>(url: string, options?: RequestInit): Promise<ApiResponse<T>> {
  21. const token = getStorage('token')
  22. const headers: Record<string, string> = {
  23. 'Content-Type': 'application/json',
  24. ...(token ? {Authorization: `Bearer ${token}`} : {}),
  25. }
  26. const baseUrl = import.meta.env.VITE_API_BASE || '/dgapi'
  27. let res: Response
  28. try {
  29. res = await fetch(`${baseUrl}${url}`, {
  30. ...options,
  31. headers: {...headers, ...(options?.headers as Record<string, string> || {})},
  32. })
  33. } catch {
  34. await showError('网络连接失败,请检查网络')
  35. throw new Error('网络连接失败')
  36. }
  37. // HTTP 状态码错误(500、404 等)
  38. if (!res.ok) {
  39. let errMsg = ''
  40. try {
  41. const body = await res.json()
  42. errMsg = body.msg
  43. } catch {
  44. // 响应体不是 JSON(如 HTML 错误页)
  45. }
  46. if (!errMsg) {
  47. errMsg = `服务器开小差了 (${res.status})`
  48. }
  49. await showError(errMsg)
  50. throw new Error(errMsg)
  51. }
  52. // 业务错误码
  53. let json: ApiResponse
  54. try {
  55. json = await res.json()
  56. } catch {
  57. await showError('数据解析失败')
  58. throw new Error('数据解析失败')
  59. }
  60. if (json.code !== 200) {
  61. const errMsg = json.msg || '请求失败'
  62. await showError(errMsg)
  63. throw new Error(errMsg)
  64. }
  65. return json
  66. }