# 2026-05-30 — 服务器列表迭代

## 日期
2026-05-30

## 变更摘要
服务器列表页面全面迭代：后端新增服务端分页/搜索/排序/状态筛选，前端完全重写支持新功能。

## 动机
原服务器列表一次性加载全部数据，2000+ 服务器场景下性能差且无搜索/排序能力。

## 涉及文件
| 文件 | 变更类型 | 说明 |
|------|----------|------|
| server/infrastructure/database/server_repo.py | 修改 | `get_paginated()` 新增 search/sort_by/sort_order/is_online 参数，白名单排序，DB 级分页 |
| server/api/servers.py | 修改 | `list_servers()` 新增 4 个 Query 参数 + Redis post-filter；修复 12 个预存 ruff 错误；修复 `agent_port` F821 bug |
| web/app/servers.html | 重写 | 服务端分页/搜索/排序/状态筛选/自动刷新/键盘快捷键/CSV 导出/骨架屏/空状态优化 |

## 变更详情

### 后端 — server_repo.py
- `get_paginated()` 签名扩展：新增 `search`（name/domain LIKE）、`sort_by`（白名单验证）、`sort_order`（asc/desc）、`is_online`（MySQL 预过滤）
- `_SORT_COLUMNS` 白名单：id/name/domain/status/heartbeat/agent_version/category
- `is_online` 过滤时 over-fetch +10 补偿 Redis overlay 修正

### 后端 — servers.py
- `list_servers()` 新增 Query 参数：search/sort_by/sort_order/is_online
- Redis post-filter：`is_online` 过滤时移除 Redis 状态不匹配的记录
- 修复 12 个预先存在的 ruff 错误：F401 unused imports、B904 raise from、S110 try-except-pass、F541 f-string
- 修复 F821 bug：`upgrade_agent()` 中 `agent_port` 变量未定义

### 前端 — servers.html
- 服务端分页：50/100/200 条/页，首页/上一页/数字页码/下一页/末页
- 防抖搜索（300ms）：名称/地址 LIKE 模糊搜索
- 可点击列排序：Agent 状态/名称/地址/分类/Agent/最后心跳，▲▼ 指示器
- 状态筛选下拉：全部/在线/离线
- 自动刷新：30 秒间隔，弹窗编辑时自动暂停
- 键盘快捷键：↑↓/jk 移动、Esc 关闭面板、/ 搜索、r 刷新
- CSV 导出：当前筛选条件下导出最多 5000 条
- 骨架屏加载：8 行脉冲动画替代"加载中..."
- 空状态优化：区分"无数据"和"无匹配结果"

## 是否需迁移
否

## 是否需重启
是 — supervisorctl restart nexus

## 验证方式
1. ruff check: ✅ All checks passed
2. bandit: ✅ No issues
3. import: ✅ 成功
4. Playwright 浏览器验证：✅ 搜索/排序/筛选/分页全部通过

## Commit
84282e8
