From ddf1040d80f0ecf2d4660982db22a1d7bf245264 Mon Sep 17 00:00:00 2001 From: Dong Xia Date: Thu, 2 Feb 2023 02:16:17 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=AF=B9=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E7=9A=84=E8=AF=B7=E6=B1=82=E3=80=81=E5=93=8D=E5=BA=94?= =?UTF-8?q?=E6=8B=A6=E6=88=AA=E5=99=A8=E5=B0=81=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Dong Xia --- src/utils/request.js | 180 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 src/utils/request.js diff --git a/src/utils/request.js b/src/utils/request.js new file mode 100644 index 0000000..ce1550b --- /dev/null +++ b/src/utils/request.js @@ -0,0 +1,180 @@ +import Vue from 'vue' +import axios from 'axios' +import Qs from 'qs' +import store from '../store' +import router from '../router' +import { NO_NOTIFY_KEY, NO_LOADING_KEY, TOKEN_HEADER_KEY } from './const' +import { refreshToken } from '../api/user' +import { notification } from 'ant-design-vue' + +// 静态全局baseUrl +const serverIp = window.localStorage.getItem('mini_serverIp') +axios.defaults.baseURL = serverIp ? `http://${serverIp}:2122` : process.env.VUE_APP_BASE_API +if (!serverIp) { + let url = process.env.VUE_APP_BASE_API + let ip = url.split(':')[1].slice(2) + localStorage.setItem('mini_serverIp', ip) +} +let $global_loading +let startTime +var delTimeout = 20 * 1000 +var apiTimeout = window.apiTimeout === '' ? delTimeout : window.apiTimeout +const request = axios.create({ + timeout: apiTimeout || delTimeout, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', + loading: 'no' + }, + responseType: 'json' +}) + +// request interceptors +request.interceptors.request.use( + (config) => { + // 如果 headers 里面配置了 loading: no 就不用 loading + if (!config.headers[NO_LOADING_KEY]) { + $global_loading = Vue.prototype.$loading.service({ + lock: true, + text: '加载数据中,请稍候...', + spinner: 'el-icon-loading', + background: 'rgba(0, 0, 0, 0.7)' + }) + startTime = new Date().getTime() + } + // 处理数据 + if (window.routerBase) { + // 防止 url 出现 // + config.url = (window.routerBase + config.url).replace(new RegExp('//', 'gm'), '/') + } + if (config.headers['Content-Type'].indexOf('application/x-www-form-urlencoded') !== -1) { + config.data = Qs.stringify(config.data) + } + config.headers[TOKEN_HEADER_KEY] = store.getters.getToken + return config + }, + (error) => { + return Promise.reject(error) + } +) + +// response interceptors +request.interceptors.response.use( + (response) => { + // 如果 headers 里面配置了 loading: no 就不用 loading + if (!response.config?.headers[NO_LOADING_KEY]) { + const endTime = new Date().getTime() + if (endTime - startTime < 1000) { + setTimeout(() => { + $global_loading && $global_loading.close() + }, 300) + } else { + $global_loading && $global_loading.close() + } + } + // 如果 responseType 是 blob 表示是下载文件 + if (response.request.responseType === 'blob') { + return response.data + } + // 判断返回值,权限等... + const res = response.data + + // 先判断 jwt token 状态 + if (res.code === 800 || res.code === 801) { + return checkJWTToken(res, response) + } + + // 其他情况 + if (res.code !== 200) { + // 如果 headers 里面配置了 tip: no 就不用弹出提示信息 + if (!response.config.headers[NO_NOTIFY_KEY]) { + notification.error({ + message: res.msg, + duration: 2 + }) + } + } + + return res + }, + (error) => { + if (!error.response) { + // NETWORK ERR + $global_loading && $global_loading.close() + notification.error({ + message: '网络错误', + description: '网络开了小差,请检查服务器IP后重试...', + duration: 2 + }) + // for debug + return Promise.reject(error) + } + // 如果 headers 里面配置了 loading: no 就不用 loading + if (!error.response.config.headers[NO_LOADING_KEY]) { + $global_loading && $global_loading.close() + } + // 如果 headers 里面配置了 tip: no 就不用弹出提示信息 + if (!error.response.config.headers[NO_NOTIFY_KEY]) { + const { status, statusText, data } = error.response + if (!status) { + notification.error({ + message: '网络错误', + description: '网络开了小差,请检查服务器IP后重试...', + duration: 2 + }) + } else { + notification.error({ + message: status, + description: (statusText || '') + (data || ''), + duration: 2 + }) + } + } + return Promise.reject(error) + } +) + +// 判断 jwt token 状态 +function checkJWTToken(res, response) { + // 如果是登录信息失效 + if (res.code === 800) { + notification.warn({ + message: res.msg, + // description: response.config.url, + duration: 3 + }) + store.dispatch('logOut').then(() => { + router.push('/login') + location.reload() + }) + return false + } + // 如果 jwt token 还可以续签 + if (res.code === 801) { + notification.close() + notification.info({ + message: '登录信息过期,尝试自动续签...', + description: '如果不需要自动续签,请修改配置文件。该续签将不会影响页面。', + duration: 3 + }) + // 续签且重试请求 + return redoRequest(response.config) + } +} + +// 刷新 jwt token 并且重试上次请求 +function redoRequest(config) { + return new Promise((resolve) => { + Promise.resolve(refreshToken()).then((result) => { + if (result.code === 200) { + // 调用 store action 存储当前登录的用户名和 token + store.dispatch('login', result.data) + resolve() + } + }) + }).then(() => { + // 重试原来的请求 + return request(config) + }) +} + +export default request -- Gitee From 7cf3386b22c52a5424928281d579dc9d95012d88 Mon Sep 17 00:00:00 2001 From: Dong Xia Date: Thu, 2 Feb 2023 02:26:30 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=E5=AE=9A=E4=B9=89=E5=B8=B8=E9=87=8F?= =?UTF-8?q?=E6=B1=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Dong Xia --- src/utils/const.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/utils/const.js diff --git a/src/utils/const.js b/src/utils/const.js new file mode 100644 index 0000000..4100d43 --- /dev/null +++ b/src/utils/const.js @@ -0,0 +1,28 @@ +// const pool +export const USER_NAME_KEY = 'Mpms-UserName' + +export const TOKEN_KEY = 'Mpms-Token' + +export const LONG_TERM_TOKEN = 'Mpms-Long-Term-Token' + +export const USER_INFO_KEY = 'Mpms-User' + +export const MENU_KEY = 'Mpms-Menus' + +export const TOKEN_HEADER_KEY = 'Authorization' + +export const ACTIVE_TAB_KEY = 'Mpms-ActiveTab' + +export const TAB_LIST_KEY = 'Mpms-TabList' + +export const ACTIVE_MENU_KEY = 'Mpms-ActiveMenu' + +export const GUIDE_FLAG_KEY = 'Mpms-GuideFlag' + +export const GUIDE_HOME_USED_KEY = 'Mpms-Home-Guide-Used' + +export const GUIDE_NODE_USED_KEY = 'Mpms-Node-Guide-Used' + +export const NO_NOTIFY_KEY = 'tip' + +export const NO_LOADING_KEY = 'loading' -- Gitee