# Changelog: 全站 bug 审查修复 (前端9项 + 后端5项) **日期**: 2026-06-01 **变更摘要**: 全站巡检发现并修复 14 个 bug(1 P0 + 9 P1 + 4 P2),涵盖前端全局搜索崩溃、TOTP登录流程断裂、服务器编辑域名污染、后端Redis阻塞、并发session竞态等 ## 动机 对 Nexus 全站进行系统性 bug 审查,发现多个影响生产使用的问题。最严重的 3 个:全局搜索因 `http` 未导入直接崩溃、TOTP 双因素登录完全不可用、编辑服务器后域名被端口字符串污染导致后续连接失败。 ## 涉及文件 | 文件 | 变更类型 | 说明 | |------|----------|------| | `frontend/src/App.vue` | 修改 | 添加 `http` 导入 | | `frontend/src/pages/LoginPage.vue` | 修改 | TOTP异常捕获 + 锁定倒计时响应式 | | `frontend/src/pages/ServersPage.vue` | 修改 | 编辑时 domain 不再拼接端口 | | `frontend/src/pages/PushPage.vue` | 修改 | Set 索引 → 迭代器 | | `frontend/src/pages/SettingsPage.vue` | 修改 | API字符串值转数字 | | `frontend/src/api/index.ts` | 修改 | 删除重复 getList 定义 | | `frontend/src/pages/TerminalPage.vue` | 修改 | 路径验证正则放松 | | `frontend/src/composables/useWebSocket.ts` | 修改 | 关闭旧连接再建新连接 | | `server/api/websocket.py` | 修改 | redis.keys → scan_iter | | `server/application/services/auth_service.py` | 修改 | TTL 仅在无TTL时设置 | | `server/api/servers.py` | 修改 | 批量操作加 asyncio.Lock | | `server/api/settings.py` | 修改 | 弃用API替换 | ## 详细变更 ### 前端 P0 修复 1. **App.vue `http` 未导入** — 第320行 `doSearch()` 调用 `http.get()` 但只导入了 `api`,导致 `ReferenceError: http is not defined`。修复:`import { api, http } from '@/api'` ### 前端 P1 修复 2. **TOTP 登录流程断裂** — `api()` 在后端返回 202 时抛 `TotpRequiredError`(非 `ApiError` 子类),`LoginPage` catch 只检查 `e instanceof ApiError`,TOTP 用户看到"网络错误"无法登录。修复:导入 `TotpRequiredError` 并在 catch 中优先检查 3. **ServersPage 编辑域名污染** — `editServer()` 设置 `form.address = domain:port`,保存时 `domain: form.address` 发送含端口字符串。修复:`form.address = item.domain` 4. **PushPage Set 索引无效** — `selectedIds.value[0]` 对 `Set` 返回 `undefined`。修复:`selectedIds.value.values().next().value` 5. **SettingsPage 类型转换** — API 返回 `value: "80"` 字符串直接赋值给 number 字段。修复:正则检测纯数字字符串并 `Number()` 转换 ### 前端 P2 修复 6. **api/index.ts 重复定义** — `getList` 方法定义两次,删除第二个 7. **LoginPage 锁定倒计时** — `remainingMinutes` computed 依赖 `Date.now()` 非响应式。修复:使用 `ref(Date.now())` + `watch(lockoutUntil)` + 30秒定时器 8. **TerminalPage 路径验证过严** — 正则 `/^[a-zA-Z0-9/._\-]+$/` 排除空格/中文/~。修复:`/^[^\x00-\x1f\x7f"']+$/` 仅排除控制字符和引号 9. **useWebSocket 连接泄漏** — CONNECTING/CLOSING 状态时创建新连接但不关闭旧连接。修复:关闭旧连接后再创建新的 ### 后端 P1 修复 10. **websocket.py redis.keys() 阻塞** — `KEYS` 命令 O(N) 扫描整个键空间。修复:`scan_iter(match="ws:count:*")` 非阻塞迭代 11. **auth_service.py TTL 重置** — 每次 `sadd` 后 `expire` 重置 TTL,频繁刷新的管理员 refresh token 键永不过期。修复:`ttl = await redis.ttl(key)`,仅在 `ttl < 0` 时设置 expire 12. **servers.py 并发 session commit** — 批量操作中 `asyncio.gather` 并发协程共享同一 db session 并 `commit()`。修复:添加 `asyncio.Lock()` 序列化 commit ### 后端 P2 修复 13. **settings.py asyncio.get_event_loop()** — Python 3.10+ 弃用。修复:`asyncio.get_running_loop()` 14. **settings.py datetime.utcfromtimestamp()** — Python 3.12+ 弃用。修复:`datetime.fromtimestamp(ts, tz=timezone.utc)` ## 是否需迁移/重启 - ✅ 需重启 — 后端代码变更 - ✅ 前端需重新构建部署 ## 验证方式 1. 登录页 → 输入 admin/Nexus@2026 → 成功跳转仪表盘 ✓ 2. 全局搜索框 → 输入"机器人" → 无崩溃(之前会 ReferenceError)✓ 3. 控制台零错误 ✓ 4. 健康检查 → `ok` ✓