import config from './config.js' // 创建请求实例 const service = { // 默认配置 defaults: { headers: { 'Content-Type': 'application/json;charset=utf-8', // 'token':uni.getStorageSync('token') }, timeout: 100000 }, // 基础URL baseURL: config.apiBaseUrl || '' } // 请求拦截器 const requestInterceptors = [] // 响应拦截器 const responseInterceptors = [] addRequestInterceptor(async (cfg) => { const needToken = !(cfg.headers && cfg.headers.isToken === false) if (needToken) { const token = uni.getStorageSync('token') if (!token) { try { uni.reLaunch({ url: '/subpackage/login/login' }) } catch (e) { } return Promise.reject({ message: 'NO_TOKEN' }) } cfg.headers = { ...(cfg.headers || {}), 'Authorization': `Bearer ${token}` } } else { const headers = { ...(cfg.headers || {}) } if ('Authorization' in headers) { delete headers.Authorization } cfg.headers = headers } return cfg }) let isRedirecting = false; addResponseInterceptor(async (res) => { // 1. 判断HTTP状态码是否为401(核心判断) const is401 = (res.statusCode === 200 && res.data.code === 401 ); // 2. 可选:判断业务码是否为401(根据你的后端返回格式调整,比如 res.data.code === 401) // const isBiz401 = res.data && res.data.code === 401; if (is401) { // 防重复跳转:如果正在跳转,直接拒绝Promise if (isRedirecting) { return Promise.reject({ message: '已在跳转登录页', statusCode: 401 }); } isRedirecting = true; try { // 清除本地无效Token uni.removeStorageSync('token'); // 跳转到登录页(使用reLaunch关闭所有页面,避免返回原页面) await uni.reLaunch({ url: '/subpackage/login/login' }); } catch (e) { console.error('401跳转登录失败:', e); } finally { // 重置跳转标识 isRedirecting = false; } // 拒绝Promise,阻止后续业务逻辑执行 return Promise.reject({ message: 'Token无效或已过期,请重新登录', statusCode: 401 }); } // 非401响应,直接返回原响应 return res; }) /** * 添加请求拦截器 * @param {Function} fn 拦截器函数 */ function addRequestInterceptor(fn) { requestInterceptors.push(fn) } /** * 添加响应拦截器 * @param {Function} fn 拦截器函数 */ function addResponseInterceptor(fn) { responseInterceptors.push(fn) } /** * 处理请求拦截 * @param {Object} config 请求配置 * @returns {Object} 处理后的配置 */ async function handleRequestInterceptors(config) { let handledConfig = { ...config } for (const interceptor of requestInterceptors) { handledConfig = await interceptor(handledConfig) } return handledConfig } /** * 处理响应拦截 * @param {Object} response 响应数据 * @returns {Object} 处理后的响应 */ async function handleResponseInterceptors(response) { let handledResponse = { ...response } for (const interceptor of responseInterceptors) { handledResponse = await interceptor(handledResponse) } return handledResponse } /** * 转换请求参数为查询字符串 * @param {Object} params 参数对象 * @returns {String} 查询字符串 */ function tansParams(params) { let result = '' for (const propName of Object.keys(params)) { const value = params[propName] var part = encodeURIComponent(propName) + "=" if (value !== null && value !== "" && typeof (value) !== "undefined") { if (typeof value === 'object') { for (const key of Object.keys(value)) { if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== "undefined") { let params = propName + "[" + key + "]" var subPart = encodeURIComponent(params) + "=" result += subPart + encodeURIComponent(value[key]) + "&" } } } else { result += part + encodeURIComponent(value) + "&" } } } return result } /** * 通用请求方法 * @param {Object} options 请求配置 * @returns {Promise} */ function request(options) { // 合并默认配置 const config = { method: 'GET', headers: { ...service.defaults.headers }, timeout: service.defaults.timeout, baseURL: service.baseURL, ...options } // 执行请求拦截器 return handleRequestInterceptors(config) .then(processedConfig => { // 构建完整URL let url = processedConfig.baseURL + processedConfig.url // 处理GET请求参数 if (processedConfig.method.toUpperCase() === 'GET' && processedConfig.params) { const paramsStr = tansParams(processedConfig.params) if (paramsStr) { url += (url.includes('?') ? '&' : '?') + paramsStr.slice(0, -1) } } // 构建uni.request参数 const requestOptions = { url: url, method: processedConfig.method.toUpperCase(), header: processedConfig.headers, timeout: processedConfig.timeout } // 添加请求体(非GET请求) if (processedConfig.method.toUpperCase() !== 'GET' && processedConfig.data) { requestOptions.data = processedConfig.data } // 发起请求 return new Promise((resolve, reject) => { uni.request({ ...requestOptions, success: (res) => { // 处理响应拦截器 handleResponseInterceptors(res) .then(processedRes => { resolve(processedRes) }) .catch(error => { reject(error) }) }, fail: (err) => { reject(err) } }) }) }) .catch(error => { console.error('Request interceptor error:', error) return Promise.reject(error) }) } /** * GET请求 * @param {String} url 请求地址 * @param {Object} params 请求参数 * @param {Object} config 请求配置 * @returns {Promise} */ function get(url, params = {}, config = {}) { return request({ method: 'GET', url, params, ...config }) } /** * POST请求 * @param {String} url 请求地址 * @param {Object} data 请求数据 * @param {Object} config 请求配置 * @returns {Promise} */ function post(url, data = {}, config = {}) { return request({ method: 'POST', url, data, ...config }) } /** * PUT请求 * @param {String} url 请求地址 * @param {Object} data 请求数据 * @param {Object} config 请求配置 * @returns {Promise} */ function put(url, data = {}, config = {}) { return request({ method: 'PUT', url, data, ...config }) } /** * DELETE请求 * @param {String} url 请求地址 * @param {Object} params 请求参数 * @param {Object} config 请求配置 * @returns {Promise} */ function del(url, params = {}, config = {}) { return request({ method: 'DELETE', url, params, ...config }) } /** * 通用上传文件方法 * @param {Object} options 上传配置 * @returns {Promise} */ function uploadFile(options) { const config = { headers: { ...service.defaults.headers }, timeout: service.defaults.timeout, baseURL: service.baseURL, ...options } return handleRequestInterceptors(config) .then(processedConfig => { return new Promise((resolve, reject) => { uni.uploadFile({ url: processedConfig.baseURL + processedConfig.url, filePath: processedConfig.filePath, name: processedConfig.name || 'file', header: processedConfig.headers, formData: processedConfig.formData, success: (res) => { // uni.uploadFile 的 data 是字符串,尝试解析为对象 if (typeof res.data === 'string') { try { res.data = JSON.parse(res.data) } catch (e) { // 解析失败则保持原样 } } handleResponseInterceptors(res) .then(processedRes => { resolve(processedRes) }) .catch(error => { reject(error) }) }, fail: (err) => { reject(err) } }) }) }) } // 导出方法 export default { request, uploadFile, get, post, put, delete: del, addRequestInterceptor, addResponseInterceptor, service }