request.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. import axios from "axios";
  2. import {
  3. ElNotification,
  4. ElMessageBox,
  5. ElMessage,
  6. ElLoading,
  7. } from "element-plus";
  8. import { getToken, getTenant } from "@/utils/auth";
  9. import errorCode from "@/utils/errorCode";
  10. import { tansParams, blobValidate } from "@/utils/ruoyi";
  11. import cache from "@/plugins/cache";
  12. import { saveAs } from "file-saver";
  13. import useUserStore from "@/store/modules/user";
  14. let sendingRequestList = [];
  15. let downloadLoadingInstance;
  16. // 是否显示重新登录
  17. export let isRelogin = { show: false };
  18. axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8";
  19. // 创建axios实例
  20. const service = axios.create({
  21. // axios中请求配置有baseURL选项,表示请求URL公共部分
  22. baseURL: import.meta.env.VITE_APP_BASE_API,
  23. // 超时
  24. timeout: 100000,
  25. });
  26. function startRepeatSubmitRequest(config) {
  27. const requestObj = {
  28. url: config.url,
  29. data:
  30. typeof config.data === "object"
  31. ? JSON.stringify(config.data)
  32. : config.data,
  33. time: new Date().getTime(),
  34. };
  35. for (var index = 0; index < sendingRequestList.length; index++) {
  36. const request = sendingRequestList[index];
  37. const s_url = request.url; // 请求地址
  38. const s_data = request.data; // 请求数据
  39. const s_time = request.time; // 请求时间
  40. const timeout = config.timeout; // 间隔时间(ms),小于此时间视为重复提交
  41. if (s_data === requestObj.data && s_url === requestObj.url) {
  42. if (requestObj.time - s_time < timeout) {
  43. return false;
  44. } else {
  45. sendingRequestList.splice(index, 1);
  46. break;
  47. }
  48. }
  49. }
  50. sendingRequestList.push(requestObj);
  51. return true;
  52. }
  53. function stopRepeatSubmitRequest(config) {
  54. const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;
  55. if (
  56. !isRepeatSubmit &&
  57. (config.method === "post" || config.method === "put")
  58. ) {
  59. const requestObj = {
  60. url: config.url,
  61. data:
  62. typeof config.data === "object"
  63. ? JSON.stringify(config.data)
  64. : config.data,
  65. };
  66. for (var index = 0; index < sendingRequestList.length; index++) {
  67. const request = sendingRequestList[index];
  68. const s_url = request.url; // 请求地址
  69. const s_data = request.data; // 请求数据
  70. if (s_data === requestObj.data && s_url === requestObj.url) {
  71. sendingRequestList.splice(index, 1);
  72. break;
  73. }
  74. }
  75. }
  76. }
  77. // request拦截器
  78. service.interceptors.request.use(
  79. (config) => {
  80. // 是否需要设置 token
  81. const isToken = (config.headers || {}).isToken === false;
  82. // 是否需要防止数据重复提交
  83. const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;
  84. if (getToken() && !isToken) {
  85. config.headers["Authorization"] = "Bearer " + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
  86. }
  87. config.headers["appKey"] = "ezhizao-identity";
  88. config.headers["tenantId"] = getTenant();
  89. // get请求映射params参数
  90. if (config.method === "get" && config.params) {
  91. let url = config.url + "?" + tansParams(config.params);
  92. url = url.slice(0, -1);
  93. config.params = {};
  94. config.url = url;
  95. }
  96. if (
  97. !isRepeatSubmit &&
  98. (config.method === "post" || config.method === "put")
  99. ) {
  100. const requestObj = {
  101. url: config.url,
  102. data:
  103. typeof config.data === "object"
  104. ? JSON.stringify(config.data)
  105. : config.data,
  106. time: new Date().getTime(),
  107. };
  108. const sessionObj = cache.session.getJSON("sessionObj");
  109. if (
  110. sessionObj === undefined ||
  111. sessionObj === null ||
  112. sessionObj === ""
  113. ) {
  114. cache.session.setJSON("sessionObj", requestObj);
  115. } else {
  116. const s_url = sessionObj.url; // 请求地址
  117. const s_data = sessionObj.data; // 请求数据
  118. const s_time = sessionObj.time; // 请求时间
  119. const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交
  120. if (
  121. s_data === requestObj.data &&
  122. requestObj.time - s_time < interval &&
  123. s_url === requestObj.url
  124. ) {
  125. const message = "数据正在处理,请勿重复提交";
  126. console.warn(`[${s_url}]: ` + message);
  127. return Promise.reject(new Error(message));
  128. } else {
  129. cache.session.setJSON("sessionObj", requestObj);
  130. }
  131. }
  132. console.log("config", config, config.data, typeof config.data)
  133. if (!startRepeatSubmitRequest(config)) {
  134. const message = "数据正在处理,请勿重复提交";
  135. console.warn(`[${config.url}]: ` + message);
  136. return Promise.reject(new Error(message));
  137. }
  138. }
  139. return config;
  140. },
  141. (error) => {
  142. console.log(error);
  143. Promise.reject(error);
  144. }
  145. );
  146. // 响应拦截器
  147. service.interceptors.response.use(
  148. (res) => {
  149. console.log("res config", res.config, res.config.data, typeof res.config.data)
  150. // 是否需要防止数据重复提交
  151. stopRepeatSubmitRequest(res.config);
  152. // 未设置状态码则默认成功状态
  153. const code = res.data.code || 200;
  154. // 获取错误信息
  155. const msg = errorCode[code] || res.data.msg || errorCode["default"];
  156. // 二进制数据则直接返回
  157. if (
  158. res.request.responseType === "blob" ||
  159. res.request.responseType === "arraybuffer"
  160. ) {
  161. return res.data;
  162. }
  163. if (code === 401) {
  164. if (!isRelogin.show) {
  165. isRelogin.show = true;
  166. ElMessageBox.confirm(
  167. "登录状态已过期,您可以继续留在该页面,或者重新登录",
  168. "系统提示",
  169. {
  170. confirmButtonText: "重新登录",
  171. cancelButtonText: "取消",
  172. type: "warning",
  173. }
  174. )
  175. .then(() => {
  176. isRelogin.show = false;
  177. useUserStore()
  178. .logOut()
  179. .then(() => {
  180. location.href = "/index";
  181. });
  182. })
  183. .catch(() => {
  184. isRelogin.show = false;
  185. });
  186. }
  187. return Promise.reject("无效的会话,或者会话已过期,请重新登录。");
  188. } else if (code === 500) {
  189. ElMessage({ message: msg, type: "error" });
  190. return Promise.reject(new Error(msg));
  191. } else if (code === 601) {
  192. ElMessage({ message: msg, type: "warning" });
  193. return Promise.reject(new Error(msg));
  194. } else if (code !== 200) {
  195. ElNotification.error({ title: msg });
  196. return Promise.reject("error");
  197. } else {
  198. return Promise.resolve(res.data);
  199. }
  200. },
  201. (error) => {
  202. console.log("err" + error);
  203. let { message } = error;
  204. if (message == "Network Error") {
  205. message = "后端接口连接异常";
  206. } else if (message.includes("timeout")) {
  207. message = "系统接口请求超时";
  208. } else if (message.includes("Request failed with status code")) {
  209. message = "系统接口" + message.substr(message.length - 3) + "异常";
  210. }
  211. ElMessage({ message: message, type: "error", duration: 5 * 1000 });
  212. return Promise.reject(error);
  213. }
  214. );
  215. // 通用下载方法
  216. export function download(url, params, filename, config) {
  217. downloadLoadingInstance = ElLoading.service({
  218. text: "正在下载数据,请稍候",
  219. background: "rgba(0, 0, 0, 0.7)",
  220. });
  221. return service
  222. .post(url, params, {
  223. transformRequest: [
  224. (params) => {
  225. return tansParams(params);
  226. },
  227. ],
  228. headers: { "Content-Type": "application/x-www-form-urlencoded" },
  229. responseType: "blob",
  230. timeout: 1000000,
  231. ...config,
  232. })
  233. .then(async (data) => {
  234. const isLogin = await blobValidate(data);
  235. if (isLogin) {
  236. const blob = new Blob([data]);
  237. saveAs(blob, filename);
  238. } else {
  239. const resText = await data.text();
  240. const rspObj = JSON.parse(resText);
  241. const errMsg =
  242. errorCode[rspObj.code] || rspObj.msg || errorCode["default"];
  243. ElMessage.error(errMsg);
  244. }
  245. downloadLoadingInstance.close();
  246. })
  247. .catch((r) => {
  248. console.error(r);
  249. ElMessage.error("下载文件出现错误,请联系管理员!");
  250. downloadLoadingInstance.close();
  251. });
  252. }
  253. // 通用pdf打印方法
  254. export function downloadPdf(url, params, filename, config) {
  255. downloadLoadingInstance = ElLoading.service({
  256. text: "正在下载数据,请稍候",
  257. background: "rgba(0, 0, 0, 0.7)",
  258. });
  259. return service
  260. .post(url, params, {
  261. transformRequest: [
  262. (params) => {
  263. return tansParams(params);
  264. },
  265. ],
  266. headers: { "Content-Type": "application/x-www-form-urlencoded" },
  267. responseType: "blob",
  268. ...config,
  269. })
  270. .then(async (data) => {
  271. const isLogin = await blobValidate(data);
  272. if (isLogin) {
  273. const blob = new Blob([data], { type: "application/pdf" });
  274. var url = URL.createObjectURL(blob);
  275. window.open(url, "filename");
  276. } else {
  277. const resText = await data.text();
  278. const rspObj = JSON.parse(resText);
  279. const errMsg =
  280. errorCode[rspObj.code] || rspObj.msg || errorCode["default"];
  281. ElMessage.error(errMsg);
  282. }
  283. downloadLoadingInstance.close();
  284. })
  285. .catch((r) => {
  286. console.error(r);
  287. ElMessage.error("下载文件出现错误,请联系管理员!");
  288. downloadLoadingInstance.close();
  289. });
  290. }
  291. export default service;