import Taro from '@tarojs/taro' /** * 后端接口请求封装 * 后端统一响应:{ code, message, data },code === 0 表示成功 * token 通过 Authorization: Bearer 传入 */ export const BASE_URL = 'https://wxbackend.tokenleaping.com' const TOKEN_KEY = 'smart_access_token' /** 安全隐藏 loading:没有活动 loading 时调用 hideLoading 会抛 hideToast:fail,这里吞掉 */ export function safeHideLoading(): void { try { Taro.hideLoading() } catch { /* ignore */ } } // ---------- token 存取 ---------- export function getToken(): string { try { return Taro.getStorageSync(TOKEN_KEY) || '' } catch { return '' } } export function setToken(token: string): void { Taro.setStorageSync(TOKEN_KEY, token) } export function clearToken(): void { try { Taro.removeStorageSync(TOKEN_KEY) } catch { /* ignore */ } } // ---------- 类型 ---------- interface ApiResponse { code: number message: string data: T } export interface RequestOptions { method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' data?: unknown /** 额外请求头 */ headers?: Record /** 是否自动携带 token,默认 true */ auth?: boolean } // ---------- request ---------- /** * 发请求。成功(code===0)返回 data;业务失败抛 Error(message);HTTP 401 清 token 并抛错。 * 调用方可自行 catch 或用 onUnauthorized 钩子统一处理跳登录。 */ export async function request( path: string, options: RequestOptions = {}, ): Promise { const { method = 'GET', data, headers = {}, auth = true } = options const token = getToken() const finalHeaders: Record = { 'Content-Type': 'application/json', ...(auth && token ? { Authorization: `Bearer ${token}` } : {}), ...headers, } let res: Taro.request.SuccessCallbackResult try { res = await Taro.request({ url: `${BASE_URL}${path}`, method, data, header: finalHeaders, }) } catch (e) { // 网络层异常 throw new Error('网络异常,请稍后重试') } // HTTP 未授权:清 token,交回调处理 if (res.statusCode === 401) { clearToken() onUnauthorized?.() throw new Error('登录已过期,请重新登录') } const body = res.data as ApiResponse // 后端业务码非 0:当作错误抛出 if (body && typeof body.code === 'number' && body.code !== 0) { throw new Error(body.message || '请求失败') } return (body && typeof body.code === 'number' ? body.data : body) as T } /** 401 钩子,由业务方注册(如跳转登录页) */ export let onUnauthorized: (() => void) | null = null export function setOnUnauthorized(handler: () => void): void { onUnauthorized = handler } // ---------- 便捷方法 ---------- export const http = { get: (path: string, options?: RequestOptions) => request(path, { ...options, method: 'GET' }), post: (path: string, data?: unknown, options?: RequestOptions) => request(path, { ...options, method: 'POST', data }), put: (path: string, data?: unknown, options?: RequestOptions) => request(path, { ...options, method: 'PUT', data }), patch: (path: string, data?: unknown, options?: RequestOptions) => request(path, { ...options, method: 'PATCH', data }), del: (path: string, options?: RequestOptions) => request(path, { ...options, method: 'DELETE' }), } export default http