import axios from 'axios' import store from '@/store' import { MessageBox } from 'element-ui' import { getToken } from '@/utils/token' import { DES3 } from '@/utils/3des' import { parseTime } from '@/utils/index' import router from '@/router/index' import { ElMessage } from '../utils/message.js' const Message = new ElMessage() const requestList = [] // 请求列表 const CancelToken = axios.CancelToken const sources = {} const successCode = '000000000' | '0000000' // 成功编码 // axios配置 // 全局的 axios 默认值:指定将被用在各个请求的配置默认值 axios.defaults.timeout = 20000 // 设置超时时间 axios.defaults.baseURL = process.env.VUE_APP_BASE_API // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL // axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;//根据项目需要配置 axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded' // 设置请求头的类型 // 添加请求拦截器 axios.interceptors.request.use(config => { const request = JSON.stringify(config.url) + (config.data ? JSON.stringify(config.data) : JSON.stringify(config.params)) config.cancelToken = new CancelToken((cancel) => { sources[request] = cancel }) // 判断请求是否已存在请求列表,避免重复请求,将当前请求添加进请求列表数组; // if (requestList.includes(request)) { // console.log(request) // sources[request]('取消重复请求') // requestList.splice(requestList.findIndex(item => item === request), 1) // } else { // requestList.push(request) // } // 因本项目部分请求需要重复获取所以不用去重 requestList.push(request) // 登录控制中根据本地是否存在token判断用户的登录情况, // 但即使token存在,也有可能token是过期的,所以在每次的请求头中携带token, // 后台根据携带的token判断用户的登录情况,并返回给我们对应的状态码, // 而后我们可以在响应拦截器中,根据状态码进行一些统一的操作。 // 本项目不用请求头判断而是在报文体中发送token // let token = store.getters.token || getToken(); // token && (config.headers.Authorization = token); return config }, error => Promise.reject(error)) // 添加响应拦截器 axios.interceptors.response.use(res => { const request = JSON.stringify(res.config.url) + (res.config.data ? JSON.stringify(res.config.data) : JSON.stringify(res.config.params)) requestList.splice(requestList.findIndex(item => item === request), 1) if (res.status == 200) { const { data } = res if (data.returnCode == successCode) { return Promise.resolve(data) } else { if (data.returnMsg === '系统没有登录或会话超时!') { store.dispatch('user/changeState', { key: 'token', value: '' }) store.dispatch('user/changeState', { key: 'name', value: '' }) store.dispatch('user/changeState', { key: 'userId', value: '' }) store.dispatch('user/changeState', { key: 'loginStatus', value: false }) MessageBox.confirm('系统没有登录或会话超时, 是否登录?', '提示', { confirmButtonText: '登录', cancelButtonText: '取消', center: true, closeOnClickModal: false, type: 'warning' }) .then(() => { MessageBox.close() router.replace(`/indexLayout/home?type=reLogin`) }) .catch(() => { Message.info('已取消!') MessageBox.close() }) } return Promise.reject(data) } } else { return Promise.reject(res) } }, err => { const { res } = err if (res) { // 请求已发出,但是不在2xx的范围 requestList.length = 0 errorHandle(res.status, res.data.message) return Promise.reject(res) } else { console.log(err) if (err.message === '取消上传') { return Promise.reject('cancel') } // 处理断网的情况 // eg:请求超时或断网时,更新network状态,可在app.vue中控制着一个全局的断网提示组件的显示隐藏 if (err.message === '取消重复请求') { // console.log(err) } else { const error = err.message.indexOf('timeout') != -1 ? { returnMsg: '请求超时' } : { returnMsg: '网络通讯异常' } requestList.splice(requestList.findIndex(item => item === request), 1) return Promise.reject(error) } } }) // 完善请求url function getUrl(channelNo = 'service') { let url = '' if (channelNo === 'service') { url = '/TransServlet' } else if (channelNo === 'manager') { url = '/managersvr/TransServlet' } return url } // 配置上行报文公共包头 function getParams(params, channelNo) { params['clientToken'] = store.getters.token || getToken() const userId = store.getters.userId if (userId) { params['userId'] = userId } params['transTime'] = parseTime(new Date().getTime(), '{y}-{m}-{d} {h}:{i}:{s} {t}') params['channelNo'] = channelNo return params } // 请求 const request = (params, channelNo = 'service', method = 'post') => { const url = getUrl(channelNo) // 完善请求url params = getParams(params, channelNo) // 配置上行报文公共包头 return new Promise((resolve, reject) => { if (method === 'post') { axios.post(url, params).then(res => { resolve(res) }).catch(err => { Message.error(err.returnMsg) reject(err) }) } else if (method === 'get') { axios.get(url, { params }).then(res => { resolve(res) }).catch(err => { Message.error(err.returnMsg) reject(err) }) } }) } // 文件上传 const uploadFile = (params, channelNo = 'service', callback1) => { const config = { timeout: 60000, headers: { 'Content-Type': 'multipart/form-data' }, onUploadProgress: progressEvent => { // 属性lengthComputable主要表明总共需要完成的工作量和已经完成的工作是否可以被测量,如果lengthComputable为false,就获取不到progress.total和progress.loaded if (progressEvent.lengthComputable) { const loaded = progressEvent.loaded const total = progressEvent.total const progress = Math.floor((loaded / total) * 100) > 1 ? Math.floor((loaded / total) * 100) : 1 // console.log('上传进度 ' + progress + '%'); // callback1(progress) } } } const url = getUrl(channelNo) // 完善请求url params.append('clientToken', store.getters.token || getToken()) params.append('userId', store.getters.userId) params.append('transTime', parseTime(new Date().getTime(), '{y}-{m}-{d} {h}:{i}:{s} {t}')) params.append('channelNo', channelNo) // 配置上行报文公共包头 return new Promise((resolve, reject) => { axios.post(url, params, config).then(res => { resolve(res) }).catch(err => { if (err !== 'cancel') { Message.error(err.returnMsg) } reject(err) }) }) } // 获取图片验证码 const getCode = (channelNo = 'service') => { const rand = Math.random() const token = store.getters.token || getToken() return process.env.VUE_APP_BASE_API + getUrl(channelNo) + '?transCode=HM0000&randomKey=' + rand + '&clientToken=' + token } // 获取图片Url const getImage = (id, channelNo = 'service') => { const token = store.getters.token || getToken() return process.env.VUE_APP_BASE_API + getUrl(channelNo) + '?transCode=B00022&clientToken=' + token + '&id=' + id } //download const download = (params, channelNo = 'service') => { let url = process.env.VUE_APP_BASE_API + getUrl(channelNo) + "?"; Object.getOwnPropertyNames(params).forEach((key) => { url += '&' + key + '=' + params[key] }) let link = document.createElement('a'); link.style.display = 'none'; link.href = url; link.target = '_blank'; document.body.appendChild(link); link.click(); document.body.removeChild(link); } // 加密密码 const enPassword = (password) => { const token = store.getters.token || getToken() return DES3.encrypt(token, password) } // 解密密码 const dePassword = (password) => { const token = store.getters.token || getToken() return DES3.decrypt(token, password) } export { request, uploadFile, getCode, getImage, download, enPassword, dePassword, sources }