axios.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. import axios from "axios";
  2. import Vue from "vue";
  3. import { Message, MessageBox, Notification } from "element-ui";
  4. import router from "../router";
  5. import qs from "qs";
  6. import GLOBAL from "../config";
  7. import { getAuthorization } from "./crypto";
  8. import { PLATFORM, DEVICE_ID } from "../constants/app";
  9. import { initSyncTime, fetchTime } from "./syncServerTime";
  10. // axios interceptors
  11. var load = "";
  12. // 同一时间有多个请求时,会形成队列。在第一个请求创建loading,在最后一个响应关闭loading
  13. var queue = [];
  14. // 设置延迟时效
  15. axios.defaults.timeout = GLOBAL.timeout;
  16. axios.interceptors.request.use(
  17. config => {
  18. // 显示loading提示
  19. if (!queue.length) {
  20. load = Message({
  21. customClass: "el-message-loading",
  22. iconClass: "el-message__icon el-icon-loading",
  23. message: "Loading...",
  24. duration: 0
  25. });
  26. }
  27. queue.push(1);
  28. // 为请求头添加鉴权信息
  29. let token = Vue.ls.get("token");
  30. if (token) {
  31. // 新版鉴权
  32. const sessionId = Vue.ls.get("user", { session: "" }).session;
  33. const timestamp = fetchTime();
  34. const Authorization = getAuthorization(
  35. {
  36. token: token,
  37. timestamp,
  38. account: sessionId,
  39. uri: config.url.split("?")[0],
  40. method: config.method
  41. },
  42. "token"
  43. );
  44. config.headers["Authorization"] = Authorization;
  45. config.headers["time"] = timestamp;
  46. }
  47. config.headers["deviceId"] = DEVICE_ID;
  48. config.headers["platform"] = PLATFORM;
  49. config.headers["domain"] = window.location.origin;
  50. return config;
  51. },
  52. error => {
  53. // 关闭loading提示
  54. // 串联并发请求,延时处理是为防止多个loading实例闪屏。
  55. setTimeout(() => {
  56. queue.shift();
  57. if (!queue.length) load.close();
  58. }, 100);
  59. return Promise.reject(error);
  60. }
  61. );
  62. axios.interceptors.response.use(
  63. response => {
  64. initSyncTime(new Date(response.headers.date).getTime());
  65. // 关闭loading提示
  66. setTimeout(() => {
  67. queue.shift();
  68. if (!queue.length) load.close();
  69. }, 100);
  70. return response;
  71. },
  72. error => {
  73. initSyncTime(new Date(error.response.headers.date).getTime());
  74. // 关闭loading提示
  75. setTimeout(() => {
  76. queue.shift();
  77. if (!queue.length) load.close();
  78. }, 100);
  79. return Promise.reject(error);
  80. }
  81. );
  82. // request instance
  83. // 防止鉴权失效之后多次弹窗。
  84. let unauthMsgBoxIsShow = false;
  85. const mdData = datas => {
  86. let nData = {};
  87. if (!datas) return nData;
  88. Object.entries(datas).forEach(([key, val]) => {
  89. if (val === null || val === "null" || val === "") return;
  90. nData[key] = val;
  91. });
  92. return nData;
  93. };
  94. /**
  95. * errorCallback 请求失败的回调
  96. * @param {Object} error 请求失败时的错误信息
  97. */
  98. const errorCallback = error => {
  99. if (error.response) {
  100. return errorDataCallback(error.response);
  101. }
  102. if (error.request) {
  103. let message = "请求错误";
  104. if (error.message.indexOf("timeout") > -1) {
  105. message = "请求超时";
  106. }
  107. Notification.error({ title: "错误提示", message });
  108. }
  109. return error;
  110. };
  111. /**
  112. * errorDataCallback 请求成功,结果有误的回调
  113. * @param {Object} response Response信息
  114. */
  115. const errorDataCallback = response => {
  116. const error = response.data;
  117. let message = error.message || error.error || "请求错误";
  118. const unauthCodes = [401, 403];
  119. if (unauthCodes.includes(response.status)) {
  120. if (unauthMsgBoxIsShow) return error;
  121. unauthMsgBoxIsShow = true;
  122. message = "身份验证失效,请重新登录";
  123. MessageBox.confirm(message, "重新登陆?", {
  124. type: "warning",
  125. cancelButtonClass: "el-button--danger is-plain",
  126. confirmButtonClass: "el-button--primary",
  127. closeOnClickModal: false,
  128. closeOnPressEscape: false,
  129. showClose: false,
  130. callback: action => {
  131. unauthMsgBoxIsShow = false;
  132. if (action !== "confirm") return;
  133. Vue.ls.clear();
  134. router.push({ name: "Login" });
  135. }
  136. });
  137. } else {
  138. Notification.error({ title: "错误提示", message });
  139. }
  140. return error;
  141. };
  142. /**
  143. * response format
  144. * {
  145. config, header, data, request, status, statusText
  146. }
  147. *
  148. */
  149. /**
  150. * successCallback 请求成功的回调
  151. * @param {Object} data Response中的data信息
  152. */
  153. const successCallback = data => {
  154. return data;
  155. // if (data.code === 200) {
  156. // return data.data;
  157. // } else {
  158. // return Promise.reject(data.data);
  159. // }
  160. };
  161. /**
  162. * get请求
  163. * @param {String} url 请求地址
  164. * @param {Object} datas 请求数据
  165. */
  166. const $get = (url, datas) => {
  167. return axios
  168. .get(url, { params: mdData(datas) })
  169. .then(rep => {
  170. return successCallback(rep.data);
  171. })
  172. .catch(error => {
  173. return Promise.reject(errorCallback(error));
  174. });
  175. };
  176. /**
  177. * get请求
  178. * @param {String} url 请求地址
  179. * @param {Object} datas 请求数据
  180. */
  181. const $postParam = (url, datas, config = {}) => {
  182. return axios
  183. .post(url, {}, { ...config, params: mdData(datas) })
  184. .then(rep => {
  185. if (config["responseType"] === "blob") return rep;
  186. return successCallback(rep.data);
  187. })
  188. .catch(error => {
  189. return Promise.reject(errorCallback(error));
  190. });
  191. };
  192. /**
  193. * post请求
  194. * @param {String} url 请求地址
  195. * @param {Object} datas 请求数据
  196. */
  197. const $post = (url, datas, config = {}) => {
  198. let sqDatas = {};
  199. if (datas.constructor === Object) {
  200. sqDatas = mdData(datas);
  201. } else {
  202. sqDatas = datas;
  203. }
  204. return axios
  205. .post(url, sqDatas, config)
  206. .then(rep => {
  207. if (config["responseType"] === "blob") return rep;
  208. return successCallback(rep.data);
  209. })
  210. .catch(error => {
  211. return Promise.reject(errorCallback(error));
  212. });
  213. };
  214. /**
  215. * delete请求
  216. * @param {String} url
  217. * @param {Object} datas
  218. */
  219. const $del = (url, datas) => {
  220. return axios
  221. .delete(url, {
  222. params: mdData(datas)
  223. })
  224. .then(rep => {
  225. return rep.data;
  226. })
  227. .catch(error => {
  228. return Promise.reject(errorCallback(error));
  229. });
  230. };
  231. /**
  232. * put 请求
  233. * @param {String} url 请求地址
  234. * @param {Object} datas 请求数据
  235. */
  236. const $put = (url, datas) => {
  237. return axios
  238. .put(url, {
  239. params: mdData(datas)
  240. })
  241. .then(rep => {
  242. return rep.data;
  243. })
  244. .catch(error => {
  245. return Promise.reject(errorCallback(error));
  246. });
  247. };
  248. /**
  249. * patch请求
  250. * @param {String} url 请求地址
  251. * @param {Object} datas 请求数据
  252. */
  253. const $patch = (url, datas) => {
  254. return axios
  255. .patch(url, {
  256. params: mdData(datas)
  257. })
  258. .then(rep => {
  259. return rep.data;
  260. })
  261. .catch(error => {
  262. return Promise.reject(errorCallback(error));
  263. });
  264. };
  265. export { $get, $postParam, $post, $del, $put, $patch };
  266. // qs
  267. export function qsRepeatParams(params) {
  268. return qs.stringify(params, { arrayFormat: "repeat" });
  269. }