request.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. /*
  2. * @Author: Rindy
  3. * @Date: 2019-08-06 16:25:08
  4. * @LastEditors: Rindy
  5. * @LastEditTime: 2020-07-29 17:36:36
  6. * @Description: Request
  7. */
  8. import Vue from "vue";
  9. import logger from "./logger";
  10. import browser from "./browser";
  11. import { base64ToBlob } from "./file";
  12. import { checkLogin } from "@/api";
  13. import { LoginDetector } from "@/utils/starter";
  14. import { $alert, $confirm } from "@/components/shared/message";
  15. import { i18n } from "@/lang";
  16. let vue = new Vue();
  17. // 空函数
  18. const noop = function () {};
  19. // 请求回调队列
  20. let postQueue = [];
  21. // 阻止多个弹窗
  22. let isDiglog = false;
  23. const statusCode = {
  24. NEXT: "__not_important__", //继续执行
  25. SUCCESS: 0, //成功
  26. FAILURE_CODE_3001: 3001, // "对象不存在"
  27. FAILURE_CODE_3002: 3002, //请至少保留一个场景。
  28. FAILURE_CODE_3003: 3003, //文件名称不允许超过50个字符
  29. FAILURE_CODE_3005: 3005, //不是该用户作品
  30. FAILURE_CODE_3006: 3006, //作品已被删除,无法编辑
  31. FAILURE_CODE_3007: 3007, //素材已被引用,无法删除。
  32. // 301X -> 权限问题类
  33. FAILURE_CODE_3010: 3010, // "Token为空"
  34. FAILURE_CODE_3011: 3011, // "没有操作权限"
  35. // 302X -> 文件类
  36. FAILURE_CODE_3020: 3020, // "空文件"
  37. FAILURE_CODE_3021: 3021, // "非法文件"
  38. FAILURE_CODE_3022: 3022, // "上传文件超过最大值"
  39. FAILURE_CODE_3023: 3023, // "非法格式"
  40. FAILURE_CODE_3024: 3024, // "存储空间已满"
  41. FAILURE_CODE_3025: 3025, // "上传失败"
  42. // 31XX -> 自定义异常
  43. FAILURE_CODE_3101: 3101, // "素材已经被引用, 不能删除"
  44. FAILURE_CODE_3102: 3102, // "计算中的场景不能删除"
  45. FAILURE_CODE_3103: 3103, // "服务器someData.json文件不存在"
  46. FAILURE_CODE_3104: 3104, // "存在同名文件夹,请直接移动素材"
  47. // 32XX -> 请求第三方API错误
  48. FAILURE_CODE_3200: 3200, // "请求第三方API失败"
  49. FAILURE_CODE_3201: 3201, // "请求第三方API返回失败"
  50. FAILURE_CODE_5001: 5001, //token失效
  51. FAILURE_CODE_5002: 5002, //token失效
  52. FAILURE_CODE_5003: 5003, //不支持此图片
  53. FAILURE_CODE_5004: 5004, // 密码错误
  54. FAILURE_CODE_7005: 7005, //审核中不能编辑
  55. FAILURE_CODE_7006: 7006, //已审核不能编辑
  56. };
  57. let __showNetworkError = false;
  58. export const showLoginTips = () => {
  59. // 防止多次请求弹出
  60. if (showLoginTips.__is_show) {
  61. return;
  62. }
  63. showLoginTips.__is_show = true;
  64. return $confirm({
  65. title: i18n.t("tips_code.tips"),
  66. content: i18n.t("tips_code.relogin"),
  67. okText: i18n.t("tips_code.goto_login"),
  68. noText: i18n.t("tips_code.login_success"),
  69. okLink: "/",
  70. ok: function () {
  71. showLoginTips.__is_show = false;
  72. return false;
  73. },
  74. no: function () {
  75. checkLogin().then((response) => {
  76. if (response.code === statusCode.SUCCESS) {
  77. postQueue.length && postQueue.forEach((item) => item());
  78. postQueue = [];
  79. LoginDetector.valid();
  80. location.reload();
  81. } else if (
  82. response.code === statusCode.FAILURE_CODE_5001 ||
  83. response.code === statusCode.FAILURE_CODE_5002
  84. ) {
  85. showLoginTips();
  86. }
  87. });
  88. showLoginTips.__is_show = false;
  89. },
  90. });
  91. };
  92. function getCookie(objname) {
  93. //获取指定名称的cookie的值
  94. var arrstr = document.cookie.split("; ");
  95. for (var i = 0; i < arrstr.length; i++) {
  96. var temp = arrstr[i].split("=");
  97. if (temp[0] == objname) return unescape(temp[1]);
  98. }
  99. }
  100. export function getToken() {
  101. return localStorage.getItem("token") || getCookie("fdkankantoken") || "";
  102. }
  103. export function statusCodesHandler(result, callback) {
  104. if (result.code == statusCode.FAILURE_CODE_3002) {
  105. $alert({ content: i18n.t("tips_code.need_one") });
  106. return false;
  107. }
  108. if (result.code == statusCode.FAILURE_CODE_3003) {
  109. $alert({ content: i18n.t("tips_code.not_less_than") });
  110. return false;
  111. }
  112. if (result.code == statusCode.FAILURE_CODE_3005) {
  113. $alert({ content: i18n.t("tips_code.FAILURE_3011") });
  114. return false;
  115. }
  116. if (result.code == statusCode.FAILURE_CODE_3011) {
  117. $alert({ content: i18n.t("tips_code.FAILURE_3011") });
  118. return false;
  119. }
  120. if (result.code == statusCode.FAILURE_CODE_3006) {
  121. $alert({ content: i18n.t("tips_code.work_had_delete") });
  122. return;
  123. }
  124. if (result.code == statusCode.FAILURE_CODE_3007) {
  125. $alert({ content: i18n.t("tips_code.material_can_not_delete") });
  126. return;
  127. }
  128. if (result.code == statusCode.FAILURE_CODE_3101) {
  129. $alert({ content: i18n.t("tips_code.FAILURE_3101") });
  130. return;
  131. }
  132. if (result.code == statusCode.FAILURE_CODE_3104) {
  133. $alert({ content: i18n.t("tips_code.FAILURE_3104") });
  134. return;
  135. }
  136. if (
  137. result.code == statusCode.FAILURE_CODE_5001 ||
  138. result.code === statusCode.FAILURE_CODE_5002
  139. ) {
  140. callback(result.code);
  141. showLoginTips();
  142. return false;
  143. }
  144. if (result.code == statusCode.FAILURE_CODE_5003) {
  145. $alert({ content: i18n.t("tips_code.illegality_image") });
  146. return false;
  147. }
  148. if (result.code == statusCode.FAILURE_CODE_5004) {
  149. vue.$msg.error(i18n.t("tips_code.password_error"));
  150. return false;
  151. }
  152. if (result.code == statusCode.FAILURE_CODE_3024) {
  153. if (!isDiglog) {
  154. isDiglog = true;
  155. $alert({
  156. content: i18n.t("tips_code.FAILURE_3024"),
  157. forceOK: true,
  158. ok: () => {
  159. isDiglog = false;
  160. },
  161. });
  162. }
  163. return false;
  164. }
  165. if (![statusCode.SUCCESS,200].includes(result.code) ) {
  166. console.log(result.msg);
  167. $alert({ content: `${result.msg}` });
  168. return false;
  169. }
  170. return statusCode.NEXT;
  171. }
  172. $.ajaxSetup({
  173. headers: {},
  174. beforeSend: function (xhr) {
  175. const token = getToken();
  176. if (token) {
  177. xhr.setRequestHeader("token", token);
  178. }
  179. },
  180. error: function () {
  181. // 出错时默认的处理函数
  182. if (__showNetworkError) {
  183. return;
  184. }
  185. __showNetworkError = true;
  186. $alert({
  187. content: i18n.t("tips_code.FAILURE_error"),
  188. forceOK: true,
  189. ok: () => {
  190. __showNetworkError = false;
  191. },
  192. });
  193. return;
  194. },
  195. success: function () {},
  196. complete: function (data) {},
  197. });
  198. export const http = {
  199. statusCode,
  200. __request(xhr, method, url, data, done, fail) {
  201. if (typeof done != "function") {
  202. done = noop;
  203. }
  204. if (typeof fail != "function") {
  205. fail = noop;
  206. }
  207. xhr.done((result) => {
  208. if (typeof result.code !== "undefined") {
  209. const flag = statusCodesHandler(result, function (code) {
  210. // 需要登录的状态
  211. if (
  212. code == statusCode.FAILURE_CODE_5001 ||
  213. code === statusCode.FAILURE_CODE_5002
  214. ) {
  215. postQueue.push(function () {
  216. http[method](url, data, done, fail);
  217. });
  218. }
  219. });
  220. if (!flag) {
  221. fail(result);
  222. }
  223. if (flag === statusCode.NEXT) {
  224. done(result, result.code == 0);
  225. }
  226. } else {
  227. console.log("ajax返回数据里没有code.");
  228. done(result);
  229. }
  230. });
  231. xhr.fail(fail);
  232. xhr.always(() => (xhr = null));
  233. return xhr;
  234. },
  235. /**
  236. * Get请求
  237. * @param {String} url 请求地址
  238. * @param {Object?} data 请求参数
  239. * @param {Function?} done 成功回调
  240. * @param {Function?} fail 失败回调
  241. */
  242. get(url, data = {}, done, fail) {
  243. if (/\.json/.test(url)) {
  244. // json文件格式自动调用getJson方法
  245. return this.getJson(url, data, done, fail);
  246. }
  247. return this.__request($.get(url, data), "get", url, data, done, fail);
  248. },
  249. /**
  250. * Get Blob请求
  251. * @param {String} url 请求地址
  252. * @param {Object?} data 请求参数
  253. * @param {Function?} done 成功回调
  254. * @param {Function?} fail 失败回调
  255. */
  256. getText(url, data = {}, done, fail) {
  257. return this.__request(
  258. $.ajax({
  259. url: url,
  260. dataType: "text",
  261. }),
  262. "getText",
  263. url,
  264. data,
  265. done,
  266. fail
  267. );
  268. },
  269. /**
  270. * GetJson请求 读取json文件数据
  271. * @param {String} url 请求地址
  272. * @param {Object?} data 请求参数
  273. * @param {Function?} done 成功回调
  274. * @param {Function?} fail 失败回调
  275. */
  276. getJson(url, data = {}, done, fail) {
  277. return this.__request($.getJSON(url, data), "get", url, data, done, fail);
  278. },
  279. /**
  280. * Get Blob请求
  281. * @param {String} url 请求地址
  282. * @param {Object?} data 请求参数
  283. * @param {Function?} done 成功回调
  284. * @param {Function?} fail 失败回调
  285. */
  286. getBlob(url, data = {}, done, fail) {
  287. return this.__request(
  288. $.ajax({
  289. url: url,
  290. dataType: "blob",
  291. }),
  292. "getBlob",
  293. url,
  294. data,
  295. done,
  296. fail
  297. );
  298. },
  299. /**
  300. * Get Arraybuffer请求
  301. * @param {String} url 请求地址
  302. * @param {Object?} data 请求参数
  303. * @param {Function?} done 成功回调
  304. * @param {Function?} fail 失败回调
  305. */
  306. getArraybuffer(url, data = {}, done, fail) {
  307. return this.__request(
  308. $.ajax({
  309. url: url,
  310. dataType: "arraybuffer",
  311. }),
  312. "getArraybuffer",
  313. url,
  314. data,
  315. done,
  316. fail
  317. );
  318. },
  319. /**
  320. * Post 请求
  321. * @param {String} url 请求地址
  322. * @param {Object?} data 请求参数
  323. * @param {Function?} done 成功回调
  324. * @param {Function?} fail 失败回调
  325. */
  326. post(url, data = {}, done, fail) {
  327. return this.__request($.post(url, data), "post", url, data, done, fail);
  328. },
  329. /**
  330. * PostJson 请求
  331. * @param {String} url 请求地址
  332. * @param {Object?} data 请求参数
  333. * @param {Function?} done 成功回调
  334. * @param {Function?} fail 失败回调
  335. */
  336. postJson(url, data = {}, done, fail) {
  337. return this.__request(
  338. $.ajax({
  339. type: "POST",
  340. url: url,
  341. contentType: "application/json",
  342. data: JSON.stringify(data),
  343. }),
  344. "postJson",
  345. url,
  346. data,
  347. done,
  348. fail
  349. );
  350. },
  351. postJsonWithHeader(url, data = {}, headers, done, fail) {
  352. return this.__request(
  353. $.ajax({
  354. type: "POST",
  355. url: url,
  356. contentType: "application/json",
  357. data: JSON.stringify(data),
  358. headers: headers,
  359. beforeSend: function (xhr) {
  360. xhr.headers = null;
  361. // console.log(xhr.headers)
  362. },
  363. }),
  364. "postJson",
  365. url,
  366. data,
  367. done,
  368. fail
  369. );
  370. },
  371. /**
  372. * Post 表单 支持文件上传
  373. * @param {String} url 请求地址
  374. * @param {FormData?} formData 请求参数
  375. * @param {Function?} done 成功回调
  376. * @param {Function?} fail 失败回调
  377. */
  378. postForm(url, formData, done, fail, onProgress) {
  379. if (typeof onProgress === "function") {
  380. return this.__request(
  381. $.ajax({
  382. type: "POST",
  383. url: url,
  384. processData: false,
  385. contentType: false,
  386. data: formData,
  387. xhr: function () {
  388. const xhr = new XMLHttpRequest();
  389. xhr.upload.addEventListener("progress", function (e) {
  390. onProgress(e.loaded / e.total);
  391. });
  392. xhr.onabort = () => {
  393. console.log("xhr aborted.");
  394. };
  395. return xhr;
  396. },
  397. // 覆盖全局配置的失败回调。因为无论是上传子集失败还是用户取消了上传,都不需要弹窗。
  398. error: function () {},
  399. }),
  400. "postForm",
  401. url,
  402. formData,
  403. done,
  404. fail
  405. );
  406. } else {
  407. return this.__request(
  408. $.ajax({
  409. type: "POST",
  410. url: url,
  411. processData: false,
  412. contentType: false,
  413. data: formData,
  414. }),
  415. "postForm",
  416. url,
  417. formData,
  418. done,
  419. fail
  420. );
  421. }
  422. },
  423. /**
  424. * 加载图片
  425. * @param {String} url 请求地址
  426. * @param {Number?} retry 重试次数,默认为3
  427. */
  428. loadImage(url, retry = 3) {
  429. const def = $.Deferred();
  430. const img = new Image();
  431. const load = () => {
  432. logger.warn("Retrying load image: " + url);
  433. this.loadImage(url, retry - 1)
  434. .done(def.resolve.bind(def))
  435. .progress(def.notify.bind(def))
  436. .fail(def.reject.bind(def));
  437. };
  438. img.onerror = function () {
  439. retry > 0
  440. ? setTimeout(() => load(), 1e3)
  441. : def.reject(`[${url}]${i18n.t("tips_code.loading_fail")}`);
  442. };
  443. img.onload = function () {
  444. def.resolve(img);
  445. };
  446. img.crossOrigin = "anonymous";
  447. img.src = url;
  448. return def;
  449. },
  450. /**
  451. * 上传文件
  452. * @param {String} url 请求地址
  453. * @param {Object?} data 请求参数
  454. * @param {Function?} done 成功回调
  455. * @param {Function?} fail 失败回调
  456. */
  457. uploadFile(url, data = {}, done, fail, onProgress) {
  458. const form = new FormData();
  459. // if (file.needTransfer) { //ie和苹果都不支持dataURLtoFile得传送,所以只能用blob
  460. // form.append("file", common.dataURLtoBlob(file.file), file.name || file.file.name);
  461. // } else {
  462. // form.append("file", file.file, file.name || file.file.name);
  463. // }
  464. for (let key in data) {
  465. if (key == "file") {
  466. form.append("file", data[key], data.filename || data[key].name);
  467. } else if (key != "filename") {
  468. form.append(key, data[key]);
  469. }
  470. }
  471. return this.postForm(url, form, done, fail, onProgress);
  472. },
  473. /**
  474. * 上传文件
  475. * @param {String} url 请求地址
  476. * @param {Object?} data 请求参数 {file:'base64 string',filename:'image.jpg',...}
  477. * @param {Function?} done 成功回调
  478. * @param {Function?} fail 失败回调
  479. */
  480. uploadBlobFile(url, data = {}, done, fail) {
  481. const form = new FormData();
  482. for (let key in data) {
  483. if (key === "file") {
  484. form.append("file", base64ToBlob(data.file), data.filename);
  485. } else if (key != "filename") {
  486. form.append(key, data[key]);
  487. }
  488. }
  489. return this.postForm(url, form, done, fail);
  490. },
  491. };