|
|
@@ -0,0 +1,222 @@
|
|
|
+import { isDev, ignoreTokens, config } from "@/config";
|
|
|
+import { locale, t } from "../locale";
|
|
|
+import { isNull, isObject, parse, storage } from "../utils";
|
|
|
+import { useStore } from "../store";
|
|
|
+
|
|
|
+// 请求参数类型定义
|
|
|
+export type RequestOptions = {
|
|
|
+ url: string; // 请求地址
|
|
|
+ method?: RequestMethod; // 请求方法
|
|
|
+ data?: any; // 请求体数据
|
|
|
+ params?: any; // URL参数
|
|
|
+ header?: any; // 请求头
|
|
|
+ timeout?: number; // 超时时间
|
|
|
+ withCredentials?: boolean; // 是否携带凭证
|
|
|
+ firstIpv4?: boolean; // 是否优先使用IPv4
|
|
|
+ enableChunked?: boolean; // 是否启用分块传输
|
|
|
+};
|
|
|
+
|
|
|
+// 响应数据类型定义
|
|
|
+export type Response = {
|
|
|
+ code: number;
|
|
|
+ message: string;
|
|
|
+ data?: any;
|
|
|
+};
|
|
|
+
|
|
|
+// 请求队列(用于等待token刷新后继续请求)
|
|
|
+let requests: ((token: string) => void)[] = [];
|
|
|
+
|
|
|
+// 标记token是否正在刷新
|
|
|
+let isRefreshing = false;
|
|
|
+
|
|
|
+// 判断当前url是否忽略token校验
|
|
|
+const isIgnoreToken = (url: string) => {
|
|
|
+ return ignoreTokens.some((e) => {
|
|
|
+ const pattern = e.replace(/\*/g, ".*");
|
|
|
+ return new RegExp(pattern).test(url);
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * 通用请求方法
|
|
|
+ * @param options 请求参数
|
|
|
+ * @returns Promise<T>
|
|
|
+ */
|
|
|
+export function request<R = any>(options: RequestOptions): Promise<Response> {
|
|
|
+ let { url, method = "GET", data = {}, header = {}, timeout = 60000 } = options;
|
|
|
+
|
|
|
+ const { user } = useStore();
|
|
|
+
|
|
|
+ // 开发环境下打印请求信息
|
|
|
+ if (isDev) {
|
|
|
+ console.log(`[${method}] ${url}`);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 拼接基础url
|
|
|
+ if (!url.startsWith("http")) {
|
|
|
+ url = config.baseUrl + url;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取当前token
|
|
|
+ let Authorization: string | null = user.token;
|
|
|
+
|
|
|
+ console.log(Authorization);
|
|
|
+
|
|
|
+
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ // 发起请求的实际函数
|
|
|
+ const next = () => {
|
|
|
+ console.log(222);
|
|
|
+
|
|
|
+ uni.request({
|
|
|
+ url,
|
|
|
+ method,
|
|
|
+ data,
|
|
|
+ header: {
|
|
|
+ Authorization,
|
|
|
+ language: locale.value,
|
|
|
+ ...(header as UTSJSONObject)
|
|
|
+ },
|
|
|
+ timeout,
|
|
|
+
|
|
|
+ success(res) {
|
|
|
+ console.log(res);
|
|
|
+
|
|
|
+ // 401 无权限
|
|
|
+ if (res.statusCode == 401) {
|
|
|
+ user.logout();
|
|
|
+ reject({ message: t("无权限") } as Response);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 502 服务异常
|
|
|
+ else if (res.statusCode == 502) {
|
|
|
+ reject({
|
|
|
+ message: t("服务异常")
|
|
|
+ } as Response);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 404 未找到
|
|
|
+ else if (res.statusCode == 404) {
|
|
|
+ return reject({
|
|
|
+ message: `[404] ${url}`
|
|
|
+ } as Response);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 200 正常响应
|
|
|
+ else if (res.statusCode == 0 || res.statusCode == 200) {
|
|
|
+ if (res.data == null) {
|
|
|
+ resolve(null);
|
|
|
+ } else if (!isObject(res.data as any)) {
|
|
|
+ resolve(res.data);
|
|
|
+ } else {
|
|
|
+ // 解析响应数据
|
|
|
+ const { code, message, data } = parse<Response>(
|
|
|
+ res.data ?? { code: 0 }
|
|
|
+ )!;
|
|
|
+
|
|
|
+ switch (code) {
|
|
|
+ case 1000:
|
|
|
+ resolve(data);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ reject({ message, code } as Response);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ reject({ message: t("服务异常") } as Response);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 网络请求失败
|
|
|
+ fail(err) {
|
|
|
+ reject({ message: err.errMsg } as Response);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ };
|
|
|
+ console.log(2222);
|
|
|
+ next();
|
|
|
+ // 非刷新token接口才进行token有效性校验
|
|
|
+ if (!options.url.includes("/refreshToken")) {
|
|
|
+ if (!isNull(Authorization)) {
|
|
|
+ // 判断token是否过期
|
|
|
+ // if (storage.isExpired("token")) {
|
|
|
+ // // 判断refreshToken是否过期
|
|
|
+ // if (storage.isExpired("refreshToken")) {
|
|
|
+ // // 刷新token也过期,直接退出登录
|
|
|
+ // user.logout();
|
|
|
+ // return;
|
|
|
+ // }
|
|
|
+
|
|
|
+ // // 如果当前没有在刷新token,则发起刷新
|
|
|
+ // if (!isRefreshing) {
|
|
|
+ // isRefreshing = true;
|
|
|
+ // user.refreshToken()
|
|
|
+ // .then((token) => {
|
|
|
+ // // 刷新成功后,执行队列中的请求
|
|
|
+ // requests.forEach((cb) => cb(token));
|
|
|
+ // requests = [];
|
|
|
+ // isRefreshing = false;
|
|
|
+ // })
|
|
|
+ // .catch((err) => {
|
|
|
+ // reject(err);
|
|
|
+ // user.logout();
|
|
|
+ // });
|
|
|
+ // }
|
|
|
+
|
|
|
+ // // 将当前请求加入队列,等待token刷新后再执行
|
|
|
+ // new Promise((resolve) => {
|
|
|
+ // requests.push((token: string) => {
|
|
|
+ // // 重新设置token
|
|
|
+ // Authorization = token;
|
|
|
+ // next();
|
|
|
+ // resolve(true);
|
|
|
+ // });
|
|
|
+ // });
|
|
|
+ // // 此处return,等待token刷新
|
|
|
+ // return;
|
|
|
+ // }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // token有效,直接发起请求
|
|
|
+ // next();
|
|
|
+ });
|
|
|
+}
|
|
|
+export function useGet<R = any>(url: string, params?: any, config?: RequestOptions): Promise<Response> {
|
|
|
+ const options: RequestOptions = {
|
|
|
+ url,
|
|
|
+ params,
|
|
|
+ method: 'GET',
|
|
|
+ ...config,
|
|
|
+ }
|
|
|
+ return request<R>(options)
|
|
|
+}
|
|
|
+export function usePost<R = any>(url: string, data?: any, config?: RequestOptions): Promise<Response> {
|
|
|
+ const options: RequestOptions = {
|
|
|
+ url,
|
|
|
+ data,
|
|
|
+ method: 'POST',
|
|
|
+ ...config,
|
|
|
+ }
|
|
|
+ return request<R>(options)
|
|
|
+}
|
|
|
+export function usePut<R = any>(url: string, data?: any, config?: RequestOptions): Promise<Response> {
|
|
|
+ const options: RequestOptions = {
|
|
|
+ url,
|
|
|
+ data,
|
|
|
+ method: 'PUT',
|
|
|
+ ...config,
|
|
|
+ }
|
|
|
+ return request<R>(options)
|
|
|
+}
|
|
|
+export function useDelete<R = any>(url: string, data?: any, config?: RequestOptions): Promise<Response> {
|
|
|
+ const options: RequestOptions = {
|
|
|
+ url,
|
|
|
+ data,
|
|
|
+ method: 'DELETE',
|
|
|
+ ...config,
|
|
|
+ }
|
|
|
+ return request<R>(options)
|
|
|
+}
|