// 统一请求工具 import { getTempToken, shouldUseTempToken, getAppId } from '@/config/dev.js' import { showLoading, hideLoading, forceHideLoading, initGlobalLoadingManager, config as loadingConfig, getLoadingStatus, setLoadingConfig, getLoadingConfig, showLoadingWithDelay, hideLoadingWithDelay, AutoLoadingManager } from './loading-manager.js' // 环境配置 const ENV_CONFIG = { develop: { // 开发环境 baseUrl: 'http://192.168.2.136:4501', appId: 1 // TODO: 根据实际后端配置调整 }, trial: { // 体验版 baseUrl: 'https://testlu.chuangtewl.com/prod-api', appId: 1 // TODO: 根据实际后端配置调整 }, release: { // 正式版 baseUrl: 'https://testlu.chuangtewl.com/prod-api', appId: 1 // TODO: 根据实际后端配置调整 } } // 获取当前环境配置 const getCurrentConfig = () => { try { const { envVersion } = wx.getAccountInfoSync().miniProgram console.log('当前环境:', envVersion) const envConfig = ENV_CONFIG[envVersion] || ENV_CONFIG.release // 确保配置对象包含所有必要属性 return { baseUrl: envConfig.baseUrl, appId: envConfig.appId || 1 // 确保appId有默认值 } } catch (error) { console.warn('获取环境失败,默认使用正式环境:', error) const fallbackConfig = ENV_CONFIG.release return { baseUrl: fallbackConfig.baseUrl, appId: fallbackConfig.appId || 1 // 确保appId有默认值 } } } const config = getCurrentConfig() const BASE_URL = config.baseUrl // 调试信息 console.log('HTTP配置:', { baseUrl: BASE_URL, config: config }) /** * 获取请求头 * @param {Object} customHeader - 自定义请求头 * @returns {Object} 请求头对象 */ function getRequestHeaders(customHeader = {}) { let token = uni.getStorageSync('token') // 开发环境使用临时token if (shouldUseTempToken() && !token) { token = getTempToken() } 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)) } // Loading相关函数已从loading-manager.js导入 /** * 统一请求方法 * @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 - 是否显示加载状态(默认true) * @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) { if (err.errMsg.includes('timeout')) { errorMessage = '请求超时' } else if (err.errMsg.includes('fail')) { errorMessage = '网络连接失败' } } uni.showToast({ title: errorMessage, icon: 'none', duration: 2000 }) reject(err) } } // 特殊接口处理(不需要token的接口) const noTokenUrls = ['/wxLogin', '/user/login'] if (noTokenUrls.includes(url) || options.noToken) { delete requestOptions.header.Authorization console.log('跳过token验证的接口:', url) } // 处理请求参数 if (options.params && Object.keys(options.params).length > 0) { requestOptions.data = { ...options.params } } else if (options.data && Object.keys(options.data).length > 0) { requestOptions.data = { ...options.data } } else { // 如果既没有params也没有data,初始化为空对象 requestOptions.data = {} } // 自动添加appId到所有请求参数中(除非明确指定不添加) try { if (!options.noAppId && requestOptions.data && !requestOptions.data.appId) { const appId = getCurrentAppId() requestOptions.data.appId = appId console.log('自动添加appId:', appId, '到请求:', requestOptions.url) } } catch (error) { console.error('添加appId时出错:', error) // 确保即使出错也有appId if (requestOptions.data) { requestOptions.data.appId = 1 } } // 发起请求 console.log('发起请求:', { url: requestOptions.url, method: requestOptions.method, header: requestOptions.header, data: requestOptions.data, timeout: requestOptions.timeout, baseUrl: BASE_URL }) // 显示loading(默认显示,但减少延迟) if (options.showLoading !== false) { showLoading(options.loadingText || loadingConfig.loadingText) } 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 }) } /** * 获取当前环境的appId * @returns {number} 当前环境的appId */ export function getCurrentAppId() { try { return config.appId || getAppId() || 1 } catch (error) { console.error('获取appId失败,使用默认值:', error) return 1 } } /** * 设置请求配置 * @param {Object} newConfig - 新的配置 */ export function setRequestConfig(newConfig) { Object.assign(config, newConfig) console.log('更新请求配置:', config) } /** * 获取请求配置 * @returns {Object} 当前配置 */ export function getRequestConfig() { return { ...config } } /** * 清除token */ export function clearToken() { uni.removeStorageSync('token') console.log('Token已清除') } /** * 设置token * @param {string} token - token值 */ export function setToken(token) { uni.setStorageSync('token', token) console.log('Token已设置') } /** * 获取token * @returns {string} token值 */ export function getToken() { return uni.getStorageSync('token') } // 导出loading相关函数,作为统一入口 export { // 基础loading函数 showLoading, hideLoading, forceHideLoading, // 高级loading函数 showLoadingWithDelay, hideLoadingWithDelay, // 状态和配置管理 getLoadingStatus, setLoadingConfig, getLoadingConfig, // 全局初始化 initGlobalLoadingManager, // 自动loading管理器类 AutoLoadingManager } // Loading管理相关函数已从loading-manager.js导入 // 默认导出request函数,方便API文件导入 export default request