// utils/http.ts /* * *   ┏┓   ┏┓+ + *  ┏┛┻━━━┛┻┓ + + *  ┃       ┃ *  ┃   ━   ┃ ++ + + + * ████━████ ┃+ *  ┃       ┃ + *  ┃   ┻   ┃ *  ┃       ┃ + + *  ┗━┓   ┏━┛ *    ┃   ┃ *    ┃   ┃ + + + + *    ┃   ┃ *    ┃   ┃ + 神兽保佑 *    ┃   ┃ 代码无bug *    ┃   ┃  + *    ┃    ┗━━━┓ + + *    ┃        ┣┓ *    ┃        ┏┛ *    ┗┓┓┏━┳┓┏┛ + + + + *     ┃┫┫ ┃┫┫ *     ┗┻┛ ┗┻┛+ + + + */ import type { RequestTask } from '@dcloudio/types' import type { UniRequestConfig, UniResponse } from '@dcloudio/uni-app' // 定义基础响应类型 export interface HttpResponse { code: number message: string data: T [key: string]: any } // 请求配置类型 export interface RequestConfig extends UniRequestConfig { baseURL?: string retry?: number // 重试次数 retryDelay?: number // 重试延迟时间(ms) loading?: boolean // 是否显示加载状态 headers?: Record timeout?: number skipAuth?: boolean // 是否跳过认证检查 data?: any url?: string method?: UniRequestConfig['method'] } export class HttpClient { private defaults: RequestConfig private pendingRequests: Map constructor(config: RequestConfig = {}) { this.defaults = { baseURL: '', timeout: 20000, retry: 0, retryDelay: 1000, loading: false, ...config } this.pendingRequests = new Map() } // token检查方法 static checkTokenValidity(token: any): string | null { let tokenValue: string | null = null try { if (token) { if (typeof token === 'string') { try { const parsed = JSON.parse(token) if (parsed && typeof parsed.value === 'string') { tokenValue = parsed.value } else { tokenValue = token } } catch (e) { tokenValue = token } } else if (typeof token === 'object' && token.value) { tokenValue = token.value } } } catch (e) { console.error('Token 有效性检查失败:', e) } return tokenValue } private createRequestKey(config: RequestConfig): string { return `${config.method}-${config.url}-${JSON.stringify(config.data)}` } async request(config: RequestConfig): Promise { let mergedConfig: RequestConfig = { ...this.defaults, ...config } const requestKey = this.createRequestKey(mergedConfig) // 取消重复请求 if (this.pendingRequests.has(requestKey)) { this.pendingRequests.get(requestKey)?.abort() } return new Promise((resolve, reject) => { const sendRequest = (retryCount = 0) => { if (mergedConfig.loading) { uni.showLoading({ title: '加载中...', mask: true }) } try { const task = uni.request({ ...mergedConfig, url: (mergedConfig.baseURL ?? '') + mergedConfig.url, success: (response) => { const res = response.data as HttpResponse if (res.code === 200) { resolve(res as T) } else { uni.showToast({ title: res.message, icon: 'none' }) reject(res) } }, fail: (error) => { // 重试逻辑 if (retryCount < mergedConfig.retry!) { setTimeout(() => { sendRequest(retryCount + 1) }, mergedConfig.retryDelay) } else { uni.showToast({ title: '网络错误,请重试', icon: 'none' }) reject(error) } }, complete: () => { this.pendingRequests.delete(requestKey) if (mergedConfig.loading) { uni.hideLoading() } } }) as RequestTask this.pendingRequests.set(requestKey, task) } catch (error) { reject(error) } } sendRequest() }) } // 快捷方法 get(url: string, config?: RequestConfig) { return this.request({ ...config, url, method: 'GET' }) } post(url: string, data?: any, config?: RequestConfig) { return this.request({ ...config, url, data, method: 'POST' }) } delete(url: string, data?: any, config?: RequestConfig) { return this.request({ ...config, url, data, method: 'DELETE' }) } put(url: string, data?: any, config?: RequestConfig) { return this.request({ ...config, url, data, method: 'PUT' }) } } // 创建实例 export const http = new HttpClient({ // baseURL: 'http://192.168.1.34:8080/jeecg-boot/app', baseURL: 'http://192.168.1.166:8080/jeecg-boot/app', // baseURL: 'http://192.168.0.11:8080/jeecg-boot/app', headers: { 'Content-Type': 'application/json' } }) // 请求拦截器 uni.addInterceptor('request', { invoke(args: UniApp.RequestOptions) { // 跳过不需要认证的请求 if (args.header && (args.header as any).skipAuth) return const tokenStorage = uni.getStorageSync('TOKEN') const tokenValue = HttpClient.checkTokenValidity(tokenStorage) if (tokenValue) { args.header = args.header || {} args.header['x-access-token'] = tokenValue } else { console.log('[请求拦截器] 无有效Token') } }, fail(err) { console.error('请求拦截器失败:', err) } }) //响应拦截器 uni.addInterceptor('request', { success: (res) => { const data = res.data as HttpResponse if (data.code === 401) { uni.showToast({ title: data.message || '登录已失效,请重新登录', icon: 'none', duration: 2000 }) setTimeout(() => { uni.clearStorage() }, 500) return { ...res, errMsg: `Token失效: ${data.message}`, data: null } } else if (data.code !== 200) { uni.showToast({ title: data.message, icon: 'none' }) return { ...res, errMsg: `业务错误: ${data.message}`, data: null } } return res }, fail: (err) => { console.error('响应拦截器捕获错误:', err) uni.showToast({ title: '网络错误,请重试', icon: 'none' }) return err } })