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 |
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 |
VITE_PORT = 8848 |
||||
# title |
|
||||
VITE_TITLE = vue-pure-admin |
|
||||
# version |
|
||||
VITE_VERSION = 2.6.0 |
|
||||
# open |
|
||||
VITE_OPEN = false |
|
||||
|
|
||||
# public path |
|
||||
|
|
||||
|
# 开发环境读取配置文件路径 |
||||
VITE_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"; |
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, { |
import Axios, { |
||||
AxiosRequestConfig, |
|
||||
Canceler, |
|
||||
AxiosResponse, |
|
||||
Method, |
Method, |
||||
AxiosError |
|
||||
|
AxiosError, |
||||
|
AxiosResponse, |
||||
|
AxiosRequestConfig |
||||
} from "axios"; |
} from "axios"; |
||||
|
|
||||
import { METHODS } from "./config"; |
|
||||
|
|
||||
export type cancelTokenType = { cancelKey: string; cancelExecutor: Canceler }; |
|
||||
|
export type resultType = { |
||||
|
accessToken?: string; |
||||
|
}; |
||||
|
|
||||
export type RequestMethods = Extract< |
export type RequestMethods = Extract< |
||||
Method, |
Method, |
||||
"get" | "post" | "put" | "delete" | "patch" | "option" | "head" |
"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>( |
request<T>( |
||||
method: RequestMethods, |
method: RequestMethods, |
||||
url: string, |
url: string, |
||||
param?: AxiosRequestConfig, |
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>; |
): 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