From 6dd3bd8e9d43e2b1ebca4c6a8f3722520ed63b18 Mon Sep 17 00:00:00 2001 From: Xu Liang Date: Sat, 2 May 2026 19:25:15 +0800 Subject: [PATCH] feat: improve login UX and add admin login lock reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Translate all login error messages to Chinese (network errors, HTTP status codes, URL validation errors) - Add password visibility toggle (eye icon) to login form - Add live countdown timer when login is locked, disable login button during cooldown, auto-clear error when countdown ends - Add X button red hover feedback in server settings dialog - Add LoginGuard.Unlock() method to clear Redis lock/failure keys - Expose POST /admin-users/:id/reset-login-lock endpoint in ops API - Add "重置登录保护" button in ops-web user management table Co-Authored-By: Claude Sonnet 4.6 --- .../renderer/composables/useDesktopSession.ts | 19 +++- .../src/renderer/views/LoginView.vue | 99 +++++++++++++++++-- .../src/renderer/views/SettingsView.vue | 5 +- apps/ops-web/src/views/AdminUsersView.vue | 31 ++++++ server/cmd/ops-api/main.go | 3 +- server/internal/ops/app/admin_user.go | 29 +++++- .../ops/transport/admin_user_handler.go | 15 +++ server/internal/ops/transport/router.go | 1 + server/internal/shared/auth/login_guard.go | 33 +++++-- 9 files changed, 212 insertions(+), 23 deletions(-) diff --git a/apps/desktop-client/src/renderer/composables/useDesktopSession.ts b/apps/desktop-client/src/renderer/composables/useDesktopSession.ts index c9f5476..5569513 100644 --- a/apps/desktop-client/src/renderer/composables/useDesktopSession.ts +++ b/apps/desktop-client/src/renderer/composables/useDesktopSession.ts @@ -391,10 +391,23 @@ function formatLoginError(err: unknown): string { login_in_progress: '登录请求正在处理中', login_guard_unavailable: '登录保护暂时不可用', } - const message = messages[err.message] ?? err.message.replaceAll('_', ' ') - return err.detail ? `${message},${err.detail}` : message + if (err.message in messages) { + const message = messages[err.message]! + return err.message === 'login_locked' && err.detail ? `${message},${err.detail}` : message + } + if (err.status === 404) return '登录接口不存在,请确认服务器地址' + if (err.status && err.status >= 500) return '服务器内部错误,请稍后重试' + if (err.status && err.status >= 400) return '请求被服务器拒绝,请检查账号信息' + if (!err.status) return '网络连接失败,请检查服务器地址或网络' + return err.message.replaceAll('_', ' ') } - return err instanceof Error ? err.message : '登录失败,请稍后重试' + if (err instanceof Error) { + const msg = err.message + if (msg.includes('Invalid URL') || msg.includes('Failed to construct')) { + return '服务器地址无效,请检查网关 API 地址设置' + } + } + return '登录失败,请稍后重试' } async function performLogin(payload: LoginRequest): Promise { diff --git a/apps/desktop-client/src/renderer/views/LoginView.vue b/apps/desktop-client/src/renderer/views/LoginView.vue index 769e616..3a5fc00 100644 --- a/apps/desktop-client/src/renderer/views/LoginView.vue +++ b/apps/desktop-client/src/renderer/views/LoginView.vue @@ -1,11 +1,12 @@ @@ -122,14 +156,25 @@ onBeforeUnmount(() => { /> -
+
+
@@ -139,11 +184,11 @@ onBeforeUnmount(() => {
- -

{{ error }}

+

{{ displayError }}

@@ -171,7 +216,6 @@ onBeforeUnmount(() => { spellcheck="false" /> -

修改后对本机下次登录生效。