diff --git a/apps/web/src/api/client.ts b/apps/web/src/api/client.ts index 771b76256..042e54a64 100644 --- a/apps/web/src/api/client.ts +++ b/apps/web/src/api/client.ts @@ -3,6 +3,7 @@ * 封装 Axios 实例,配置拦截器和 Token 管理 */ import axios, { AxiosError, InternalAxiosRequestConfig } from 'axios'; +import { message } from 'antd'; import { useAuthStore } from '@/store/authStore'; // 创建 Axios 实例 @@ -28,14 +29,43 @@ apiClient.interceptors.request.use( } ); -// 响应拦截器:处理未授权状态 +// 响应拦截器:统一错误提示 + 处理未授权状态 apiClient.interceptors.response.use( (response) => response, - async (error: AxiosError) => { + async (error: AxiosError<{ detail?: string; message?: string; msg?: string }>) => { + // 401 → 清除登录态 if (error.response?.status === 401) { useAuthStore.getState().clearAuth(); } + // 提取后端返回的错误信息(detail / message / msg) + const data = error.response?.data; + const serverMsg = data?.detail || data?.message || data?.msg; + let handled = false; + + if (error.code === 'ECONNABORTED' || error.message?.includes('timeout')) { + message.error('请求超时,请检查网络后重试'); + handled = true; + } else if (!error.response) { + message.error('网络连接异常,请检查网络设置'); + handled = true; + } else if (serverMsg) { + message.error(serverMsg); + handled = true; + } else { + const status = error.response?.status; + if (status && status >= 500) { + message.error('服务器繁忙,请稍后再试'); + handled = true; + } + // 4xx 且无具体信息时不弹通用提示,由各组件自行处理 + } + + // 标记已展示过提示,组件 onError 可据此跳过重复 toast + if (handled) { + (error as any).__msgShown = true; + } + return Promise.reject(error); } ); diff --git a/apps/web/src/pages/assets/AssetLibrary.tsx b/apps/web/src/pages/assets/AssetLibrary.tsx index 16fee17f3..dd53be6ad 100644 --- a/apps/web/src/pages/assets/AssetLibrary.tsx +++ b/apps/web/src/pages/assets/AssetLibrary.tsx @@ -120,6 +120,7 @@ const AssetLibrary: React.FC = () => { queryClient.invalidateQueries({ queryKey: ['assets', activeLibrary] }); queryClient.invalidateQueries({ queryKey: ['asset-libraries'] }); }, + onError: (err: any) => { if (!err?.__msgShown) message.error('删除失败') }, }); /** 处理上传 */ diff --git a/apps/web/src/pages/dashboard/Dashboard.tsx b/apps/web/src/pages/dashboard/Dashboard.tsx index 6d2b674ae..891ea5fc5 100644 --- a/apps/web/src/pages/dashboard/Dashboard.tsx +++ b/apps/web/src/pages/dashboard/Dashboard.tsx @@ -16,6 +16,7 @@ import { Button, Progress, Space, + Alert, } from 'antd'; import { FileOutlined, @@ -60,7 +61,7 @@ const StatusTag: React.FC<{ status: string }> = ({ status }) => { const Dashboard: React.FC = () => { const navigate = useNavigate(); - const { data, isLoading } = useQuery({ + const { data, isLoading, isError } = useQuery({ queryKey: ['dashboard-overview'], queryFn: getDashboardOverview, }); @@ -111,6 +112,14 @@ const Dashboard: React.FC = () => { ); } + if (isError) { + return ( +