/** * 网络请求封装 * 统一处理HTTP请求、响应、错误、Token等 * * 特性: * - 自动添加Token(Blade-Auth格式) * - 统一错误处理 * - 请求/响应拦截 * - 超时控制 * - Loading状态管理 */ import config from '@/config/env.config.js' /** * 构建请求头 * @param {Object} customHeader 自定义头部 * @returns {Object} 完整的请求头 */ function getHeaders(customHeader = {}) { const token = uni.getStorageSync('token') || '' return { 'Content-Type': 'application/json', // 重要:后端使用 Blade-Auth 而不是 Authorization 'Blade-Auth': token ? `Bearer ${token}` : '', ...customHeader } } /** * 统一请求方法 * @param {Object} options 请求配置 * @param {String} options.url 请求路径(不含baseURL) * @param {String} options.method 请求方法(GET/POST/PUT/DELETE) * @param {Object} options.data 请求数据 * @param {Object} options.header 自定义请求头 * @param {Boolean} options.showLoading 是否显示Loading * @param {String} options.loadingText Loading文本 * @returns {Promise} */ function request(options = {}) { const { url = '', method = 'GET', data = {}, header = {}, showLoading = false, loadingText = '加载中...' } = options // 显示Loading if (showLoading) { uni.showLoading({ title: loadingText, mask: true }) } // 打印调试信息 if (config.debug) { console.log(`[API请求] ${method} ${url}`, data) } return new Promise((resolve, reject) => { uni.request({ url: config.apiBaseURL + url, method, data, header: getHeaders(header), timeout: config.timeout, success: (res) => { if (config.debug) { console.log(`[API响应] ${method} ${url}`, res.data) } // 隐藏Loading if (showLoading) { uni.hideLoading() } // BladeX框架标准响应格式 // { code: 200, success: true, data: {}, msg: "操作成功" } if (res.statusCode === 200) { const response = res.data // 业务成功 if (response.code === 200 || response.success) { resolve({ code: 200, message: response.msg || response.message || '成功', data: response.data, success: true }) } else { // 业务失败 const errorMsg = response.msg || response.message || '请求失败' uni.showToast({ title: errorMsg, icon: 'none', duration: 2000 }) reject({ code: response.code, message: errorMsg, data: response.data }) } } else if (res.statusCode === 401) { // Token过期或未登录 uni.showToast({ title: 'Token已过期,请重新登录', icon: 'none' }) // 清除Token uni.removeStorageSync('token') // 跳转到登录页 setTimeout(() => { uni.reLaunch({ url: '/pages/login/login' }) }, 1500) reject({ code: 401, message: 'Token已过期' }) } else { // HTTP错误 const errorMsg = `请求失败 (${res.statusCode})` uni.showToast({ title: errorMsg, icon: 'none' }) reject({ code: res.statusCode, message: errorMsg }) } }, fail: (err) => { if (config.debug) { console.error(`[API错误] ${method} ${url}`, err) } // 隐藏Loading if (showLoading) { uni.hideLoading() } // 网络错误 const errorMsg = err.errMsg || '网络错误,请检查网络连接' uni.showToast({ title: errorMsg, icon: 'none', duration: 2000 }) reject({ code: -1, message: errorMsg, error: err }) } }) }) } /** * GET 请求 */ export function get(url, data = {}, options = {}) { return request({ url, method: 'GET', data, ...options }) } /** * POST 请求 */ export function post(url, data = {}, options = {}) { return request({ url, method: 'POST', data, ...options }) } /** * PUT 请求 */ export function put(url, data = {}, options = {}) { return request({ url, method: 'PUT', data, ...options }) } /** * DELETE 请求 */ export function del(url, data = {}, options = {}) { return request({ url, method: 'DELETE', data, ...options }) } // 默认导出 export default request /** * 使用示例: * * // 方式1:直接使用 request * import request from '@/utils/request.js' * * request({ * url: '/martial/score/list', * method: 'GET', * data: { page: 1, size: 10 }, * showLoading: true * }).then(res => { * console.log(res.data) * }).catch(err => { * console.error(err.message) * }) * * // 方式2:使用快捷方法 * import { get, post, put, del } from '@/utils/request.js' * * // GET请求 * get('/martial/athlete/list', { venueId: 1 }) * .then(res => console.log(res.data)) * * // POST请求 * post('/martial/score/submit', { athleteId: 1, score: 8.907 }) * .then(res => console.log(res.data)) */