|
@@ -120,6 +120,34 @@ apiClient.interceptors.response.use(
|
|
|
_retry?: boolean;
|
|
_retry?: boolean;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ // Handle network errors (CORS, connection refused, etc.)
|
|
|
|
|
+ if (!error.response) {
|
|
|
|
|
+ console.error('Network Error:', error.message);
|
|
|
|
|
+
|
|
|
|
|
+ // Check if it's a CORS error or connection error
|
|
|
|
|
+ if (error.message === 'Network Error' || error.code === 'ERR_NETWORK') {
|
|
|
|
|
+ // Check if user has auth tokens - if yes, might be a CORS issue with expired token
|
|
|
|
|
+ const tokens = getStoredTokens();
|
|
|
|
|
+ if (tokens) {
|
|
|
|
|
+ // Clear auth data and redirect to login
|
|
|
|
|
+ clearStoredAuth();
|
|
|
|
|
+ toast.error('网络连接失败或登录已过期,请重新登录', '连接错误', 2000);
|
|
|
|
|
+
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ window.location.href = '/login';
|
|
|
|
|
+ }, 500);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ toast.error('无法连接到服务器,请检查网络连接', '网络错误');
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return Promise.reject({
|
|
|
|
|
+ status: 0,
|
|
|
|
|
+ message: error.message || '网络错误',
|
|
|
|
|
+ originalError: error,
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// Handle 401 Unauthorized errors (token expired or invalid)
|
|
// Handle 401 Unauthorized errors (token expired or invalid)
|
|
|
if (error.response?.status === 401) {
|
|
if (error.response?.status === 401) {
|
|
|
const errorData = error.response.data as any;
|
|
const errorData = error.response.data as any;
|
|
@@ -189,11 +217,13 @@ apiClient.interceptors.response.use(
|
|
|
processQueue(refreshError);
|
|
processQueue(refreshError);
|
|
|
clearStoredAuth();
|
|
clearStoredAuth();
|
|
|
|
|
|
|
|
- // Show error message
|
|
|
|
|
- toast.error('登录已过期,请重新登录');
|
|
|
|
|
|
|
+ // Show error message and wait a bit before redirecting
|
|
|
|
|
+ toast.error('登录已过期,请重新登录', '认证失败', 2000);
|
|
|
|
|
|
|
|
- // Redirect to login page
|
|
|
|
|
- window.location.href = '/login';
|
|
|
|
|
|
|
+ // Redirect to login page after a short delay to allow toast to show
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ window.location.href = '/login';
|
|
|
|
|
+ }, 500);
|
|
|
|
|
|
|
|
return Promise.reject(refreshError);
|
|
return Promise.reject(refreshError);
|
|
|
} finally {
|
|
} finally {
|
|
@@ -201,12 +231,17 @@ apiClient.interceptors.response.use(
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
// 401 error but not token expiration (invalid credentials, etc.)
|
|
// 401 error but not token expiration (invalid credentials, etc.)
|
|
|
|
|
+ // OR token refresh already attempted but still failed
|
|
|
// Clear auth data and redirect to login
|
|
// Clear auth data and redirect to login
|
|
|
clearStoredAuth();
|
|
clearStoredAuth();
|
|
|
- toast.error('认证失败,请重新登录');
|
|
|
|
|
|
|
|
|
|
- // Redirect to login page
|
|
|
|
|
- window.location.href = '/login';
|
|
|
|
|
|
|
+ // Show error message and wait a bit before redirecting
|
|
|
|
|
+ toast.error('认证失败,请重新登录', '认证失败', 2000);
|
|
|
|
|
+
|
|
|
|
|
+ // Redirect to login page after a short delay to allow toast to show
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ window.location.href = '/login';
|
|
|
|
|
+ }, 500);
|
|
|
|
|
|
|
|
return Promise.reject(error);
|
|
return Promise.reject(error);
|
|
|
}
|
|
}
|
|
@@ -253,9 +288,18 @@ apiClient.interceptors.response.use(
|
|
|
originalData: error.response?.data,
|
|
originalData: error.response?.data,
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- // Show error toast (skip for 401 errors as they're handled above)
|
|
|
|
|
|
|
+ // Show error toast (skip for 401 errors as they're handled above with their own messages)
|
|
|
if (error.response?.status !== 401) {
|
|
if (error.response?.status !== 401) {
|
|
|
- toast.error(errorMessage);
|
|
|
|
|
|
|
+ // Determine toast type based on status code
|
|
|
|
|
+ if (error.response?.status === 403) {
|
|
|
|
|
+ toast.warning(errorMessage, '权限不足');
|
|
|
|
|
+ } else if (error.response?.status === 404) {
|
|
|
|
|
+ toast.warning(errorMessage, '资源不存在');
|
|
|
|
|
+ } else if (error.response?.status && error.response.status >= 500) {
|
|
|
|
|
+ toast.error(errorMessage, '服务器错误');
|
|
|
|
|
+ } else {
|
|
|
|
|
+ toast.error(errorMessage, '请求失败');
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Return a rejected promise with formatted error
|
|
// Return a rejected promise with formatted error
|