/* * @Author: Rindy * @Date: 2019-08-06 16:25:08 * @LastEditors: Rindy * @LastEditTime: 2020-07-29 17:36:36 * @Description: Request */ import Vue from "vue"; import logger from "./logger"; import browser from "./browser"; import { base64ToBlob } from "./file"; import { checkLogin } from "@/api"; import { LoginDetector } from "@/utils/starter"; import { $alert, $confirm } from "@/components/shared/message"; import {i18n} from '@/lang' let vue = new Vue(); // 空函数 const noop = function() {}; // 请求回调队列 let postQueue = []; // 阻止多个弹窗 let isDiglog = false const statusCode = { NEXT: '__not_important__', //继续执行 SUCCESS: 0, //成功 FAILURE_CODE_3001: 3001, // "对象不存在" FAILURE_CODE_3002: 3002, //请至少保留一个场景。 FAILURE_CODE_3003: 3003, //文件名称不允许超过50个字符 FAILURE_CODE_3005: 3005, //不是该用户作品 FAILURE_CODE_3006: 3006, //作品已被删除,无法编辑 FAILURE_CODE_3007: 3007, //素材已被引用,无法删除。 // 301X -> 权限问题类 FAILURE_CODE_3010: 3010, // "Token为空" FAILURE_CODE_3011: 3011, // "没有操作权限" // 302X -> 文件类 FAILURE_CODE_3020: 3020, // "空文件" FAILURE_CODE_3021: 3021, // "非法文件" FAILURE_CODE_3022: 3022, // "上传文件超过最大值" FAILURE_CODE_3023: 3023, // "非法格式" FAILURE_CODE_3024: 3024, // "存储空间已满" FAILURE_CODE_3025: 3025, // "上传失败" // 31XX -> 自定义异常 FAILURE_CODE_3101: 3101, // "素材已经被引用, 不能删除" FAILURE_CODE_3102: 3102, // "计算中的场景不能删除" FAILURE_CODE_3103: 3103, // "服务器someData.json文件不存在" // 32XX -> 请求第三方API错误 FAILURE_CODE_3200: 3200, // "请求第三方API失败" FAILURE_CODE_3201: 3201, // "请求第三方API返回失败" FAILURE_CODE_5001: 5001, //token失效 FAILURE_CODE_5002: 5002, //token失效 FAILURE_CODE_5003: 5003, //不支持此图片 FAILURE_CODE_5004: 5004, // 密码错误 FAILURE_CODE_7005: 7005, //审核中不能编辑 FAILURE_CODE_7006: 7006, //已审核不能编辑 }; let __showNetworkError = false; export const showLoginTips = () => { // 防止多次请求弹出 if (showLoginTips.__is_show) { return; } showLoginTips.__is_show = true; return $confirm({ title: i18n.t('tips_code.tips'), content: i18n.t('tips_code.relogin'), okText: i18n.t('tips_code.goto_login'), noText: i18n.t('tips_code.login_success'), okLink: "/", ok: function() { showLoginTips.__is_show = false; return false; }, no: function() { checkLogin().then((response) => { if (response.code === statusCode.SUCCESS) { postQueue.length && postQueue.forEach((item) => item()); postQueue = []; LoginDetector.valid(); location.reload() } else if (response.code === statusCode.FAILURE_CODE_5001||response.code === statusCode.FAILURE_CODE_5002) { showLoginTips(); } }) showLoginTips.__is_show = false; }, }); }; function getCookie(objname) { //获取指定名称的cookie的值 var arrstr = document.cookie.split("; "); for (var i = 0; i < arrstr.length; i++) { var temp = arrstr[i].split("="); if (temp[0] == objname) return unescape(temp[1]); } } export function getToken() { return ( browser.urlHasValue("token", true) || localStorage.getItem("token") || getCookie("fdkankantoken") || "" ); } export function statusCodesHandler(result, callback) { if (result.code == statusCode.FAILURE_CODE_3002) { $alert({ content: i18n.t('tips_code.need_one') }); return false } if (result.code == statusCode.FAILURE_CODE_3003) { $alert({ content: i18n.t('tips_code.not_less_than') }) return false } if (result.code == statusCode.FAILURE_CODE_3005) { $alert({ content: i18n.t('tips_code.work_had_delete') }); return false } if (result.code == statusCode.FAILURE_CODE_3006) { $alert({ content: i18n.t('tips_code.work_had_delete') }); return } if (result.code == statusCode.FAILURE_CODE_3007) { $alert({ content: i18n.t('tips_code.material_can_not_delete') }); return } if (result.code == statusCode.FAILURE_CODE_5001||result.code === statusCode.FAILURE_CODE_5002) { callback(result.code); showLoginTips(); return false } if (result.code == statusCode.FAILURE_CODE_5003) { $alert({ content: i18n.t('tips_code.illegality_image') }) return false } if (result.code == statusCode.FAILURE_CODE_5004) { vue.$msg.error(i18n.t('tips_code.password_error')); return false } if (result.code == statusCode.FAILURE_CODE_3024) { if (!isDiglog) { isDiglog = true $alert({ content: i18n.t('tips_code.FAILURE_3024'), forceOK: true, ok: () => { isDiglog = false }, }); } return false } if (result.code != statusCode.SUCCESS) { console.log('result.msg'); $alert({ content: `${result.msg}` }); return false } return statusCode.NEXT; } $.ajaxSetup({ headers: {}, beforeSend: function(xhr) { const token = getToken(); if (token) { xhr.setRequestHeader("token", token); } }, error: function() { // 出错时默认的处理函数 if (__showNetworkError) { return; } __showNetworkError = true; $alert({ content: i18n.t('tips_code.FAILURE_error'), forceOK: true, ok: () => { __showNetworkError = false; }, }); return; }, success: function() {}, complete: function(data) { }, }); export const http = { statusCode, __request(xhr, method, url, data, done, fail) { if (typeof done != "function") { done = noop; } if (typeof fail != "function") { fail = noop; } xhr.done((result) => { if (typeof result.code !== "undefined") { const flag = statusCodesHandler(result, function(code) { // 需要登录的状态 if (code == statusCode.FAILURE_CODE_5001||code === statusCode.FAILURE_CODE_5002) { postQueue.push(function() { http[method](url, data, done, fail); }); } }); if (!flag) { fail(result) } if (flag === statusCode.NEXT) { done(result, result.code == 0); } } else { console.log('ajax返回数据里没有code.') done(result); } }); xhr.fail(fail); xhr.always(() => (xhr = null)); return xhr; }, /** * Get请求 * @param {String} url 请求地址 * @param {Object?} data 请求参数 * @param {Function?} done 成功回调 * @param {Function?} fail 失败回调 */ get(url, data = {}, done, fail) { if (/\.json/.test(url)) { // json文件格式自动调用getJson方法 return this.getJson(url, data, done, fail); } return this.__request($.get(url, data), "get", url, data, done, fail); }, /** * Get Blob请求 * @param {String} url 请求地址 * @param {Object?} data 请求参数 * @param {Function?} done 成功回调 * @param {Function?} fail 失败回调 */ getText(url, data = {}, done, fail) { return this.__request( $.ajax({ url: url, dataType: "text", }), "getText", url, data, done, fail ); }, /** * GetJson请求 读取json文件数据 * @param {String} url 请求地址 * @param {Object?} data 请求参数 * @param {Function?} done 成功回调 * @param {Function?} fail 失败回调 */ getJson(url, data = {}, done, fail) { return this.__request($.getJSON(url, data), "get", url, data, done, fail); }, /** * Get Blob请求 * @param {String} url 请求地址 * @param {Object?} data 请求参数 * @param {Function?} done 成功回调 * @param {Function?} fail 失败回调 */ getBlob(url, data = {}, done, fail) { return this.__request( $.ajax({ url: url, dataType: "blob", }), "getBlob", url, data, done, fail ); }, /** * Get Arraybuffer请求 * @param {String} url 请求地址 * @param {Object?} data 请求参数 * @param {Function?} done 成功回调 * @param {Function?} fail 失败回调 */ getArraybuffer(url, data = {}, done, fail) { return this.__request( $.ajax({ url: url, dataType: "arraybuffer", }), "getArraybuffer", url, data, done, fail ); }, /** * Post 请求 * @param {String} url 请求地址 * @param {Object?} data 请求参数 * @param {Function?} done 成功回调 * @param {Function?} fail 失败回调 */ post(url, data = {}, done, fail) { return this.__request($.post(url, data), "post", url, data, done, fail); }, /** * PostJson 请求 * @param {String} url 请求地址 * @param {Object?} data 请求参数 * @param {Function?} done 成功回调 * @param {Function?} fail 失败回调 */ postJson(url, data = {}, done, fail) { return this.__request( $.ajax({ type: "POST", url: url, contentType: "application/json", data: JSON.stringify(data), }), "postJson", url, data, done, fail ); }, /** * Post 表单 支持文件上传 * @param {String} url 请求地址 * @param {FormData?} formData 请求参数 * @param {Function?} done 成功回调 * @param {Function?} fail 失败回调 */ postForm(url, formData, done, fail, onProgress) { if (typeof onProgress === "function") { return this.__request( $.ajax({ type: "POST", url: url, processData: false, contentType: false, data: formData, xhr: function() { const xhr = new XMLHttpRequest(); xhr.upload.addEventListener("progress", function(e) { onProgress(e.loaded / e.total); }); xhr.onabort = () => { console.log('xhr aborted.'); } return xhr; }, // 覆盖全局配置的失败回调。因为无论是上传子集失败还是用户取消了上传,都不需要弹窗。 error: function() { }, }), "postForm", url, formData, done, fail ); } else { return this.__request( $.ajax({ type: "POST", url: url, processData: false, contentType: false, data: formData, }), "postForm", url, formData, done, fail ); } }, /** * 加载图片 * @param {String} url 请求地址 * @param {Number?} retry 重试次数,默认为3 */ loadImage(url, retry = 3) { const def = $.Deferred(); const img = new Image(); const load = () => { logger.warn("Retrying load image: " + url); this.loadImage(url, retry - 1) .done(def.resolve.bind(def)) .progress(def.notify.bind(def)) .fail(def.reject.bind(def)); }; img.onerror = function() { retry > 0 ? setTimeout(() => load(), 1e3) : def.reject(`[${url}]${i18n.t('tips_code.loading_fail')}`); }; img.onload = function() { def.resolve(img); }; img.crossOrigin = "anonymous"; img.src = url; return def; }, /** * 上传文件 * @param {String} url 请求地址 * @param {Object?} data 请求参数 * @param {Function?} done 成功回调 * @param {Function?} fail 失败回调 */ uploadFile(url, data = {}, done, fail, onProgress) { const form = new FormData(); // if (file.needTransfer) { //ie和苹果都不支持dataURLtoFile得传送,所以只能用blob // form.append("file", common.dataURLtoBlob(file.file), file.name || file.file.name); // } else { // form.append("file", file.file, file.name || file.file.name); // } for (let key in data) { if (key == "file") { form.append("file", data[key], data.filename || data[key].name); } else if (key != "filename") { form.append(key, data[key]); } } return this.postForm(url, form, done, fail, onProgress); }, /** * 上传文件 * @param {String} url 请求地址 * @param {Object?} data 请求参数 {file:'base64 string',filename:'image.jpg',...} * @param {Function?} done 成功回调 * @param {Function?} fail 失败回调 */ uploadBlobFile(url, data = {}, done, fail) { const form = new FormData(); for (let key in data) { if (key === "file") { form.append("file", base64ToBlob(data.file), data.filename); } else if (key != "filename") { form.append(key, data[key]); } } return this.postForm(url, form, done, fail); }, };