提示词保存
This commit is contained in:
152
frontend/api/axios/client.js
Normal file
152
frontend/api/axios/client.js
Normal file
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* Mono 级别的 C 端 Axios 实例
|
||||
* 供 monorepo 中所有应用使用的统一 HTTP 客户端
|
||||
*/
|
||||
|
||||
import axios from 'axios'
|
||||
import { getAuthHeader, clearAllTokens } from '@gold/utils/token-manager'
|
||||
|
||||
/**
|
||||
* 不需要 token 的接口白名单
|
||||
*/
|
||||
const WHITE_LIST = [
|
||||
'/auth/login',
|
||||
'/auth/send-sms-code',
|
||||
'/auth/sms-login',
|
||||
'/auth/validate-sms-code',
|
||||
'/auth/register',
|
||||
'/auth/reset-password',
|
||||
'/auth/refresh-token',
|
||||
]
|
||||
|
||||
/**
|
||||
* 检查 URL 是否在白名单中
|
||||
*/
|
||||
function isInWhiteList(url) {
|
||||
if (!url) return false
|
||||
return WHITE_LIST.some((path) => url.includes(path))
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 401 未授权错误
|
||||
*/
|
||||
let isHandling401 = false
|
||||
function handle401Error() {
|
||||
if (isHandling401) return
|
||||
|
||||
isHandling401 = true
|
||||
|
||||
try {
|
||||
clearAllTokens()
|
||||
} catch (e) {
|
||||
console.error('清空 token 失败:', e)
|
||||
}
|
||||
|
||||
// 延迟重置标志
|
||||
setTimeout(() => {
|
||||
isHandling401 = false
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 C 端 Axios 实例
|
||||
* @param {Object} options - 配置选项
|
||||
* @param {string} options.baseURL - 基础 URL
|
||||
* @param {number} options.timeout - 超时时间(毫秒)
|
||||
* @param {Function} options.on401 - 401 错误处理函数
|
||||
* @param {Function} options.on403 - 403 错误处理函数
|
||||
* @returns {AxiosInstance} Axios 实例
|
||||
*/
|
||||
export function createClientAxios(options = {}) {
|
||||
const {
|
||||
baseURL = '/',
|
||||
timeout = 180000,
|
||||
on401 = handle401Error,
|
||||
on403 = null,
|
||||
} = options
|
||||
|
||||
const client = axios.create({
|
||||
baseURL,
|
||||
timeout,
|
||||
})
|
||||
|
||||
// 请求拦截器
|
||||
client.interceptors.request.use((config) => {
|
||||
// 添加 tenant-id
|
||||
const tenantId =
|
||||
(typeof import.meta !== 'undefined' && import.meta.env?.VITE_TENANT_ID) ||
|
||||
(typeof process !== 'undefined' && process.env?.VITE_TENANT_ID) ||
|
||||
'1'
|
||||
|
||||
if (tenantId) {
|
||||
config.headers['tenant-id'] = tenantId
|
||||
}
|
||||
|
||||
// 添加 Authorization header
|
||||
const needToken = config.headers?.isToken !== false && !isInWhiteList(config.url || '')
|
||||
if (needToken) {
|
||||
const authHeader = getAuthHeader()
|
||||
if (authHeader) {
|
||||
config.headers.Authorization = authHeader
|
||||
}
|
||||
}
|
||||
|
||||
return config
|
||||
})
|
||||
|
||||
// 响应拦截器
|
||||
client.interceptors.response.use(
|
||||
(response) => {
|
||||
const data = response.data
|
||||
|
||||
// 检查业务状态码
|
||||
if (data && typeof data.code === 'number') {
|
||||
if (data.code === 0 || data.code === 200) {
|
||||
return data
|
||||
}
|
||||
|
||||
// 处理 401
|
||||
if (data.code === 401 && typeof on401 === 'function') {
|
||||
on401()
|
||||
}
|
||||
|
||||
// 处理 403(业务状态码)
|
||||
if (data.code === 403 && typeof on403 === 'function') {
|
||||
on403()
|
||||
}
|
||||
|
||||
// 抛出业务错误
|
||||
const error = new Error(data?.message || data?.msg || '请求失败')
|
||||
error.code = data?.code
|
||||
error.data = data
|
||||
return Promise.reject(error)
|
||||
}
|
||||
|
||||
return data
|
||||
},
|
||||
(error) => {
|
||||
// 处理 HTTP 401
|
||||
if (error.response?.status === 401 && typeof on401 === 'function') {
|
||||
on401()
|
||||
}
|
||||
|
||||
// 处理 HTTP 403
|
||||
if (error.response?.status === 403 && typeof on403 === 'function') {
|
||||
on403()
|
||||
}
|
||||
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认导出的 C 端 Axios 实例
|
||||
* 可在应用层覆盖配置
|
||||
*/
|
||||
export const clientAxios = createClientAxios()
|
||||
|
||||
export default clientAxios
|
||||
|
||||
Reference in New Issue
Block a user