refactor: refactor axios
This commit is contained in:
parent
9adc84c396
commit
3eb11e2658
yudao-ui-admin-vue3/src
api
bpm
form
leave
model
processInstance
task
taskAssignRule
userGroup
infra
apiAccessLog
apiErrorLog
codegen
config
dataSourceConfig
dbDoc
fileConfig
fileList
job
jobLog
redis
login
pay
system
dept
dict
errorCode
loginLog
menu
notice
oauth2
operatelog
permission
post
role
sensitiveWord
sms
tenant
tenantPackage
user
config/axios
hooks/web
router
@ -1,6 +1,5 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import { FormVO } from './types'
|
||||
const request = useAxios()
|
||||
|
||||
// 创建工作流的表单定义
|
||||
export const createFormApi = async (data: FormVO) => {
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import { LeaveVO } from './types'
|
||||
const request = useAxios()
|
||||
|
||||
// 创建请假申请
|
||||
export const createLeaveApi = async (data: LeaveVO) => {
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import { ModelVO } from './types'
|
||||
const request = useAxios()
|
||||
|
||||
export const getModelPageApi = async (params) => {
|
||||
return await request.get({ url: '/bpm/model/page', params })
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import { ProcessInstanceVO } from './types'
|
||||
const request = useAxios()
|
||||
|
||||
export const getMyProcessInstancePageApi = async (params) => {
|
||||
return await request.get({ url: '/bpm/process-instance/my-page', params })
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
|
||||
const request = useAxios()
|
||||
import request from '@/config/axios'
|
||||
|
||||
export const getTodoTaskPage = async (params) => {
|
||||
return await request.get({ url: '/bpm/task/todo-page', params })
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import { TaskAssignVO } from './types'
|
||||
const request = useAxios()
|
||||
|
||||
export const getTaskAssignRuleList = async (params) => {
|
||||
return await request.get({ url: '/bpm/task-assign-rule/list', params })
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import { UserGroupVO } from './types'
|
||||
const request = useAxios()
|
||||
|
||||
// 创建用户组
|
||||
export const createUserGroupApi = async (data: UserGroupVO) => {
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
|
||||
const request = useAxios()
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 查询列表API 访问日志
|
||||
export const getApiAccessLogPageApi = (params) => {
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
|
||||
const request = useAxios()
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 查询列表API 访问日志
|
||||
export const getApiErrorLogPageApi = (params) => {
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { CodegenUpdateReqVO, CodegenCreateListReqVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询列表代码生成表定义
|
||||
export const getCodegenTablePageApi = (params) => {
|
||||
return request.get({ url: '/infra/codegen/table/page', params })
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { ConfigVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询参数列表
|
||||
export const getConfigPageApi = (params) => {
|
||||
return request.get({ url: '/infra/config/page', params })
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { DataSourceConfigVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询数据源配置列表
|
||||
export const getDataSourceConfigListApi = () => {
|
||||
return request.get({ url: '/infra/data-source-config/list' })
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
|
||||
const request = useAxios()
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 导出Html
|
||||
export const exportHtmlApi = () => {
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { FileConfigVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询文件配置列表
|
||||
export const getFileConfigPageApi = (params) => {
|
||||
return request.get({ url: '/infra/file-config/page', params })
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
|
||||
const request = useAxios()
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 查询文件列表
|
||||
export const getFilePageApi = (params) => {
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { JobVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 任务列表
|
||||
export const getJobPageApi = (params) => {
|
||||
return request.get({ url: '/infra/job/page', params })
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
|
||||
const request = useAxios()
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 任务日志列表
|
||||
export const getJobLogPageApi = (params) => {
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
|
||||
const request = useAxios()
|
||||
import request from '@/config/axios'
|
||||
|
||||
/**
|
||||
* 获取redis 监控信息
|
||||
|
@ -1,9 +1,7 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import { getRefreshToken } from '@/utils/auth'
|
||||
import type { UserLoginVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
export interface CodeImgResult {
|
||||
captchaOnOff: boolean
|
||||
img: string
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { AppVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询列表支付应用
|
||||
export const getAppPageApi = (params) => {
|
||||
return request.get({ url: '/pay/app/page', params })
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { ChannelVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询列表支付渠道
|
||||
export const getChannelPageApi = (params) => {
|
||||
return request.get({ url: '/pay/channel/page', params })
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { MerchantVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询列表支付商户
|
||||
export const getMerchantPageApi = (params) => {
|
||||
return request.get({ url: '/pay/merchant/page', params })
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { OrderVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询列表支付订单
|
||||
export const getOrderPageApi = async (params) => {
|
||||
return await request.get({ url: '/pay/order/page', params })
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { RefundVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询列表退款订单
|
||||
export const getRefundPageApi = (params) => {
|
||||
return request.get({ url: '/pay/refund/page', params })
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { DeptVO, DeptListReqVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询部门(精简)列表
|
||||
export const listSimpleDeptApi = () => {
|
||||
return request.get({ url: '/system/dept/list-all-simple' })
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { DictDataVO, DictDataPageReqVO, DictDataExportReqVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询字典数据(精简)列表
|
||||
export const listSimpleDictDataApi = () => {
|
||||
return request.get({ url: '/system/dict-data/list-all-simple' })
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { DictTypeVO, DictTypePageReqVO, DictTypeExportReqVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询字典(精简)列表
|
||||
export const listSimpleDictTypeApi = () => {
|
||||
return request.get({ url: '/system/dict-type/list-all-simple' })
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { ErrorCodeVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询错误码列表
|
||||
export const getErrorCodePageApi = (params) => {
|
||||
return request.get({ url: '/system/error-code/page', params })
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
|
||||
const request = useAxios()
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 查询登录日志列表
|
||||
export const getLoginLogPageApi = (params) => {
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { MenuVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询菜单(精简)列表
|
||||
export const listSimpleMenusApi = () => {
|
||||
return request.get({ url: '/system/menu/list-all-simple' })
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { NoticeVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询公告列表
|
||||
export const getNoticePageApi = (params) => {
|
||||
return request.get({ url: '/system/notice/page', params })
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import { OAuth2ClientVo } from './client.types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询 OAuth2列表
|
||||
export const getOAuth2ClientPageApi = (params) => {
|
||||
return request.get({ url: '/system/oauth2-client/page', params })
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
|
||||
const request = useAxios()
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 查询 token列表
|
||||
export const getAccessTokenPageApi = (params) => {
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
|
||||
const request = useAxios()
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 查询操作日志列表
|
||||
export const getOperateLogPageApi = (params) => {
|
||||
|
@ -1,12 +1,10 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type {
|
||||
PermissionAssignRoleDataScopeReqVO,
|
||||
PermissionAssignRoleMenuReqVO,
|
||||
PermissionAssignUserRoleReqVO
|
||||
} from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询角色拥有的菜单权限
|
||||
export const listRoleMenusApi = async (roleId: number) => {
|
||||
return await request.get({ url: '/system/permission/list-role-resources?roleId=' + roleId })
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { PostVO, PostPageReqVO, PostExportReqVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询岗位列表
|
||||
export const getPostPageApi = async (params: PostPageReqVO) => {
|
||||
return await request.get({ url: '/system/post/page', params })
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { RoleVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询角色列表
|
||||
export const getRolePageApi = async (params) => {
|
||||
return await request.get({ url: '/system/role/page', params })
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { SensitiveWordVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询敏感词列表
|
||||
export const getSensitiveWordPageApi = (params) => {
|
||||
return request.get({ url: '/system/sensitive-word/page', params })
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { SmsChannelVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询短信渠道列表
|
||||
export const getSmsChannelPageApi = (params) => {
|
||||
return request.get({ url: '/system/sms-channel/page', params })
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
|
||||
const request = useAxios()
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 查询短信日志列表
|
||||
export const getSmsLogPageApi = (params) => {
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { SmsTemplateVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询短信模板列表
|
||||
export const getSmsTemplatePageApi = (params) => {
|
||||
return request.get({ url: '/system/sms-template/page', params })
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { TenantVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询租户列表
|
||||
export const getTenantPageApi = (params) => {
|
||||
return request.get({ url: '/system/tenant/page', params })
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { TenantPackageVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询租户套餐列表
|
||||
export const getTenantPackageTypePageApi = (params) => {
|
||||
return request.get({ url: '/system/tenant-package/page', params })
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import request from '@/config/axios'
|
||||
import type { UserVO } from './types'
|
||||
|
||||
const request = useAxios()
|
||||
|
||||
// 查询用户管理列表
|
||||
export const getUserPageApi = (params) => {
|
||||
return request.get({ url: '/system/user/page', params })
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
|
||||
const request = useAxios()
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 查询用户个人信息
|
||||
export const getUserProfileApi = () => {
|
||||
|
@ -1,229 +1,46 @@
|
||||
import axios, {
|
||||
AxiosInstance,
|
||||
AxiosRequestConfig,
|
||||
AxiosRequestHeaders,
|
||||
AxiosResponse,
|
||||
AxiosError
|
||||
} from 'axios'
|
||||
import { ElMessage, ElMessageBox, ElNotification } from 'element-plus'
|
||||
import qs from 'qs'
|
||||
import { config } from '@/config/axios/config'
|
||||
import { getAccessToken, getRefreshToken, getTenantId, removeToken, setToken } from '@/utils/auth'
|
||||
import errorCode from './errorCode'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { resetRouter } from '@/router'
|
||||
import { useCache } from '@/hooks/web/useCache'
|
||||
import { service } from './service'
|
||||
|
||||
const tenantEnable = import.meta.env.VITE_APP_TENANT_ENABLE
|
||||
const { result_code, base_url, request_timeout } = config
|
||||
import { config } from './config'
|
||||
|
||||
// 需要忽略的提示。忽略后,自动 Promise.reject('error')
|
||||
const ignoreMsgs = [
|
||||
'无效的刷新令牌', // 刷新令牌被删除时,不用提示
|
||||
'刷新令牌已过期' // 使用刷新令牌,刷新获取新的访问令牌时,结果因为过期失败,此时需要忽略。否则,会导致继续 401,无法跳转到登出界面
|
||||
]
|
||||
// 是否显示重新登录
|
||||
export const isRelogin = { show: false }
|
||||
// Axios 无感知刷新令牌,参考 https://www.dashingdog.cn/article/11 与 https://segmentfault.com/a/1190000020210980 实现
|
||||
// 请求队列
|
||||
let requestList: any[] = []
|
||||
// 是否正在刷新中
|
||||
let isRefreshToken = false
|
||||
const { default_headers } = config
|
||||
|
||||
// 创建axios实例
|
||||
const service: AxiosInstance = axios.create({
|
||||
baseURL: base_url, // api 的 base_url
|
||||
timeout: request_timeout, // 请求超时时间
|
||||
withCredentials: false // 禁用 Cookie 等信息
|
||||
})
|
||||
|
||||
// request拦截器
|
||||
service.interceptors.request.use(
|
||||
(config: AxiosRequestConfig) => {
|
||||
// 是否需要设置 token
|
||||
const isToken = (config!.headers || {}).isToken === false
|
||||
if (getAccessToken() && !isToken) {
|
||||
;(config as Recordable).headers.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token
|
||||
const request = (option: any) => {
|
||||
const { url, method, params, data, headersType, responseType } = option
|
||||
return service({
|
||||
url: url,
|
||||
method,
|
||||
params,
|
||||
data,
|
||||
responseType: responseType,
|
||||
headers: {
|
||||
'Content-Type': headersType || default_headers
|
||||
}
|
||||
// 设置租户
|
||||
if (tenantEnable) {
|
||||
const tenantId = getTenantId()
|
||||
if (tenantId) (config as Recordable).headers.common['tenant-id'] = tenantId
|
||||
}
|
||||
const params = config.params || {}
|
||||
const data = config.data || false
|
||||
if (
|
||||
config.method?.toUpperCase() === 'POST' &&
|
||||
(config.headers as AxiosRequestHeaders)['Content-Type'] ===
|
||||
'application/x-www-form-urlencoded'
|
||||
) {
|
||||
config.data = qs.stringify(data)
|
||||
}
|
||||
// get参数编码
|
||||
if (config.method?.toUpperCase() === 'GET' && params) {
|
||||
let url = config.url + '?'
|
||||
for (const propName of Object.keys(params)) {
|
||||
const value = params[propName]
|
||||
if (value !== void 0 && value !== null && typeof value !== 'undefined') {
|
||||
if (typeof value === 'object') {
|
||||
for (const val of Object.keys(value)) {
|
||||
const params = propName + '[' + val + ']'
|
||||
const subPart = encodeURIComponent(params) + '='
|
||||
url += subPart + encodeURIComponent(value[val]) + '&'
|
||||
}
|
||||
} else {
|
||||
url += `${propName}=${encodeURIComponent(value)}&`
|
||||
}
|
||||
}
|
||||
}
|
||||
// 给 get 请求加上时间戳参数,避免从缓存中拿数据
|
||||
// const now = new Date().getTime()
|
||||
// params = params.substring(0, url.length - 1) + `?_t=${now}`
|
||||
url = url.slice(0, -1)
|
||||
config.params = {}
|
||||
config.url = url
|
||||
}
|
||||
return config
|
||||
},
|
||||
(error: AxiosError) => {
|
||||
// Do something with request error
|
||||
console.log(error) // for debug
|
||||
Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
// response 拦截器
|
||||
service.interceptors.response.use(
|
||||
async (response: AxiosResponse<Recordable>) => {
|
||||
const { data } = response
|
||||
const config = response.config
|
||||
if (!data) {
|
||||
// 返回“[HTTP]请求没有返回值”;
|
||||
throw new Error()
|
||||
}
|
||||
const { t } = useI18n()
|
||||
// 未设置状态码则默认成功状态
|
||||
const code = data.code || result_code
|
||||
// 二进制数据则直接返回
|
||||
if (
|
||||
response.request.responseType === 'blob' ||
|
||||
response.request.responseType === 'arraybuffer'
|
||||
) {
|
||||
return response.data
|
||||
}
|
||||
// 获取错误信息
|
||||
const msg = data.msg || errorCode[code] || errorCode['default']
|
||||
if (ignoreMsgs.indexOf(msg) !== -1) {
|
||||
// 如果是忽略的错误码,直接返回 msg 异常
|
||||
return Promise.reject(msg)
|
||||
} else if (code === 401) {
|
||||
// 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了
|
||||
if (!isRefreshToken) {
|
||||
isRefreshToken = true
|
||||
// 1. 如果获取不到刷新令牌,则只能执行登出操作
|
||||
if (!getRefreshToken()) {
|
||||
return handleAuthorized()
|
||||
}
|
||||
// 2. 进行刷新访问令牌
|
||||
try {
|
||||
const refreshTokenRes = await refreshToken()
|
||||
// 2.1 刷新成功,则回放队列的请求 + 当前请求
|
||||
setToken(refreshTokenRes.data.data)
|
||||
config.headers!.Authorization = 'Bearer ' + getAccessToken()
|
||||
requestList.forEach((cb: any) => {
|
||||
cb()
|
||||
})
|
||||
requestList = []
|
||||
return service(config)
|
||||
} catch (e) {
|
||||
// 为什么需要 catch 异常呢?刷新失败时,请求因为 Promise.reject 触发异常。
|
||||
// 2.2 刷新失败,只回放队列的请求
|
||||
requestList.forEach((cb: any) => {
|
||||
cb()
|
||||
})
|
||||
// 提示是否要登出。即不回放当前请求!不然会形成递归
|
||||
return handleAuthorized()
|
||||
} finally {
|
||||
requestList = []
|
||||
isRefreshToken = false
|
||||
}
|
||||
} else {
|
||||
// 添加到队列,等待刷新获取到新的令牌
|
||||
return new Promise((resolve) => {
|
||||
requestList.push(() => {
|
||||
config.headers!.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token 请根据实际情况自行修改
|
||||
resolve(service(config))
|
||||
})
|
||||
})
|
||||
}
|
||||
} else if (code === 500) {
|
||||
ElMessage.error(t('sys.api.errMsg500'))
|
||||
return Promise.reject(new Error(msg))
|
||||
} else if (code === 901) {
|
||||
ElMessage.error(
|
||||
'<div>' +
|
||||
t('sys.api.errMsg901') +
|
||||
'</div>' +
|
||||
'<div> </div>' +
|
||||
'<div>参考 https://doc.iocoder.cn/ 教程</div>' +
|
||||
'<div> </div>' +
|
||||
'<div>5 分钟搭建本地环境</div>'
|
||||
)
|
||||
return Promise.reject(new Error(msg))
|
||||
} else if (code !== 200) {
|
||||
if (msg === '无效的刷新令牌') {
|
||||
// hard coding:忽略这个提示,直接登出
|
||||
console.log(msg)
|
||||
} else {
|
||||
ElNotification.error({
|
||||
title: msg
|
||||
})
|
||||
}
|
||||
return Promise.reject('error')
|
||||
} else {
|
||||
return data
|
||||
}
|
||||
},
|
||||
(error: AxiosError) => {
|
||||
console.log('err' + error) // for debug
|
||||
let { message } = error
|
||||
const { t } = useI18n()
|
||||
if (message === 'Network Error') {
|
||||
message = t('sys.api.errorMessage')
|
||||
} else if (message.includes('timeout')) {
|
||||
message = t('sys.api.apiTimeoutMessage')
|
||||
} else if (message.includes('Request failed with status code')) {
|
||||
message = t('sys.api.apiRequestFailed') + message.substr(message.length - 3)
|
||||
}
|
||||
ElMessage.error(message)
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
const refreshToken = async () => {
|
||||
return await axios.post(base_url + '/system/auth/refresh-token?refreshToken=' + getRefreshToken())
|
||||
})
|
||||
}
|
||||
const handleAuthorized = () => {
|
||||
const { t } = useI18n()
|
||||
if (!isRelogin.show) {
|
||||
isRelogin.show = true
|
||||
ElMessageBox.confirm(t('sys.api.timeoutMessage'), t('common.confirmTitle'), {
|
||||
confirmButtonText: t('login.relogin'),
|
||||
cancelButtonText: t('common.cancel'),
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
const { wsCache } = useCache()
|
||||
resetRouter() // 重置静态路由表
|
||||
wsCache.clear()
|
||||
removeToken()
|
||||
isRelogin.show = false
|
||||
window.location.href = '/'
|
||||
})
|
||||
.catch(() => {
|
||||
isRelogin.show = false
|
||||
})
|
||||
export default {
|
||||
get: async <T = any>(option: any) => {
|
||||
const res = await request({ method: 'GET', ...option })
|
||||
return res.data as unknown as T
|
||||
},
|
||||
post: async <T = any>(option: any) => {
|
||||
const res = await request({ method: 'POST', ...option })
|
||||
return res.data as unknown as T
|
||||
},
|
||||
delete: async <T = any>(option: any) => {
|
||||
const res = await request({ method: 'DELETE', ...option })
|
||||
return res.data as unknown as T
|
||||
},
|
||||
put: async <T = any>(option: any) => {
|
||||
const res = await request({ method: 'PUT', ...option })
|
||||
return res.data as unknown as T
|
||||
},
|
||||
download: async <T = any>(option: any) => {
|
||||
const res = await request({ method: 'GET', responseType: 'blob', ...option })
|
||||
return res as unknown as Promise<T>
|
||||
},
|
||||
upload: async <T = any>(option: any) => {
|
||||
option.headersType = 'multipart/form-data'
|
||||
const res = await request({ method: 'PUT', ...option })
|
||||
return res as unknown as Promise<T>
|
||||
}
|
||||
return Promise.reject(t('sys.api.timeoutMessage'))
|
||||
}
|
||||
export { service }
|
||||
|
229
yudao-ui-admin-vue3/src/config/axios/service.ts
Normal file
229
yudao-ui-admin-vue3/src/config/axios/service.ts
Normal file
@ -0,0 +1,229 @@
|
||||
import axios, {
|
||||
AxiosInstance,
|
||||
AxiosRequestConfig,
|
||||
AxiosRequestHeaders,
|
||||
AxiosResponse,
|
||||
AxiosError
|
||||
} from 'axios'
|
||||
import { ElMessage, ElMessageBox, ElNotification } from 'element-plus'
|
||||
import qs from 'qs'
|
||||
import { config } from '@/config/axios/config'
|
||||
import { getAccessToken, getRefreshToken, getTenantId, removeToken, setToken } from '@/utils/auth'
|
||||
import errorCode from './errorCode'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { resetRouter } from '@/router'
|
||||
import { useCache } from '@/hooks/web/useCache'
|
||||
|
||||
const tenantEnable = import.meta.env.VITE_APP_TENANT_ENABLE
|
||||
const { result_code, base_url, request_timeout } = config
|
||||
|
||||
// 需要忽略的提示。忽略后,自动 Promise.reject('error')
|
||||
const ignoreMsgs = [
|
||||
'无效的刷新令牌', // 刷新令牌被删除时,不用提示
|
||||
'刷新令牌已过期' // 使用刷新令牌,刷新获取新的访问令牌时,结果因为过期失败,此时需要忽略。否则,会导致继续 401,无法跳转到登出界面
|
||||
]
|
||||
// 是否显示重新登录
|
||||
export const isRelogin = { show: false }
|
||||
// Axios 无感知刷新令牌,参考 https://www.dashingdog.cn/article/11 与 https://segmentfault.com/a/1190000020210980 实现
|
||||
// 请求队列
|
||||
let requestList: any[] = []
|
||||
// 是否正在刷新中
|
||||
let isRefreshToken = false
|
||||
|
||||
// 创建axios实例
|
||||
const service: AxiosInstance = axios.create({
|
||||
baseURL: base_url, // api 的 base_url
|
||||
timeout: request_timeout, // 请求超时时间
|
||||
withCredentials: false // 禁用 Cookie 等信息
|
||||
})
|
||||
|
||||
// request拦截器
|
||||
service.interceptors.request.use(
|
||||
(config: AxiosRequestConfig) => {
|
||||
// 是否需要设置 token
|
||||
const isToken = (config!.headers || {}).isToken === false
|
||||
if (getAccessToken() && !isToken) {
|
||||
;(config as Recordable).headers.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token
|
||||
}
|
||||
// 设置租户
|
||||
if (tenantEnable) {
|
||||
const tenantId = getTenantId()
|
||||
if (tenantId) (config as Recordable).headers.common['tenant-id'] = tenantId
|
||||
}
|
||||
const params = config.params || {}
|
||||
const data = config.data || false
|
||||
if (
|
||||
config.method?.toUpperCase() === 'POST' &&
|
||||
(config.headers as AxiosRequestHeaders)['Content-Type'] ===
|
||||
'application/x-www-form-urlencoded'
|
||||
) {
|
||||
config.data = qs.stringify(data)
|
||||
}
|
||||
// get参数编码
|
||||
if (config.method?.toUpperCase() === 'GET' && params) {
|
||||
let url = config.url + '?'
|
||||
for (const propName of Object.keys(params)) {
|
||||
const value = params[propName]
|
||||
if (value !== void 0 && value !== null && typeof value !== 'undefined') {
|
||||
if (typeof value === 'object') {
|
||||
for (const val of Object.keys(value)) {
|
||||
const params = propName + '[' + val + ']'
|
||||
const subPart = encodeURIComponent(params) + '='
|
||||
url += subPart + encodeURIComponent(value[val]) + '&'
|
||||
}
|
||||
} else {
|
||||
url += `${propName}=${encodeURIComponent(value)}&`
|
||||
}
|
||||
}
|
||||
}
|
||||
// 给 get 请求加上时间戳参数,避免从缓存中拿数据
|
||||
// const now = new Date().getTime()
|
||||
// params = params.substring(0, url.length - 1) + `?_t=${now}`
|
||||
url = url.slice(0, -1)
|
||||
config.params = {}
|
||||
config.url = url
|
||||
}
|
||||
return config
|
||||
},
|
||||
(error: AxiosError) => {
|
||||
// Do something with request error
|
||||
console.log(error) // for debug
|
||||
Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
// response 拦截器
|
||||
service.interceptors.response.use(
|
||||
async (response: AxiosResponse<Recordable>) => {
|
||||
const { data } = response
|
||||
const config = response.config
|
||||
if (!data) {
|
||||
// 返回“[HTTP]请求没有返回值”;
|
||||
throw new Error()
|
||||
}
|
||||
const { t } = useI18n()
|
||||
// 未设置状态码则默认成功状态
|
||||
const code = data.code || result_code
|
||||
// 二进制数据则直接返回
|
||||
if (
|
||||
response.request.responseType === 'blob' ||
|
||||
response.request.responseType === 'arraybuffer'
|
||||
) {
|
||||
return response.data
|
||||
}
|
||||
// 获取错误信息
|
||||
const msg = data.msg || errorCode[code] || errorCode['default']
|
||||
if (ignoreMsgs.indexOf(msg) !== -1) {
|
||||
// 如果是忽略的错误码,直接返回 msg 异常
|
||||
return Promise.reject(msg)
|
||||
} else if (code === 401) {
|
||||
// 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了
|
||||
if (!isRefreshToken) {
|
||||
isRefreshToken = true
|
||||
// 1. 如果获取不到刷新令牌,则只能执行登出操作
|
||||
if (!getRefreshToken()) {
|
||||
return handleAuthorized()
|
||||
}
|
||||
// 2. 进行刷新访问令牌
|
||||
try {
|
||||
const refreshTokenRes = await refreshToken()
|
||||
// 2.1 刷新成功,则回放队列的请求 + 当前请求
|
||||
setToken(refreshTokenRes.data.data)
|
||||
config.headers!.Authorization = 'Bearer ' + getAccessToken()
|
||||
requestList.forEach((cb: any) => {
|
||||
cb()
|
||||
})
|
||||
requestList = []
|
||||
return service(config)
|
||||
} catch (e) {
|
||||
// 为什么需要 catch 异常呢?刷新失败时,请求因为 Promise.reject 触发异常。
|
||||
// 2.2 刷新失败,只回放队列的请求
|
||||
requestList.forEach((cb: any) => {
|
||||
cb()
|
||||
})
|
||||
// 提示是否要登出。即不回放当前请求!不然会形成递归
|
||||
return handleAuthorized()
|
||||
} finally {
|
||||
requestList = []
|
||||
isRefreshToken = false
|
||||
}
|
||||
} else {
|
||||
// 添加到队列,等待刷新获取到新的令牌
|
||||
return new Promise((resolve) => {
|
||||
requestList.push(() => {
|
||||
config.headers!.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token 请根据实际情况自行修改
|
||||
resolve(service(config))
|
||||
})
|
||||
})
|
||||
}
|
||||
} else if (code === 500) {
|
||||
ElMessage.error(t('sys.api.errMsg500'))
|
||||
return Promise.reject(new Error(msg))
|
||||
} else if (code === 901) {
|
||||
ElMessage.error(
|
||||
'<div>' +
|
||||
t('sys.api.errMsg901') +
|
||||
'</div>' +
|
||||
'<div> </div>' +
|
||||
'<div>参考 https://doc.iocoder.cn/ 教程</div>' +
|
||||
'<div> </div>' +
|
||||
'<div>5 分钟搭建本地环境</div>'
|
||||
)
|
||||
return Promise.reject(new Error(msg))
|
||||
} else if (code !== 200) {
|
||||
if (msg === '无效的刷新令牌') {
|
||||
// hard coding:忽略这个提示,直接登出
|
||||
console.log(msg)
|
||||
} else {
|
||||
ElNotification.error({
|
||||
title: msg
|
||||
})
|
||||
}
|
||||
return Promise.reject('error')
|
||||
} else {
|
||||
return data
|
||||
}
|
||||
},
|
||||
(error: AxiosError) => {
|
||||
console.log('err' + error) // for debug
|
||||
let { message } = error
|
||||
const { t } = useI18n()
|
||||
if (message === 'Network Error') {
|
||||
message = t('sys.api.errorMessage')
|
||||
} else if (message.includes('timeout')) {
|
||||
message = t('sys.api.apiTimeoutMessage')
|
||||
} else if (message.includes('Request failed with status code')) {
|
||||
message = t('sys.api.apiRequestFailed') + message.substr(message.length - 3)
|
||||
}
|
||||
ElMessage.error(message)
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
const refreshToken = async () => {
|
||||
return await axios.post(base_url + '/system/auth/refresh-token?refreshToken=' + getRefreshToken())
|
||||
}
|
||||
const handleAuthorized = () => {
|
||||
const { t } = useI18n()
|
||||
if (!isRelogin.show) {
|
||||
isRelogin.show = true
|
||||
ElMessageBox.confirm(t('sys.api.timeoutMessage'), t('common.confirmTitle'), {
|
||||
confirmButtonText: t('login.relogin'),
|
||||
cancelButtonText: t('common.cancel'),
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
const { wsCache } = useCache()
|
||||
resetRouter() // 重置静态路由表
|
||||
wsCache.clear()
|
||||
removeToken()
|
||||
isRelogin.show = false
|
||||
window.location.href = '/'
|
||||
})
|
||||
.catch(() => {
|
||||
isRelogin.show = false
|
||||
})
|
||||
}
|
||||
return Promise.reject(t('sys.api.timeoutMessage'))
|
||||
}
|
||||
export { service }
|
@ -1,60 +0,0 @@
|
||||
import { service } from '@/config/axios'
|
||||
|
||||
import { config } from '@/config/axios/config'
|
||||
|
||||
const { default_headers } = config
|
||||
|
||||
const request = (option: AxiosConfig) => {
|
||||
const { url, method, params, data, headersType, responseType } = option
|
||||
return service({
|
||||
url: url,
|
||||
method,
|
||||
params,
|
||||
data,
|
||||
responseType: responseType,
|
||||
headers: {
|
||||
'Content-Type': headersType || default_headers
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function getFn<T = any>(option: AxiosConfig): Promise<T> {
|
||||
const res = await request({ method: 'GET', ...option })
|
||||
return res.data
|
||||
}
|
||||
|
||||
async function postFn<T = any>(option: AxiosConfig): Promise<T> {
|
||||
const res = await request({ method: 'POST', ...option })
|
||||
return res.data
|
||||
}
|
||||
|
||||
async function deleteFn<T = any>(option: AxiosConfig): Promise<T> {
|
||||
const res = await request({ method: 'DELETE', ...option })
|
||||
return res.data
|
||||
}
|
||||
|
||||
async function putFn<T = any>(option: AxiosConfig): Promise<T> {
|
||||
const res = await request({ method: 'PUT', ...option })
|
||||
return res.data
|
||||
}
|
||||
async function downloadFn<T = any>(option: AxiosConfig): Promise<T> {
|
||||
const res = await request({ method: 'GET', responseType: 'blob', ...option })
|
||||
return res as unknown as Promise<T>
|
||||
}
|
||||
|
||||
async function uploadFn<T = any>(option: AxiosConfig): Promise<T> {
|
||||
option.headersType = 'multipart/form-data'
|
||||
const res = await request({ method: 'PUT', ...option })
|
||||
return res as unknown as Promise<T>
|
||||
}
|
||||
|
||||
export const useAxios = () => {
|
||||
return {
|
||||
get: getFn,
|
||||
post: postFn,
|
||||
delete: deleteFn,
|
||||
put: putFn,
|
||||
download: downloadFn,
|
||||
upload: uploadFn
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ import { usePermissionStoreWithOut } from '@/store/modules/permission'
|
||||
import { useDictStoreWithOut } from '@/store/modules/dict'
|
||||
import { useUserStoreWithOut } from '@/store/modules/user'
|
||||
import { listSimpleDictDataApi } from '@/api/system/dict/dict.data'
|
||||
import { isRelogin } from '@/config/axios'
|
||||
import { isRelogin } from '@/config/axios/service'
|
||||
import { getInfoApi } from '@/api/login'
|
||||
|
||||
const { start, done } = useNProgress()
|
||||
|
Loading…
Reference in New Issue
Block a user