import { useUserStore } from '@/store' // TODO: 替换为实际的 API 地址 export const baseUrl = ' https://lygcgs.com.cn:8078/shjapi/api/' // ===== 防止重复请求 ===== const pendingRequests = new Map() /** * 生成请求唯一标识 */ function getRequestKey(config) { const { url = '', method = 'GET', data = {} } = config const paramStr = JSON.stringify(data) return `${method}:${url}:${paramStr}` } /** * 检查是否为重复请求 */ function checkDuplicate(config) { const key = getRequestKey(config) if (pendingRequests.has(key)) { const meta = config.meta || {} if (meta.toast !== false) { uni.showToast({ title: '请求过于频繁,请稍后再试', icon: 'none' }) } return new Error('duplicate request') } pendingRequests.set(key, true) return null } /** * 移除请求标识 */ function removePending(config) { const key = getRequestKey(config) pendingRequests.delete(key) } // ======================== // uview-pro 全局请求配置 export const httpRequestConfig = { baseUrl, header: { 'content-type': 'application/json' }, meta: { originalData: true, toast: true, loading: true } } // 全局请求/响应拦截器 export const httpInterceptor = { request: (config) => { // 检查重复请求 const dupError = checkDuplicate(config) if (dupError) throw dupError const meta = config.meta || {} if (meta.loading) { uni.showLoading({ title: '加载中...', mask: true }) } const userStore = useUserStore() if (userStore.token) { config.header.token = userStore.token } return config }, response: (response) => { const meta = response.config?.meta || {} if (meta.loading) { uni.hideLoading() } // 请求完成,移除标识 removePending(response.config) // 根据业务处理错误、例如登录失效等处理接口返回错误码 if (response.data.code !== 1) { if (meta.toast) { uni.showToast({ title: response.data.message || '请求失败', icon: 'none' }) } // 401 登录失效,跳转登录页 if (response.data.code === 401) { const userStore = useUserStore() userStore.logout() uni.reLaunch({ url: '/pages/login/index' }) } throw new Error(response.data.message || '请求失败') } uni.showToast({ title: response.data.message || '请求成功', icon: 'none' }) return response.data } } /** * 便捷请求方法(基于 uni.request 封装) * 也可用 uni.$http.get / uni.$http.post(uview-pro) */ export function request(options) { return new Promise((resolve, reject) => { // 运行请求拦截器 const config = { ...httpRequestConfig, ...options } const finalConfig = httpInterceptor.request({ ...config, header: { ...httpRequestConfig.header, ...options.header } }) uni.request({ ...finalConfig, url: `${finalConfig.baseUrl}${finalConfig.url}`, success: (res) => { try { const data = httpInterceptor.response({ data: res.data, config: finalConfig }) resolve(data) } catch (err) { reject(err) } }, fail: (err) => { removePending(finalConfig) // 网络失败也要清理标识 uni.showToast({ title: '网络连接失败', icon: 'none' }) reject(err) } }) }) } // GET 快捷方法 export function get(url, params = {}) { return request({ url, method: 'GET', data: params }) } // POST 快捷方法 export function post(url, data = {}) { return request({ url, method: 'POST', data }) }