// utils/http.js /** * 环境配置 */ const envConfig = { development: { baseUrl: 'https://feiniaotech-dev.sysuimars.cn/' }, production: { baseUrl: 'https://feiniaotech-dev.sysuimars.cn/' } } const currentEnv = process.env.NODE_ENV || 'development' const BASE_URL = envConfig[currentEnv].baseUrl /** * 请求封装类 */ class HttpRequest { constructor() { this.queue = {} // 请求队列 this.interceptors = { beforeRequest: null, afterResponse: null } } /** * 获取基础配置 */ getDefaultConfig() { return { baseUrl: BASE_URL, url: '', header: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' }, timeout: 10000, data: {}, method: 'GET' } } /** * 设置拦截器 */ setupInterceptors(instance) { this.interceptors.beforeRequest = (config) => { // 添加全局loading uni.showLoading({ title: '加载中', mask: true }) // 添加token const token = uni.getStorageSync('token') if (token) { config.header = config.header || {} config.header.Authorization = `Bearer ${token}` } // 记录请求开始时间(用于计算请求耗时) config.metadata = { startTime: new Date() } return config } this.interceptors.afterResponse = (response) => { uni.hideLoading() // 计算请求耗时 const endTime = new Date() const duration = endTime - response.config.metadata.startTime console.log(`请求 ${response.config.url} 耗时: ${duration}ms`) const { data, statusCode } = response // 根据业务逻辑调整 if (statusCode === 200) { return data } else { return this.handleError(response) } } } /** * 错误处理 */ handleError(error) { let errMsg = '请求失败' let needLogin = false if (error.statusCode) { switch (error.statusCode) { case 400: errMsg = error.data?.message || '请求参数错误' break case 401: errMsg = '未授权,请重新登录' needLogin = true break case 403: errMsg = '拒绝访问' break case 404: errMsg = '请求资源不存在' break case 500: errMsg = '服务器错误' break default: errMsg = `请求错误:${error.statusCode}` } } else if (error.errMsg && error.errMsg.includes('timeout')) { errMsg = '网络请求超时' } else if (error.errMsg && error.errMsg.includes('network')) { errMsg = '网络连接失败,请检查网络' } // 显示错误提示 uni.showToast({ title: errMsg, icon: 'none', duration: 2000 }) // 需要登录的情况 if (needLogin) { setTimeout(() => { uni.navigateTo({ url: '/pages/login/login' }) }, 1500) } return Promise.reject(error) } /** * 创建请求实例 */ create() { const instance = { request: (options) => { // 合并配置 let config = { ...this.getDefaultConfig(), ...options } // 处理URL if (!config.url.startsWith('http') && !config.url.startsWith('https')) { config.url = config.baseUrl + config.url } // 应用请求拦截 if (typeof this.interceptors.beforeRequest === 'function') { config = this.interceptors.beforeRequest(config) || config } return new Promise((resolve, reject) => { uni.request({ ...config, success: (res) => { // 应用响应拦截 try { const processed = typeof this.interceptors.afterResponse === 'function' ? this.interceptors.afterResponse(res) : res resolve(processed) } catch (err) { reject(this.handleError(err)) } }, fail: (err) => { reject(this.handleError(err)) } }) }) }, // 添加常用方法别名 get: (url, params = {}, options = {}) => { return this.request({ url, method: 'GET', data: params, ...options }) }, post: (url, data = {}, options = {}) => { return this.request({ url, method: 'POST', data, ...options }) }, put: (url, data = {}, options = {}) => { return this.request({ url, method: 'PUT', data, ...options }) }, delete: (url, data = {}, options = {}) => { return this.request({ url, method: 'DELETE', data, ...options }) }, upload: (url, filePath, name = 'file', formData = {}, options = {}) => { return new Promise((resolve, reject) => { const fullUrl = url.startsWith('http') ? url : BASE_URL + url const token = uni.getStorageSync('token') uni.uploadFile({ url: fullUrl, filePath, name, formData, header: { 'Authorization': token ? `Bearer ${token}` : '', ...(options.header || {}) }, success: (res) => { if (res.statusCode === 200) { try { resolve(JSON.parse(res.data)) } catch (e) { resolve(res.data) } } else { reject(this.handleError(res)) } }, fail: (err) => { reject(this.handleError(err)) }, ...options }) }) } } // 初始化拦截器 this.setupInterceptors(instance) // 绑定this instance.request = instance.request.bind(this) instance.get = instance.get.bind(this) instance.post = instance.post.bind(this) instance.put = instance.put.bind(this) instance.delete = instance.delete.bind(this) instance.upload = instance.upload.bind(this) return instance } } // 创建单例 const http = new HttpRequest().create() export default http