request.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  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 (response.code === statusCode.FAILURE_CODE_5001||response.code === statusCode.FAILURE_CODE_5002) {
  82. showLoginTips();
  83. }
  84. })
  85. showLoginTips.__is_show = false;
  86. },
  87. });
  88. };
  89. function getCookie(objname) {
  90. //获取指定名称的cookie的值
  91. var arrstr = document.cookie.split("; ");
  92. for (var i = 0; i < arrstr.length; i++) {
  93. var temp = arrstr[i].split("=");
  94. if (temp[0] == objname) return unescape(temp[1]);
  95. }
  96. }
  97. export function getToken() {
  98. return (
  99. localStorage.getItem("token") || getCookie("fdkankantoken") || ""
  100. );
  101. }
  102. export function statusCodesHandler(result, callback) {
  103. if (result.code == statusCode.FAILURE_CODE_3002) {
  104. $alert({ content: i18n.t('tips_code.need_one') });
  105. return false
  106. }
  107. if (result.code == statusCode.FAILURE_CODE_3003) {
  108. $alert({ content: i18n.t('tips_code.not_less_than') })
  109. return false
  110. }
  111. if (result.code == statusCode.FAILURE_CODE_3005) {
  112. $alert({ content: i18n.t('tips_code.FAILURE_3011') });
  113. return false
  114. }
  115. if (result.code == statusCode.FAILURE_CODE_3011) {
  116. $alert({ content: i18n.t('tips_code.FAILURE_3011') });
  117. return false
  118. }
  119. if (result.code == statusCode.FAILURE_CODE_3006) {
  120. $alert({ content: i18n.t('tips_code.work_had_delete') });
  121. return
  122. }
  123. if (result.code == statusCode.FAILURE_CODE_3007) {
  124. $alert({ content: i18n.t('tips_code.material_can_not_delete') });
  125. return
  126. }
  127. if (result.code == statusCode.FAILURE_CODE_3101) {
  128. $alert({ content: i18n.t('tips_code.FAILURE_3101') });
  129. return
  130. }
  131. if (result.code == statusCode.FAILURE_CODE_3104) {
  132. $alert({ content: i18n.t('tips_code.FAILURE_3104') });
  133. return
  134. }
  135. if (result.code == statusCode.FAILURE_CODE_5001||result.code === statusCode.FAILURE_CODE_5002) {
  136. callback(result.code);
  137. showLoginTips();
  138. return false
  139. }
  140. if (result.code == statusCode.FAILURE_CODE_5003) {
  141. $alert({ content: i18n.t('tips_code.illegality_image') })
  142. return false
  143. }
  144. if (result.code == statusCode.FAILURE_CODE_5004) {
  145. vue.$msg.error(i18n.t('tips_code.password_error'));
  146. return false
  147. }
  148. if (result.code == statusCode.FAILURE_CODE_3024) {
  149. if (!isDiglog) {
  150. isDiglog = true
  151. $alert({
  152. content: i18n.t('tips_code.FAILURE_3024'),
  153. forceOK: true,
  154. ok: () => {
  155. isDiglog = false
  156. },
  157. });
  158. }
  159. return false
  160. }
  161. if (result.code != statusCode.SUCCESS) {
  162. console.log(result.msg);
  163. $alert({ content: `${result.msg}` });
  164. return false
  165. }
  166. return statusCode.NEXT;
  167. }
  168. $.ajaxSetup({
  169. headers: {},
  170. beforeSend: function(xhr) {
  171. const token = getToken();
  172. if (token) {
  173. xhr.setRequestHeader("token", token);
  174. }
  175. },
  176. error: function() {
  177. // 出错时默认的处理函数
  178. if (__showNetworkError) {
  179. return;
  180. }
  181. __showNetworkError = true;
  182. $alert({
  183. content: i18n.t('tips_code.FAILURE_error'),
  184. forceOK: true,
  185. ok: () => {
  186. __showNetworkError = false;
  187. },
  188. });
  189. return;
  190. },
  191. success: function() {},
  192. complete: function(data) {
  193. },
  194. });
  195. export const http = {
  196. statusCode,
  197. __request(xhr, method, url, data, done, fail) {
  198. if (typeof done != "function") {
  199. done = noop;
  200. }
  201. if (typeof fail != "function") {
  202. fail = noop;
  203. }
  204. xhr.done((result) => {
  205. if (typeof result.code !== "undefined") {
  206. const flag = statusCodesHandler(result, function(code) {
  207. // 需要登录的状态
  208. if (code == statusCode.FAILURE_CODE_5001||code === statusCode.FAILURE_CODE_5002) {
  209. postQueue.push(function() {
  210. http[method](url, data, done, fail);
  211. });
  212. }
  213. });
  214. if (!flag) {
  215. fail(result)
  216. }
  217. if (flag === statusCode.NEXT) {
  218. done(result, result.code == 0);
  219. }
  220. } else {
  221. console.log('ajax返回数据里没有code.')
  222. done(result);
  223. }
  224. });
  225. xhr.fail(fail);
  226. xhr.always(() => (xhr = null));
  227. return xhr;
  228. },
  229. /**
  230. * Get请求
  231. * @param {String} url 请求地址
  232. * @param {Object?} data 请求参数
  233. * @param {Function?} done 成功回调
  234. * @param {Function?} fail 失败回调
  235. */
  236. get(url, data = {}, done, fail) {
  237. if (/\.json/.test(url)) {
  238. // json文件格式自动调用getJson方法
  239. return this.getJson(url, data, done, fail);
  240. }
  241. return this.__request($.get(url, data), "get", url, data, done, fail);
  242. },
  243. /**
  244. * Get Blob请求
  245. * @param {String} url 请求地址
  246. * @param {Object?} data 请求参数
  247. * @param {Function?} done 成功回调
  248. * @param {Function?} fail 失败回调
  249. */
  250. getText(url, data = {}, done, fail) {
  251. return this.__request(
  252. $.ajax({
  253. url: url,
  254. dataType: "text",
  255. }),
  256. "getText",
  257. url,
  258. data,
  259. done,
  260. fail
  261. );
  262. },
  263. /**
  264. * GetJson请求 读取json文件数据
  265. * @param {String} url 请求地址
  266. * @param {Object?} data 请求参数
  267. * @param {Function?} done 成功回调
  268. * @param {Function?} fail 失败回调
  269. */
  270. getJson(url, data = {}, done, fail) {
  271. return this.__request($.getJSON(url, data), "get", url, data, done, fail);
  272. },
  273. /**
  274. * Get Blob请求
  275. * @param {String} url 请求地址
  276. * @param {Object?} data 请求参数
  277. * @param {Function?} done 成功回调
  278. * @param {Function?} fail 失败回调
  279. */
  280. getBlob(url, data = {}, done, fail) {
  281. return this.__request(
  282. $.ajax({
  283. url: url,
  284. dataType: "blob",
  285. }),
  286. "getBlob",
  287. url,
  288. data,
  289. done,
  290. fail
  291. );
  292. },
  293. /**
  294. * Get Arraybuffer请求
  295. * @param {String} url 请求地址
  296. * @param {Object?} data 请求参数
  297. * @param {Function?} done 成功回调
  298. * @param {Function?} fail 失败回调
  299. */
  300. getArraybuffer(url, data = {}, done, fail) {
  301. return this.__request(
  302. $.ajax({
  303. url: url,
  304. dataType: "arraybuffer",
  305. }),
  306. "getArraybuffer",
  307. url,
  308. data,
  309. done,
  310. fail
  311. );
  312. },
  313. /**
  314. * Post 请求
  315. * @param {String} url 请求地址
  316. * @param {Object?} data 请求参数
  317. * @param {Function?} done 成功回调
  318. * @param {Function?} fail 失败回调
  319. */
  320. post(url, data = {}, done, fail) {
  321. return this.__request($.post(url, data), "post", url, data, done, fail);
  322. },
  323. /**
  324. * PostJson 请求
  325. * @param {String} url 请求地址
  326. * @param {Object?} data 请求参数
  327. * @param {Function?} done 成功回调
  328. * @param {Function?} fail 失败回调
  329. */
  330. postJson(url, data = {}, done, fail) {
  331. return this.__request(
  332. $.ajax({
  333. type: "POST",
  334. url: url,
  335. contentType: "application/json",
  336. data: JSON.stringify(data),
  337. }),
  338. "postJson",
  339. url,
  340. data,
  341. done,
  342. fail
  343. );
  344. },
  345. /**
  346. * Post 表单 支持文件上传
  347. * @param {String} url 请求地址
  348. * @param {FormData?} formData 请求参数
  349. * @param {Function?} done 成功回调
  350. * @param {Function?} fail 失败回调
  351. */
  352. postForm(url, formData, done, fail, onProgress) {
  353. if (typeof onProgress === "function") {
  354. return this.__request(
  355. $.ajax({
  356. type: "POST",
  357. url: url,
  358. processData: false,
  359. contentType: false,
  360. data: formData,
  361. xhr: function() {
  362. const xhr = new XMLHttpRequest();
  363. xhr.upload.addEventListener("progress", function(e) {
  364. onProgress(e.loaded / e.total);
  365. });
  366. xhr.onabort = () => {
  367. console.log('xhr aborted.');
  368. }
  369. return xhr;
  370. },
  371. // 覆盖全局配置的失败回调。因为无论是上传子集失败还是用户取消了上传,都不需要弹窗。
  372. error: function() {
  373. },
  374. }),
  375. "postForm",
  376. url,
  377. formData,
  378. done,
  379. fail
  380. );
  381. } else {
  382. return this.__request(
  383. $.ajax({
  384. type: "POST",
  385. url: url,
  386. processData: false,
  387. contentType: false,
  388. data: formData,
  389. }),
  390. "postForm",
  391. url,
  392. formData,
  393. done,
  394. fail
  395. );
  396. }
  397. },
  398. /**
  399. * 加载图片
  400. * @param {String} url 请求地址
  401. * @param {Number?} retry 重试次数,默认为3
  402. */
  403. loadImage(url, retry = 3) {
  404. const def = $.Deferred();
  405. const img = new Image();
  406. const load = () => {
  407. logger.warn("Retrying load image: " + url);
  408. this.loadImage(url, retry - 1)
  409. .done(def.resolve.bind(def))
  410. .progress(def.notify.bind(def))
  411. .fail(def.reject.bind(def));
  412. };
  413. img.onerror = function() {
  414. retry > 0
  415. ? setTimeout(() => load(), 1e3)
  416. : def.reject(`[${url}]${i18n.t('tips_code.loading_fail')}`);
  417. };
  418. img.onload = function() {
  419. def.resolve(img);
  420. };
  421. img.crossOrigin = "anonymous";
  422. img.src = url;
  423. return def;
  424. },
  425. /**
  426. * 上传文件
  427. * @param {String} url 请求地址
  428. * @param {Object?} data 请求参数
  429. * @param {Function?} done 成功回调
  430. * @param {Function?} fail 失败回调
  431. */
  432. uploadFile(url, data = {}, done, fail, onProgress) {
  433. const form = new FormData();
  434. // if (file.needTransfer) { //ie和苹果都不支持dataURLtoFile得传送,所以只能用blob
  435. // form.append("file", common.dataURLtoBlob(file.file), file.name || file.file.name);
  436. // } else {
  437. // form.append("file", file.file, file.name || file.file.name);
  438. // }
  439. for (let key in data) {
  440. if (key == "file") {
  441. form.append("file", data[key], data.filename || data[key].name);
  442. } else if (key != "filename") {
  443. form.append(key, data[key]);
  444. }
  445. }
  446. return this.postForm(url, form, done, fail, onProgress);
  447. },
  448. /**
  449. * 上传文件
  450. * @param {String} url 请求地址
  451. * @param {Object?} data 请求参数 {file:'base64 string',filename:'image.jpg',...}
  452. * @param {Function?} done 成功回调
  453. * @param {Function?} fail 失败回调
  454. */
  455. uploadBlobFile(url, data = {}, done, fail) {
  456. const form = new FormData();
  457. for (let key in data) {
  458. if (key === "file") {
  459. form.append("file", base64ToBlob(data.file), data.filename);
  460. } else if (key != "filename") {
  461. form.append(key, data[key]);
  462. }
  463. }
  464. return this.postForm(url, form, done, fail);
  465. },
  466. };