/** * 网络请求工具类 * 封装uni-app的request方法 */ import errorHandler from './errorHandler.js'; import { apiBaseUrl } from '@/common/config.js'; // 基础URL,可以根据环境变量等动态设置 const BASE_URL = apiBaseUrl; // 请求超时时间 const TIMEOUT = 60000; // 请求拦截器 const requestInterceptor = (config) => { // 获取token const token = uni.getStorageSync('token'); // 获取 CSRF token const csrfToken = uni.getStorageSync('csrfToken'); // 设置请求头 if (!config.header) { config.header = {}; } // 添加token到请求头 if (token) { config.header['Authorization'] = `Bearer ${token}`; } // 添加 CSRF token 到请求头 if (csrfToken) { config.header['X-CSRF-Token'] = csrfToken; } // 添加内容类型 if (!config.header['Content-Type']) { config.header['Content-Type'] = 'application/json'; } // 添加基础URL if (!config.url.startsWith('http')) { config.url = BASE_URL + config.url; } // 如果是 POST 请求,也可以添加到请求体 if (config.method === 'POST' && config.data) { config.data._csrf = csrfToken; } return config; }; // 错误提示 const showError = (message, duration = 2000) => { // 避免重复显示相同的错误提示 if (showError.lastMessage === message && Date.now() - showError.lastTime < 3000) { return; } uni.showToast({ title: message, icon: 'none', duration: duration }); // 记录最后显示的错误信息和时间 showError.lastMessage = message; showError.lastTime = Date.now(); }; // 初始化错误提示状态 showError.lastMessage = ''; showError.lastTime = 0; // 错误码映射表 const ERROR_CODE_MAP = { 400: '请求参数错误', 401: '登录已过期,请重新登录', 403: '没有权限执行此操作', 404: '请求的资源不存在', 500: '服务器错误,请稍后重试', 502: '网关错误', 503: '服务不可用,请稍后重试', 504: '网关超时' }; // 响应拦截器 const responseInterceptor = (response) => { // 这里可以对响应数据做统一处理 if (response.statusCode === 200) { // 服务器正常响应 const { data } = response; // 检查是否有特定错误码 if (data.status === 999 || data.code === 999) { // 微信 code 无效错误 const error = new Error(data.message || '微信登录失败: code无效'); error.status = 999; return Promise.reject(error); } // 处理成功响应 - 适配不同的返回格式 if (data.status === 2000 || data.code === 0 || data.code === 2000) { // 如果返回的是完整数据对象,直接返回 if (data.data) { return data.data; } // 如果没有data字段,但有其他用户信息字段,返回整个对象 if (data.openid || data.userId || data.user_id) { return data; } // 默认返回 return data; } else { // 业务错误 const error = errorHandler.handleBusinessError(data); return Promise.reject(error); } } else { // HTTP错误 const error = errorHandler.handleHttpError(response.statusCode, response); return Promise.reject(error); } }; // 请求方法 const request = (options = {}) => { return new Promise((resolve, reject) => { // 应用请求拦截器 options = requestInterceptor(options); // 设置超时时间 if (!options.timeout) { options.timeout = TIMEOUT; } // 发起请求 uni.request({ ...options, success: (res) => { try { // 应用响应拦截器 const data = responseInterceptor(res); resolve(data); } catch (error) { errorHandler.logError(error, 'request.responseInterceptor'); reject(error); } }, fail: (err) => { const error = errorHandler.handleRequestFail(err); errorHandler.logError(error, 'request.fail'); reject(error); } }); }); }; // 封装常用请求方法 const http = { get(url, data = {}, options = {}) { return request({ url, data, method: 'GET', ...options }); }, post(url, data = {}, options = {}) { return request({ url, data, method: 'POST', ...options }); }, put(url, data = {}, options = {}) { return request({ url, data, method: 'PUT', ...options }); }, delete(url, data = {}, options = {}) { return request({ url, data, method: 'DELETE', ...options }); }, // 上传文件 upload(url, filePath, name = 'file', formData = {}, options = {}) { return new Promise((resolve, reject) => { // 获取token const token = uni.getStorageSync('token'); // 设置请求头 const header = options.header || {}; if (token) { header['Authorization'] = `Bearer ${token}`; } // 添加基础URL if (!url.startsWith('http')) { url = BASE_URL + url; } uni.uploadFile({ url, filePath, name, formData, header, success: (res) => { try { // 上传接口可能返回的是字符串 if (typeof res.data === 'string') { res.data = JSON.parse(res.data); } // 应用响应拦截器 const data = responseInterceptor({ statusCode: res.statusCode, data: res.data }); resolve(data); } catch (error) { reject(error); } }, fail: (err) => { showError('文件上传失败'); reject(err); } }); }); } }; export default http;