|
|
@@ -1,197 +1,217 @@
|
|
|
-import { isDev, ignoreTokens, config } from "@/config";
|
|
|
-import { locale, t } from "../locale";
|
|
|
-import { isNull, isObject, parse, storage } from "../utils";
|
|
|
-import { useStore } from "../store";
|
|
|
-import { useUi } from "@/uni_modules/cool-ui";
|
|
|
-// 请求参数类型定义
|
|
|
-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;
|
|
|
-};
|
|
|
-const ui = useUi();
|
|
|
-// 请求队列(用于等待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(options: RequestOptions): Promise<any | null> {
|
|
|
- let { url, method = "GET", data = {}, header = {}, timeout = 60000 } = options;
|
|
|
-
|
|
|
- const { user } = useStore();
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- // 拼接基础url
|
|
|
- if (!url.startsWith("http")) {
|
|
|
- url = config.baseUrl + url;
|
|
|
- }
|
|
|
- // 开发环境下打印请求信息
|
|
|
- if (isDev) {
|
|
|
- console.log(`[${method}] ${url}`);
|
|
|
- }
|
|
|
- // 获取当前token
|
|
|
- let Authorization: string | null = user.token;
|
|
|
-
|
|
|
- // 如果是忽略token的接口,则不携带token
|
|
|
- if (isIgnoreToken(url)) {
|
|
|
- Authorization = null;
|
|
|
- }
|
|
|
-
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- // 发起请求的实际函数
|
|
|
- const next = () => {
|
|
|
- uni.request({
|
|
|
- url,
|
|
|
- method,
|
|
|
- data,
|
|
|
- header: {
|
|
|
- Authorization,
|
|
|
- language: locale.value,
|
|
|
- ...(header as UTSJSONObject)
|
|
|
- },
|
|
|
- timeout,
|
|
|
-
|
|
|
- success(res) {
|
|
|
- if (isNull(res.data)) {
|
|
|
- res.data = {};
|
|
|
- }
|
|
|
- const { code, message, data } = parse<Response>(
|
|
|
- (res.data as Response)
|
|
|
- )!
|
|
|
-
|
|
|
- // 401 无权限
|
|
|
- if (res.statusCode == 401) {
|
|
|
- user.logout();
|
|
|
- ui.showToast({
|
|
|
- message: "无权限",
|
|
|
- type: "warn",
|
|
|
- })
|
|
|
- reject({ message: t("无权限") } as Response);
|
|
|
- }
|
|
|
-
|
|
|
- // 502 服务异常
|
|
|
- else if (res.statusCode == 502 || res.statusCode == 405) {
|
|
|
- ui.showToast({
|
|
|
- message: message || "服务异常",
|
|
|
- type: "warn",
|
|
|
- })
|
|
|
- reject({
|
|
|
- message: message || t("服务异常")
|
|
|
- } as Response);
|
|
|
- }
|
|
|
-
|
|
|
- // 404 未找到
|
|
|
- else if (res.statusCode == 404) {
|
|
|
- ui.showToast({
|
|
|
- message: `[404] ${url}`,
|
|
|
- type: "warn",
|
|
|
- })
|
|
|
- return reject({
|
|
|
- message: `[404] ${url}`
|
|
|
- } as Response);
|
|
|
- }
|
|
|
-
|
|
|
- // 200 正常响应
|
|
|
- else if (res.statusCode == 200) {
|
|
|
- if (res.data == null) {
|
|
|
- resolve(null);
|
|
|
- } else if (!isObject(res.data as any)) {
|
|
|
- resolve(res.data);
|
|
|
- } else {
|
|
|
- // 解析响应数据
|
|
|
- if (code == 200 || code == 0) {
|
|
|
- resolve(data);
|
|
|
- } else if (code == 1) {
|
|
|
- reject(res.data);
|
|
|
- }
|
|
|
- else {
|
|
|
- ui.showToast({
|
|
|
- message: message ?? t("服务异常"),
|
|
|
- type: "warn",
|
|
|
- })
|
|
|
- reject({ message: message } as Response);
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- ui.showToast({
|
|
|
- message: message || "服务异常",
|
|
|
- type: "warn",
|
|
|
- })
|
|
|
- reject({ message: message || "服务异常" } as Response);
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- // 网络请求失败
|
|
|
- fail(err) {
|
|
|
- reject({ message: err.errMsg } as Response);
|
|
|
- }
|
|
|
- });
|
|
|
- };
|
|
|
-
|
|
|
- next();
|
|
|
- });
|
|
|
-}
|
|
|
-export function useGet(url: string, data?: any, config?: RequestOptions): Promise<any> {
|
|
|
- const options: RequestOptions = {
|
|
|
- url,
|
|
|
- data,
|
|
|
- method: 'GET',
|
|
|
- ...config,
|
|
|
- }
|
|
|
- return request(options)
|
|
|
-}
|
|
|
-export function usePost(url: string, data?: any, config?: RequestOptions): Promise<any> {
|
|
|
- const options: RequestOptions = {
|
|
|
- url,
|
|
|
- data,
|
|
|
- method: 'POST',
|
|
|
- ...config,
|
|
|
- }
|
|
|
- return request(options)
|
|
|
-}
|
|
|
-export function usePut(url: string, data?: any, config?: RequestOptions): Promise<any> {
|
|
|
- const options: RequestOptions = {
|
|
|
- url,
|
|
|
- data,
|
|
|
- method: 'PUT',
|
|
|
- ...config,
|
|
|
- }
|
|
|
- return request(options)
|
|
|
-}
|
|
|
-export function useDelete(url: string, data?: any, config?: RequestOptions): Promise<any> {
|
|
|
- const options: RequestOptions = {
|
|
|
- url,
|
|
|
- data,
|
|
|
- method: 'DELETE',
|
|
|
- ...config,
|
|
|
- }
|
|
|
- return request(options)
|
|
|
+import { isDev, ignoreTokens, config } from "@/config";
|
|
|
+import { locale, t } from "../locale";
|
|
|
+import { isNull, isObject, parse, storage } from "../utils";
|
|
|
+import { useStore } from "../store";
|
|
|
+import { useUi } from "@/uni_modules/cool-ui";
|
|
|
+// 请求参数类型定义
|
|
|
+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;
|
|
|
+};
|
|
|
+const ui = useUi();
|
|
|
+// 请求队列(用于等待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(options: RequestOptions): Promise<any | null> {
|
|
|
+ let { url, method = "GET", data = {}, header = {}, timeout = 60000 } = options;
|
|
|
+
|
|
|
+ const { user } = useStore();
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // 拼接基础url
|
|
|
+ if (!url.startsWith("http")) {
|
|
|
+ url = config.baseUrl + url;
|
|
|
+ }
|
|
|
+ // 开发环境下打印请求信息
|
|
|
+ if (isDev) {
|
|
|
+ console.log(`[${method}] ${url}`);
|
|
|
+ }
|
|
|
+ // 获取当前token
|
|
|
+ let Authorization: string | null = user.token;
|
|
|
+
|
|
|
+ // 如果是忽略token的接口,则不携带token
|
|
|
+ if (isIgnoreToken(url)) {
|
|
|
+ Authorization = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ let isRetry = false;
|
|
|
+ // 发起请求的实际函数
|
|
|
+ function next() {
|
|
|
+ uni.request({
|
|
|
+ url,
|
|
|
+ method,
|
|
|
+ data,
|
|
|
+ header: {
|
|
|
+ Authorization,
|
|
|
+ language: locale.value,
|
|
|
+ ...(header as UTSJSONObject)
|
|
|
+ },
|
|
|
+ timeout,
|
|
|
+
|
|
|
+ success(res) {
|
|
|
+ if (isNull(res.data)) {
|
|
|
+ res.data = {};
|
|
|
+ }
|
|
|
+ const { code, message, data } = parse<Response>(
|
|
|
+ (res.data as Response)
|
|
|
+ )!
|
|
|
+
|
|
|
+ // 401 无权限
|
|
|
+ if (res.statusCode == 401) {
|
|
|
+ // 不对token接口本身做刷新,防止死循环
|
|
|
+ if (!isRetry && url.indexOf('/oauth/token') === -1) {
|
|
|
+ isRetry = true;
|
|
|
+ user.refreshToken()
|
|
|
+ .then(() => {
|
|
|
+ Authorization = user.token;
|
|
|
+ next();
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ user.logout();
|
|
|
+ ui.showToast({
|
|
|
+ message: "无权限",
|
|
|
+ type: "warn",
|
|
|
+ })
|
|
|
+ reject({ message: t("无权限") } as Response);
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 刷新后仍然401,强制登出
|
|
|
+ user.logout();
|
|
|
+ ui.showToast({
|
|
|
+ message: "无权限",
|
|
|
+ type: "warn",
|
|
|
+ })
|
|
|
+ reject({ message: t("无权限") } as Response);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 502 服务异常
|
|
|
+ else if (res.statusCode == 502 || res.statusCode == 405) {
|
|
|
+ ui.showToast({
|
|
|
+ message: message || "服务异常",
|
|
|
+ type: "warn",
|
|
|
+ })
|
|
|
+ reject({
|
|
|
+ message: message || t("服务异常")
|
|
|
+ } as Response);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 404 未找到
|
|
|
+ else if (res.statusCode == 404) {
|
|
|
+ ui.showToast({
|
|
|
+ message: `[404] ${url}`,
|
|
|
+ type: "warn",
|
|
|
+ })
|
|
|
+ return reject({
|
|
|
+ message: `[404] ${url}`
|
|
|
+ } as Response);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 200 正常响应
|
|
|
+ else if (res.statusCode == 200) {
|
|
|
+ if (res.data == null) {
|
|
|
+ resolve(null);
|
|
|
+ } else if (!isObject(res.data as any)) {
|
|
|
+ resolve(res.data);
|
|
|
+ } else {
|
|
|
+ // 解析响应数据
|
|
|
+ if (code == 200 || code == 0) {
|
|
|
+ resolve(data);
|
|
|
+ } else if (code == 1) {
|
|
|
+ reject(res.data);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ ui.showToast({
|
|
|
+ message: message ?? t("服务异常"),
|
|
|
+ type: "warn",
|
|
|
+ })
|
|
|
+ reject({ message: message } as Response);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ ui.showToast({
|
|
|
+ message: message || "服务异常",
|
|
|
+ type: "warn",
|
|
|
+ })
|
|
|
+ reject({ message: message || "服务异常" } as Response);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 网络请求失败
|
|
|
+ fail(err) {
|
|
|
+ reject({ message: err.errMsg } as Response);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ next();
|
|
|
+ });
|
|
|
+}
|
|
|
+export function useGet(url: string, data?: any, config?: RequestOptions): Promise<any> {
|
|
|
+ const options: RequestOptions = {
|
|
|
+ url,
|
|
|
+ data,
|
|
|
+ method: 'GET',
|
|
|
+ ...config,
|
|
|
+ }
|
|
|
+ return request(options)
|
|
|
+}
|
|
|
+export function usePost(url: string, data?: any, config?: RequestOptions): Promise<any> {
|
|
|
+ const options: RequestOptions = {
|
|
|
+ url,
|
|
|
+ data,
|
|
|
+ method: 'POST',
|
|
|
+ ...config,
|
|
|
+ }
|
|
|
+ return request(options)
|
|
|
+}
|
|
|
+export function usePut(url: string, data?: any, config?: RequestOptions): Promise<any> {
|
|
|
+ const options: RequestOptions = {
|
|
|
+ url,
|
|
|
+ data,
|
|
|
+ method: 'PUT',
|
|
|
+ ...config,
|
|
|
+ }
|
|
|
+ return request(options)
|
|
|
+}
|
|
|
+export function useDelete(url: string, data?: any, config?: RequestOptions): Promise<any> {
|
|
|
+ const options: RequestOptions = {
|
|
|
+ url,
|
|
|
+ data,
|
|
|
+ method: 'DELETE',
|
|
|
+ ...config,
|
|
|
+ }
|
|
|
+ return request(options)
|
|
|
}
|