request.js 13 KB

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