const KEY_TOKEN = 'ICE_MEMBER_TOKEN' const KEY_TOKEN_EXPIRES_AT = 'ICE_MEMBER_TOKEN_EXPIRES_AT' const API_BASE_URL = import.meta.env.VITE_ICE_API_BASE_URL || 'http://127.0.0.1:8000' export const authStorage = { setToken(token, expiresIn) { uni.setStorageSync(KEY_TOKEN, token) if (expiresIn) { uni.setStorageSync(KEY_TOKEN_EXPIRES_AT, Date.now() + Number(expiresIn) * 1000) } }, getToken() { return uni.getStorageSync(KEY_TOKEN) }, isTokenExpired() { const expiresAt = Number(uni.getStorageSync(KEY_TOKEN_EXPIRES_AT) || 0) return expiresAt > 0 && Date.now() >= expiresAt }, clear() { uni.removeStorageSync(KEY_TOKEN) uni.removeStorageSync(KEY_TOKEN_EXPIRES_AT) } } export const normalizeApiError = (rawError = {}) => { const statusCode = rawError.statusCode const body = rawError.data || rawError const code = body?.code const backendMessage = body?.message || '' if (statusCode === 401 || code === 40001) { return { type: 'auth_expired', code, statusCode, message: '登录状态已过期,请重新登录', raw: rawError } } if (code === 40002) { return { type: 'profile_required', code, statusCode, message: '请先完善会员资料', raw: rawError } } if (code === 40003) { return { type: 'bind_conflict', code, statusCode, message: backendMessage || '该手机号已绑定其他微信账号,请联系场馆前台处理', raw: rawError } } if (!statusCode) { return { type: 'network_error', code, statusCode, message: '网络连接失败,请检查后重试', raw: rawError } } if (statusCode === 404 || code === 40400) { return { type: 'not_found', code, statusCode, message: backendMessage || '未找到对应信息或无访问权限', raw: rawError } } return { type: 'api_error', code, statusCode, message: backendMessage || '服务暂时不可用,请稍后重试', raw: rawError } } export function request(options = {}) { const token = authStorage.getToken() const header = { 'Content-Type': 'application/json', ...(options.header || {}) } if (token) { header.Authorization = `Bearer ${token}` } return new Promise((resolve, reject) => { uni.request({ url: options.url.startsWith('http') ? options.url : `${API_BASE_URL}${options.url}`, method: options.method || 'GET', data: options.data, header, success: (res) => { const body = res.data if (res.statusCode >= 200 && res.statusCode < 300) { if (body && body.code === 0) { resolve(body.data) return } reject(normalizeApiError({ statusCode: res.statusCode, data: body })) return } reject(normalizeApiError({ statusCode: res.statusCode, data: body })) }, fail: (err) => { reject(normalizeApiError(err)) } }) }) }