(
+ url: string,
+ params?: AxiosRequestConfig,
+ config?: PureHttpRequestConfig
+ ): Promise {
+ return this.request("post", url, params, config);
+ }
+
+ /** 单独抽离的`get`工具函数 */
+ public get(
+ url: string,
+ params?: AxiosRequestConfig,
+ config?: PureHttpRequestConfig
+ ): Promise {
+ return this.request("get", url, params, config);
+ }
+}
+
+export const http = new PureHttp();
diff --git a/sop-admin/sop-admin-frontend/src/utils/http/types.d.ts b/sop-admin/sop-admin-frontend/src/utils/http/types.d.ts
new file mode 100644
index 00000000..ef7c25f3
--- /dev/null
+++ b/sop-admin/sop-admin-frontend/src/utils/http/types.d.ts
@@ -0,0 +1,47 @@
+import type {
+ Method,
+ AxiosError,
+ AxiosResponse,
+ AxiosRequestConfig
+} from "axios";
+
+export type resultType = {
+ accessToken?: string;
+};
+
+export type RequestMethods = Extract<
+ Method,
+ "get" | "post" | "put" | "delete" | "patch" | "option" | "head"
+>;
+
+export interface PureHttpError extends AxiosError {
+ isCancelRequest?: boolean;
+}
+
+export interface PureHttpResponse extends AxiosResponse {
+ config: PureHttpRequestConfig;
+}
+
+export interface PureHttpRequestConfig extends AxiosRequestConfig {
+ beforeRequestCallback?: (request: PureHttpRequestConfig) => void;
+ beforeResponseCallback?: (response: PureHttpResponse) => void;
+}
+
+export default class PureHttp {
+ request(
+ method: RequestMethods,
+ url: string,
+ param?: AxiosRequestConfig,
+ axiosConfig?: PureHttpRequestConfig
+ ): Promise;
+ post(
+ url: string,
+ params?: P,
+ config?: PureHttpRequestConfig
+ ): Promise;
+ get(
+ url: string,
+ params?: P,
+ config?: PureHttpRequestConfig
+ ): Promise;
+}
diff --git a/sop-admin/sop-admin-frontend/src/utils/index.ts b/sop-admin/sop-admin-frontend/src/utils/index.ts
deleted file mode 100644
index 197bab31..00000000
--- a/sop-admin/sop-admin-frontend/src/utils/index.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-type TargetContext = '_self' | '_parent' | '_blank' | '_top';
-
-export const openWindow = (
- url: string,
- opts?: { target?: TargetContext; [key: string]: any }
-) => {
- const { target = '_blank', ...others } = opts || {};
- window.open(
- url,
- target,
- Object.entries(others)
- .reduce((preValue: string[], curValue) => {
- const [key, value] = curValue;
- return [...preValue, `${key}=${value}`];
- }, [])
- .join(',')
- );
-};
-
-export const regexUrl = new RegExp(
- '^(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$',
- 'i'
-);
-
-export default null;
diff --git a/sop-admin/sop-admin-frontend/src/utils/is.ts b/sop-admin/sop-admin-frontend/src/utils/is.ts
deleted file mode 100644
index 99deea81..00000000
--- a/sop-admin/sop-admin-frontend/src/utils/is.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-const opt = Object.prototype.toString;
-
-export function isArray(obj: any): obj is any[] {
- return opt.call(obj) === '[object Array]';
-}
-
-export function isObject(obj: any): obj is { [key: string]: any } {
- return opt.call(obj) === '[object Object]';
-}
-
-export function isString(obj: any): obj is string {
- return opt.call(obj) === '[object String]';
-}
-
-export function isNumber(obj: any): obj is number {
- return opt.call(obj) === '[object Number]' && obj === obj; // eslint-disable-line
-}
-
-export function isRegExp(obj: any) {
- return opt.call(obj) === '[object RegExp]';
-}
-
-export function isFile(obj: any): obj is File {
- return opt.call(obj) === '[object File]';
-}
-
-export function isBlob(obj: any): obj is Blob {
- return opt.call(obj) === '[object Blob]';
-}
-
-export function isUndefined(obj: any): obj is undefined {
- return obj === undefined;
-}
-
-export function isNull(obj: any): obj is null {
- return obj === null;
-}
-
-export function isFunction(obj: any): obj is (...args: any[]) => any {
- return typeof obj === 'function';
-}
-
-export function isEmptyObject(obj: any): boolean {
- return isObject(obj) && Object.keys(obj).length === 0;
-}
-
-export function isExist(obj: any): boolean {
- return obj || obj === 0;
-}
-
-export function isWindow(el: any): el is Window {
- return el === window;
-}
diff --git a/sop-admin/sop-admin-frontend/src/utils/localforage/index.ts b/sop-admin/sop-admin-frontend/src/utils/localforage/index.ts
new file mode 100644
index 00000000..013545fb
--- /dev/null
+++ b/sop-admin/sop-admin-frontend/src/utils/localforage/index.ts
@@ -0,0 +1,109 @@
+import forage from "localforage";
+import type { LocalForage, ProxyStorage, ExpiresData } from "./types.d";
+
+class StorageProxy implements ProxyStorage {
+ protected storage: LocalForage;
+ constructor(storageModel) {
+ this.storage = storageModel;
+ this.storage.config({
+ // 首选IndexedDB作为第一驱动,不支持IndexedDB会自动降级到localStorage(WebSQL被弃用,详情看https://developer.chrome.com/blog/deprecating-web-sql)
+ driver: [this.storage.INDEXEDDB, this.storage.LOCALSTORAGE],
+ name: "pure-admin"
+ });
+ }
+
+ /**
+ * @description 将对应键名的数据保存到离线仓库
+ * @param k 键名
+ * @param v 键值
+ * @param m 缓存时间(单位`分`,默认`0`分钟,永久缓存)
+ */
+ public async setItem(k: string, v: T, m = 0): Promise {
+ return new Promise((resolve, reject) => {
+ this.storage
+ .setItem(k, {
+ data: v,
+ expires: m ? new Date().getTime() + m * 60 * 1000 : 0
+ })
+ .then(value => {
+ resolve(value.data);
+ })
+ .catch(err => {
+ reject(err);
+ });
+ });
+ }
+
+ /**
+ * @description 从离线仓库中获取对应键名的值
+ * @param k 键名
+ */
+ public async getItem(k: string): Promise {
+ return new Promise((resolve, reject) => {
+ this.storage
+ .getItem(k)
+ .then((value: ExpiresData) => {
+ value && (value.expires > new Date().getTime() || value.expires === 0)
+ ? resolve(value.data)
+ : resolve(null);
+ })
+ .catch(err => {
+ reject(err);
+ });
+ });
+ }
+
+ /**
+ * @description 从离线仓库中删除对应键名的值
+ * @param k 键名
+ */
+ public async removeItem(k: string) {
+ return new Promise((resolve, reject) => {
+ this.storage
+ .removeItem(k)
+ .then(() => {
+ resolve();
+ })
+ .catch(err => {
+ reject(err);
+ });
+ });
+ }
+
+ /**
+ * @description 从离线仓库中删除所有的键名,重置数据库
+ */
+ public async clear() {
+ return new Promise((resolve, reject) => {
+ this.storage
+ .clear()
+ .then(() => {
+ resolve();
+ })
+ .catch(err => {
+ reject(err);
+ });
+ });
+ }
+
+ /**
+ * @description 获取数据仓库中所有的key
+ */
+ public async keys() {
+ return new Promise((resolve, reject) => {
+ this.storage
+ .keys()
+ .then(keys => {
+ resolve(keys);
+ })
+ .catch(err => {
+ reject(err);
+ });
+ });
+ }
+}
+
+/**
+ * 二次封装 [localforage](https://localforage.docschina.org/) 支持设置过期时间,提供完整的类型提示
+ */
+export const localForage = () => new StorageProxy(forage);
diff --git a/sop-admin/sop-admin-frontend/src/utils/localforage/types.d.ts b/sop-admin/sop-admin-frontend/src/utils/localforage/types.d.ts
new file mode 100644
index 00000000..b013c5b8
--- /dev/null
+++ b/sop-admin/sop-admin-frontend/src/utils/localforage/types.d.ts
@@ -0,0 +1,166 @@
+// https://github.com/localForage/localForage/blob/master/typings/localforage.d.ts
+
+interface LocalForageDbInstanceOptions {
+ name?: string;
+
+ storeName?: string;
+}
+
+interface LocalForageOptions extends LocalForageDbInstanceOptions {
+ driver?: string | string[];
+
+ size?: number;
+
+ version?: number;
+
+ description?: string;
+}
+
+interface LocalForageDbMethodsCore {
+ getItem(
+ key: string,
+ callback?: (err: any, value: T | null) => void
+ ): Promise;
+
+ setItem(
+ key: string,
+ value: T,
+ callback?: (err: any, value: T) => void
+ ): Promise;
+
+ removeItem(key: string, callback?: (err: any) => void): Promise;
+
+ clear(callback?: (err: any) => void): Promise