axios.js 8.6 KB

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