Files
biji/biji-qianduan/src/utils/axios.js
ikmkj 23ced99e20 feat: 添加XSS防护工具函数并优化多个功能模块
refactor(前端): 重构登录页面和用户状态管理逻辑

fix(后端): 修复用户密码更新逻辑和错误提示

feat(后端): 实现分页搜索功能并优化文件删除逻辑

perf(前端): 优化笔记编辑器自动保存和状态提示

fix(后端): 增强图片上传安全验证

style(前端): 调整笔记预览页面按钮权限控制

chore: 更新生产环境配置和测试数据库依赖

feat(前端): 添加虚拟列表组件优化性能

fix(前端): 修复笔记编辑器返回逻辑和状态保存

refactor(前端): 优化axios拦截器错误处理逻辑

docs: 更新方法注释和参数说明
2026-03-04 18:29:52 +08:00

129 lines
3.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import axios from 'axios'
import { useUserStore } from '../stores/user'
import { ElMessage } from 'element-plus'
import router from '../router'
import { getReplayAttackHeaders, needsReplayAttackValidation } from './security'
let retryCount = 0
const MAX_RETRIES = 3
const instance = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
headers: {
'Content-Type': 'application/json'
}
})
// 请求拦截器
instance.interceptors.request.use(
config => {
try {
const userStore = useUserStore()
if (userStore.token) {
config.headers['Authorization'] = `Bearer ${userStore.token}`
}
// 添加 CSRF token
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content
if (csrfToken) {
config.headers['X-CSRF-Token'] = csrfToken
}
// 添加防重放攻击请求头POST/PUT/DELETE 请求)
if (needsReplayAttackValidation(config.method, config.url)) {
const replayHeaders = getReplayAttackHeaders()
config.headers['X-Timestamp'] = replayHeaders['X-Timestamp']
config.headers['X-Nonce'] = replayHeaders['X-Nonce']
}
} catch (error) {
console.warn('Failed to get user store:', error)
}
return config
},
error => {
return Promise.reject(error)
}
)
// 响应拦截器
instance.interceptors.response.use(
response => {
retryCount = 0
const res = response.data;
if (res.code !== 200) {
ElMessage({
message: res.msg || 'Error',
type: 'error',
duration: 5 * 1000
});
return Promise.reject(new Error(res.msg || 'Error'));
} else {
return res.data;
}
},
async error => {
if (error.response) {
const status = error.response.status;
const data = error.response.data;
// 503 - 服务器繁忙,重试
if (status === 503 && retryCount < MAX_RETRIES) {
retryCount++
await new Promise(resolve => setTimeout(resolve, 1000 * retryCount))
return instance(error.config)
}
retryCount = 0
// 401 - 未授权
if (status === 401) {
try {
const userStore = useUserStore()
userStore.logout();
ElMessage.error('登录已过期,请重新登录');
router.push('/login');
} catch (error) {
console.warn('Failed to get user store:', error)
}
return Promise.reject(error);
}
// 403 - 权限不足
if (status === 403) {
const msg = data?.msg || '无权操作';
ElMessage.error(msg);
return Promise.reject(new Error(msg));
}
// 429 - 请求过于频繁
if (status === 429) {
const msg = data?.msg || '请求过于频繁,请稍后再试';
ElMessage.error(msg);
return Promise.reject(new Error(msg));
}
// 400 - 验证码错误等
if (status === 400) {
const msg = data?.msg || '请求参数错误';
ElMessage.error(msg);
return Promise.reject(new Error(msg));
}
// 其他错误
const isDev = import.meta.env.DEV;
const msg = isDev
? (data?.msg || error.message)
: (data?.msg || '操作失败,请稍后重试');
ElMessage.error(msg);
} else {
ElMessage({
message: error.message,
type: 'error',
duration: 5 * 1000
});
}
return Promise.reject(error);
}
)
export default instance