useFetchRequest.ts 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /** @format */
  2. // MyRequest.ts
  3. import { ElMessage } from "element-plus"
  4. import { useFetch, useRequestHeaders, useRuntimeConfig } from "#app"
  5. import { ResultEnum } from "@/enums/httpEnum"
  6. import { useUserStore } from "@/stores/modules/user"
  7. type UrlType =
  8. | string
  9. | Request
  10. | Ref<string | Request>
  11. | (() => string | Request)
  12. export interface RequestOptions {
  13. method?: any
  14. params?: any
  15. server?: boolean
  16. }
  17. export function useMyRequest() {
  18. const request = async (
  19. url: UrlType,
  20. params: any,
  21. options: RequestOptions = {}
  22. ) => {
  23. const headers = useRequestHeaders(["cookie"])
  24. const { apiBase: baseURL } = useRuntimeConfig().public
  25. let { method = (options?.method || "GET") as string } = options
  26. method = method.toUpperCase()
  27. // 处理请求体
  28. let requestBody: any
  29. if (method === "POST") {
  30. // 如果参数是 FormData 类型(文件上传),直接使用,不要 JSON.stringify
  31. if (params instanceof FormData) {
  32. requestBody = params
  33. // 删除 Content-Type header,让浏览器自动设置正确的 boundary
  34. delete headers["Content-Type"]
  35. } else {
  36. requestBody = JSON.stringify(params)
  37. headers["Content-Type"] = "application/json"
  38. }
  39. }
  40. const isProduction = process.env.NODE_ENV === "production"
  41. // eslint-disable-next-line no-async-promise-executor
  42. return new Promise(async (resolve, reject) => {
  43. await useFetch(url as string, {
  44. default: () => [],
  45. baseURL,
  46. method,
  47. params: { ...params },
  48. headers,
  49. server: options.server || false,
  50. credentials: "include",
  51. body: requestBody,
  52. onRequest: ({ request, options }) => {
  53. const userStore = useUserStore()
  54. const { token } = storeToRefs(userStore)
  55. if (token.value) {
  56. options.headers = {
  57. ...options.headers,
  58. Authorization: token.value,
  59. "X-Access-Token": token.value,
  60. }
  61. }
  62. },
  63. onRequestError: ({ request, options, error }) => {
  64. ElMessage.closeAll()
  65. console.log("onRequestError--------error------>>121", error)
  66. error &&
  67. ElMessage({
  68. message: "Sorry, The Data Request Failed",
  69. type: "error",
  70. plain: true,
  71. })
  72. },
  73. onResponse: ({ request, response, options }) => {
  74. try {
  75. const data = response._data
  76. const { code, result, message } = data
  77. // 这里逻辑可以根据项目进行修改
  78. const hasSuccess =
  79. data && Reflect.has(data, "code") && code === ResultEnum.SUCCESS
  80. if (hasSuccess) return resolve(result)
  81. let msg = ""
  82. switch (code) {
  83. case ResultEnum.TIMEOUT:
  84. msg = "Login timeout, please login again."
  85. // 被动登出,带redirect地址
  86. useUserStore().logout()
  87. break
  88. case 10010:
  89. // 此处10010控制无效的分享
  90. msg = ""
  91. break
  92. default:
  93. if (message) msg = message
  94. }
  95. if (msg) {
  96. ElMessage({
  97. message: msg,
  98. type: "error",
  99. plain: true,
  100. })
  101. }
  102. throw new Error(msg || "Error in request, please try again later.")
  103. } catch (error) {
  104. return reject(response._data)
  105. }
  106. },
  107. onResponseError: (error: any) => {
  108. const { response, code, message } = error || {}
  109. const msg: string = response?.data?.message ?? ""
  110. const err: string = error?.toString?.() ?? ""
  111. let errMessage = ""
  112. try {
  113. if (code === "ECONNABORTED" && message.includes("timeout"))
  114. errMessage =
  115. "The interface request timed out. Please refresh the page and try again."
  116. if (err?.includes("Network Error"))
  117. errMessage =
  118. "The network is abnormal. Please check whether your network connection is normal."
  119. if (errMessage) {
  120. ElMessage({
  121. message: errMessage,
  122. type: "error",
  123. plain: true,
  124. })
  125. return reject(error)
  126. }
  127. } catch (error) {
  128. throw new Error(error as unknown as string)
  129. }
  130. const status = error?.response?.status
  131. switch (status) {
  132. case 400:
  133. errMessage = `${msg}`
  134. break
  135. // 401: Not logged in
  136. case 401:
  137. errMessage = msg || "用户没有权限"
  138. // 被动登出,带redirect地址
  139. useUserStore().logout()
  140. break
  141. case 403:
  142. errMessage = "用户得到授权,但是访问是被禁止的"
  143. break
  144. case 404:
  145. errMessage = "网络请求错误,未找到该资源"
  146. break
  147. case 405:
  148. errMessage = "网络请求错误,请求方法未允许"
  149. break
  150. case 408:
  151. errMessage = "网络请求超时"
  152. break
  153. case 500:
  154. errMessage = "服务器错误,请联系管理员"
  155. break
  156. case 501:
  157. errMessage = "网络未实现"
  158. break
  159. case 502:
  160. errMessage = "网络错误"
  161. break
  162. case 503:
  163. errMessage = "服务器不可用,服务器暂时过载或维护"
  164. break
  165. case 504:
  166. errMessage = "网络超时"
  167. break
  168. case 505:
  169. errMessage = "http版本不支持该请求"
  170. break
  171. default:
  172. }
  173. if (errMessage) {
  174. ElMessage({
  175. message: errMessage,
  176. type: "error",
  177. plain: true,
  178. })
  179. }
  180. return reject(error)
  181. },
  182. })
  183. })
  184. }
  185. return {
  186. get: (url: UrlType, params?: any, option?: RequestOptions) => {
  187. return request(url, params, { method: "GET", ...option })
  188. },
  189. post: (url: UrlType, params?: any, option?: RequestOptions) => {
  190. return request(url, params, { method: "POST", ...option })
  191. },
  192. put: (url: UrlType, params?: any, option?: RequestOptions) => {
  193. return request(url, params, { method: "GET", ...option })
  194. },
  195. delete: (url: UrlType, params?: any, option?: RequestOptions) => {
  196. return request(url, params, { method: "POST", ...option })
  197. },
  198. }
  199. }