src/api/intelligentPatrol/statistics.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/http/index.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/http/interceptor-handler.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/http/url-recorder.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/utils/loading.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/api/intelligentPatrol/statistics.js
@@ -1,21 +1,13 @@ import axios from "axios"; import { getToken } from '@/utils/helper' import http from '@/http' const baseUrl = '/sccg/intelligentPatrol/statistics' const token = { 'Authorization': getToken() } export default { // 按违规类型统计 searchByType: (data) => axios({ method: 'get', url: baseUrl + '/unlawful/type', headers: { ...token searchByType: (params) => { return http.get('/sccg/intelligentPatrol/statistics/unlawful/type', params); }, params: data }), // 按点位统计 searchByPoint: (data) => axios({ method: 'get', src/http/index.js
New file @@ -0,0 +1,218 @@ import axios from 'axios' import { handleResponseSuccess, handleResponseFail, handleRequest } from './interceptor-handler' import { showFullScreenLoading } from '../utils/loading' // import { getStorage } from '@utils/storage' // URL 记录器 import urlRecorder from './url-recorder' const axiosInstance = axios.create({ // baseURL: `${process.env.VUE_APP_API_BASE_URL}`, timeout: 1000 * 60 * 5 }) axiosInstance.interceptors.request.use(handleRequest) axiosInstance.interceptors.response.use(handleResponseSuccess, handleResponseFail) /** * 在 get 请求的 url 后面加个随机参数,以防浏览器缓存请求 * @param {string} url * @return {string} */ function addVersion(url) { return url.includes('?') ? `${url}&v=${Date.now()}` : `${url}?v=${Date.now()}` } export default { // 默认的异常处理方法,会传入完整的data对象,可以在这里弹提示框 defaultErrorHandler: null, /** * 通过get发送并接收json格式的数据(get发的本来就是json格式)。 * 并统一处理常见的错误 * @param {string} url * @param {object?} params={} * @param {boolean?} throwError 是否不使用默认的异常处理方法,而把异常抛出来 * @param {int?} timeout 超时时间,默认10秒 * @return {Promise} 返回一个promise对象。其中then方法传递回包中的data数据;catch事件则传递整个回包,其参数为{data:{},status{code:123,message:'xxx'}} */ get(url, params = {}, throwError, timeout) { const config = { method: 'GET', url: addVersion(url), params, errorHandler: (!throwError && this.defaultErrorHandler) || null, // headers: { 'Content-Type': 'application/json', token: thisToken }, headers: { 'Content-Type': 'application/json' }, withCredentials: this.withCredentials, timeout: timeout } if (params.showLoading === undefined) { showFullScreenLoading() } return axiosInstance(config) }, /** * 通过post发送数据,使后端直接收到json格式的数据。并统一处理常见的错误 * @param {string} url * @param {object?} data={} * @param {boolean?} throwError 是否不使用默认的异常处理方法,而把异常抛出来 * @param {int?} timeout 超时时间,默认10秒 * @return {Promise} 返回一个promise对象。其中then方法传递回包中的data数据;catch事件则传递整个回包,其参数为{data:{},status{code:123,message:'xxx'}} */ post(url, data = {}, throwError) { const config = { method: 'POST', url, data: JSON.stringify(data), errorHandler: (!throwError && this.defaultErrorHandler) || null, headers: { 'Content-Type': 'application/json' }, withCredentials: this.withCredentials } urlRecorder.add(config) if (data.showLoading === undefined) { showFullScreenLoading() } return axiosInstance(config) }, // PUT更新数据 put(url, data = {}, throwError) { const config = { method: 'PUT', url, data: JSON.stringify(data), errorHandler: (!throwError && this.defaultErrorHandler) || null, headers: { 'Content-Type': 'application/json' }, withCredentials: this.withCredentials } urlRecorder.add(config) if (data.showLoading === undefined) { showFullScreenLoading() } return axiosInstance(config) }, // DELETE更新数据 delete(url, data = {}, throwError) { const config = { method: 'delete', url, data: JSON.stringify(data), errorHandler: (!throwError && this.defaultErrorHandler) || null, headers: { 'Content-Type': 'application/json' }, withCredentials: this.withCredentials } urlRecorder.add(config) if (data.showLoading === undefined) { showFullScreenLoading() } return axiosInstance(config) }, /** * 通过表单get下载文件。并统一处理常见的错误 * @param {string} url * @param {String} fileName 文件名 * @param {Object?} data 上传进度回调,参数为event * @param {Function?} throwError 是否不使用默认的异常处理方法,而把异常抛出来 * @return {Promise} 返回一个promise对象 */ downloadFile(url, params, data = {}, throwError) { const { fileName, type } = params return axiosInstance({ method: 'GET', url, responseType: 'arraybuffer', data: JSON.stringify(data), errorHandler: (!throwError && this.defaultErrorHandler) || null, timeout: 50000, headers: { 'Content-Type': 'application/json' } }).then(response => { const blob = new Blob([response], { type }) // 不兼容type // 利用a标签实现下载 const link = document.createElement('a') link.style.display = 'none' link.setAttribute('type', MimeType) // 并不支持 const downUrl = window.URL.createObjectURL(blob) link.href = downUrl // 添加到浏览器为了兼容 firefox document.body.appendChild(link) // 为了兼容qq浏览器,fileName中必须加上文件后缀 link.download = fileName link.click() document.body.removeChild(link) }) }, /** * 通过a标签打开文件 * @param {string} url */ downloadFileByA(url) { // const {fileName} = params // 利用a标签实现下载 const link = document.createElement('a') link.style.display = 'none' link.href = `${process.env.VUE_APP_DOWN_FILE}${url}` // 添加到浏览器为了兼容 firefox document.body.appendChild(link) // 为了兼容qq浏览器,fileName中必须加上文件后缀 // link.download = fileName link.click() document.body.removeChild(link) return Promise.resolve() }, /** * 通过a标签下载文件 * @param {string} url */ downloadFileByAtag(url) { // 利用a标签实现下载 const link = document.createElement('a') link.download = url link.target = '_blank' link.style.display = 'none' link.href = url document.body.appendChild(link) link.click() document.body.removeChild(link) return Promise.resolve() }, /** * 通过表单post上传文件并接收json格式的数据。并统一处理常见的错误 * @param {string} url * @param {FormData|object} formElem FormData对象,或form Dom元素,其中需要含有一个name为files的选择文件的input元素 * @param {Function?} onUploadProgress 上传进度回调,参数为event * @param {boolean?} throwError 是否不使用默认的异常处理方法,而把异常抛出来 * @param {int?} timeout 超时时间,默认50秒 * @return {Promise} 返回一个promise对象。其中then方法传递回包中的data数据;catch事件则传递整个回包,其参数为{data:{},status{code:123,message:'xxx'}} */ uploadFile(url, formElem, onUploadProgress, throwError) { return axiosInstance({ method: 'POST', url, data: formElem instanceof FormData ? formElem : new FormData(formElem), onUploadProgress, errorHandler: (!throwError && this.defaultErrorHandler) || null, timeout: 500000, enableRepeat: true }) } } src/http/interceptor-handler.js
New file @@ -0,0 +1,106 @@ // URL 记录器 import Vue from 'vue' import urlRecorder from './url-recorder' import { tryHideFullScreenLoading } from '../utils/loading' /** * 对成功返回的请求回包进行数据预处理 * @param response * @returns {Promise} */ export function handleResponseSuccess(response) { debugger tryHideFullScreenLoading() urlRecorder.remove(response.config) const result = response.data // return result.content if (result.code === 200) { return result.data || result.content } else if (result.code && result.code !== 0) { return handleError(response.config, result) } else if (result === '') { Vue.prototype.$message({ type: 'error', message: '服务内部错误' }) return result } else { // 来自其它服务器的请求 return result } } /** * 对发送失败的请求进行数据预处理,将error对象封装为统一的形式 * @param error * @returns {Promise} */ export function handleResponseFail(error) { tryHideFullScreenLoading() urlRecorder.remove(error.config) let result if (error.response) { // 请求已发送,响应中返回了非2xx的错误码,包括304等 result = { data: error.response.data, msg: error.response.statusText } } else if (error.request) { // 请求没有发送成功时的错误 result = { data: error.request, msg: error.message } } else { // 设置请求时出错 result = { msg: error.message } } return handleError(error.config, result) } /** * 统一的异常对象封装逻辑,在这里抛出异常 * @param {object} requestConfig 发请求时传入axios的配置信息对象 * @param {object|Error} result 请求回包对象,或异常信息 * @param {object} result.content * @param {number} result.code * @param {string} result.msg * @returns {Promise} */ export function handleError(requestConfig, result) { // 必须是Error对象,否则throw时vuex要报warning // let err // if (result instanceof Error) { // err = result // } else { // err = new Error(result.msg) // err.content = result.content // err.code = result.code // err.msg = result.msg // } if (requestConfig && requestConfig.errorHandler) { result.url = requestConfig.url requestConfig.errorHandler(result) result.processed = true } return Promise.reject(result) } /** * 请求拦截器,添加用户token */ export function handleRequest(config) { const token = sessionStorage.getItem('token'); const tokenHead = sessionStorage.getItem('tokenHead'); if (token && tokenHead) { // 这里经常搭配token使用,将token值配置到tokenkey中,将tokenkey放在请求头中 config.headers['Authorization'] = tokenHead + token } return config } src/http/url-recorder.js
New file @@ -0,0 +1,54 @@ // 记录正在发送中的请求,以判断是否重复发包 export default { // 正在进行中的请求列表 urlList: [], /** * 添加一个新的请求记录,如果已经存在进行中的请求了,就抛出异常 * @param {string} config * @param {string} config.url 请求地址 * @param {string} config.enableRepeat 允许同时发送多个相同请求 * @return {Promise} */ add(config) { // 允许同时发送多个相同请求 // 比如批量上传图片的时候 if (config.enableRepeat) return Promise.resolve() const url = config.url // 如果请求还在队列里,说明还在处理,没有回包 if (this.urlList.includes(url)) { const errorMessage = `请求 ${url} 正在处理,请稍后再试!` console.error(errorMessage) const error = { status: { code: 1007, // 临时写的 debugMessage: url, // eslint-disable-next-line no-use-before-define message: error.message } } return Promise.reject(error) } // 这里没有前缀,但是remove中有 this.urlList.push(`${process.env.VUE_APP_API_BASE_URL}${url}`) return Promise.resolve() }, /** * 删除一个正在进行的请求记录 * @param {string} config * @param {string} config.url 请求地址 */ remove(config) { // 允许同时发送多个相同请求 if (config.enableRepeat) return const index = this.urlList.indexOf(config.url) if (index >= 0) { this.urlList.splice(index, 1) } } } src/utils/loading.js
New file @@ -0,0 +1,47 @@ import { Loading } from 'element-ui' /** 定义loading变量 */ let loading /** 使用Element loading-start 方法 */ function startLoading() { loading = Loading.service({ lock: true, text: '加载中……', background: 'rgba(0, 0, 0, 0.7)' }) } /** 使用Element loading-close 方法 */ function endLoading() { loading.close() } /** * 那么 showFullScreenLoading() tryHideFullScreenLoading() 要干的事儿就是将同一时刻的请求合并。 * 声明一个变量 needLoadingRequestCount,每次调用showFullScreenLoading方法 needLoadingRequestCount + 1。 * 调用tryHideFullScreenLoading()方法,needLoadingRequestCount - 1。needLoadingRequestCount为 0 时,结束 loading。 */ let needLoadingRequestCount = 0 /** 显示Loading */ export function showFullScreenLoading() { if (needLoadingRequestCount === 0) { startLoading() } needLoadingRequestCount++ } /** 隐藏Loading */ export function tryHideFullScreenLoading() { if (needLoadingRequestCount <= 0) return needLoadingRequestCount-- if (needLoadingRequestCount === 0) { endLoading() } } export default { showFullScreenLoading, tryHideFullScreenLoading }