|  | @@ -28,314 +28,203 @@ import type { UniRequestConfig, UniResponse } from '@dcloudio/uni-app'
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  // 定义基础响应类型
 |  |  // 定义基础响应类型
 | 
											
												
													
														|  |  export interface HttpResponse<T = any> {
 |  |  export interface HttpResponse<T = any> {
 | 
											
												
													
														|  | -	code : number
 |  | 
 | 
											
												
													
														|  | -	message : string
 |  | 
 | 
											
												
													
														|  | -	data : T
 |  | 
 | 
											
												
													
														|  | -	[key : string] : any
 |  | 
 | 
											
												
													
														|  | 
 |  | +  code: number
 | 
											
												
													
														|  | 
 |  | +  message: string
 | 
											
												
													
														|  | 
 |  | +  data: T
 | 
											
												
													
														|  | 
 |  | +  [key: string]: any
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  // 请求配置类型
 |  |  // 请求配置类型
 | 
											
												
													
														|  |  export interface RequestConfig extends UniRequestConfig {
 |  |  export interface RequestConfig extends UniRequestConfig {
 | 
											
												
													
														|  | -	baseURL ?: string
 |  | 
 | 
											
												
													
														|  | -	retry ?: number // 重试次数
 |  | 
 | 
											
												
													
														|  | -	retryDelay ?: number // 重试延迟时间(ms)
 |  | 
 | 
											
												
													
														|  | -	loading ?: boolean // 是否显示加载状态
 |  | 
 | 
											
												
													
														|  | -	headers ?: Record<string, string>
 |  | 
 | 
											
												
													
														|  | -	timeout ?: number
 |  | 
 | 
											
												
													
														|  | -	skipAuth ?: boolean // 是否跳过认证检查
 |  | 
 | 
											
												
													
														|  | -}
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -// 定义 Token 类型
 |  | 
 | 
											
												
													
														|  | -export interface TokenData {
 |  | 
 | 
											
												
													
														|  | -	value : string
 |  | 
 | 
											
												
													
														|  | -	expire : number
 |  | 
 | 
											
												
													
														|  | -}
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -// 拦截器类型
 |  | 
 | 
											
												
													
														|  | -interface Interceptor<V> {
 |  | 
 | 
											
												
													
														|  | -	fulfilled : (value : V) => V | Promise<V>
 |  | 
 | 
											
												
													
														|  | -	rejected ?: (error : any) => any
 |  | 
 | 
											
												
													
														|  | 
 |  | +  baseURL?: string
 | 
											
												
													
														|  | 
 |  | +  retry?: number // 重试次数
 | 
											
												
													
														|  | 
 |  | +  retryDelay?: number // 重试延迟时间(ms)
 | 
											
												
													
														|  | 
 |  | +  loading?: boolean // 是否显示加载状态
 | 
											
												
													
														|  | 
 |  | +  headers?: Record<string, string>
 | 
											
												
													
														|  | 
 |  | +  timeout?: number
 | 
											
												
													
														|  | 
 |  | +  skipAuth?: boolean // 是否跳过认证检查
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  export class HttpClient {
 |  |  export class HttpClient {
 | 
											
												
													
														|  | -	private defaults : RequestConfig
 |  | 
 | 
											
												
													
														|  | -	private interceptors : {
 |  | 
 | 
											
												
													
														|  | -		request : Interceptor<RequestConfig>[]
 |  | 
 | 
											
												
													
														|  | -		response : Interceptor<UniResponse<HttpResponse>>[]
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | -	private pendingRequests : Map<string, RequestTask>
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -	// 新增刷新相关属性
 |  | 
 | 
											
												
													
														|  | -	private isRefreshing = false
 |  | 
 | 
											
												
													
														|  | -	private refreshSubscribers : ((token : string) => void)[] = []
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -	constructor(config : RequestConfig = {}) {
 |  | 
 | 
											
												
													
														|  | -		this.defaults = {
 |  | 
 | 
											
												
													
														|  | -			baseURL: '',
 |  | 
 | 
											
												
													
														|  | -			timeout: 10000,
 |  | 
 | 
											
												
													
														|  | -			retry: 0,
 |  | 
 | 
											
												
													
														|  | -			retryDelay: 1000,
 |  | 
 | 
											
												
													
														|  | -			loading: false,
 |  | 
 | 
											
												
													
														|  | -			...config
 |  | 
 | 
											
												
													
														|  | -		}
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -		this.interceptors = {
 |  | 
 | 
											
												
													
														|  | -			request: [],
 |  | 
 | 
											
												
													
														|  | -			response: []
 |  | 
 | 
											
												
													
														|  | -		}
 |  | 
 | 
											
												
													
														|  | -		this.pendingRequests = new Map()
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -	//token检查方法
 |  | 
 | 
											
												
													
														|  | -	static checkTokenValidity(token : any) : string | null {
 |  | 
 | 
											
												
													
														|  | -		let tokenValue : string | null = null
 |  | 
 | 
											
												
													
														|  | -		let tokenExpire : number | null = null
 |  | 
 | 
											
												
													
														|  | -		try {
 |  | 
 | 
											
												
													
														|  | -			if (token) {
 |  | 
 | 
											
												
													
														|  | -				// 处理字符串类型的token(可能是JSON或原始字符串)
 |  | 
 | 
											
												
													
														|  | -				if (typeof token === 'string') {
 |  | 
 | 
											
												
													
														|  | -					try {
 |  | 
 | 
											
												
													
														|  | -						// 尝试解析为JSON对象
 |  | 
 | 
											
												
													
														|  | -						const parsed = JSON.parse(token)
 |  | 
 | 
											
												
													
														|  | -						if (parsed && typeof parsed.value === 'string') {
 |  | 
 | 
											
												
													
														|  | -							tokenValue = parsed.value
 |  | 
 | 
											
												
													
														|  | -							tokenExpire = parsed.expire
 |  | 
 | 
											
												
													
														|  | -						} else {
 |  | 
 | 
											
												
													
														|  | -							// 不是有效JSON对象,当作原始token字符串
 |  | 
 | 
											
												
													
														|  | -							tokenValue = token
 |  | 
 | 
											
												
													
														|  | -						}
 |  | 
 | 
											
												
													
														|  | -					} catch (e) {
 |  | 
 | 
											
												
													
														|  | -						// JSON解析失败,当作原始token字符串
 |  | 
 | 
											
												
													
														|  | -						tokenValue = token
 |  | 
 | 
											
												
													
														|  | -					}
 |  | 
 | 
											
												
													
														|  | -				}
 |  | 
 | 
											
												
													
														|  | -				else if (typeof token === 'object' && token.value) {
 |  | 
 | 
											
												
													
														|  | -					tokenValue = token.value
 |  | 
 | 
											
												
													
														|  | -					tokenExpire = token.expire
 |  | 
 | 
											
												
													
														|  | -				}
 |  | 
 | 
											
												
													
														|  | -				if (tokenValue) {
 |  | 
 | 
											
												
													
														|  | -					const now = Date.now() + 10000 // 10秒缓冲
 |  | 
 | 
											
												
													
														|  | -					// 如果有过期时间则检查,否则认为有效
 |  | 
 | 
											
												
													
														|  | -					if (tokenExpire) {
 |  | 
 | 
											
												
													
														|  | -						return tokenExpire > now ? tokenValue : null
 |  | 
 | 
											
												
													
														|  | -					}
 |  | 
 | 
											
												
													
														|  | -					return tokenValue
 |  | 
 | 
											
												
													
														|  | -				}
 |  | 
 | 
											
												
													
														|  | -			}
 |  | 
 | 
											
												
													
														|  | -		} catch (e) {
 |  | 
 | 
											
												
													
														|  | -			console.error('Token 有效性检查失败:', e)
 |  | 
 | 
											
												
													
														|  | -		}
 |  | 
 | 
											
												
													
														|  | -		return null
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -	private createRequestKey(config : RequestConfig) : string {
 |  | 
 | 
											
												
													
														|  | -		return `${config.method}-${config.url}-${JSON.stringify(config.data)}`
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -	// token刷新
 |  | 
 | 
											
												
													
														|  | -	private async refreshToken() : Promise<void> {
 |  | 
 | 
											
												
													
														|  | -		try {
 |  | 
 | 
											
												
													
														|  | -			const refreshToken = uni.getStorageSync('refreshToken');
 |  | 
 | 
											
												
													
														|  | -			const tokenValue = HttpClient.checkTokenValidity(refreshToken);
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -			const response = await this.request<{
 |  | 
 | 
											
												
													
														|  | -				accessToken : string;
 |  | 
 | 
											
												
													
														|  | -				refreshToken : string;
 |  | 
 | 
											
												
													
														|  | -			}>({
 |  | 
 | 
											
												
													
														|  | -				url: `/member/auth/refresh-token?refreshToken=${tokenValue}`,
 |  | 
 | 
											
												
													
														|  | -				method: 'POST',
 |  | 
 | 
											
												
													
														|  | -				data: '',
 |  | 
 | 
											
												
													
														|  | -				skipAuth: true
 |  | 
 | 
											
												
													
														|  | -			});
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -			uni.setStorageSync('token', response.accessToken);
 |  | 
 | 
											
												
													
														|  | -			uni.setStorageSync('refreshToken', response.refreshToken);
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -			this.refreshSubscribers.forEach(callback => callback(response.accessToken));
 |  | 
 | 
											
												
													
														|  | -			this.refreshSubscribers = [];
 |  | 
 | 
											
												
													
														|  | -		} catch (error) {
 |  | 
 | 
											
												
													
														|  | -			console.error('刷新Token失败:', error);
 |  | 
 | 
											
												
													
														|  | -			uni.removeStorageSync('token');
 |  | 
 | 
											
												
													
														|  | -			uni.removeStorageSync('refreshToken');
 |  | 
 | 
											
												
													
														|  | -			uni.reLaunch({ url: '/pages/login/selectLogin' });
 |  | 
 | 
											
												
													
														|  | -			throw error;
 |  | 
 | 
											
												
													
														|  | -		} finally {
 |  | 
 | 
											
												
													
														|  | -			this.isRefreshing = false;
 |  | 
 | 
											
												
													
														|  | -		}
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -	// 核心方法增加无感刷新逻辑
 |  | 
 | 
											
												
													
														|  | -	async request<T = any>(config : RequestConfig) : Promise<T> {
 |  | 
 | 
											
												
													
														|  | -		let mergedConfig : RequestConfig = { ...this.defaults, ...config }
 |  | 
 | 
											
												
													
														|  | -		// 执行请求拦截器
 |  | 
 | 
											
												
													
														|  | -		for (const interceptor of this.interceptors.request) {
 |  | 
 | 
											
												
													
														|  | -			try {
 |  | 
 | 
											
												
													
														|  | -				mergedConfig = await interceptor.fulfilled(mergedConfig)
 |  | 
 | 
											
												
													
														|  | -			} catch (error) {
 |  | 
 | 
											
												
													
														|  | -				interceptor.rejected?.(error)
 |  | 
 | 
											
												
													
														|  | -				throw error
 |  | 
 | 
											
												
													
														|  | -			}
 |  | 
 | 
											
												
													
														|  | -		}
 |  | 
 | 
											
												
													
														|  | -		const requestKey = this.createRequestKey(mergedConfig)
 |  | 
 | 
											
												
													
														|  | -		// 取消重复请求
 |  | 
 | 
											
												
													
														|  | -		if (this.pendingRequests.has(requestKey)) {
 |  | 
 | 
											
												
													
														|  | -			this.pendingRequests.get(requestKey)?.abort()
 |  | 
 | 
											
												
													
														|  | -		}
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -		return new Promise((resolve, reject) => {
 |  | 
 | 
											
												
													
														|  | -			const sendRequest = async (retryCount = 0) => {
 |  | 
 | 
											
												
													
														|  | -				if (mergedConfig.loading) {
 |  | 
 | 
											
												
													
														|  | -					uni.showLoading({ title: '加载中...', mask: true })
 |  | 
 | 
											
												
													
														|  | -				}
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -				try {
 |  | 
 | 
											
												
													
														|  | -					const task = uni.request({
 |  | 
 | 
											
												
													
														|  | -						...mergedConfig,
 |  | 
 | 
											
												
													
														|  | -						url: mergedConfig.baseURL + mergedConfig.url,
 |  | 
 | 
											
												
													
														|  | -						success: async (response) => {
 |  | 
 | 
											
												
													
														|  | -							const res = response.data as HttpResponse;
 |  | 
 | 
											
												
													
														|  | -							if (res.code === 401 && !mergedConfig.skipAuth) {
 |  | 
 | 
											
												
													
														|  | -								const retryOriginalRequest = new Promise<T>((resolve) => {
 |  | 
 | 
											
												
													
														|  | -									this.refreshSubscribers.push((newToken) => {
 |  | 
 | 
											
												
													
														|  | -										// 使用新Token重试请求
 |  | 
 | 
											
												
													
														|  | -										const retryConfig = {
 |  | 
 | 
											
												
													
														|  | -											...mergedConfig,
 |  | 
 | 
											
												
													
														|  | -											header: {
 |  | 
 | 
											
												
													
														|  | -												...mergedConfig.header,
 |  | 
 | 
											
												
													
														|  | -												Authorization: `Bearer ${newToken}`
 |  | 
 | 
											
												
													
														|  | -											}
 |  | 
 | 
											
												
													
														|  | -										}
 |  | 
 | 
											
												
													
														|  | -										this.request(retryConfig).then(resolve)
 |  | 
 | 
											
												
													
														|  | -									})
 |  | 
 | 
											
												
													
														|  | -								})
 |  | 
 | 
											
												
													
														|  | -								if (!this.isRefreshing) {
 |  | 
 | 
											
												
													
														|  | -									this.isRefreshing = true
 |  | 
 | 
											
												
													
														|  | -									this.refreshToken().catch((error) => {
 |  | 
 | 
											
												
													
														|  | -										this.refreshSubscribers = []
 |  | 
 | 
											
												
													
														|  | -										reject(error)
 |  | 
 | 
											
												
													
														|  | -									})
 |  | 
 | 
											
												
													
														|  | -								}
 |  | 
 | 
											
												
													
														|  | -								return resolve(await retryOriginalRequest)
 |  | 
 | 
											
												
													
														|  | -							}
 |  | 
 | 
											
												
													
														|  | -							// 执行响应拦截器
 |  | 
 | 
											
												
													
														|  | -							let processedResponse = response
 |  | 
 | 
											
												
													
														|  | -							for (const interceptor of this.interceptors.response) {
 |  | 
 | 
											
												
													
														|  | -								try {
 |  | 
 | 
											
												
													
														|  | -									processedResponse = await interceptor.fulfilled(processedResponse)
 |  | 
 | 
											
												
													
														|  | -								} catch (error) {
 |  | 
 | 
											
												
													
														|  | -									interceptor.rejected?.(error)
 |  | 
 | 
											
												
													
														|  | -									reject(error)
 |  | 
 | 
											
												
													
														|  | -									return
 |  | 
 | 
											
												
													
														|  | -								}
 |  | 
 | 
											
												
													
														|  | -							}
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -							const resData = processedResponse.data as HttpResponse<T>
 |  | 
 | 
											
												
													
														|  | -							if (resData.code === 0) {
 |  | 
 | 
											
												
													
														|  | -								resolve(resData.data)
 |  | 
 | 
											
												
													
														|  | -							} else {
 |  | 
 | 
											
												
													
														|  | -								uni.showToast({
 |  | 
 | 
											
												
													
														|  | -									title: resData.msg || '请求失败',
 |  | 
 | 
											
												
													
														|  | -									icon: 'none'
 |  | 
 | 
											
												
													
														|  | -								})
 |  | 
 | 
											
												
													
														|  | -								reject(resData)
 |  | 
 | 
											
												
													
														|  | -							}
 |  | 
 | 
											
												
													
														|  | -						},
 |  | 
 | 
											
												
													
														|  | -						fail: async (error) => {
 |  | 
 | 
											
												
													
														|  | -							// 重试逻辑
 |  | 
 | 
											
												
													
														|  | -							if (retryCount < mergedConfig.retry!) {
 |  | 
 | 
											
												
													
														|  | -								setTimeout(() => {
 |  | 
 | 
											
												
													
														|  | -									sendRequest(retryCount + 1)
 |  | 
 | 
											
												
													
														|  | -								}, mergedConfig.retryDelay)
 |  | 
 | 
											
												
													
														|  | -							} else {
 |  | 
 | 
											
												
													
														|  | -								reject(error)
 |  | 
 | 
											
												
													
														|  | -							}
 |  | 
 | 
											
												
													
														|  | -						},
 |  | 
 | 
											
												
													
														|  | -						complete: () => {
 |  | 
 | 
											
												
													
														|  | -							this.pendingRequests.delete(requestKey)
 |  | 
 | 
											
												
													
														|  | -							if (mergedConfig.loading) {
 |  | 
 | 
											
												
													
														|  | -								uni.hideLoading()
 |  | 
 | 
											
												
													
														|  | -							}
 |  | 
 | 
											
												
													
														|  | -						}
 |  | 
 | 
											
												
													
														|  | -					}) as RequestTask
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -					this.pendingRequests.set(requestKey, task)
 |  | 
 | 
											
												
													
														|  | -				} catch (error) {
 |  | 
 | 
											
												
													
														|  | -					reject(error)
 |  | 
 | 
											
												
													
														|  | -				}
 |  | 
 | 
											
												
													
														|  | -			}
 |  | 
 | 
											
												
													
														|  | -			sendRequest()
 |  | 
 | 
											
												
													
														|  | -		})
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -	// 添加请求拦截器
 |  | 
 | 
											
												
													
														|  | -	useRequestInterceptor(interceptor : Interceptor<RequestConfig>) {
 |  | 
 | 
											
												
													
														|  | -		this.interceptors.request.push(interceptor)
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -	// 添加响应拦截器
 |  | 
 | 
											
												
													
														|  | -	useResponseInterceptor(interceptor : Interceptor<UniResponse<HttpResponse>>) {
 |  | 
 | 
											
												
													
														|  | -		this.interceptors.response.push(interceptor)
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -	// 快捷方法
 |  | 
 | 
											
												
													
														|  | -	get<T = any>(url : string, config ?: RequestConfig) {
 |  | 
 | 
											
												
													
														|  | -		return this.request<T>({ ...config, url, method: 'GET' })
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -	post<T = any>(url : string, data ?: any, config ?: RequestConfig) {
 |  | 
 | 
											
												
													
														|  | -		return this.request<T>({ ...config, url, data, method: 'POST' })
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -	delete<T = any>(url : string, data ?: any, config ?: RequestConfig) {
 |  | 
 | 
											
												
													
														|  | -		return this.request<T>({ ...config, url, data, method: 'DELETE' })
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -	put<T = any>(url : string, data ?: any, config ?: RequestConfig) {
 |  | 
 | 
											
												
													
														|  | -		return this.request<T>({ ...config, url, data, method: 'PUT' })
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | 
 |  | +  private defaults: RequestConfig
 | 
											
												
													
														|  | 
 |  | +  private pendingRequests: Map<string, RequestTask>
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +  constructor(config: RequestConfig = {}) {
 | 
											
												
													
														|  | 
 |  | +    this.defaults = {
 | 
											
												
													
														|  | 
 |  | +      baseURL: '',
 | 
											
												
													
														|  | 
 |  | +      timeout: 10000,
 | 
											
												
													
														|  | 
 |  | +      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<T = any>(config: RequestConfig): Promise<T> {
 | 
											
												
													
														|  | 
 |  | +    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<T = any>(url: string, config?: RequestConfig) {
 | 
											
												
													
														|  | 
 |  | +    return this.request<T>({ ...config, url, method: 'GET' })
 | 
											
												
													
														|  | 
 |  | +  }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +  post<T = any>(url: string, data?: any, config?: RequestConfig) {
 | 
											
												
													
														|  | 
 |  | +    return this.request<T>({ ...config, url, data, method: 'POST' })
 | 
											
												
													
														|  | 
 |  | +  }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +  delete<T = any>(url: string, data?: any, config?: RequestConfig) {
 | 
											
												
													
														|  | 
 |  | +    return this.request<T>({ ...config, url, data, method: 'DELETE' })
 | 
											
												
													
														|  | 
 |  | +  }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +  put<T = any>(url: string, data?: any, config?: RequestConfig) {
 | 
											
												
													
														|  | 
 |  | +    return this.request<T>({ ...config, url, data, method: 'PUT' })
 | 
											
												
													
														|  | 
 |  | +  }
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  // 创建实例
 |  |  // 创建实例
 | 
											
												
													
														|  |  export const http = new HttpClient({
 |  |  export const http = new HttpClient({
 | 
											
												
													
														|  | -	baseURL: 'http://qhmall.natapp1.cc/app-api',
 |  | 
 | 
											
												
													
														|  | -	headers: {
 |  | 
 | 
											
												
													
														|  | -		'Content-Type': 'application/json'
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | 
 |  | +  baseURL: 'http://192.168.1.34:8080/jeecg-boot/app',
 | 
											
												
													
														|  | 
 |  | +  headers: {
 | 
											
												
													
														|  | 
 |  | +    'Content-Type': 'application/json'
 | 
											
												
													
														|  | 
 |  | +  }
 | 
											
												
													
														|  |  })
 |  |  })
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -// 添加请求拦截器 - 处理鉴权
 |  | 
 | 
											
												
													
														|  | -http.useRequestInterceptor({
 |  | 
 | 
											
												
													
														|  | -	fulfilled: (config) => {
 |  | 
 | 
											
												
													
														|  | -		// 跳过不需要认证的请求
 |  | 
 | 
											
												
													
														|  | -		if (config.skipAuth) return config
 |  | 
 | 
											
												
													
														|  | -		const tokenStorage = uni.getStorageSync('token')
 |  | 
 | 
											
												
													
														|  | -		// 检查 token 有效性并提取值
 |  | 
 | 
											
												
													
														|  | -		const tokenValue = HttpClient.checkTokenValidity(tokenStorage)
 |  | 
 | 
											
												
													
														|  | -		if (tokenValue) {
 |  | 
 | 
											
												
													
														|  | -			config.header = config.header || {}
 |  | 
 | 
											
												
													
														|  | -			config.header.Authorization = `Bearer ${tokenValue}`
 |  | 
 | 
											
												
													
														|  | -		} else {
 |  | 
 | 
											
												
													
														|  | -			console.log('[请求拦截器] 无有效Token')
 |  | 
 | 
											
												
													
														|  | -		}
 |  | 
 | 
											
												
													
														|  | -		return config
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | 
 |  | +// 使用UniApp原生请求拦截器
 | 
											
												
													
														|  | 
 |  | +uni.addInterceptor('request', {
 | 
											
												
													
														|  | 
 |  | +  invoke(args: UniApp.RequestOptions) {
 | 
											
												
													
														|  | 
 |  | +    // 跳过不需要认证的请求
 | 
											
												
													
														|  | 
 |  | +    if (args.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)
 | 
											
												
													
														|  | 
 |  | +  }
 | 
											
												
													
														|  |  })
 |  |  })
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -// 添加响应拦截器 - 错误处理
 |  | 
 | 
											
												
													
														|  | -http.useResponseInterceptor({
 |  | 
 | 
											
												
													
														|  | -	fulfilled: (response) => {
 |  | 
 | 
											
												
													
														|  | -		const resData = response.data as HttpResponse;
 |  | 
 | 
											
												
													
														|  | -		if (resData.code !== 0) {
 |  | 
 | 
											
												
													
														|  | -			return Promise.reject(response)
 |  | 
 | 
											
												
													
														|  | -		}
 |  | 
 | 
											
												
													
														|  | -		return response
 |  | 
 | 
											
												
													
														|  | -	},
 |  | 
 | 
											
												
													
														|  | -	rejected: (error) => {
 |  | 
 | 
											
												
													
														|  | -		console.log(error.data, 'err');
 |  | 
 | 
											
												
													
														|  | -		uni.showToast({
 |  | 
 | 
											
												
													
														|  | -			title: error.data.msg || '请求失败',
 |  | 
 | 
											
												
													
														|  | -			icon: 'none'
 |  | 
 | 
											
												
													
														|  | -		})
 |  | 
 | 
											
												
													
														|  | -		return Promise.reject(error)
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | 
 |  | +// 使用UniApp原生响应拦截器
 | 
											
												
													
														|  | 
 |  | +uni.addInterceptor('request', {
 | 
											
												
													
														|  | 
 |  | +  success: (res) => {
 | 
											
												
													
														|  | 
 |  | +    const data = res.data as HttpResponse
 | 
											
												
													
														|  | 
 |  | +    if (data.code !== 200) {
 | 
											
												
													
														|  | 
 |  | +      uni.showToast({
 | 
											
												
													
														|  | 
 |  | +        title: data.message || '请求失败',
 | 
											
												
													
														|  | 
 |  | +        icon: 'none'
 | 
											
												
													
														|  | 
 |  | +      })
 | 
											
												
													
														|  | 
 |  | +      // 返回自定义错误对象,触发fail回调
 | 
											
												
													
														|  | 
 |  | +      return {
 | 
											
												
													
														|  | 
 |  | +        ...res,
 | 
											
												
													
														|  | 
 |  | +        errMsg: `业务错误: ${data.message}`,
 | 
											
												
													
														|  | 
 |  | +        data: null
 | 
											
												
													
														|  | 
 |  | +      }
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +    return res
 | 
											
												
													
														|  | 
 |  | +  },
 | 
											
												
													
														|  | 
 |  | +  fail: (err) => {
 | 
											
												
													
														|  | 
 |  | +    console.error('响应拦截器捕获错误:', err)
 | 
											
												
													
														|  | 
 |  | +    uni.showToast({
 | 
											
												
													
														|  | 
 |  | +      title: '网络错误,请重试',
 | 
											
												
													
														|  | 
 |  | +      icon: 'none'
 | 
											
												
													
														|  | 
 |  | +    })
 | 
											
												
													
														|  | 
 |  | +    return err
 | 
											
												
													
														|  | 
 |  | +  }
 | 
											
												
													
														|  |  })
 |  |  })
 |