xiaoxian521
3 years ago
40 changed files with 671 additions and 667 deletions
-
14.env
-
20.env.development
-
7.env.production
-
6.eslintrc.js
-
4README.en-US.md
-
4README.md
-
25build/index.ts
-
19build/proxy.ts
-
4package.json
-
89pnpm-lock.yaml
-
4src/api/routes.ts
-
26src/api/user.ts
-
BINsrc/assets/avatars.jpg
-
8src/config/index.ts
-
2src/layout/components/appMain.vue
-
17src/layout/components/navbar.vue
-
2src/layout/components/sidebar/breadCrumb.vue
-
13src/layout/components/sidebar/horizontal.vue
-
2src/layout/components/sidebar/sidebarItem.vue
-
3src/layout/components/tag/index.vue
-
24src/plugins/i18n/index.ts
-
32src/router/index.ts
-
16src/store/modules/app.ts
-
15src/store/modules/multiTags.ts
-
9src/store/modules/settings.ts
-
29src/store/modules/types.ts
-
84src/store/modules/user.ts
-
43src/utils/auth.ts
-
25src/utils/http/README.md
-
32src/utils/http/config.ts
-
236src/utils/http/core.ts
-
168src/utils/http/index.ts
-
45src/utils/http/types.d.ts
-
29src/utils/http/utils.ts
-
19src/utils/i18n.ts
-
53src/utils/storage/cookie.ts
-
93src/utils/storage/db.ts
-
16types/global.d.ts
-
55vite.config.ts
@ -1,14 +1,2 @@ |
|||
# port |
|||
# 项目本地运行端口号 |
|||
VITE_PORT = 8848 |
|||
# title |
|||
VITE_TITLE = vue-pure-admin |
|||
# version |
|||
VITE_VERSION = 2.6.0 |
|||
# open |
|||
VITE_OPEN = false |
|||
|
|||
# public path |
|||
VITE_PUBLIC_PATH = / |
|||
|
|||
# Cross-domain proxy, you can configure multiple |
|||
VITE_PROXY = [ ["/api", "http://127.0.0.1:3000" ] ] |
@ -1,14 +1,12 @@ |
|||
# port |
|||
# 项目本地运行端口号 |
|||
VITE_PORT = 8848 |
|||
# title |
|||
VITE_TITLE = vue-pure-admin |
|||
# version |
|||
VITE_VERSION = 2.6.0 |
|||
# open |
|||
VITE_OPEN = false |
|||
|
|||
# public path |
|||
|
|||
# 开发环境读取配置文件路径 |
|||
VITE_PUBLIC_PATH = / |
|||
|
|||
# Cross-domain proxy, you can configure multiple |
|||
VITE_PROXY = [ ["/api", "http://127.0.0.1:3000" ] ] |
|||
# 开发环境代理 |
|||
VITE_PROXY_DOMAIN = /api |
|||
|
|||
# 开发环境后端地址 |
|||
VITE_PROXY_DOMAIN_REAL = "http://127.0.0.1:3000" |
|||
|
@ -1,2 +1,5 @@ |
|||
# public path |
|||
VITE_PUBLIC_PATH = /manages/ |
|||
# 线上环境项目打包路径 |
|||
VITE_PUBLIC_PATH = / |
|||
|
|||
# 线上环境后端地址 |
|||
VITE_PROXY_DOMAIN_REAL = "" |
@ -1,19 +0,0 @@ |
|||
type ProxyItem = [string, string]; |
|||
|
|||
type ProxyList = ProxyItem[]; |
|||
|
|||
const regExps = (value: string, reg: string): string => { |
|||
return value.replace(new RegExp(reg, "g"), ""); |
|||
}; |
|||
|
|||
export function createProxy(list: ProxyList = []) { |
|||
const ret: any = {}; |
|||
for (const [prefix, target] of list) { |
|||
ret[prefix] = { |
|||
target: target, |
|||
changeOrigin: true, |
|||
rewrite: (path: string) => regExps(path, prefix) |
|||
}; |
|||
} |
|||
return ret; |
|||
} |
@ -1,5 +1,5 @@ |
|||
import { http } from "../utils/http"; |
|||
|
|||
export const getAsyncRoutes = (data?: object) => { |
|||
return http.request("get", "/getAsyncRoutes", data); |
|||
export const getAsyncRoutes = (params?: object) => { |
|||
return http.request("get", "/getAsyncRoutes", { params }); |
|||
}; |
@ -0,0 +1,26 @@ |
|||
import { http } from "../utils/http"; |
|||
|
|||
interface userType extends Promise<any> { |
|||
svg?: string; |
|||
code?: number; |
|||
info?: object; |
|||
} |
|||
|
|||
// 获取验证码
|
|||
export const getVerify = (): userType => { |
|||
return http.request("get", "/captcha"); |
|||
}; |
|||
|
|||
// 登录
|
|||
export const getLogin = (data: object) => { |
|||
return http.request("post", "/login", { data }); |
|||
}; |
|||
|
|||
// 刷新token
|
|||
export const refreshToken = (data: object) => { |
|||
return http.request("post", "/refreshToken", { data }); |
|||
}; |
|||
|
|||
// export const searchVague = (data: object) => {
|
|||
// return http.request("post", "/searchVague", { data });
|
|||
// };
|
After Width: 400 | Height: 400 | Size: 23 KiB |
@ -0,0 +1,84 @@ |
|||
import { defineStore } from "pinia"; |
|||
import { store } from "/@/store"; |
|||
import { userType } from "./types"; |
|||
import { useRouter } from "vue-router"; |
|||
import { getLogin, refreshToken } from "/@/api/user"; |
|||
import { storageLocal, storageSession } from "/@/utils/storage"; |
|||
import { getToken, setToken, removeToken } from "/@/utils/auth"; |
|||
import { useMultiTagsStoreHook } from "/@/store/modules/multiTags"; |
|||
|
|||
const data = getToken(); |
|||
let token = ""; |
|||
let name = ""; |
|||
if (data) { |
|||
const dataJson = JSON.parse(data); |
|||
if (dataJson) { |
|||
token = dataJson?.accessToken; |
|||
name = dataJson?.name ?? "admin"; |
|||
} |
|||
} |
|||
|
|||
export const useUserStore = defineStore({ |
|||
id: "pure-user", |
|||
state: (): userType => ({ |
|||
token, |
|||
name |
|||
}), |
|||
actions: { |
|||
SET_TOKEN(token) { |
|||
this.token = token; |
|||
}, |
|||
SET_NAME(name) { |
|||
this.name = name; |
|||
}, |
|||
// 登入
|
|||
async loginByUsername(data) { |
|||
return new Promise<void>((resolve, reject) => { |
|||
getLogin(data) |
|||
.then(data => { |
|||
if (data) { |
|||
setToken(data); |
|||
resolve(); |
|||
} |
|||
}) |
|||
.catch(error => { |
|||
reject(error); |
|||
}); |
|||
}); |
|||
}, |
|||
// 登出 清空缓存
|
|||
logOut() { |
|||
this.token = ""; |
|||
this.name = ""; |
|||
removeToken(); |
|||
storageLocal.clear(); |
|||
storageSession.clear(); |
|||
useMultiTagsStoreHook().handleTags("equal", [ |
|||
{ |
|||
path: "/welcome", |
|||
parentPath: "/", |
|||
meta: { |
|||
title: "message.hshome", |
|||
icon: "el-icon-s-home", |
|||
i18n: true, |
|||
showLink: true |
|||
} |
|||
} |
|||
]); |
|||
useRouter().push("/login"); |
|||
}, |
|||
// 刷新token
|
|||
async refreshToken(data) { |
|||
return refreshToken(data).then(data => { |
|||
if (data) { |
|||
setToken(data); |
|||
return data; |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
}); |
|||
|
|||
export function useUserStoreHook() { |
|||
return useUserStore(store); |
|||
} |
@ -0,0 +1,43 @@ |
|||
import Cookies from "js-cookie"; |
|||
import { useUserStoreHook } from "/@/store/modules/user"; |
|||
|
|||
const TokenKey = "authorized-token"; |
|||
|
|||
type paramsMapType = { |
|||
name: string; |
|||
expires: number; |
|||
accessToken: string; |
|||
}; |
|||
|
|||
// 获取token
|
|||
export function getToken() { |
|||
// 此处与TokenKey相同,此写法解决初始化时Cookies中不存在TokenKey报错
|
|||
return Cookies.get("authorized-token"); |
|||
} |
|||
|
|||
// 设置token以及过期时间(cookies、sessionStorage各一份)
|
|||
// 后端需要将用户信息和token以及过期时间都返回给前端,过期时间主要用于刷新token
|
|||
export function setToken(data) { |
|||
const { accessToken, expires, name } = data; |
|||
// 提取关键信息进行存储
|
|||
const paramsMap: paramsMapType = { |
|||
name, |
|||
expires: Date.now() + parseInt(expires), |
|||
accessToken |
|||
}; |
|||
const dataString = JSON.stringify(paramsMap); |
|||
useUserStoreHook().SET_TOKEN(accessToken); |
|||
useUserStoreHook().SET_NAME(name); |
|||
expires > 0 |
|||
? Cookies.set(TokenKey, dataString, { |
|||
expires: expires / 86400000 |
|||
}) |
|||
: Cookies.set(TokenKey, dataString); |
|||
sessionStorage.setItem(TokenKey, dataString); |
|||
} |
|||
|
|||
// 删除token
|
|||
export function removeToken() { |
|||
Cookies.remove(TokenKey); |
|||
sessionStorage.removeItem(TokenKey); |
|||
} |
@ -0,0 +1,25 @@ |
|||
## 用法 |
|||
|
|||
### Get 请求 |
|||
|
|||
``` |
|||
import { http } from "/@/utils/http"; |
|||
|
|||
// params传参 |
|||
http.request('get', '/xxx', { params: param }); |
|||
|
|||
// url拼接传参 |
|||
http.request('get', '/xxx?message=' + msg); |
|||
``` |
|||
|
|||
### Post 请求 |
|||
|
|||
``` |
|||
import { http } from "/@/utils/http"; |
|||
|
|||
// params传参 |
|||
http.request('get', '/xxx', { params: param }); |
|||
|
|||
// data传参 |
|||
http.request('get', '/xxx', { data: param }); |
|||
``` |
@ -1,32 +0,0 @@ |
|||
import { AxiosRequestConfig } from "axios"; |
|||
import { excludeProps } from "./utils"; |
|||
/** |
|||
* 默认配置 |
|||
*/ |
|||
export const defaultConfig: AxiosRequestConfig = { |
|||
baseURL: "", |
|||
//10秒超时
|
|||
timeout: 10000, |
|||
headers: { |
|||
Accept: "application/json, text/plain, */*", |
|||
"Content-Type": "application/json", |
|||
"X-Requested-With": "XMLHttpRequest" |
|||
} |
|||
}; |
|||
|
|||
export function genConfig(config?: AxiosRequestConfig): AxiosRequestConfig { |
|||
if (!config) { |
|||
return defaultConfig; |
|||
} |
|||
|
|||
const { headers } = config; |
|||
if (headers && typeof headers === "object") { |
|||
defaultConfig.headers = { |
|||
...defaultConfig.headers, |
|||
...headers |
|||
}; |
|||
} |
|||
return { ...excludeProps(config!, "headers"), ...defaultConfig }; |
|||
} |
|||
|
|||
export const METHODS = ["post", "get", "put", "delete", "option", "patch"]; |
@ -1,236 +0,0 @@ |
|||
import Axios, { |
|||
AxiosRequestConfig, |
|||
CancelTokenStatic, |
|||
AxiosInstance |
|||
} from "axios"; |
|||
|
|||
import NProgress from "../progress"; |
|||
|
|||
import { genConfig } from "./config"; |
|||
|
|||
import { transformConfigByMethod } from "./utils"; |
|||
|
|||
import { |
|||
cancelTokenType, |
|||
RequestMethods, |
|||
EnclosureHttpRequestConfig, |
|||
EnclosureHttpResoponse, |
|||
EnclosureHttpError |
|||
} from "./types.d"; |
|||
|
|||
class EnclosureHttp { |
|||
constructor() { |
|||
this.httpInterceptorsRequest(); |
|||
this.httpInterceptorsResponse(); |
|||
} |
|||
// 初始化配置对象
|
|||
private static initConfig: EnclosureHttpRequestConfig = {}; |
|||
|
|||
// 保存当前Axios实例对象
|
|||
private static axiosInstance: AxiosInstance = Axios.create(genConfig()); |
|||
|
|||
// 保存 EnclosureHttp实例
|
|||
private static EnclosureHttpInstance: EnclosureHttp; |
|||
|
|||
// axios取消对象
|
|||
private CancelToken: CancelTokenStatic = Axios.CancelToken; |
|||
|
|||
// 取消的凭证数组
|
|||
private sourceTokenList: Array<cancelTokenType> = []; |
|||
|
|||
// 记录当前这一次cancelToken的key
|
|||
private currentCancelTokenKey = ""; |
|||
|
|||
public get cancelTokenList(): Array<cancelTokenType> { |
|||
return this.sourceTokenList; |
|||
} |
|||
|
|||
// eslint-disable-next-line class-methods-use-this
|
|||
public set cancelTokenList(value) { |
|||
throw new Error("cancelTokenList不允许赋值"); |
|||
} |
|||
|
|||
/** |
|||
* @description 私有构造不允许实例化 |
|||
* @returns void 0 |
|||
*/ |
|||
// constructor() {}
|
|||
|
|||
/** |
|||
* @description 生成唯一取消key |
|||
* @param config axios配置 |
|||
* @returns string |
|||
*/ |
|||
// eslint-disable-next-line class-methods-use-this
|
|||
private static genUniqueKey(config: EnclosureHttpRequestConfig): string { |
|||
return `${config.url}--${JSON.stringify(config.data)}`; |
|||
} |
|||
|
|||
/** |
|||
* @description 取消重复请求 |
|||
* @returns void 0 |
|||
*/ |
|||
private cancelRepeatRequest(): void { |
|||
const temp: { [key: string]: boolean } = {}; |
|||
|
|||
this.sourceTokenList = this.sourceTokenList.reduce<Array<cancelTokenType>>( |
|||
(res: Array<cancelTokenType>, cancelToken: cancelTokenType) => { |
|||
const { cancelKey, cancelExecutor } = cancelToken; |
|||
if (!temp[cancelKey]) { |
|||
temp[cancelKey] = true; |
|||
res.push(cancelToken); |
|||
} else { |
|||
cancelExecutor(); |
|||
} |
|||
return res; |
|||
}, |
|||
[] |
|||
); |
|||
} |
|||
|
|||
/** |
|||
* @description 删除指定的CancelToken |
|||
* @returns void 0 |
|||
*/ |
|||
private deleteCancelTokenByCancelKey(cancelKey: string): void { |
|||
this.sourceTokenList = |
|||
this.sourceTokenList.length < 1 |
|||
? this.sourceTokenList.filter( |
|||
cancelToken => cancelToken.cancelKey !== cancelKey |
|||
) |
|||
: []; |
|||
} |
|||
|
|||
/** |
|||
* @description 拦截请求 |
|||
* @returns void 0 |
|||
*/ |
|||
|
|||
private httpInterceptorsRequest(): void { |
|||
EnclosureHttp.axiosInstance.interceptors.request.use( |
|||
(config: EnclosureHttpRequestConfig) => { |
|||
const $config = config; |
|||
NProgress.start(); // 每次切换页面时,调用进度条
|
|||
const cancelKey = EnclosureHttp.genUniqueKey($config); |
|||
$config.cancelToken = new this.CancelToken( |
|||
(cancelExecutor: (cancel: any) => void) => { |
|||
this.sourceTokenList.push({ cancelKey, cancelExecutor }); |
|||
} |
|||
); |
|||
this.cancelRepeatRequest(); |
|||
this.currentCancelTokenKey = cancelKey; |
|||
// 优先判断post/get等方法是否传入回掉,否则执行初始化设置等回掉
|
|||
if (typeof config.beforeRequestCallback === "function") { |
|||
config.beforeRequestCallback($config); |
|||
return $config; |
|||
} |
|||
if (EnclosureHttp.initConfig.beforeRequestCallback) { |
|||
EnclosureHttp.initConfig.beforeRequestCallback($config); |
|||
return $config; |
|||
} |
|||
return $config; |
|||
}, |
|||
error => { |
|||
return Promise.reject(error); |
|||
} |
|||
); |
|||
} |
|||
|
|||
/** |
|||
* @description 清空当前cancelTokenList |
|||
* @returns void 0 |
|||
*/ |
|||
public clearCancelTokenList(): void { |
|||
this.sourceTokenList.length = 0; |
|||
} |
|||
|
|||
/** |
|||
* @description 拦截响应 |
|||
* @returns void 0 |
|||
*/ |
|||
private httpInterceptorsResponse(): void { |
|||
const instance = EnclosureHttp.axiosInstance; |
|||
instance.interceptors.response.use( |
|||
(response: EnclosureHttpResoponse) => { |
|||
const $config = response.config; |
|||
// 请求每次成功一次就删除当前canceltoken标记
|
|||
const cancelKey = EnclosureHttp.genUniqueKey($config); |
|||
this.deleteCancelTokenByCancelKey(cancelKey); |
|||
|
|||
NProgress.done(); |
|||
// 优先判断post/get等方法是否传入回掉,否则执行初始化设置等回掉
|
|||
if (typeof $config.beforeResponseCallback === "function") { |
|||
$config.beforeResponseCallback(response); |
|||
return response.data; |
|||
} |
|||
if (EnclosureHttp.initConfig.beforeResponseCallback) { |
|||
EnclosureHttp.initConfig.beforeResponseCallback(response); |
|||
return response.data; |
|||
} |
|||
return response.data; |
|||
}, |
|||
(error: EnclosureHttpError) => { |
|||
const $error = error; |
|||
// 判断当前的请求中是否在 取消token数组理存在,如果存在则移除(单次请求流程)
|
|||
if (this.currentCancelTokenKey) { |
|||
const haskey = this.sourceTokenList.filter( |
|||
cancelToken => cancelToken.cancelKey === this.currentCancelTokenKey |
|||
).length; |
|||
if (haskey) { |
|||
this.sourceTokenList = this.sourceTokenList.filter( |
|||
cancelToken => |
|||
cancelToken.cancelKey !== this.currentCancelTokenKey |
|||
); |
|||
this.currentCancelTokenKey = ""; |
|||
} |
|||
} |
|||
$error.isCancelRequest = Axios.isCancel($error); |
|||
NProgress.done(); |
|||
// 所有的响应异常 区分来源为取消请求/非取消请求
|
|||
return Promise.reject($error); |
|||
} |
|||
); |
|||
} |
|||
|
|||
public request<T>( |
|||
method: RequestMethods, |
|||
url: string, |
|||
param?: AxiosRequestConfig, |
|||
axiosConfig?: EnclosureHttpRequestConfig |
|||
): Promise<T> { |
|||
const config = transformConfigByMethod(param, { |
|||
method, |
|||
url, |
|||
...axiosConfig |
|||
} as EnclosureHttpRequestConfig); |
|||
// 单独处理自定义请求/响应回掉
|
|||
return new Promise((resolve, reject) => { |
|||
EnclosureHttp.axiosInstance |
|||
.request(config) |
|||
.then((response: undefined) => { |
|||
resolve(response); |
|||
}) |
|||
.catch((error: any) => { |
|||
reject(error); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
public post<T>( |
|||
url: string, |
|||
params?: T, |
|||
config?: EnclosureHttpRequestConfig |
|||
): Promise<T> { |
|||
return this.request<T>("post", url, params, config); |
|||
} |
|||
|
|||
public get<T>( |
|||
url: string, |
|||
params?: T, |
|||
config?: EnclosureHttpRequestConfig |
|||
): Promise<T> { |
|||
return this.request<T>("get", url, params, config); |
|||
} |
|||
} |
|||
|
|||
export default EnclosureHttp; |
@ -1,2 +1,166 @@ |
|||
import EnclosureHttp from "./core"; |
|||
export const http = new EnclosureHttp(); |
|||
import Axios, { AxiosInstance, AxiosRequestConfig } from "axios"; |
|||
import { |
|||
resultType, |
|||
PureHttpError, |
|||
RequestMethods, |
|||
PureHttpResoponse, |
|||
PureHttpRequestConfig |
|||
} from "./types.d"; |
|||
import qs from "qs"; |
|||
import NProgress from "../progress"; |
|||
// import { loadEnv } from "@build/index";
|
|||
import { getToken } from "/@/utils/auth"; |
|||
import { useUserStoreHook } from "/@/store/modules/user"; |
|||
|
|||
// 加载环境变量 VITE_PROXY_DOMAIN(开发环境) VITE_PROXY_DOMAIN_REAL(打包后的线上环境)
|
|||
// const { VITE_PROXY_DOMAIN, VITE_PROXY_DOMAIN_REAL } = loadEnv();
|
|||
|
|||
// 相关配置请参考:www.axios-js.com/zh-cn/docs/#axios-request-config-1
|
|||
const defaultConfig: AxiosRequestConfig = { |
|||
// baseURL:
|
|||
// process.env.NODE_ENV === "production"
|
|||
// ? VITE_PROXY_DOMAIN_REAL
|
|||
// : VITE_PROXY_DOMAIN,
|
|||
// 当前使用mock模拟请求,将baseURL制空,如果你的环境用到了http请求,请删除下面的baseURL启用上面的baseURL,并将11行、16行代码注释取消
|
|||
baseURL: "", |
|||
timeout: 10000, |
|||
headers: { |
|||
Accept: "application/json, text/plain, */*", |
|||
"Content-Type": "application/json", |
|||
"X-Requested-With": "XMLHttpRequest" |
|||
}, |
|||
// 数组格式参数序列化
|
|||
paramsSerializer: params => qs.stringify(params, { indices: false }) |
|||
}; |
|||
|
|||
class PureHttp { |
|||
constructor() { |
|||
this.httpInterceptorsRequest(); |
|||
this.httpInterceptorsResponse(); |
|||
} |
|||
// 初始化配置对象
|
|||
private static initConfig: PureHttpRequestConfig = {}; |
|||
|
|||
// 保存当前Axios实例对象
|
|||
private static axiosInstance: AxiosInstance = Axios.create(defaultConfig); |
|||
|
|||
// 请求拦截
|
|||
private httpInterceptorsRequest(): void { |
|||
PureHttp.axiosInstance.interceptors.request.use( |
|||
(config: PureHttpRequestConfig) => { |
|||
const $config = config; |
|||
// 开启进度条动画
|
|||
NProgress.start(); |
|||
// 优先判断post/get等方法是否传入回掉,否则执行初始化设置等回掉
|
|||
if (typeof config.beforeRequestCallback === "function") { |
|||
config.beforeRequestCallback($config); |
|||
return $config; |
|||
} |
|||
if (PureHttp.initConfig.beforeRequestCallback) { |
|||
PureHttp.initConfig.beforeRequestCallback($config); |
|||
return $config; |
|||
} |
|||
const token = getToken(); |
|||
if (token) { |
|||
const data = JSON.parse(token); |
|||
const now = new Date().getTime(); |
|||
const expired = parseInt(data.expires) - now <= 0; |
|||
if (expired) { |
|||
// token过期刷新
|
|||
useUserStoreHook() |
|||
.refreshToken(data) |
|||
.then((res: resultType) => { |
|||
config.headers["Authorization"] = "Bearer " + res.accessToken; |
|||
return $config; |
|||
}); |
|||
} else { |
|||
config.headers["Authorization"] = "Bearer " + data.accessToken; |
|||
return $config; |
|||
} |
|||
} else { |
|||
return $config; |
|||
} |
|||
}, |
|||
error => { |
|||
return Promise.reject(error); |
|||
} |
|||
); |
|||
} |
|||
|
|||
// 响应拦截
|
|||
private httpInterceptorsResponse(): void { |
|||
const instance = PureHttp.axiosInstance; |
|||
instance.interceptors.response.use( |
|||
(response: PureHttpResoponse) => { |
|||
const $config = response.config; |
|||
// 关闭进度条动画
|
|||
NProgress.done(); |
|||
// 优先判断post/get等方法是否传入回掉,否则执行初始化设置等回掉
|
|||
if (typeof $config.beforeResponseCallback === "function") { |
|||
$config.beforeResponseCallback(response); |
|||
return response.data; |
|||
} |
|||
if (PureHttp.initConfig.beforeResponseCallback) { |
|||
PureHttp.initConfig.beforeResponseCallback(response); |
|||
return response.data; |
|||
} |
|||
return response.data; |
|||
}, |
|||
(error: PureHttpError) => { |
|||
const $error = error; |
|||
$error.isCancelRequest = Axios.isCancel($error); |
|||
// 关闭进度条动画
|
|||
NProgress.done(); |
|||
// 所有的响应异常 区分来源为取消请求/非取消请求
|
|||
return Promise.reject($error); |
|||
} |
|||
); |
|||
} |
|||
|
|||
// 通用请求工具函数
|
|||
public request<T>( |
|||
method: RequestMethods, |
|||
url: string, |
|||
param?: AxiosRequestConfig, |
|||
axiosConfig?: PureHttpRequestConfig |
|||
): Promise<T> { |
|||
const config = { |
|||
method, |
|||
url, |
|||
...param, |
|||
...axiosConfig |
|||
} as PureHttpRequestConfig; |
|||
|
|||
// 单独处理自定义请求/响应回掉
|
|||
return new Promise((resolve, reject) => { |
|||
PureHttp.axiosInstance |
|||
.request(config) |
|||
.then((response: undefined) => { |
|||
resolve(response); |
|||
}) |
|||
.catch(error => { |
|||
reject(error); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
// 单独抽离的post工具函数
|
|||
public post<T>( |
|||
url: string, |
|||
params?: T, |
|||
config?: PureHttpRequestConfig |
|||
): Promise<T> { |
|||
return this.request<T>("post", url, params, config); |
|||
} |
|||
|
|||
// 单独抽离的get工具函数
|
|||
public get<T>( |
|||
url: string, |
|||
params?: T, |
|||
config?: PureHttpRequestConfig |
|||
): Promise<T> { |
|||
return this.request<T>("get", url, params, config); |
|||
} |
|||
} |
|||
|
|||
export const http = new PureHttp(); |
@ -1,50 +1,39 @@ |
|||
import Axios, { |
|||
AxiosRequestConfig, |
|||
Canceler, |
|||
AxiosResponse, |
|||
Method, |
|||
AxiosError |
|||
AxiosError, |
|||
AxiosResponse, |
|||
AxiosRequestConfig |
|||
} from "axios"; |
|||
|
|||
import { METHODS } from "./config"; |
|||
|
|||
export type cancelTokenType = { cancelKey: string; cancelExecutor: Canceler }; |
|||
export type resultType = { |
|||
accessToken?: string; |
|||
}; |
|||
|
|||
export type RequestMethods = Extract< |
|||
Method, |
|||
"get" | "post" | "put" | "delete" | "patch" | "option" | "head" |
|||
>; |
|||
|
|||
export interface EnclosureHttpRequestConfig extends AxiosRequestConfig { |
|||
beforeRequestCallback?: (request: EnclosureHttpRequestConfig) => void; // 请求发送之前
|
|||
beforeResponseCallback?: (response: EnclosureHttpResoponse) => void; // 相应返回之前
|
|||
export interface PureHttpError extends AxiosError { |
|||
isCancelRequest?: boolean; |
|||
} |
|||
|
|||
export interface EnclosureHttpResoponse extends AxiosResponse { |
|||
config: EnclosureHttpRequestConfig; |
|||
export interface PureHttpResoponse extends AxiosResponse { |
|||
config: PureHttpRequestConfig; |
|||
} |
|||
|
|||
export interface EnclosureHttpError extends AxiosError { |
|||
isCancelRequest?: boolean; |
|||
export interface PureHttpRequestConfig extends AxiosRequestConfig { |
|||
beforeRequestCallback?: (request: PureHttpRequestConfig) => void; |
|||
beforeResponseCallback?: (response: PureHttpResoponse) => void; |
|||
} |
|||
|
|||
export default class EnclosureHttp { |
|||
cancelTokenList: Array<cancelTokenType>; |
|||
clearCancelTokenList(): void; |
|||
export default class PureHttp { |
|||
request<T>( |
|||
method: RequestMethods, |
|||
url: string, |
|||
param?: AxiosRequestConfig, |
|||
axiosConfig?: EnclosureHttpRequestConfig |
|||
): Promise<T>; |
|||
post<T>( |
|||
url: string, |
|||
params?: T, |
|||
config?: EnclosureHttpRequestConfig |
|||
): Promise<T>; |
|||
get<T>( |
|||
url: string, |
|||
params?: T, |
|||
config?: EnclosureHttpRequestConfig |
|||
axiosConfig?: PureHttpRequestConfig |
|||
): Promise<T>; |
|||
post<T>(url: string, params?: T, config?: PureHttpRequestConfig): Promise<T>; |
|||
get<T>(url: string, params?: T, config?: PureHttpRequestConfig): Promise<T>; |
|||
} |
@ -1,29 +0,0 @@ |
|||
import { EnclosureHttpRequestConfig } from "./types.d"; |
|||
|
|||
export function excludeProps<T extends { [key: string]: any }>( |
|||
origin: T, |
|||
prop: string |
|||
): { [key: string]: T } { |
|||
return Object.keys(origin) |
|||
.filter(key => !prop.includes(key)) |
|||
.reduce((res, key) => { |
|||
res[key] = origin[key]; |
|||
return res; |
|||
}, {} as { [key: string]: T }); |
|||
} |
|||
|
|||
export function transformConfigByMethod( |
|||
params: any, |
|||
config: EnclosureHttpRequestConfig |
|||
): EnclosureHttpRequestConfig { |
|||
const { method } = config; |
|||
const props = ["delete", "get", "head", "options"].includes( |
|||
method!.toLocaleLowerCase() |
|||
) |
|||
? "params" |
|||
: "data"; |
|||
return { |
|||
...config, |
|||
[props]: params |
|||
}; |
|||
} |
@ -1,19 +0,0 @@ |
|||
import { i18n } from "../plugins/i18n"; |
|||
|
|||
/** |
|||
* 消息转换 |
|||
* @param message message |
|||
* @param isI18n 如果true,获取对应的消息,否则返回this |
|||
* @returns message |
|||
*/ |
|||
export function transformI18n(message = "", isI18n = false) { |
|||
if (!message) { |
|||
return ""; |
|||
} |
|||
if (isI18n) { |
|||
//@ts-ignore
|
|||
return i18n.global.tc.call(i18n.global, message); |
|||
} else { |
|||
return message; |
|||
} |
|||
} |
@ -1,53 +0,0 @@ |
|||
import { loadEnv } from "@build/utils"; |
|||
import { merge } from "lodash-es"; |
|||
import tsCookies from "typescript-cookie/dist/src/compat"; |
|||
|
|||
class Cookies { |
|||
private static env = loadEnv(); |
|||
constructor() {} |
|||
/** |
|||
* 存储 cookie 值 |
|||
* @param name |
|||
* @param value |
|||
* @param cookieSetting |
|||
*/ |
|||
set(name = "default", value = "", cookieSetting = {}) { |
|||
const currentCookieSetting = { |
|||
expires: 1 |
|||
}; |
|||
merge(currentCookieSetting, cookieSetting); |
|||
tsCookies.set( |
|||
`${Cookies.env.VITE_TITLE}-${Cookies.env.VITE_VERSION}-${name}`, |
|||
value, |
|||
currentCookieSetting |
|||
); |
|||
} |
|||
/** |
|||
* 拿到 cookie 值 |
|||
* @param name |
|||
* @returns |
|||
*/ |
|||
get(name = "default") { |
|||
return tsCookies.get( |
|||
`${Cookies.env.VITE_TITLE}-${Cookies.env.VITE_VERSION}-${name}` |
|||
); |
|||
} |
|||
/** |
|||
* 拿到 cookie 全部的值 |
|||
* @returns |
|||
*/ |
|||
getAll() { |
|||
return tsCookies.get(); |
|||
} |
|||
/** |
|||
* 删除 cookie |
|||
* @param name |
|||
*/ |
|||
remove(name = "default") { |
|||
tsCookies.remove( |
|||
`${Cookies.env.VITE_TITLE}-${Cookies.env.VITE_VERSION}-${name}` |
|||
); |
|||
} |
|||
} |
|||
|
|||
export const cookies = new Cookies(); |
@ -1,93 +0,0 @@ |
|||
import { loadEnv } from "@build/utils"; |
|||
import { LocalStorage, LowSync } from "lowdb"; |
|||
import { chain, cloneDeep } from "lodash-es"; |
|||
import { storageLocal } from "."; |
|||
import { cookies } from "./cookie"; |
|||
type Data = { |
|||
database: {}; |
|||
sys: {}; |
|||
}; |
|||
/** |
|||
* db 数据存储,采用 LocalStorage存储 |
|||
*/ |
|||
class DB { |
|||
private db: LowSync<Data>; |
|||
private static env = loadEnv(); |
|||
constructor() { |
|||
this.db = new LowSync<Data>( |
|||
new LocalStorage<Data>(`${DB.env.VITE_TITLE}-${DB.env.VITE_VERSION}`) |
|||
); |
|||
this.initialization(); |
|||
// @ts-ignore
|
|||
this.db.chain = chain(this.db.data); |
|||
} |
|||
private initialization() { |
|||
this.db.data = storageLocal.getItem( |
|||
`${DB.env.VITE_TITLE}-${DB.env.VITE_VERSION}` |
|||
) || { database: {}, sys: {} }; |
|||
this.db.write(); |
|||
} |
|||
/** |
|||
* 检查路径是否存在 不存在的话初始化 |
|||
* @param param0 |
|||
* @returns path |
|||
*/ |
|||
pathInit({ |
|||
dbName = "database", |
|||
path = "", |
|||
user = true, |
|||
validator = () => true, |
|||
defaultValue = "" |
|||
}): string { |
|||
const uuid = cookies.get("uuid") || "ghost-uuid"; |
|||
const currentPath = `${dbName}.${user ? `user.${uuid}` : "public"}${ |
|||
path ? `.${path}` : "" |
|||
}`;
|
|||
// @ts-ignore
|
|||
const value = this.db.chain.get(currentPath).value(); |
|||
// @ts-ignore
|
|||
if (!(value !== undefined && validator(value))) { |
|||
// @ts-ignore
|
|||
this.db.chain.set(currentPath, defaultValue).value(); |
|||
this.db.write(); |
|||
} |
|||
return currentPath; |
|||
} |
|||
/** |
|||
*将数据存储到指定位置 | 路径不存在会自动初始化 |
|||
* |
|||
* 效果类似于取值 dbName.path = value |
|||
* @param param0 |
|||
*/ |
|||
dbSet({ dbName = "database", path = "", value = "", user = false }): void { |
|||
const currentPath = this.pathInit({ |
|||
dbName, |
|||
path, |
|||
user |
|||
}); |
|||
// @ts-ignore
|
|||
this.db.chain.set(currentPath, value).value(); |
|||
this.db.write(); |
|||
} |
|||
/** |
|||
* 获取数据 |
|||
* |
|||
* 效果类似于取值 dbName.path || defaultValue |
|||
* @param param0 |
|||
* @returns |
|||
*/ |
|||
dbGet({ |
|||
dbName = "database", |
|||
path = "", |
|||
defaultValue = "", |
|||
user = false |
|||
}): any { |
|||
// @ts-ignore
|
|||
const values = this.db.chain |
|||
.get(this.pathInit({ dbName, path, user, defaultValue })) |
|||
.value(); |
|||
return cloneDeep(values); |
|||
} |
|||
} |
|||
|
|||
export const db = new DB(); |
Write
Preview
Loading…
Cancel
Save
Reference in new issue