// 统一请求工具 import { getTempToken, shouldUseTempToken } from '@/config/dev.js' // 环境配置 const ENV_CONFIG = { develop: { // 开发环境 baseUrl: 'http://192.168.2.7:4501', loadingText: '开发环境加载中~', }, trial: { // 体验版 baseUrl: 'https://testlu.chuangtewl.com/prod-api', loadingText: '体验版加载中~', }, release: { // 正式版 baseUrl: 'https://testlu.chuangtewl.com/prod-api', loadingText: '加载中~', } } // 获取当前环境配置 const getCurrentConfig = () => { try { const { envVersion } = wx.getAccountInfoSync().miniProgram console.log('当前环境:', envVersion) return ENV_CONFIG[envVersion] || ENV_CONFIG.release // 默认正式环境 } catch (error) { console.warn('获取环境失败,默认使用正式环境:', error) return ENV_CONFIG.release } } const config = getCurrentConfig() const BASE_URL = config.baseUrl // 全局loading状态管理 let isLoading = false let loadingTimer = null // 设置loading超时自动清除 const setLoadingTimeout = () => { if (loadingTimer) { clearTimeout(loadingTimer) } loadingTimer = setTimeout(() => { console.warn('Loading超时,强制清除') forceHideLoading() }, 30000) // 30秒超时 } // 调试信息 console.log('HTTP配置:', { baseUrl: BASE_URL, config: config }) /** * 获取请求头 * @param {Object} customHeader - 自定义请求头 * @returns {Object} 请求头对象 */ function getRequestHeaders(customHeader = {}) { const token = uni.getStorageSync('token') let authorization = token // 平台差异化处理 // #ifdef H5 authorization = token ? `Bearer ${token}` : '' // #endif return { 'Content-Type': 'application/json;charset=UTF-8', 'Authorization': authorization, ...customHeader } } /** * 处理响应错误 * @param {Object} res - 响应对象 * @param {Function} reject - Promise reject函数 */ function handleResponseError(res, reject, options = {}) { // 先清除loading状态 if (options.showLoading !== false) { hideLoading() } const errorMap = { 401: { title: '登录已过期,请重新登录', action: () => { setTimeout(() => { uni.reLaunch({ url: '/pages/login/login' }) }, 1500) } }, 403: { title: '权限不足', action: () => {} }, 404: { title: '请求的资源不存在', action: () => {} }, 500: { title: '服务器错误', action: () => {} } } const error = errorMap[res.statusCode] || { title: res.data?.msg || '请求失败', action: () => {} } // 显示错误提示 uni.showToast({ title: error.title, icon: 'none', duration: 2000 }) // 执行错误处理动作 error.action() reject(new Error(error.title)) } /** * 显示加载状态 * @param {string} text - 加载提示文字 */ function showLoading(text = config.loadingText) { try { if (!isLoading) { isLoading = true uni.showLoading({ title: text, mask: true }) // 设置超时清除 setLoadingTimeout() } } catch (error) { console.warn('显示loading失败:', error) } } /** * 隐藏加载状态 */ function hideLoading() { try { if (isLoading) { isLoading = false // 清除超时定时器 if (loadingTimer) { clearTimeout(loadingTimer) loadingTimer = null } uni.hideLoading() } } catch (error) { console.warn('隐藏loading失败:', error) } } /** * 统一请求方法 * @param {Object} options - 请求配置 * @param {string} options.url - 请求地址 * @param {string} options.method - 请求方法 * @param {Object} options.params - 查询参数 * @param {Object} options.data - 请求体数据 * @param {Object} options.header - 请求头 * @param {number} options.timeout - 超时时间 * @param {boolean} options.showLoading - 是否显示加载状态 * @param {string} options.loadingText - 加载提示文字 * @param {boolean} options.noToken - 是否需要token * @returns {Promise} 返回请求结果 */ export function request(options = {}) { return new Promise((resolve, reject) => { // 获取token,优先使用本地存储的token,如果没有则使用临时token const localToken = uni.getStorageSync('token') let token = localToken // 如果本地没有token且启用了临时token,则使用临时token if (!token && shouldUseTempToken() && !options.noToken) { token = getTempToken() console.log('使用临时token进行开发测试') } // 验证URL格式 if (!options.url || typeof options.url !== 'string') { reject(new Error('无效的URL')) return } // 确保URL以/开头 const url = options.url.startsWith('/') ? options.url : '/' + options.url // 构建请求配置 const requestOptions = { url: BASE_URL + url, method: options.method || 'GET', header: getRequestHeaders(options.header), timeout: options.timeout || 60000, // 默认60秒超时 success: (res) => { // 隐藏加载状态 if (options.showLoading !== false) { hideLoading() } // 请求成功处理 if (res.statusCode === 200) { resolve(res.data) } else { // 处理错误响应 handleResponseError(res, reject, options) } }, fail: (err) => { // 隐藏加载状态 if (options.showLoading !== false) { hideLoading() } // 请求失败处理 console.error('请求失败:', { error: err, url: requestOptions.url, method: requestOptions.method, baseUrl: BASE_URL, originalUrl: options.url }) // 根据错误类型显示不同的提示 let errorMessage = '网络错误' if (err.errMsg && err.errMsg.includes('invalid url')) { errorMessage = '请求地址无效' } else if (err.errMsg && err.errMsg.includes('timeout')) { errorMessage = '请求超时' } uni.showToast({ title: errorMessage, icon: 'none', duration: 2000 }) reject(err) } } // 特殊接口处理 if (url === '/login/login' || url === '/wxLogin' || url === '/user/login') { requestOptions.header.noToken = true } // 添加参数 if (options.params) { requestOptions.data = options.params } if (options.data) { requestOptions.data = options.data } // 显示加载状态 if (options.showLoading !== false) { setTimeout(() => { showLoading(options.loadingText || config.loadingText) }, config.loadingTime) } // 发起请求 console.log('发起请求:', { url: requestOptions.url, method: requestOptions.method, header: requestOptions.header, data: requestOptions.data, timeout: requestOptions.timeout, baseUrl: BASE_URL }) uni.request(requestOptions) }) } /** * GET请求 * @param {string} url - 请求地址 * @param {Object} params - 查询参数 * @param {Object} options - 请求选项 * @returns {Promise} 返回请求结果 */ export function get(url, params = {}, options = {}) { return request({ url, method: 'GET', params, ...options }) } /** * POST请求 * @param {string} url - 请求地址 * @param {Object} data - 请求体数据 * @param {Object} options - 请求选项 * @returns {Promise} 返回请求结果 */ export function post(url, data = {}, options = {}) { return request({ url, method: 'POST', data, ...options }) } /** * PUT请求 * @param {string} url - 请求地址 * @param {Object} data - 请求体数据 * @param {Object} options - 请求选项 * @returns {Promise} 返回请求结果 */ export function put(url, data = {}, options = {}) { return request({ url, method: 'PUT', data, ...options }) } /** * DELETE请求 * @param {string} url - 请求地址 * @param {Object} options - 请求选项 * @returns {Promise} 返回请求结果 */ export function del(url, options = {}) { return request({ url, method: 'DELETE', ...options }) } /** * 设置请求配置 * @param {Object} newConfig - 新的配置对象 */ export function setRequestConfig(newConfig) { Object.assign(config, newConfig) } /** * 获取当前配置 * @returns {Object} 当前配置对象 */ export function getRequestConfig() { return { ...config } } /** * 清除token */ export function clearToken() { uni.removeStorageSync('token') uni.removeStorageSync('refreshToken') } /** * 设置token * @param {string} token - token值 */ export function setToken(token) { uni.setStorageSync('token', token) } /** * 获取token * @returns {string} token值 */ export function getToken() { return uni.getStorageSync('token') } /** * 强制清除loading状态 */ export function forceHideLoading() { isLoading = false // 清除超时定时器 if (loadingTimer) { clearTimeout(loadingTimer) loadingTimer = null } try { uni.hideLoading() } catch (error) { console.warn('强制清除loading失败:', error) } } /** * 初始化全局loading管理 */ export function initGlobalLoadingManager() { // 监听页面显示事件 uni.$on('page-show', () => { forceHideLoading() }) // 监听页面隐藏事件 uni.$on('page-hide', () => { forceHideLoading() }) // 监听应用进入前台 uni.$on('app-show', () => { forceHideLoading() }) // 监听应用进入后台 uni.$on('app-hide', () => { forceHideLoading() }) console.log('全局loading管理器已初始化') } /** * 页面级别的loading管理 */ export class PageLoadingManager { constructor() { this.isLoading = false this.timer = null } show(text = '加载中...') { this.hide() // 先清除之前的loading this.isLoading = true try { uni.showLoading({ title: text, mask: true }) // 设置超时 this.timer = setTimeout(() => { console.warn('页面Loading超时,强制清除') this.hide() }, 30000) } catch (error) { console.warn('显示页面loading失败:', error) } } hide() { this.isLoading = false if (this.timer) { clearTimeout(this.timer) this.timer = null } try { uni.hideLoading() } catch (error) { console.warn('隐藏页面loading失败:', error) } } // 页面卸载时清理 destroy() { this.hide() } }