import config from './config.js' // 请求队列(用于处理token刷新) const requestQueue = [] let isRefreshing = false class Request { constructor() { this.baseURL = config.baseURL this.timeout = config.timeout this.interceptors = { request: [], response: [] } } // 添加请求拦截器 addRequestInterceptor(interceptor) { this.interceptors.request.push(interceptor) } // 添加响应拦截器 addResponseInterceptor(interceptor) { this.interceptors.response.push(interceptor) } // 执行请求拦截器 async runRequestInterceptors(config) { for (const interceptor of this.interceptors.request) { config = await interceptor(config) } return config } // 执行响应拦截器 async runResponseInterceptors(response) { for (const interceptor of this.interceptors.response) { response = await interceptor(response) } return response } // 核心请求方法 async request(options) { try { // 合并配置 const requestConfig = { url: options.url.startsWith('http') ? options.url : `${this.baseURL}${options.url}`, method: options.method || 'GET', header: { 'Content-Type': 'application/json', ...options.header }, data: options.data, timeout: this.timeout } // 执行请求拦截器 const finalConfig = await this.runRequestInterceptors(requestConfig) // 发起请求 const response = await uni.request(finalConfig) // 执行响应拦截器 const finalResponse = await this.runResponseInterceptors(response) return finalResponse[1] // uni.request返回的是数组[error, success] } catch (error) { console.error('Request error:', error) throw error } } // GET请求 get(url, data = {}, options = {}) { return this.request({ url, method: 'GET', data, ...options }) } // POST请求 post(url, data = {}, options = {}) { return this.request({ url, method: 'POST', data, ...options }) } // PUT请求 put(url, data = {}, options = {}) { return this.request({ url, method: 'PUT', data, ...options }) } // DELETE请求 delete(url, data = {}, options = {}) { return this.request({ url, method: 'DELETE', data, ...options }) } // 上传文件 upload(url, filePath, formData = {}, options = {}) { return new Promise((resolve, reject) => { uni.uploadFile({ url: `${this.baseURL}${url}`, filePath, name: 'file', formData, success: resolve, fail: reject, ...options }) }) } // 下载文件 download(url, options = {}) { return new Promise((resolve, reject) => { uni.downloadFile({ url: `${this.baseURL}${url}`, success: resolve, fail: reject, ...options }) }) } } // 创建请求实例 const request = new Request() // 添加请求拦截器 - Token处理 request.addRequestInterceptor(async (config) => { const token = uni.getStorageSync('token') if (token) { config.header.Authorization = `Bearer ${token}` } return config }) // 添加响应拦截器 - 错误处理 request.addResponseInterceptor(async (response) => { const { statusCode, data } = response if (statusCode === 200) { if (data.code === 0) { return data.data } else { // 业务错误 const error = new Error(data.message || '业务错误') error.code = data.code throw error } } else if (statusCode === 401) { // Token过期,尝试刷新 return handleTokenExpired(response) } else { // 网络错误 throw new Error(`网络错误: ${statusCode}`) } }) // Token过期处理 async function handleTokenExpired(response) { if (isRefreshing) { // 如果正在刷新,将请求加入队列 return new Promise((resolve) => { requestQueue.push(() => resolve(request.request(response.config))) }) } isRefreshing = true const refreshToken = uni.getStorageSync('refreshToken') if (!refreshToken) { // 没有refreshToken,跳转到登录页 uni.navigateTo({ url: '/pages/auth/login' }) throw new Error('请重新登录') } try { // 尝试刷新Token const result = await request.post(config.endpoints.USER.REFRESH_TOKEN, { refreshToken }) // 保存新Token uni.setStorageSync('token', result.token) uni.setStorageSync('refreshToken', result.refreshToken) // 重试原始请求 const retryResponse = await request.request(response.config) // 处理队列中的请求 processRequestQueue() return retryResponse } catch (error) { // 刷新失败,清空Token并跳转登录 uni.removeStorageSync('token') uni.removeStorageSync('refreshToken') uni.navigateTo({ url: '/pages/auth/login' }) throw error } finally { isRefreshing = false } } // 处理请求队列 function processRequestQueue() { while (requestQueue.length > 0) { const retry = requestQueue.shift() retry() } } export default request