Initial project commit
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user