2025-11-10 00:59:40 +08:00
|
|
|
|
import axios from 'axios'
|
|
|
|
|
|
import { getAuthHeader } from '@/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', // 刷新token(可选,根据后端要求)
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检查 URL 是否在白名单中
|
|
|
|
|
|
* @param {string} url - 请求 URL
|
|
|
|
|
|
* @returns {boolean}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function isInWhiteList(url) {
|
|
|
|
|
|
if (!url) return false
|
|
|
|
|
|
return WHITE_LIST.some((path) => url.includes(path))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-11 23:51:17 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-11-10 00:59:40 +08:00
|
|
|
|
// 创建 axios 实例
|
|
|
|
|
|
const http = axios.create({
|
|
|
|
|
|
baseURL: '/',
|
|
|
|
|
|
timeout: 180000, // 3分钟
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 请求拦截:自动注入 Token
|
|
|
|
|
|
http.interceptors.request.use((config) => {
|
|
|
|
|
|
// 检查是否需要 token(不在白名单中且未显式设置 isToken = false)
|
|
|
|
|
|
const needToken = config.headers?.isToken !== false && !isInWhiteList(config.url || '')
|
2025-11-11 23:51:17 +08:00
|
|
|
|
config.headers['tenant-id'] = import.meta.env.VITE_TENANT_ID
|
2025-11-10 00:59:40 +08:00
|
|
|
|
if (needToken) {
|
|
|
|
|
|
// 使用统一的 token 管理器获取 header
|
|
|
|
|
|
const authHeader = getAuthHeader()
|
|
|
|
|
|
if (authHeader) {
|
|
|
|
|
|
config.headers.Authorization = authHeader
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 允许跨域第三方域名,使用绝对地址时保持原样
|
|
|
|
|
|
return config
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
http.interceptors.response.use(
|
|
|
|
|
|
(resp) => {
|
|
|
|
|
|
const data = resp.data
|
|
|
|
|
|
// 检查响应数据中的 code 字段
|
|
|
|
|
|
if (data && typeof data.code === 'number' && (data.code === 0 || data.code === 200)) {
|
|
|
|
|
|
return data
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// code 不为 0 时,抛出错误
|
|
|
|
|
|
const error = new Error(data?.message || data?.msg || '请求失败')
|
|
|
|
|
|
error.code = data?.code
|
|
|
|
|
|
error.data = data
|
|
|
|
|
|
return Promise.reject(error)
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
(error) => {
|
|
|
|
|
|
// 统一错误处理:输出关键信息,便于排查 403 等问题
|
|
|
|
|
|
return Promise.reject(error)
|
|
|
|
|
|
}
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
export default http
|
|
|
|
|
|
|
|
|
|
|
|
|