import { API_BASE } from "./config"; let isRefreshing = false; let pendingQueue = []; const isHtmlLike = (value) => typeof value === "string" && value.trim().startsWith("<"); export const extractList = (payload) => { if (Array.isArray(payload?.items)) return payload.items; if (Array.isArray(payload?.data)) return payload.data; if (Array.isArray(payload)) return payload; return []; }; const doRequest = (options) => { return new Promise((resolve, reject) => { const token = uni.getStorageSync("access_token"); uni.request({ url: API_BASE + options.url, method: options.method || "GET", data: options.data, header: { "Content-Type": "application/json", ...(token ? { Authorization: `Bearer ${token}` } : {}), ...options.header, }, success: (res) => resolve(res), fail: (err) => reject(err), }); }); }; const tryRefreshToken = () => { return new Promise((resolve, reject) => { const rt = uni.getStorageSync("refresh_token"); if (!rt) return reject(new Error("no_refresh_token")); uni.request({ url: API_BASE + "/auth/refresh", method: "POST", header: { "Content-Type": "application/json" }, data: { refresh_token: rt }, success: (res) => { if (res.statusCode >= 200 && res.statusCode < 300) { const { access_token, refresh_token } = res.data; uni.setStorageSync("access_token", access_token); if (refresh_token) uni.setStorageSync("refresh_token", refresh_token); resolve(); } else { reject(new Error("refresh_failed")); } }, fail: () => reject(new Error("refresh_network_error")), }); }); }; const goLogin = () => { uni.removeStorageSync("access_token"); uni.removeStorageSync("refresh_token"); const pages = getCurrentPages(); const current = pages[pages.length - 1]; const route = current ? `/${current.route}` : ""; if (route !== "/pages/login/index") { uni.navigateTo({ url: "/pages/login/index" }); } }; const handleError = (res) => { const code = res.statusCode; if (code === 403) return "没有权限执行此操作"; if (code === 404) return "请求的资源不存在"; if (code === 409) return "数据冲突,请刷新重试"; if (code === 422) { const detail = res.data?.detail; if (Array.isArray(detail) && detail.length > 0) { return detail.map((d) => d.msg || d.message).join(";"); } } if (code === 429) return "操作过于频繁,请稍后再试"; if (code >= 500) return "服务器繁忙,请稍后重试"; const raw = res.data?.message || res.data?.detail || "请求失败"; return typeof raw === "string" ? raw : JSON.stringify(raw); }; const request = (options) => { return new Promise((resolve, reject) => { doRequest(options) .then((res) => { if (isHtmlLike(res.data)) { const msg = "接口返回异常,请检查网络或服务状态"; uni.showToast({ title: msg, icon: "none" }); return reject(new Error(msg)); } if (res.statusCode === 401) { if (isRefreshing) { pendingQueue.push({ options, resolve, reject }); return; } isRefreshing = true; tryRefreshToken() .then(() => { isRefreshing = false; doRequest(options).then((r2) => { if (r2.statusCode >= 200 && r2.statusCode < 300) { resolve(r2.data); } else { const msg = handleError(r2); uni.showToast({ title: msg, icon: "none" }); reject(new Error(msg)); } }); pendingQueue.forEach((p) => { doRequest(p.options).then((r2) => { if (r2.statusCode >= 200 && r2.statusCode < 300) { p.resolve(r2.data); } else { p.reject(new Error(handleError(r2))); } }); }); pendingQueue = []; }) .catch(() => { isRefreshing = false; pendingQueue.forEach((p) => p.reject(new Error("登录已过期"))); pendingQueue = []; goLogin(); reject(new Error("登录已过期,请重新登录")); }); return; } if (res.statusCode >= 200 && res.statusCode < 300) { resolve(res.data); } else { const msg = handleError(res); uni.showToast({ title: msg, icon: "none" }); reject(new Error(msg)); } }) .catch((err) => { uni.showToast({ title: "网络连接失败,请检查网络", icon: "none" }); reject(err); }); }); }; export const get = (url, data) => request({ url, method: "GET", data }); export const post = (url, data) => request({ url, method: "POST", data }); export const put = (url, data) => request({ url, method: "PUT", data }); export const del = (url, data) => request({ url, method: "DELETE", data }); export default request;