import { http, toast } from '@/uni_modules/uview-plus' import store from '@/store' import { DEVE_URL, PRODUCT_URL } from '@/common/config.js' import { login } from '../../config/api.js' import { Base64 } from 'js-base64' 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 = process.env.NODE_ENV === 'development' ? DEVE_URL : PRODUCT_URL // #ifdef H5 baseURL = '' // #endif // 全局配置 http.setConfig((config) => { config.baseURL = baseURL return config }) let loadingTimer = null; let loadingCount = 0; const showLoading = () => { loadingCount++; if (loadingCount === 1) { // 延迟显示loading,避免闪烁 loadingTimer = setTimeout(() => { uni.showLoading({ mask: true }); }, 300); // 300ms延迟 } }; const hideLoading = () => { loadingCount--; if (loadingCount === 0) { if (loadingTimer) { clearTimeout(loadingTimer); loadingTimer = null; } uni.hideLoading(); } }; const requestInterceptors = (vm) => { /** * 请求拦截 */ http.interceptors.request.use((config) => { config.baseURL = baseURL // 初始化请求拦截器时,会执行此方法,此时data为undefined,赋予默认{} config.data = config.data || {} // 添加token let token = uni.getStorageSync('access_token') if (token) config.header['Blade-Auth'] = `Bearer ${token}` // 添加基础认证 config.header['Authorization'] = `Basic ${Base64.encode('saber:saber_secret')}` uni.showLoading({ mask: true }) setTimeout(() => { uni.hideLoading(); }, 5000) return config }, (config) => { return Promise.reject(config) }) } /** * 刷新令牌 */ const tryRefreshToken = async (config) => { if (!refreshToking) { refreshToking = true try { const params = { grantType: 'refresh_token', refreshToken: uni.getStorageSync('refresh_token') } const data = await store.dispatch('refreshToken', params) if (data.access_token) { requests.forEach((cb) => cb(data.access_token)) requests = [] return http.request(config) } } catch (error) { console.error('refreshToken error =>', error) store.commit('userInfo', {}) store.commit('isLogin', false) store.commit('access_token', '') store.commit('refresh_token', '') // 移除自动跳转到登录页面 toast('请登录后操作') // 添加跳转到登录页面的逻辑 uni.navigateTo({ url: '/packageUser/pages/login/index' }); return Promise.reject(error) } finally { refreshToking = false } } else { return new Promise((resolve) => { requests.push(() => { resolve(http.request(config)) }) }) } } const responseInterceptors = (vm) => { /** * 响应拦截 */ http.interceptors.response.use(async (response) => { const data = response.data uni.hideLoading() // 成功状态判断 if (data.success && data.success == 'true' || data.Code == 0) { return data } // 状态码处理 switch (data.code) { case 200: case 201: return data case 401: case 402: // token过期,尝试刷新 return await tryRefreshToken(response.config) case 403: uni.navigateTo({ url: '/pages/error/403' }) return Promise.reject(data) case 500: toast('服务器错误,请稍后重试') return Promise.reject(data) default: // 错误提示 const errMsg = data?.msg || data?.error_description || CODE_MESSAGE[data.code] || '请求失败' toast(errMsg) return Promise.reject(data) } }, async (error) => { hideLoading(); uni.hideLoading(); // HTTP状态码处理 switch (error.statusCode) { case 401: case 402: return await tryRefreshToken(error.config) case 403: uni.navigateTo({ url: '/pages/error/403' }) break case 500: toast('服务器错误,请稍后重试') break default: toast('网络错误,请检查网络连接') } return Promise.reject(error) }) } export { requestInterceptors, responseInterceptors }