/** * 网络请求封装 - 基于 uni.request 二次封装 */ import config from '@/api/config.js'; import { getToken, clearAuthInfo, getUserInfo } from './auth'; // 请求队列(用于防重复请求) const pendingRequests = new Map(); /** * 生成请求唯一标识 */ function generateRequestKey(options) { return `${options.method}_${options.url}_${JSON.stringify(options.data || {})}`; } /** * 核心请求方法 * @param {Object} options 请求配置 * @param {string} options.url 请求路径(不含 baseUrl) * @param {string} [options.method='GET'] 请求方法 * @param {Object} [options.data] 请求参数 * @param {Object} [options.header] 自定义请求头 * @param {boolean} [options.loading=false] 是否显示加载提示 * @param {string} [options.loadingText='加载中...'] 加载提示文字 * @param {boolean} [options.showError=true] 是否显示错误提示 * @param {boolean} [options.preventDuplicate=false] 是否防止重复请求 * @param {boolean} [options.isUnitId=true] 是否需要unitId参数 * @returns {Promise} */ function request(options) { const { url, method = 'GET', data = {}, header = {}, loading = false, loadingText = '加载中...', showError = true, preventDuplicate = false, isUnitId = true } = options; const fullUrl = url.startsWith('http') ? url : `${config.baseUrl}${url}`; // 防重复请求 const requestKey = generateRequestKey({ method, url: fullUrl, data }); if (preventDuplicate && pendingRequests.has(requestKey)) { return pendingRequests.get(requestKey); } // 显示加载状态 if (loading) { uni.showLoading({ title: loadingText, mask: true }); } // 构建请求头 const token = getToken(); const requestHeader = { 'Content-Type': 'application/json', ...header }; if (token) { requestHeader['token'] = token; } //获取用户的unitld const userInfo = getUserInfo(); if (userInfo?.UnitId && isUnitId) { console.log('用户id的get', userInfo.UnitId); data['unitId'] = userInfo.UnitId; } const requestPromise = new Promise((resolve, reject) => { uni.request({ url: fullUrl, method, data, header: requestHeader, timeout: config.timeout, success: (res) => { const { statusCode, data: responseData } = res; // HTTP 状态码判断 if (statusCode === 200) { // 根据业务状态码处理(按实际后端接口约定调整) if (responseData.code === 1 || responseData.code === 200) { resolve(responseData.data); } else if (responseData.code === 401) { // Token 过期/无效 handleUnauthorized(); reject(responseData); } else { // 业务错误 if (showError) { uni.showToast({ title: responseData.message || '请求失败', icon: 'none', duration: 2000 }); } reject(responseData); } } else if (statusCode === 401) { handleUnauthorized(); reject(res); } else { if (showError) { uni.showToast({ title: `请求错误 (${statusCode})`, icon: 'none' }); } reject(res); } }, fail: (err) => { if (showError) { uni.showToast({ title: '网络异常,请检查网络连接', icon: 'none' }); } reject(err); }, complete: () => { if (loading) { uni.hideLoading(); } pendingRequests.delete(requestKey); } }); }); if (preventDuplicate) { pendingRequests.set(requestKey, requestPromise); } return requestPromise; } /** * 处理 401 未授权 */ function handleUnauthorized() { clearAuthInfo(); uni.showToast({ title: '登录已过期,请重新登录', icon: 'none', duration: 2000 }); setTimeout(() => { uni.reLaunch({ url: '/pages/login/login' }); }, 1500); } /** * 文件上传 * @param {string} filePath 文件本地路径 * @param {Object} [formData] 额外表单数据 * @param {string} [name='file'] 文件字段名 * @returns {Promise} */ export function upload(filePath, formData = {}, name = 'file') { const token = getToken(); return new Promise((resolve, reject) => { uni.showLoading({ title: '上传中...', mask: true }); uni.uploadFile({ url: config.uploadUrl || `${config.baseUrl}/upload`, filePath, name, formData, header: token ? { Authorization: `Bearer ${token}` } : {}, success: (res) => { if (res.statusCode === 200) { const data = JSON.parse(res.data); if (data.code === 0 || data.code === 200) { resolve(data.data); } else { uni.showToast({ title: data.message || '上传失败', icon: 'none' }); reject(data); } } else { reject(res); } }, fail: (err) => { uni.showToast({ title: '上传失败', icon: 'none' }); reject(err); }, complete: () => { uni.hideLoading(); } }); }); } // 快捷方法 /** * 核心请求方法 * @param {Object} options 请求配置 * @param {string} options.url 请求路径(不含 baseUrl) * @param {string} [options.method='GET'] 请求方法 * @param {Object} [options.data] 请求参数 * @param {Object} [options.header] 自定义请求头 * @param {boolean} [options.loading=false] 是否显示加载提示 * @param {string} [options.loadingText='加载中...'] 加载提示文字 * @param {boolean} [options.showError=true] 是否显示错误提示 * @param {boolean} [options.preventDuplicate=false] 是否防止重复请求 * @param {boolean} [options.isUnitId=true] 是否需要unitId参数 * @returns {Promise} */ export const get = (url, data, options = {}) => request({ url, method: 'GET', data, ...options }); export const post = (url, data, options = {}) => request({ url, method: 'POST', data, ...options }); export const put = (url, data, options = {}) => request({ url, method: 'PUT', data, ...options }); export const del = (url, data, options = {}) => request({ url, method: 'DELETE', data, ...options }); export default request;