diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index cd5c1df..6998856 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -72,7 +72,15 @@ "submitting": "Connecting...", "error_title": "Login Failed", "error_required": "Please fill in complete connection information", - "error_invalid": "Connection failed, please check address and key" + "error_invalid": "Connection failed, please check address and key", + "error_network": "Network connection failed, please check your network or server address", + "error_timeout": "Connection timed out, server not responding", + "error_unauthorized": "Authentication failed, invalid management key", + "error_forbidden": "Access denied, insufficient permissions", + "error_not_found": "Server address invalid or management API not enabled", + "error_server": "Internal server error, please try again later", + "error_cors": "Cross-origin request blocked, please check server configuration", + "error_ssl": "SSL/TLS certificate verification failed" }, "header": { "check_connection": "Check Connection", diff --git a/src/i18n/locales/zh-CN.json b/src/i18n/locales/zh-CN.json index 0741e93..c69d536 100644 --- a/src/i18n/locales/zh-CN.json +++ b/src/i18n/locales/zh-CN.json @@ -72,7 +72,15 @@ "submitting": "连接中...", "error_title": "登录失败", "error_required": "请填写完整的连接信息", - "error_invalid": "连接失败,请检查地址和密钥" + "error_invalid": "连接失败,请检查地址和密钥", + "error_network": "网络连接失败,请检查网络或服务器地址", + "error_timeout": "连接超时,服务器无响应", + "error_unauthorized": "认证失败,管理密钥无效", + "error_forbidden": "访问被拒绝,权限不足", + "error_not_found": "服务器地址无效或管理接口未启用", + "error_server": "服务器内部错误,请稍后重试", + "error_cors": "跨域请求被阻止,请检查服务器配置", + "error_ssl": "SSL/TLS 证书验证失败" }, "header": { "check_connection": "检查连接", diff --git a/src/pages/LoginPage.tsx b/src/pages/LoginPage.tsx index 1f16ab0..255af84 100644 --- a/src/pages/LoginPage.tsx +++ b/src/pages/LoginPage.tsx @@ -7,8 +7,52 @@ import { IconEye, IconEyeOff } from '@/components/ui/icons'; import { useAuthStore, useLanguageStore, useNotificationStore } from '@/stores'; import { detectApiBaseFromLocation, normalizeApiBase } from '@/utils/connection'; import { INLINE_LOGO_JPEG } from '@/assets/logoInline'; +import type { ApiError } from '@/types'; import styles from './LoginPage.module.scss'; +/** + * 将 API 错误转换为本地化的用户友好消息 + */ +function getLocalizedErrorMessage(error: any, t: (key: string) => string): string { + const apiError = error as ApiError; + const status = apiError?.status; + const code = apiError?.code; + const message = apiError?.message || ''; + + // 根据 HTTP 状态码判断 + if (status === 401) { + return t('login.error_unauthorized'); + } + if (status === 403) { + return t('login.error_forbidden'); + } + if (status === 404) { + return t('login.error_not_found'); + } + if (status && status >= 500) { + return t('login.error_server'); + } + + // 根据 axios 错误码判断 + if (code === 'ECONNABORTED' || message.toLowerCase().includes('timeout')) { + return t('login.error_timeout'); + } + if (code === 'ERR_NETWORK' || message.toLowerCase().includes('network error')) { + return t('login.error_network'); + } + if (code === 'ERR_CERT_AUTHORITY_INVALID' || message.toLowerCase().includes('certificate')) { + return t('login.error_ssl'); + } + + // 检查 CORS 错误 + if (message.toLowerCase().includes('cors') || message.toLowerCase().includes('cross-origin')) { + return t('login.error_cors'); + } + + // 默认错误消息 + return t('login.error_invalid'); +} + export function LoginPage() { const { t } = useTranslation(); const navigate = useNavigate(); @@ -81,7 +125,7 @@ export function LoginPage() { showNotification(t('common.connected_status'), 'success'); navigate('/', { replace: true }); } catch (err: any) { - const message = err?.message || t('login.error_invalid'); + const message = getLocalizedErrorMessage(err, t); setError(message); showNotification(`${t('notification.login_failed')}: ${message}`, 'error'); } finally {