import { getToken, setToken, removeToken } from './auth' import { setVersion } from '../utils/version.js' import { getBaseUrl } from '../utils/version.js' let baseURL; setVersion() let isRefreshing = false let subscribers = [] // 订阅 Token 刷新 function subscribeTokenRefresh(cb) { subscribers.push(cb) } // 发布 Token 刷新完成 function onRrefreshed(token) { subscribers.forEach(cb => cb(token)) subscribers = [] } // 请求拦截器 const requestInterceptor = (options) => { // 获取token const token = uni.getStorageSync('accessToken') if (token) { options.header = { ...options.header, 'Authorization': `Bearer ${token}` } } // #ifdef H5 // H5端跨域处理 options.header = { ...options.header, 'Access-Control-Allow-Origin': '*' } // #endif return options } // 响应拦截器 const responseInterceptor = async (options, response, resolve, reject) => { const { statusCode, data } = response // 请求成功 if (statusCode >= 200 && statusCode < 300) { return data } // 处理错误 if (statusCode === 401) { return await handleUnauthorized(options, resolve, reject) } // 其他错误 uni.showToast({ title: data.message || '请求失败', icon: 'none' }) return Promise.reject(data) } // 创建 uni.request 的封装 // const request = (options) => { // return new Promise((resolve, reject) => { // uni.request({ // ...options, // success: (res) => { // if (res.statusCode === 401) { // // 处理 401 逻辑 // handleUnauthorized(options, resolve, reject) // } else { // resolve(res) // } // }, // fail: (err) => { // reject(err) // } // }) // }) // } // 请求方法 const request = async (options, isUpdate) => { // 合并配置 let url = uni.getStorageSync('baseUrl') if (uni.getStorageSync('setVersion').VersionCode == '') { setVersion() } if (!url) { await new Promise((resolve, reject) => { uni.request({ url: 'https://app.mrrweb.com.cn/api/openPuc/getApiUrl', // 接口地址 method: 'GET', // 请求方法(默认 GET) header: { 'Content-Type': 'application/json', // 请求头 'VersionCode': uni.getStorageSync('setVersion').VersionCode, 'DeviceBrand': uni.getStorageSync('setVersion').DeviceBrand, 'DeviceType': uni.getStorageSync('setVersion').DeviceType }, success: (res) => { if (res.data.code == 200) { uni.setStorageSync('baseUrl', res.data.data.url) url = res.data.data.url resolve(url) } console.log('请求成功', res.data); }, fail: (err) => { console.log('请求失败', err); }, complete: () => { console.log('请求完成(无论成功失败都会执行)'); } }); }) } if (process.env.NODE_ENV === 'development') { //baseURL = url; // 发布到生产环境时,此处代码会被摇树移除掉。 baseURL = 'http://60.247.146.5:93'; // 发布到测试环境时,此处代码会被摇树移除掉。 //baseURL = 'http://60.247.146.5:96'; // 发布到生产环境时,此处代码会被摇树移除掉。 //baseURL = 'https://app.mrrweb.com.cn'; } else { //baseURL = url; baseURL = 'http://60.247.146.5:93'; // 发布到测试环境时,此处代码会被摇树移除掉。 //baseURL = 'http://60.247.146.5:96'; // 发布到生产环境时,此处代码会被摇树移除掉。 // baseURL = 'https://app.mrrweb.com.cn'; console.log('生产环境'); } // 基础配置 const config = { baseURL: baseURL, // APP和H5的开发URL baseURL: baseURL, // APP和H5的开发URL // baseURL: 'https://app.mrrweb.com.cn', // APP和H5的生产URL header: { 'content-type': 'application/json', 'VersionCode': uni.getStorageSync('setVersion').VersionCode, 'DeviceBrand': uni.getStorageSync('setVersion').DeviceBrand, 'DeviceType': uni.getStorageSync('setVersion').DeviceType }, timeout: 60000 // 超时时间 } options = { ...config, ...options, url: !isUpdate ? `${config.baseURL}${options.url}` : options.url } // 请求拦截 options = requestInterceptor(options) // 发起请求 return new Promise((resolve, reject) => { // #ifdef H5 // H5端添加loading if (!options.hideLoading) { uni.showLoading({ title: '加载中...' }) } // #endif uni.request({ ...options, success: (res) => { // #ifdef H5 if (!options.hideLoading) { uni.hideLoading() } // #endif resolve(responseInterceptor(options, res, resolve, reject)) }, fail: (err) => { // #ifdef H5 if (!options.hideLoading) { uni.hideLoading() } // #endif // 网络错误处理 let errorMsg = '网络错误,请稍后重试' // #ifdef H5 if (err.errMsg.includes('timeout')) { errorMsg = '请求超时,请检查网络' } // #endif uni.showToast({ title: errorMsg, icon: 'none' }) reject(err) } }) }) } // 处理 401 未授权 async function handleUnauthorized(originalRequest, resolve, reject) { if (!getToken()) { return redirectToLogin() } // 如果正在刷新 Token,将请求加入队列 if (isRefreshing) { return subscribeTokenRefresh(token => { originalRequest.header['Authorization'] = `Bearer ${token}` request(originalRequest, true).then(resolve).catch(reject) }) } isRefreshing = true try { const newToken = await refreshToken() setToken(newToken) onRrefreshed(newToken) // 用新 Token 重试原始请求 originalRequest.header['Authorization'] = `Bearer ${newToken}` const response = await request(originalRequest, true) // resolve(response) return response } catch (error) { removeToken() redirectToLogin() // reject(error) return error } finally { isRefreshing = false } } // 刷新 Token async function refreshToken() { const refreshToken = uni.getStorageSync('refreshToken') if (!refreshToken) { throw new Error('No refresh token') } const res = await request({ url: '/user/refreshtoken', data: { refresh_token: uni.getStorageSync('refreshToken'), deviceid: getApp().globalData.deviceid }, method: 'POST' }) if (res.state == 1) { uni.setStorageSync('accessToken', res.access_token) uni.setStorageSync('refreshToken', res.refresh_token) return res.access_token } throw new Error('Refresh token failed') } // 跳转到登录页 function redirectToLogin() { // uni.reLaunch({ // url: '/pages/login/login' // }) //一键登录测试 // uni.oprPresentLogin() uni.navigateTo({ url: '/pages/blogPopup/blogPopup' }); } // 导出请求方法 export default { // GET请求 get(url, data = {}, options = {}) { return request({ url, data, method: 'GET', ...options }) }, // POST请求 post(url, data = {}, options = {}) { return request({ url, data, method: 'POST', ...options }) }, // PUT请求 put(url, data = {}, options = {}) { return request({ url, data, method: 'PUT', ...options }) }, // DELETE请求 delete(url, data = {}, options = {}) { return request({ url, data, method: 'DELETE', ...options }) } }