let base64 = require('../utils/base64.js').Base64; import { http, toast } from '@/uni_modules/uview-plus' import { DEVE_URL, PRODUCT_URL } from '@/common/config.js' import store from '@/store/index.js' const CODE_MESSAGE = { 0: '未可知错误,可能是因为后端不支持跨域CORS、接口地址不存在等问题引起', 200: '服务器成功返回请求数据', 201: '新建或修改数据成功', 202: '一个请求已经进入后台排队(异步任务)', 204: '删除数据成功', 400: '发出信息有误', 401: '用户没有权限(令牌失效、用户名、密码错误、登录过期)', 402: '令牌过期', 403: '用户得到授权,但是访问是被禁止的', 404: '访问资源不存在', 406: '请求格式不可得', 410: '请求资源被永久删除,且不会被看到', 500: '服务器发生错误', 502: '网关错误', 503: '服务不可用,服务器暂时过载或维护', 504: '网关超时', } let refreshToking = false let requests = [] let baseURL = '' if (process.env.NODE_ENV === 'development') { baseURL = DEVE_URL } else { baseURL = PRODUCT_URL } // #ifdef H5 baseURL = '' // #endif import { login } from '../config/api.js'; import Vue from 'vue' // 此vm参数为页面的实例,可以通过它引用vuex中的变量 const requestInterceptors = (vm) => { /** * axios请求拦截器配置 * @param config * @returns {any} */ const requestConf = (config) => { // 初始化请求拦截器时,会执行此方法,此时data为undefined,赋予默认{} config.data = config.data || {} let token = uni.getStorageSync('access_token'); if (token) config.header['Blade-Auth'] = `Bearer ${token}` // if (token) config.headers['Blade-Auth'] = `Bearer ${token}` // 根据custom参数中配置的是否需要token,添加对应的请求头 config.header['Authorization'] = `Basic ${base64.encode('saber:saber_secret')}` // uni.showLoading({ // title: '加载中...', // mask: true // }) return config } /** * 刷新刷新令牌 * @param config 过期请求配置 * @returns {any} 返回结果 */ const tryRefreshToken = async (config) => { if (!refreshToking) { refreshToking = true try { const params = {} params.grantType = 'refresh_token' params.refreshToken = uni.getStorageSync('refresh_token') const data = await store.dispatch('refreshToken', params); console.log('刷新成功,返回:') console.log(data) if (data.access_token) { requests.forEach((cb) => cb(data.access_token)) requests = [] return uni.$u.http.middleware(requestConf(config)) } } catch (error) { console.error('refreshToken error =>', error) // 使用 store 的 action 处理未登录状态 const pages = getCurrentPages(); const currentPage = pages[pages.length - 1]; const redirectPath = currentPage ? currentPage.route : ''; store.dispatch('handleUnauthorized', redirectPath); return Promise.reject(error) } finally { refreshToking = false } } else { return new Promise((resolve) => { requests.push(() => { resolve(uni.$u.http.middleware(requestConf(config))) }) }) } } // 初始化请求配置 uni.$u.http.setConfig((config) => { /* config 为默认全局配置*/ config.baseURL = baseURL; /* 根域名 */ return config }) // 请求拦截 uni.$u.http.interceptors.request.use(requestConf, config => { // 可使用async await 做异步操作 return Promise.reject(config) }) // 响应拦截 uni.$u.http.interceptors.response.use(async (response) => { uni.hideLoading() /* 对响应成功做点什么 可使用async await 做异步操作*/ const data = response.data if (data.success && data.success == 'true' || data.Code == 0) { return data } // 处理未登录和token过期情况 if (data.code === 401 || data.code === 402) { store.commit('userInfo', {}); store.commit('isLogin', false); store.commit('access_token', ''); store.commit('refresh_token', ''); // 显示提示 uni.$u.toast(data.code === 401 ? '请先登录' : 'token已过期,请重新登录'); // 获取当前页面路径 const pages = getCurrentPages(); const currentPage = pages[pages.length - 1]; const redirectUrl = currentPage ? encodeURIComponent(currentPage.route) : ''; // 延迟跳转,让用户看到提示 setTimeout(() => { uni.navigateTo({ url: `/pages/user/login?redirect=/${redirectUrl}` }); }, 1500); return Promise.reject(data); } // 处理其他状态码 switch (data.code) { case 200: case 201: return data; case 403: return vm.$route('/pages/403'); case 500: uni.$u.toast('服务器响应失败'); return Promise.reject(data); } // 其他错误统一提示 const errMsg = data.msg || data.error_description || CODE_MESSAGE[data.code] || '未知错误'; uni.$u.toast(errMsg); return Promise.reject(data); }, (error) => { uni.hideLoading(); // 处理网络错误等 uni.$u.toast('网络请求失败,请检查网络连接'); return Promise.reject(error); }) }