工程管理
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

246 lines
7.0 KiB

2 months ago
import type {
AxiosInstance,
AxiosRequestConfig,
AxiosRequestHeaders,
AxiosResponse,
InternalAxiosRequestConfig,
} from 'axios'
import qs from 'qs'
import Keys from '../Keys'
import axios, { AxiosError, isCancel } from 'axios'
// import {
// getRefreshToken,
// getTenantId,
// getToken,
// removeToken,
// setToken,
// } from '@/utils/auth'
import { authErrMap, ignoreMsgs, networkErrMap } from '../basic/utils'
import type { Result } from '../basic/httpTypes'
import type { APIConfigKeys } from './config'
import { useRouter } from 'vue-router'
import { useMessage } from '@/composables/useMessage'
const router = useRouter()
const message = useMessage()
const basicHeader = {
tenant() {
// const tenant = getTenantId()
// if (tenant) return tenant
return ''
},
token() {
// const token = getToken()
// if (token) return 'Bearer ' + token
return ''
},
}
interface Config {
baseURL?: string
baseAPI: string
}
const instances: Record<string, AxiosInstance> = {}
let isRefreshToken = false // 是否正在刷新中
let requestList: any[] = [] // 请求队列
const createAxiosInstance = (module: APIConfigKeys, config: Config) => {
if (!config || !config.baseAPI) {
throw new Error(`Invalid configuration for module: ${module}`)
}
const { baseAPI } = config
if (!instances[module]) {
const instance = axios.create({
baseURL: `${baseAPI}`,
timeout: 10000,
headers: {
'Content-Type': 'application/json',
},
})
instances[module] = instance
}
const service = instances[module]
service.interceptors.request.use(
(config: InternalAxiosRequestConfig): InternalAxiosRequestConfig => {
// config.headers.Authorization = basicHeader.token()
// config.headers['tenant-id'] = basicHeader.tenant()
if (config.url?.includes('/login')) {
config.headers['tenant-id'] = '1'
}
2 months ago
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)
}
if (config.method?.toUpperCase() === 'GET' && params) {
config.params = {}
const paramsStr = qs.stringify(params, { allowDots: true })
if (paramsStr) {
config.url = config.url + '?' + paramsStr
}
}
return config
},
(error: AxiosError): Promise<AxiosError> => {
return Promise.reject(error)
}
)
service.interceptors.response.use(
async (res: AxiosResponse) => {
const config = res.config
let { data } = res
if (!res.data) {
throw new Error('返回“[HTTP]请求没有返回值”')
}
if (
res.request.responseType === 'blob' ||
res.request.responseType === 'arraybuffer'
) {
// 注意:如果导出的响应为 json,说明可能失败了,不直接返回进行下载
if (res.data.type !== 'application/json') {
return Promise.resolve({ code: res.status, data: res.data })
}
data = await new Response(res.data).json()
}
const code = data.code || 200
const msg = data.msg || authErrMap[code] || authErrMap['default']
if (ignoreMsgs.indexOf(msg) !== -1) {
// 如果是忽略的错误码,直接返回 msg 异常
return Promise.reject({ code: null, msg })
} else
// if (code === 401) {
// if (!isRefreshToken) {
// isRefreshToken = true
// if (!getRefreshToken()) logout()
// try {
// const refreshTokenRes = await refreshToken()
// if (refreshTokenRes.data.code !== 0) {
// logout()
// return Promise.reject({ code, msg })
// }
// setToken(refreshTokenRes.data.data.accessToken)
// config.headers!.Authorization = 'Bearer ' + getToken()
// requestList.forEach((cb: any) => {
// cb()
// })
// requestList = []
// // 重连接socket
// // openSocket()
// return service(config)
// } catch (e) {
// logout()
// return Promise.reject({ code, msg })
// } finally {
// requestList = []
// isRefreshToken = false
// }
// } else {
// return new Promise(resolve => {
// requestList.push(() => {
// config.headers!.Authorization = 'Bearer ' + getToken()
// resolve(service(config))
// })
// })
// }
// } else
if (code === 500) {
return Promise.reject({ code, msg })
} else if (code !== 200) {
// if (msg === '无效的刷新令牌') {
// // hard coding:忽略这个提示,直接登出
// console.log(msg)
// } else {
// ElMessage.error(msg)
// }
return Promise.reject({ code, msg })
}
return data
},
(error: any): Promise<any> => {
if (isCancel(error)) {
return Promise.reject({
name: 'CanceledError',
message: 'canceled',
code: 10001
})
2 months ago
}
const message = '请求错误'
if (error.code === 'ECONNABORTED') {
return Promise.reject({ code: null, msg: '服务器响应超时' })
}
if (!error.response) {
return Promise.reject({ code: null, msg: message })
}
const status = error.response?.status
const unKnowError = `连接出错(${error.response.status})!`
if (status === 401) {
localStorage.removeItem(Keys.STORAGE_TOKEN)
router.push('/login')
}
const msg = networkErrMap[status] ? networkErrMap[status] : unKnowError
return Promise.reject({ code: status || null, msg: msg })
}
)
if (!service) {
throw new Error(`Failed to create Axios instance for module: ${module}`)
}
// const refreshToken = async () => {
// // axios.defaults.headers.common['tenant-id'] = getTenantId()
// return await axios.post(
// `${VITE_BASE_API_SYSTEM}/auth/refresh-token?refreshToken=` + getRefreshToken()
// )
// }
async function request<T = any>(config: AxiosRequestConfig): Promise<Result<T>> {
try {
const result = (await service(config)) as Result<T>
return result
} catch (err: any) {
const result: Result<T> = {
code: err?.code || -1,
msg: err.msg || err.message,
data: err.data || null,
}
return result
}
}
return request
}
// let isShowLogout = false
// async function logout() {
// if (isShowLogout) return
// isShowLogout = true
// await message.forceConfirm('登录状态已失效,请重新登录', '系统提示', '重新登录')
// removeToken()
// isShowLogout = false
// window.location.href = '/login'
// }
export default createAxiosInstance