| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 |
- import axios from 'axios';
- // 1. 创建 axios 实例
- const api = axios.create({
- // 根据你的环境变量或硬编码地址
- baseURL: process.env.NEXT_PUBLIC_API_URL || 'http://45.137.220.138:8888',
- headers: {
- 'Content-Type': 'application/json',
- },
- });
- // 2. 请求拦截器:自动携带 Token
- api.interceptors.request.use(
- (config) => {
- // 仅在客户端执行时获取 token
- if (typeof window !== 'undefined') {
- const token = localStorage.getItem('rsid');
- if (token) {
- config.headers.Authorization = `Bearer ${token}`;
- }
- }
- return config;
- },
- (error) => {
- return Promise.reject(error);
- }
- );
- // 3. 响应拦截器:全局处理 401 自动跳转
- api.interceptors.response.use(
- (response) => {
- // 请求成功,直接返回
- return response;
- },
- (error) => {
- // 检查响应是否存在,且状态码是否为 401
- if (error.response && error.response.status === 401) {
- console.warn('Session expired or unauthorized (401). Cleaning up...');
- // 确保在浏览器端执行
- if (typeof window !== 'undefined') {
- // A. 清除本地存储的 Token 和用户信息
- localStorage.removeItem('rsid');
- localStorage.removeItem('user_info');
- // B. 触发 storage 事件,通知 Navbar 等组件更新状态 (变为未登录)
- window.dispatchEvent(new Event('storage'));
- // C. 强制跳转到登录页
- // 增加判断:如果当前已经在 /login 页面,就不需要跳转了,防止登录失败时死循环刷新
- if (!window.location.pathname.startsWith('/login')) {
- // 使用 window.location.href 强制跳转,确保页面状态彻底重置
- // 也可以使用 router.push('/login'),但 axios 外部拿不到 router 实例,href 最通用
- window.location.href = '/login';
- }
- }
- }
-
- // 继续抛出错误,以便组件内具体的 try/catch 也能捕获(比如显示"用户名密码错误")
- return Promise.reject(error);
- }
- );
- export default api;
|