service.ts 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. import axios from 'axios';
  2. import { get } from 'lodash-es';
  3. import { ElMessage, ElMessageBox } from 'element-plus';
  4. import type { Action } from 'element-plus';
  5. // @ts-ignore
  6. import { errorLog, errorCreate } from './tools.ts';
  7. // import { env } from "/src/utils/util.env";
  8. // import { useUserStore } from "../store/modules/user";
  9. import { Local, Session } from '/@/utils/storage';
  10. import qs from 'qs';
  11. import { getBaseURL } from './baseUrl';
  12. import { successMessage } from './message.js';
  13. /**
  14. * @description 创建请求实例
  15. */
  16. function createService() {
  17. // 创建一个 axios 实例
  18. const service = axios.create({
  19. timeout: 20000,
  20. headers: {
  21. 'Content-Type': 'application/json;charset=utf-8',
  22. },
  23. paramsSerializer: {
  24. serialize(params) {
  25. interface paramsObj {
  26. [key: string]: any;
  27. }
  28. let result: paramsObj = {};
  29. for (const [key, value] of Object.entries(params)) {
  30. if (value !== '') {
  31. result[key] = value;
  32. }
  33. if (typeof value === 'boolean') {
  34. result[key] = value ? 'True' : 'False';
  35. }
  36. }
  37. return qs.stringify(result);
  38. },
  39. },
  40. });
  41. // 请求拦截
  42. service.interceptors.request.use(
  43. (config) => config,
  44. (error) => {
  45. // 发送失败
  46. console.log(error);
  47. return Promise.reject(error);
  48. }
  49. );
  50. // 响应拦截
  51. service.interceptors.response.use(
  52. (response) => {
  53. if (response.config.responseType === 'blob') {
  54. return response;
  55. }
  56. // dataAxios 是 axios 返回数据中的 data
  57. const dataAxios = response.data;
  58. // 这个状态码是和后端约定的
  59. const { code } = dataAxios;
  60. // swagger判断
  61. if (dataAxios.swagger != undefined) {
  62. return dataAxios;
  63. }
  64. // 根据 code 进行判断
  65. if (code === undefined) {
  66. // 如果没有 code 代表这不是项目后端开发的接口
  67. errorCreate(`非标准返回:${dataAxios}, ${response.config.url}`, false);
  68. return dataAxios;
  69. } else {
  70. // 有 code 代表这是一个后端接口 可以进行进一步的判断
  71. switch (code) {
  72. case 400:
  73. // Local.clear();
  74. // Session.clear();
  75. errorCreate(`${dataAxios.msg}: ${response.config.url}`);
  76. // window.location.reload();
  77. break;
  78. case 401:
  79. // Local.clear();
  80. Session.clear();
  81. dataAxios.msg = '登录认证失败,请重新登录';
  82. ElMessageBox.alert(dataAxios.msg, '提示', {
  83. confirmButtonText: 'OK',
  84. callback: (action: Action) => {
  85. // window.location.reload();
  86. },
  87. });
  88. errorCreate(`${dataAxios.msg}: ${response.config.url}`);
  89. break;
  90. case 2000:
  91. // @ts-ignore
  92. if (response.config.unpack === false) {
  93. //如果不需要解包
  94. return dataAxios;
  95. }
  96. return dataAxios;
  97. case 4000:
  98. errorCreate(`${dataAxios.msg}: ${response.config.url}`);
  99. break;
  100. default:
  101. // 不是正确的 code
  102. errorCreate(`${dataAxios.msg}: ${response.config.url}`);
  103. break;
  104. }
  105. return Promise.reject(dataAxios);
  106. }
  107. },
  108. (error) => {
  109. const status = get(error, 'response.status');
  110. switch (status) {
  111. case 400:
  112. error.message = '请求错误';
  113. break;
  114. case 401:
  115. // Local.clear();
  116. Session.clear();
  117. error.message = '登录授权过期,请重新登录';
  118. ElMessageBox.alert(error.message, '提示', {
  119. confirmButtonText: 'OK',
  120. callback: (action: Action) => {
  121. window.location.reload();
  122. },
  123. });
  124. break;
  125. case 403:
  126. error.message = '拒绝访问';
  127. break;
  128. case 404:
  129. error.message = `请求地址出错: ${error.response.config.url}`;
  130. break;
  131. case 408:
  132. error.message = '请求超时';
  133. break;
  134. case 500:
  135. error.message = '服务器内部错误';
  136. break;
  137. case 501:
  138. error.message = '服务未实现';
  139. break;
  140. case 502:
  141. error.message = '网关错误';
  142. break;
  143. case 503:
  144. error.message = '服务不可用';
  145. break;
  146. case 504:
  147. error.message = '网关超时';
  148. break;
  149. case 505:
  150. error.message = 'HTTP版本不受支持';
  151. break;
  152. default:
  153. break;
  154. }
  155. errorLog(error);
  156. if (status === 401) {
  157. // const userStore = useUserStore();
  158. // userStore.logout();
  159. }
  160. return Promise.reject(error);
  161. }
  162. );
  163. return service;
  164. }
  165. /**
  166. * @description 创建请求方法
  167. * @param {Object} service axios 实例
  168. */
  169. function createRequestFunction(service: any) {
  170. return function (config: any) {
  171. const configDefault = {
  172. headers: {
  173. 'Content-Type': get(config, 'headers.Content-Type', 'application/json'),
  174. },
  175. timeout: 5000,
  176. baseURL: getBaseURL(),
  177. data: {},
  178. };
  179. // const token = userStore.getToken;
  180. const token = Session.get('token');
  181. if (token != null) {
  182. // @ts-ignore
  183. configDefault.headers.Authorization = 'JWT ' + token;
  184. }
  185. return service(Object.assign(configDefault, config));
  186. };
  187. }
  188. // 用于真实网络请求的实例和请求方法
  189. export const service = createService();
  190. export const request = createRequestFunction(service);
  191. // 用于模拟网络请求的实例和请求方法
  192. export const serviceForMock = createService();
  193. export const requestForMock = createRequestFunction(serviceForMock);
  194. /**
  195. * 下载文件
  196. * @param url
  197. * @param params
  198. * @param method
  199. * @param filename
  200. */
  201. export const downloadFile = function ({ url,params, method, filename = '文件导出' }: any) {
  202. // return request({ url: url, method: method, params: params })
  203. // .then((res: any) => successMessage(res.msg));
  204. request({
  205. url: url,
  206. method: method,
  207. params: params,
  208. responseType: 'blob'
  209. // headers: {Accept: 'application/vnd.openxmlformats-officedocument'}
  210. }).then((res: any) => {
  211. // console.log(res.headers['content-type']); // 根据content-type不同来判断是否异步下载
  212. // if (res.headers && res.headers['Content-type'] === 'application/json') return successMessage('导入任务已创建,请前往‘下载中心’等待下载');
  213. if (res.headers['content-type'] === 'application/json') return successMessage('导入任务已创建,请前往‘下载中心’等待下载');
  214. // const xlsxName = window.decodeURI(res.headers['Content-Disposition'].split('=')[1])
  215. let xlsxName='';
  216. const disposition = res.headers['content-disposition'];
  217. if (disposition && disposition.includes('filename=')) {
  218. const match = disposition.match(/filename="?([^"]+)"?/);
  219. if (match && match[1]) {
  220. xlsxName = decodeURIComponent(match[1]);
  221. }
  222. }
  223. const fileName = xlsxName || `${filename}.xlsx`
  224. if (res) {
  225. const blob = new Blob([res.data], { type: 'charset=utf-8' })
  226. const elink = document.createElement('a')
  227. elink.download = fileName
  228. elink.style.display = 'none'
  229. elink.href = URL.createObjectURL(blob)
  230. document.body.appendChild(elink)
  231. elink.click()
  232. URL.revokeObjectURL(elink.href) // 释放URL 对象0
  233. document.body.removeChild(elink)
  234. }
  235. })
  236. }
  237. export const downloadFilePost = function ({ url,data, method, filename = '文件导出' }: any) {
  238. // return request({ url: url, method: method, params: params })
  239. // .then((res: any) => successMessage(res.msg));
  240. request({
  241. url: url,
  242. method: method,
  243. data: data,
  244. responseType: 'blob'
  245. // headers: {Accept: 'application/vnd.openxmlformats-officedocument'}
  246. }).then((res: any) => {
  247. // console.log(res.headers['content-type']); // 根据content-type不同来判断是否异步下载
  248. // if (res.headers && res.headers['Content-type'] === 'application/json') return successMessage('导入任务已创建,请前往‘下载中心’等待下载');
  249. if (res.headers['content-type'] === 'application/json') return successMessage('导入任务已创建,请前往‘下载中心’等待下载');
  250. // const xlsxName = window.decodeURI(res.headers['Content-Disposition'].split('=')[1])
  251. let xlsxName='';
  252. const disposition = res.headers['content-disposition'];
  253. if (disposition && disposition.includes('filename=')) {
  254. const match = disposition.match(/filename="?([^"]+)"?/);
  255. if (match && match[1]) {
  256. xlsxName = decodeURIComponent(match[1]);
  257. }
  258. }
  259. const fileName = xlsxName || `${filename}.xlsx`
  260. if (res) {
  261. const blob = new Blob([res.data], { type: 'charset=utf-8' })
  262. const elink = document.createElement('a')
  263. elink.download = fileName
  264. elink.style.display = 'none'
  265. elink.href = URL.createObjectURL(blob)
  266. document.body.appendChild(elink)
  267. elink.click()
  268. URL.revokeObjectURL(elink.href) // 释放URL 对象0
  269. document.body.removeChild(elink)
  270. }
  271. })
  272. }