mirror of
https://github.com/XiaoDaiGua-Ray/ray-template.git
synced 2025-04-06 03:57:49 +08:00
v3.3.6
This commit is contained in:
parent
54d370c7a0
commit
eaf6f16132
14
CHANGELOG.md
14
CHANGELOG.md
@ -1,5 +1,19 @@
|
|||||||
# CHANGE LOG
|
# CHANGE LOG
|
||||||
|
|
||||||
|
## 3.3.6
|
||||||
|
|
||||||
|
### Feats
|
||||||
|
|
||||||
|
- 重写 axios interceptor 方法。现在逻辑更加清晰,并且支持请求错误、响应错误处理。补充了两个工具函数
|
||||||
|
- MenuTag 支持动态更新所在位置
|
||||||
|
- 修复了鉴权方法的 bug
|
||||||
|
- 更新了 router permission 方法(路由守卫)
|
||||||
|
- 补充了一些模块文档
|
||||||
|
|
||||||
|
### 补充
|
||||||
|
|
||||||
|
> 文档拖欠太多了,我补不回来了,就。。。算了吧,我在每个关键模块补充了对应的 md 说明文档,凑合一下吧。真希望有一个好心人帮补充文档。
|
||||||
|
|
||||||
## 3.3.5
|
## 3.3.5
|
||||||
|
|
||||||
### Feats
|
### Feats
|
||||||
|
71
src/axios/README.md
Normal file
71
src/axios/README.md
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
## 说明
|
||||||
|
|
||||||
|
> axios 包,全局的 axios 使用入口
|
||||||
|
> `src/axios/instance.ts` 文件为 axios 实例文件,应该不可更改,如果需要有拦截器相关的操作,应该在 `src/axios/inject` 文件下按照需求在对应注册器中进行注册相关方法。该项目将 axios instance 与 axios interceptor 进行解耦,避免实例文件的臃肿。
|
||||||
|
|
||||||
|
## 工具函数
|
||||||
|
|
||||||
|
- BeforeFetchFunction
|
||||||
|
- FetchErrorFunction
|
||||||
|
|
||||||
|
> 两个工具函数方便类型推导。
|
||||||
|
|
||||||
|
## 约束
|
||||||
|
|
||||||
|
### 拦截器添加
|
||||||
|
|
||||||
|
> 这里以请求拦截器添加为示例
|
||||||
|
|
||||||
|
```ts
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 拦截器说明
|
||||||
|
*
|
||||||
|
* 注册一个根据系统当前环境是否携带测试环境请求拦截器
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { appendRequestHeaders } from '@/axios/helper/axiosCopilot'
|
||||||
|
|
||||||
|
import type {
|
||||||
|
RequestInterceptorConfig,
|
||||||
|
BeforeFetchFunction,
|
||||||
|
FetchErrorFunction,
|
||||||
|
} from '@/axios/type'
|
||||||
|
|
||||||
|
const injectRequestHeaderOfEnv: BeforeFetchFunction<
|
||||||
|
RequestInterceptorConfig
|
||||||
|
> = (ins, mode) => {
|
||||||
|
if (mode === 'development') {
|
||||||
|
appendRequestHeaders(ins, [
|
||||||
|
{
|
||||||
|
key: 'Development-Mode',
|
||||||
|
value: 'development',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 在 setupRequestInterceptor 中注册
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const setupRequestInterceptor = () => {
|
||||||
|
setImplement(
|
||||||
|
'implementRequestInterceptorArray',
|
||||||
|
[injectRequestHeaderOfEnv],
|
||||||
|
'ok',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 至此完成了请求拦截器的注册 */
|
||||||
|
```
|
||||||
|
|
||||||
|
### 注册器
|
||||||
|
|
||||||
|
> 每个类型注册器都有两个方法,用于注册拦截器方法。都以 setupXXX 开头命名。注册器以队列形式管理拦截器方法,所以可能需要注意执行顺序。如果有新的拦截器方法,需要根据其使用场景在对应的注册器中注册(注册器第二个参数中注册)。
|
||||||
|
|
||||||
|
- 请求注册器: setupRequestInterceptor
|
||||||
|
- 请求错误注册器: setupRequestErrorInterceptor
|
||||||
|
- 响应注册器: setupResponseInterceptor
|
||||||
|
- 响应错误注册器: setupResponseErrorInterceptor
|
@ -16,7 +16,8 @@
|
|||||||
* 请求拦截器、响应拦截器
|
* 请求拦截器、响应拦截器
|
||||||
* 暴露启动方法调用所有已注册方法
|
* 暴露启动方法调用所有已注册方法
|
||||||
*
|
*
|
||||||
* 为什么要把 create 方法拆成两个, emmmmmm 我也不知道
|
* 该拦截器仅适合放置公共的 axios 拦截器操作, 并且采用队列形式管理请求拦截器的注入
|
||||||
|
* 所以在使用的时候, 需要按照约定格式进行参数传递
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import RequestCanceler from '@/axios/helper/canceler'
|
import RequestCanceler from '@/axios/helper/canceler'
|
||||||
@ -25,73 +26,116 @@ import { getAppEnvironment } from '@use-utils/hook'
|
|||||||
import type {
|
import type {
|
||||||
RequestInterceptorConfig,
|
RequestInterceptorConfig,
|
||||||
ResponseInterceptorConfig,
|
ResponseInterceptorConfig,
|
||||||
ImplementKey,
|
|
||||||
ImplementQueue,
|
ImplementQueue,
|
||||||
|
ErrorImplementQueue,
|
||||||
|
FetchType,
|
||||||
} from '@/axios/type'
|
} from '@/axios/type'
|
||||||
|
|
||||||
|
/** 当前请求的实例 */
|
||||||
const axiosFetchInstance = {
|
const axiosFetchInstance = {
|
||||||
requestInstance: null as RequestInterceptorConfig | null,
|
requestInstance: null as RequestInterceptorConfig | null,
|
||||||
responseInstance: null as ResponseInterceptorConfig | null,
|
responseInstance: null as ResponseInterceptorConfig | null,
|
||||||
}
|
}
|
||||||
|
const axiosFetchError = {
|
||||||
|
requestError: null as null | unknown,
|
||||||
|
responseError: null as null | unknown,
|
||||||
|
}
|
||||||
|
/** 请求队列(区分 reslove 与 reject 状态) */
|
||||||
const implement: ImplementQueue = {
|
const implement: ImplementQueue = {
|
||||||
implementRequestInterceptorArray: [],
|
implementRequestInterceptorArray: [],
|
||||||
implementResponseInterceptorArray: [],
|
implementResponseInterceptorArray: [],
|
||||||
}
|
}
|
||||||
|
const errorImplement: ErrorImplementQueue = {
|
||||||
|
implementRequestInterceptorErrorArray: [],
|
||||||
|
implementResponseInterceptorErrorArray: [],
|
||||||
|
}
|
||||||
|
/** 取消器实例 */
|
||||||
export const axiosCanceler = new RequestCanceler()
|
export const axiosCanceler = new RequestCanceler()
|
||||||
|
|
||||||
export const useAxiosInterceptor = () => {
|
export const useAxiosInterceptor = () => {
|
||||||
const getImplementKey = (key: ImplementKey) => {
|
/** 创建拦截器实例 */
|
||||||
return key === 'requestInstance'
|
const createAxiosInstance = (
|
||||||
? 'implementRequestInterceptorArray'
|
instance: RequestInterceptorConfig | ResponseInterceptorConfig,
|
||||||
: 'implementResponseInterceptorArray'
|
instanceKey: keyof typeof axiosFetchInstance,
|
||||||
|
) => {
|
||||||
|
instanceKey === 'requestInstance'
|
||||||
|
? (axiosFetchInstance['requestInstance'] =
|
||||||
|
instance as RequestInterceptorConfig)
|
||||||
|
: (axiosFetchInstance['responseInstance'] =
|
||||||
|
instance as ResponseInterceptorConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
const createRequestAxiosInstance = (instance: RequestInterceptorConfig) => {
|
/** 获取当前实例 */
|
||||||
axiosFetchInstance['requestInstance'] = instance
|
const getAxiosInstance = (instanceKey: keyof typeof axiosFetchInstance) => {
|
||||||
|
return axiosFetchInstance[instanceKey]
|
||||||
}
|
}
|
||||||
|
|
||||||
const createResponseAxiosInstance = (instance: ResponseInterceptorConfig) => {
|
/** 设置注入方法队列 */
|
||||||
axiosFetchInstance['responseInstance'] = instance
|
const setImplement = (
|
||||||
|
key: keyof ImplementQueue | keyof ErrorImplementQueue,
|
||||||
|
func: AnyFunc[],
|
||||||
|
fetchType: FetchType,
|
||||||
|
) => {
|
||||||
|
fetchType === 'ok' ? (implement[key] = func) : (errorImplement[key] = func)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取请求实例或者响应实例 */
|
/** 获取队列中所有的所有拦截器方法 */
|
||||||
const getAxiosFetchInstance = (key: ImplementKey) => {
|
const getImplement = (
|
||||||
return axiosFetchInstance[key]
|
key: keyof ImplementQueue | keyof ErrorImplementQueue,
|
||||||
|
fetchType: FetchType,
|
||||||
|
): AnyFunc[] => {
|
||||||
|
return fetchType === 'ok' ? implement[key] : errorImplement[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 请求前, 执行队列所有方法 */
|
/** 队列执行器 */
|
||||||
const beforeAxiosFetch = (key: ImplementKey) => {
|
const implementer = (funcs: AnyFunc[], ...args: any[]) => {
|
||||||
const funcArr = implement[getImplementKey(key)]
|
if (Array.isArray(funcs)) {
|
||||||
const instance = getAxiosFetchInstance(key)
|
funcs?.forEach((curr) => {
|
||||||
const { MODE } = getAppEnvironment()
|
|
||||||
|
|
||||||
if (instance) {
|
|
||||||
funcArr?.forEach((curr) => {
|
|
||||||
if (typeof curr === 'function') {
|
if (typeof curr === 'function') {
|
||||||
curr(instance, MODE)
|
curr(...args)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 设置拦截器队列 */
|
/** 请求、响应前执行拦截器队列中的所有方法 */
|
||||||
const setImplementQueue = (func: AnyFunc[], key: ImplementKey) => {
|
const beforeFetch = (
|
||||||
if (func && key) {
|
key: keyof typeof axiosFetchInstance,
|
||||||
implement[getImplementKey(key)] = func
|
implementKey: keyof ImplementQueue | keyof ErrorImplementQueue,
|
||||||
|
fetchType: FetchType,
|
||||||
|
) => {
|
||||||
|
const funcArr =
|
||||||
|
fetchType === 'ok'
|
||||||
|
? implement[implementKey]
|
||||||
|
: errorImplement[implementKey]
|
||||||
|
const instance = getAxiosInstance(key)
|
||||||
|
const { MODE } = getAppEnvironment()
|
||||||
|
|
||||||
|
if (instance) {
|
||||||
|
implementer(funcArr, instance, MODE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取拦截器队列 */
|
/** 请求、响应错误时执行队列中所有方法 */
|
||||||
const getImplementQueue = (key: ImplementKey) => {
|
const fetchError = (
|
||||||
return implement[getImplementKey(key)]
|
key: keyof typeof axiosFetchError,
|
||||||
|
error: unknown,
|
||||||
|
errorImplementKey: keyof ErrorImplementQueue,
|
||||||
|
) => {
|
||||||
|
axiosFetchError[key] = error
|
||||||
|
|
||||||
|
const funcArr = errorImplement[errorImplementKey]
|
||||||
|
const { MODE } = getAppEnvironment()
|
||||||
|
|
||||||
|
implementer(funcArr, error, MODE)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
createRequestAxiosInstance,
|
createAxiosInstance,
|
||||||
createResponseAxiosInstance,
|
setImplement,
|
||||||
beforeAxiosFetch,
|
getImplement,
|
||||||
setImplementQueue,
|
getAxiosInstance,
|
||||||
getImplementQueue,
|
beforeFetch,
|
||||||
getAxiosFetchInstance,
|
fetchError,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
* 请求拦截器入口
|
* 请求拦截器入口
|
||||||
* 被注册方法执行时其实例能够保证获取到, 所以不需要做额外空判断
|
* 被注册方法执行时其实例能够保证获取到, 所以不需要做额外空判断
|
||||||
* 在内部执行方法中, 已经做了边界处理
|
* 在内部执行方法中, 已经做了边界处理
|
||||||
|
*
|
||||||
|
* 提供两个工具方法, 方便类型推导
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useAxiosInterceptor, axiosCanceler } from '@/axios/helper/interceptor'
|
import { useAxiosInterceptor, axiosCanceler } from '@/axios/helper/interceptor'
|
||||||
@ -21,8 +23,12 @@ import { appendRequestHeaders } from '@/axios/helper/axiosCopilot'
|
|||||||
import { APP_CATCH_KEY } from '@/appConfig/appConfig'
|
import { APP_CATCH_KEY } from '@/appConfig/appConfig'
|
||||||
import { getCache } from '@/utils/cache'
|
import { getCache } from '@/utils/cache'
|
||||||
|
|
||||||
import type { RequestInterceptorConfig, ImplementFunction } from '@/axios/type'
|
import type {
|
||||||
const { setImplementQueue } = useAxiosInterceptor()
|
RequestInterceptorConfig,
|
||||||
|
BeforeFetchFunction,
|
||||||
|
FetchErrorFunction,
|
||||||
|
} from '@/axios/type'
|
||||||
|
const { setImplement } = useAxiosInterceptor()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -46,7 +52,7 @@ const requestHeaderToken = (ins: RequestInterceptorConfig, mode: string) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 注入请求头信息 */
|
/** 注入请求头信息 */
|
||||||
const injectRequestHeaders: ImplementFunction<RequestInterceptorConfig> = (
|
const injectRequestHeaders: BeforeFetchFunction<RequestInterceptorConfig> = (
|
||||||
ins,
|
ins,
|
||||||
mode,
|
mode,
|
||||||
) => {
|
) => {
|
||||||
@ -60,7 +66,7 @@ const injectRequestHeaders: ImplementFunction<RequestInterceptorConfig> = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 注入重复请求拦截器 */
|
/** 注入重复请求拦截器 */
|
||||||
const injectCanceler: ImplementFunction<RequestInterceptorConfig> = (
|
const injectCanceler: BeforeFetchFunction<RequestInterceptorConfig> = (
|
||||||
ins,
|
ins,
|
||||||
mode,
|
mode,
|
||||||
) => {
|
) => {
|
||||||
@ -68,11 +74,28 @@ const injectCanceler: ImplementFunction<RequestInterceptorConfig> = (
|
|||||||
axiosCanceler.addPendingRequest(ins) // 把当前的请求信息添加到 pendingRequest 表中
|
axiosCanceler.addPendingRequest(ins) // 把当前的请求信息添加到 pendingRequest 表中
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const requestError: FetchErrorFunction<unknown> = (error, mode) => {
|
||||||
|
console.log(error, mode)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* 注册请求拦截器
|
* 注册请求拦截器
|
||||||
* 请注意执行顺序, setImplementQueue 方法按照注册顺序执行
|
* 请注意执行顺序
|
||||||
*/
|
*/
|
||||||
export const setupRequestInterceptor = () => {
|
export const setupRequestInterceptor = () => {
|
||||||
setImplementQueue([injectRequestHeaders, injectCanceler], 'requestInstance')
|
setImplement(
|
||||||
|
'implementRequestInterceptorArray',
|
||||||
|
[injectRequestHeaders, injectCanceler],
|
||||||
|
'ok',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 注册请求错误拦截器
|
||||||
|
* 请注意执行顺序
|
||||||
|
*/
|
||||||
|
export const setupRequestErrorInterceptor = () => {
|
||||||
|
setImplement('implementRequestInterceptorErrorArray', [requestError], 'error')
|
||||||
}
|
}
|
||||||
|
@ -14,27 +14,64 @@
|
|||||||
* 响应拦截器入口
|
* 响应拦截器入口
|
||||||
* 被注册方法执行时其实例能够保证获取到, 所以不需要做额外空判断
|
* 被注册方法执行时其实例能够保证获取到, 所以不需要做额外空判断
|
||||||
* 在内部执行方法中, 已经做了边界处理
|
* 在内部执行方法中, 已经做了边界处理
|
||||||
|
*
|
||||||
|
* 提供两个工具方法, 方便类型推导
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useAxiosInterceptor, axiosCanceler } from '@/axios/helper/interceptor'
|
import { useAxiosInterceptor, axiosCanceler } from '@/axios/helper/interceptor'
|
||||||
|
|
||||||
import type { ResponseInterceptorConfig, ImplementFunction } from '@/axios/type'
|
import type {
|
||||||
|
ResponseInterceptorConfig,
|
||||||
|
BeforeFetchFunction,
|
||||||
|
FetchErrorFunction,
|
||||||
|
} from '@/axios/type'
|
||||||
|
|
||||||
const { setImplementQueue } = useAxiosInterceptor()
|
const { setImplement } = useAxiosInterceptor()
|
||||||
|
|
||||||
/** 响应成功后移除缓存请求 url */
|
/** 响应成功后移除缓存请求 url */
|
||||||
const injectResponseCanceler: ImplementFunction<ResponseInterceptorConfig> = (
|
const injectResponseCanceler: BeforeFetchFunction<ResponseInterceptorConfig> = (
|
||||||
ins,
|
ins,
|
||||||
mode,
|
mode,
|
||||||
) => {
|
) => {
|
||||||
axiosCanceler.removePendingRequest(ins.config)
|
axiosCanceler.removePendingRequest(ins.config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param error 错误信息
|
||||||
|
* @param mode 当前环境
|
||||||
|
*
|
||||||
|
* 你可以在响应错误的时候做一些什么
|
||||||
|
* 这里不做具体演示
|
||||||
|
*
|
||||||
|
* 方法执行时会有两个参数, 可以根据报错信息与环境定做一些处理
|
||||||
|
*/
|
||||||
|
const responseError: FetchErrorFunction<unknown> = (error, mode) => {
|
||||||
|
console.log(error, mode)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* 注册响应拦截器
|
* 注册响应拦截器
|
||||||
* 请注意执行顺序, setImplementQueue 方法按照注册顺序执行
|
* 请注意执行顺序
|
||||||
*/
|
*/
|
||||||
export const setupResponseInterceptor = () => {
|
export const setupResponseInterceptor = () => {
|
||||||
setImplementQueue([injectResponseCanceler], 'responseInstance')
|
setImplement(
|
||||||
|
'implementResponseInterceptorArray',
|
||||||
|
[injectResponseCanceler],
|
||||||
|
'ok',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 注册响应错误拦截器
|
||||||
|
* 请注意执行顺序
|
||||||
|
*/
|
||||||
|
export const setupResponseErrorInterceptor = () => {
|
||||||
|
setImplement(
|
||||||
|
'implementResponseInterceptorErrorArray',
|
||||||
|
[responseError],
|
||||||
|
'error',
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* 请求, 响应拦截器
|
* 请求拦截器与响应拦截器
|
||||||
* 如果有需要拓展拦截器, 请在 inject 目录下参照示例方法继续拓展
|
* 如果有需要拓展拦截器, 请在 inject 目录下参照示例方法继续拓展
|
||||||
* 该页面不做改动与配置
|
* 该页面不做改动与配置
|
||||||
*/
|
*/
|
||||||
@ -19,42 +19,50 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { AXIOS_CONFIG } from '@/appConfig/requestConfig'
|
import { AXIOS_CONFIG } from '@/appConfig/requestConfig'
|
||||||
import { useAxiosInterceptor, axiosCanceler } from '@/axios/helper/interceptor'
|
import { useAxiosInterceptor, axiosCanceler } from '@/axios/helper/interceptor'
|
||||||
import { setupRequestInterceptor } from '@/axios/inject/requestInject'
|
import {
|
||||||
import { setupResponseInterceptor } from '@/axios/inject/responseInject'
|
setupResponseInterceptor,
|
||||||
|
setupResponseErrorInterceptor,
|
||||||
|
} from '@/axios/inject/responseInject'
|
||||||
|
import {
|
||||||
|
setupRequestInterceptor,
|
||||||
|
setupRequestErrorInterceptor,
|
||||||
|
} from '@/axios/inject/requestInject'
|
||||||
|
|
||||||
import type { AxiosInstanceExpand } from './type'
|
import type { AxiosInstanceExpand } from './type'
|
||||||
|
|
||||||
const server: AxiosInstanceExpand = axios.create(AXIOS_CONFIG)
|
const server: AxiosInstanceExpand = axios.create(AXIOS_CONFIG)
|
||||||
const {
|
const { createAxiosInstance, beforeFetch, fetchError } = useAxiosInterceptor()
|
||||||
createRequestAxiosInstance,
|
|
||||||
createResponseAxiosInstance,
|
|
||||||
beforeAxiosFetch,
|
|
||||||
} = useAxiosInterceptor()
|
|
||||||
|
|
||||||
server.interceptors.request.use(
|
server.interceptors.request.use(
|
||||||
(request) => {
|
(request) => {
|
||||||
createRequestAxiosInstance(request)
|
createAxiosInstance(request, 'requestInstance')
|
||||||
setupRequestInterceptor()
|
setupRequestInterceptor()
|
||||||
beforeAxiosFetch('requestInstance')
|
beforeFetch('requestInstance', 'implementRequestInterceptorArray', 'ok')
|
||||||
|
|
||||||
return request
|
return request
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
|
setupRequestErrorInterceptor()
|
||||||
|
fetchError('requestError', error, 'implementRequestInterceptorErrorArray')
|
||||||
|
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
server.interceptors.response.use(
|
server.interceptors.response.use(
|
||||||
(response) => {
|
(response) => {
|
||||||
createResponseAxiosInstance(response)
|
createAxiosInstance(response, 'responseInstance')
|
||||||
setupResponseInterceptor()
|
setupResponseInterceptor()
|
||||||
beforeAxiosFetch('responseInstance')
|
beforeFetch('responseInstance', 'implementResponseInterceptorArray', 'ok')
|
||||||
|
|
||||||
const { data } = response
|
const { data } = response
|
||||||
|
|
||||||
return Promise.resolve(data)
|
return Promise.resolve(data)
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
|
setupResponseErrorInterceptor()
|
||||||
|
fetchError('responseError', error, 'implementResponseInterceptorErrorArray')
|
||||||
|
|
||||||
axiosCanceler.removePendingRequest(error.config || {})
|
axiosCanceler.removePendingRequest(error.config || {})
|
||||||
|
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
|
@ -83,13 +83,23 @@ export type RequestInterceptorConfig<T = any> = InternalAxiosRequestConfig<T>
|
|||||||
|
|
||||||
export type ResponseInterceptorConfig<T = any, K = any> = AxiosResponse<T, K>
|
export type ResponseInterceptorConfig<T = any, K = any> = AxiosResponse<T, K>
|
||||||
|
|
||||||
export type ImplementKey = 'requestInstance' | 'responseInstance'
|
|
||||||
|
|
||||||
export interface ImplementQueue {
|
export interface ImplementQueue {
|
||||||
implementRequestInterceptorArray: AnyFunc[]
|
implementRequestInterceptorArray: AnyFunc[]
|
||||||
implementResponseInterceptorArray: AnyFunc[]
|
implementResponseInterceptorArray: AnyFunc[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ImplementFunction<
|
export interface ErrorImplementQueue {
|
||||||
|
implementRequestInterceptorErrorArray: AnyFunc[]
|
||||||
|
implementResponseInterceptorErrorArray: AnyFunc[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type BeforeFetchFunction<
|
||||||
T = RequestInterceptorConfig | ResponseInterceptorConfig,
|
T = RequestInterceptorConfig | ResponseInterceptorConfig,
|
||||||
> = <K extends T>(ins: K, mode: string) => void
|
> = <K extends T>(ins: K, mode: string) => void
|
||||||
|
|
||||||
|
export type FetchType = 'ok' | 'error'
|
||||||
|
|
||||||
|
export type FetchErrorFunction<T = any> = <K extends T>(
|
||||||
|
error: K,
|
||||||
|
mode: string,
|
||||||
|
) => void
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
*
|
*
|
||||||
* root path 标签不可被关闭, 所以不会显示关闭按钮
|
* root path 标签不可被关闭, 所以不会显示关闭按钮
|
||||||
* 页面刷新后, 仅会保留刷新前激活 key 的 tag 标签
|
* 页面刷新后, 仅会保留刷新前激活 key 的 tag 标签
|
||||||
|
*
|
||||||
|
* 注入 MENU_TAG_DATA 属性, 用于动态更新 MenuTag 标签所在的位置
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
@ -31,6 +33,7 @@ import { uuid } from '@/utils/hook'
|
|||||||
import { hasClass } from '@/utils/element'
|
import { hasClass } from '@/utils/element'
|
||||||
import { redirectRouterToDashboard } from '@/router/helper/routerCopilot'
|
import { redirectRouterToDashboard } from '@/router/helper/routerCopilot'
|
||||||
import { ROOT_ROUTE } from '@/appConfig/appConfig'
|
import { ROOT_ROUTE } from '@/appConfig/appConfig'
|
||||||
|
import { getElement } from '@use-utils/element'
|
||||||
|
|
||||||
import type { MenuOption, ScrollbarInst } from 'naive-ui'
|
import type { MenuOption, ScrollbarInst } from 'naive-ui'
|
||||||
|
|
||||||
@ -205,6 +208,7 @@ const MenuTag = defineComponent({
|
|||||||
y: 0,
|
y: 0,
|
||||||
actionDropdownShow: false,
|
actionDropdownShow: false,
|
||||||
})
|
})
|
||||||
|
const MENU_TAG_DATA = 'menu_tag_data'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -373,6 +377,19 @@ const MenuTag = defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 动态更新 menu tag 所在位置 */
|
||||||
|
const positionMenuTag = () => {
|
||||||
|
nextTick().then(() => {
|
||||||
|
const tags = getElement(`attr:${MENU_TAG_DATA}="${menuKey.value}"`)
|
||||||
|
|
||||||
|
if (tags?.length) {
|
||||||
|
const [menuTag] = tags
|
||||||
|
|
||||||
|
menuTag.scrollIntoView?.()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/** 如果有且只有一个标签页时, 禁止全部关闭操作 */
|
/** 如果有且只有一个标签页时, 禁止全部关闭操作 */
|
||||||
watch(
|
watch(
|
||||||
() => modelMenuTagOptions.value,
|
() => modelMenuTagOptions.value,
|
||||||
@ -388,6 +405,8 @@ const MenuTag = defineComponent({
|
|||||||
if (oldData?.length) {
|
if (oldData?.length) {
|
||||||
if (newData.length > oldData?.length) {
|
if (newData.length > oldData?.length) {
|
||||||
updateScrollBarPosition()
|
updateScrollBarPosition()
|
||||||
|
} else if (newData.length === oldData?.length) {
|
||||||
|
positionMenuTag()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -423,6 +442,7 @@ const MenuTag = defineComponent({
|
|||||||
setCurrentContentmenuIndex,
|
setCurrentContentmenuIndex,
|
||||||
menuTagMouseenter,
|
menuTagMouseenter,
|
||||||
menuTagMouseleave,
|
menuTagMouseleave,
|
||||||
|
MENU_TAG_DATA,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
@ -482,7 +502,7 @@ const MenuTag = defineComponent({
|
|||||||
onContextmenu: this.handleContextMenu.bind(this, idx),
|
onContextmenu: this.handleContextMenu.bind(this, idx),
|
||||||
onMouseenter: this.menuTagMouseenter.bind(this, curr),
|
onMouseenter: this.menuTagMouseenter.bind(this, curr),
|
||||||
onMouseleave: this.menuTagMouseleave.bind(this, curr),
|
onMouseleave: this.menuTagMouseleave.bind(this, curr),
|
||||||
tag_data: curr.path,
|
[this.MENU_TAG_DATA]: curr.path,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{typeof curr.label === 'function'
|
{typeof curr.label === 'function'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user