/** * 统一请求封装:baseURL、Bearer Token、业务 code 处理。 * 接口地址统一从 .env 的 VITE_API_BASE_URL 读取(见 api/config.js)。 */ import { getToken, logout } from '@/utils/auth.js' import { resolveBaseURL, getBaseURL } from '@/api/config.js' const BASE_URL = resolveBaseURL() export { getBaseURL } /** * @param {{ url: string, method?: string, data?: object, header?: object, silent?: boolean }} options * @returns {Promise} 业务 data 字段(若无 data 则返回整包) */ export function request(options = {}) { const { url, method = 'GET', data, header = {}, silent = false, timeout = 30000 } = options const token = getToken() const headers = { 'Content-Type': 'application/json', ...header } if (token) { headers.Authorization = `Bearer ${token}` } const fullUrl = BASE_URL.replace(/\/$/, '') + url return new Promise((resolve, reject) => { uni.request({ url: fullUrl, method: method.toUpperCase(), data: data || {}, header: headers, timeout, success(res) { const status = res.statusCode const body = res.data || {} if (status === 401 || body.code === 401) { logout() if (!silent) { uni.showToast({ title: body.msg || '请重新登录', icon: 'none' }) } setTimeout(() => { uni.reLaunch({ url: '/pages/login/login' }) }, 400) reject(new Error(body.msg || '未授权')) return } if (status < 200 || status >= 300) { const msg = body.msg || `请求失败(${status})` if (!silent) uni.showToast({ title: msg, icon: 'none' }) reject(new Error(msg)) return } // 统一后端 { code, msg, data } if (typeof body.code !== 'undefined' && body.code !== 200) { const msg = body.msg || '操作失败' if (!silent) uni.showToast({ title: msg, icon: 'none' }) const err = new Error(msg) err.code = body.code err.response = body reject(err) return } resolve(typeof body.data !== 'undefined' ? body.data : body) }, fail(err) { const detail = (err && err.errMsg) || '' console.error('[request fail]', fullUrl, detail) if (!silent) { uni.showToast({ title: detail.includes('timeout') ? '请求超时' : '网络异常,请检查接口地址', icon: 'none' }) } reject(new Error(detail || '网络异常')) } }) }) } /** 返回完整响应体(含 code/msg),用于需要自行判断 code 的场景 */ export function requestRaw(options = {}) { const { url, method = 'GET', data, header = {} } = options const token = getToken() const headers = { 'Content-Type': 'application/json', ...header } if (token) { headers.Authorization = `Bearer ${token}` } const fullUrl = BASE_URL.replace(/\/$/, '') + url return new Promise((resolve, reject) => { uni.request({ url: fullUrl, method: method.toUpperCase(), data: data || {}, header: headers, timeout: 30000, success(res) { resolve(res.data || {}) }, fail(err) { console.error('[requestRaw fail]', fullUrl, err) reject(err) } }) }) } export function generateId() { return `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}` }