From 6183047fd677ae1ffe7bdc8d6f36dcdc18a9507b Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 1 Jun 2026 11:24:55 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=85=A8=E7=AB=99=20bug=20=E5=AE=A1?= =?UTF-8?q?=E6=9F=A5=E4=BF=AE=E5=A4=8D=20(=E5=89=8D=E7=AB=AF9=E9=A1=B9=20+?= =?UTF-8?q?=20=E5=90=8E=E7=AB=AF5=E9=A1=B9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 前端修复: - P0: App.vue http 未导入导致全局搜索崩溃 - P1: TOTP 登录流程断裂 (TotpRequiredError 非 ApiError 子类) - P1: ServersPage 编辑服务器 domain 被端口字符串污染 - P1: PushPage Set[0] 无效 → values().next().value - P1: SettingsPage API 返回字符串未转数字 - P2: api/index.ts getList 重复定义移除 - P2: LoginPage 锁定倒计时 now ref + watch 更新 - P2: TerminalPage 路径验证正则放松 (允许空格/中文) - P2: useWebSocket CONNECTING/CLOSING 状态关闭旧连接 后端修复: - P1: websocket.py redis.keys() → scan_iter() 避免阻塞 - P1: auth_service.py TTL 仅在 key 无 TTL 时设置 - P1: servers.py 批量操作加 asyncio.Lock 避免并发 session commit - P2: settings.py asyncio.get_event_loop() → get_running_loop() - P2: settings.py datetime.utcfromtimestamp() → datetime.fromtimestamp(tz=utc) Co-Authored-By: Claude Opus 4.8 --- .claude/launch.json | 1 + frontend/src/App.vue | 2 +- frontend/src/api/index.ts | 6 ----- frontend/src/composables/useWebSocket.ts | 9 ++++++- frontend/src/pages/LoginPage.vue | 27 ++++++++++++++------ frontend/src/pages/PushPage.vue | 2 +- frontend/src/pages/ServersPage.vue | 2 +- frontend/src/pages/SettingsPage.vue | 7 ++++- frontend/src/pages/TerminalPage.vue | 2 +- login-before.png | Bin 0 -> 1541359 bytes login-centering-test.png | Bin 0 -> 14662 bytes login-preview.png | Bin 0 -> 96854 bytes server/api/servers.py | 19 +++++++++----- server/api/settings.py | 8 +++--- server/api/websocket.py | 7 ++--- server/application/services/auth_service.py | 6 +++-- 16 files changed, 60 insertions(+), 38 deletions(-) create mode 100644 login-before.png create mode 100644 login-centering-test.png create mode 100644 login-preview.png diff --git a/.claude/launch.json b/.claude/launch.json index 0c9df316..0ce0a156 100644 --- a/.claude/launch.json +++ b/.claude/launch.json @@ -11,6 +11,7 @@ "name": "Frontend Dev", "runtimeExecutable": "npm", "runtimeArgs": ["run", "dev"], + "cwd": "frontend", "port": 3000 } ] diff --git a/frontend/src/App.vue b/frontend/src/App.vue index f0f9f220..451a9af3 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -236,7 +236,7 @@ import { useRoute, useRouter } from 'vue-router' import { useTheme } from 'vuetify' import { useAuthStore } from '@/stores/auth' import { useWebSocket } from '@/composables/useWebSocket' -import { api } from '@/api' +import { api, http } from '@/api' const route = useRoute() const router = useRouter() diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index 1a504f27..c1f846e5 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -107,12 +107,6 @@ export const http = { /** Upload FormData (multipart, auto Content-Type with boundary) */ upload: (path: string, formData: FormData) => api(path, { method: 'POST', body: formData }), - - /** GET a list that returns a bare array — wraps in {items, total} */ - getList: async (path: string, params?: Record) => { - const arr = await api(path, { method: 'GET', params }) - return { items: (arr || []) as T[], total: (arr || []).length } - }, } export class ApiError extends Error { diff --git a/frontend/src/composables/useWebSocket.ts b/frontend/src/composables/useWebSocket.ts index 2e8cbe16..c28dfdfa 100644 --- a/frontend/src/composables/useWebSocket.ts +++ b/frontend/src/composables/useWebSocket.ts @@ -49,7 +49,14 @@ export function useWebSocket() { }) function connect() { - if (!auth.token || ws.value?.readyState === WebSocket.OPEN) return + if (!auth.token) return + if (ws.value?.readyState === WebSocket.OPEN) return + // Close stale connection if still CONNECTING/CLOSING + if (ws.value) { + ws.value.onclose = null // prevent reconnect loop + ws.value.close() + ws.value = null + } const url = `${getWsUrl()}?token=${auth.token}` const socket = new WebSocket(url) diff --git a/frontend/src/pages/LoginPage.vue b/frontend/src/pages/LoginPage.vue index 3aab0ff2..de9a51cd 100644 --- a/frontend/src/pages/LoginPage.vue +++ b/frontend/src/pages/LoginPage.vue @@ -89,10 +89,10 @@