/** * HTTP请求工具类 * 封装uni.request,统一处理请求和响应 */ import { API_CONFIG } from './config'; import { getToken, handleUnauthorized } from './auth'; /** * 请求配置接口 */ interface RequestConfig { url: string; method?: 'GET' | 'POST' | 'PUT' | 'DELETE'; data?: any; header?: any; timeout?: number; /** 是否跳过添加token,用于免登录接口 */ skipAuth?: boolean; /** 是否静默(不弹 toast),轮询类请求应设为 true */ silent?: boolean; } /** * 响应数据接口 */ interface ResponseData { code: number; message: string; data?: T; } /** * 发起HTTP请求 * @param config 请求配置 * @returns Promise<响应数据> */ export const request = (config: RequestConfig): Promise => { return new Promise((resolve, reject) => { const { url, method = 'GET', data, header = {}, timeout, skipAuth = false, silent = false } = config; const effectiveTimeout = timeout ?? (silent ? 5000 : API_CONFIG.timeout); // 构建完整URL let fullUrl = url.startsWith('http') ? url : `${API_CONFIG.baseUrl}${url}`; // 添加token到请求头(skipAuth为true时跳过) if (!skipAuth) { const token = getToken(); if (token) { header['accessToken'] = token; if (API_CONFIG.enableLog) { console.log('[请求拦截] 添加token到请求头:', token.substring(0, 8) + '...'); } } else { if (API_CONFIG.enableLog) { console.warn('[请求拦截] 未找到token,请求将不携带token'); } } } // 添加Content-Type if (!header['Content-Type']) { header['Content-Type'] = 'application/json'; } // 打印请求日志 if (API_CONFIG.enableLog && !silent) { console.log(`[请求] ${method} ${fullUrl}`, data); } // 发起请求 uni.request({ url: fullUrl, method, data, header, timeout: effectiveTimeout, success: (res: any) => { // 打印响应日志 if (API_CONFIG.enableLog && !silent) { console.log(`[响应] ${method} ${fullUrl}`, res.data); } const responseData = res.data as ResponseData; // 处理HTTP状态码 if (res.statusCode !== 200) { // HTTP 401 同样触发未授权处理 if (res.statusCode === 401) { handleUnauthorized(); } const errorMsg = `请求失败: HTTP ${res.statusCode}`; if (!silent) { uni.showToast({ title: errorMsg, icon: 'none' }); } reject(new Error(errorMsg)); return; } // 处理业务状态码 if (responseData.code === 200 || responseData.code === 0) { if (API_CONFIG.enableLog) { console.log('[响应处理] 业务成功,返回data:', responseData.data); } resolve(responseData.data as T); } else if (responseData.code === 401) { handleUnauthorized(); const authError = new Error(responseData.message || '未登录'); (authError as any).isAuthError = true; reject(authError); } else { const errorMsg = responseData.message || '操作失败'; if (!silent) { uni.showToast({ title: errorMsg, icon: 'none' }); } reject(new Error(errorMsg)); } }, fail: (err: any) => { console.error(`[请求失败] ${method} ${fullUrl}`, err); if (!silent) { let errorMsg = '网络请求失败'; if (err.errMsg) { if (err.errMsg.includes('timeout')) { errorMsg = '请求超时,请检查网络'; } else if (err.errMsg.includes('fail')) { errorMsg = '网络连接失败,请检查网络'; } } uni.showToast({ title: errorMsg, icon: 'none' }); } reject(new Error(err.errMsg || '网络请求失败')); } }); }); }; /** * GET请求 */ export const get = (url: string, data?: any, options?: { skipAuth?: boolean; silent?: boolean }): Promise => { return request({ url, method: 'GET', data, ...options }); }; /** * POST请求 */ export const post = (url: string, data?: any, options?: { silent?: boolean }): Promise => { return request({ url, method: 'POST', data, ...options }); }; /** * PUT请求 */ export const put = (url: string, data?: any, options?: { silent?: boolean }): Promise => { return request({ url, method: 'PUT', data, ...options }); }; /** * DELETE请求 */ export const del = (url: string, data?: any, options?: { silent?: boolean }): Promise => { return request({ url, method: 'DELETE', data, ...options }); };