# 2026-05-26 — 三项前端缺失功能补全

## 变更摘要

补全三项后端已有但前端缺失的重要管理功能：

1. **服务器批量导入（CSV）** — 新增 `/api/servers/import` + `/api/servers/import/template`，前端 servers.html 新增「↓ 导入」按钮和导入弹窗
2. **文件上传** — 新增 `/api/sync/upload`（SFTP），前端 files.html 新增「↑ 上传」按钮 + 拖拽上传
3. **批量 Agent 安装/升级** — 新增 `/api/servers/batch/install-agent` + `/batch/upgrade-agent`，前端 servers.html 批量操作栏新增按钮

## 动机

- 服务器批量导入：管理几十台上百台服务器时，逐台添加效率极低
- 文件上传：files.html 只能浏览/删除/重命名，无法从浏览器上传文件到远程服务器
- 批量 Agent 操作：只能从服务器详情逐台安装/升级 Agent，无法一键批量执行

## 涉及文件

| 文件 | 改动 |
|------|------|
| `server/api/schemas.py` | 新增 `ServerImportResult`、`BatchAgentAction`、`BatchAgentResult`、`BatchAgentResultItem`、`FileUpload` schema |
| `server/api/servers.py` | 新增 `import_servers()`、`download_import_template()`、`batch_install_agent()`、`batch_upgrade_agent()`；CSV 注入防护 `_sanitize_csv_cell()` |
| `server/api/sync_v2.py` | 新增 `upload_file()` 端点（asyncssh SFTP 上传，路径遍历防护，文件大小限制 100MB） |
| `web/app/servers.html` | 新增「↓ 导入」按钮 + CSV 导入弹窗 + 批量 Agent 按钮 + 结果弹窗 |
| `web/app/files.html` | 新增「↑ 上传」按钮 + 拖拽上传 + 上传逻辑 |

## 安全考量

- CSV 注入：`_sanitize_csv_cell()` 过滤 `= + - @ \t \r` 开头的单元格，防止 Excel 公式注入
- 路径遍历：上传端点检查 `..`，文件名替换 `/` 和 `\` 为 `_`
- 文件大小：CSV ≤ 1MB/500 行，上传文件 ≤ 100MB
- 命令注入：复用 `shlex.quote()` 模式（agent install/upgrade 已有）
- 审计日志：所有 CUD 操作记录审计
- 敏感数据：导入结果不返回密码/私钥明文
- SFTP 安全：复用 asyncssh_pool 的凭据加密逻辑

## 是否需迁移/重启

- **DB 迁移**: 无（无新表/新列）
- **需重启**: 是（Python 后端路由变更）

## 部署后修复

- **路由冲突**: `/batch/install-agent`、`/batch/upgrade-agent`、`/import`、`/import/template` 注册在 `/{id}` 之后，FastAPI 将 `batch`/`import` 误匹配为 `{id}` 参数。修复：将固定路径路由移到 `/{id}` 之前。

## 验证方式

1. CSV 导入：下载模板 → 填写 2-3 行 → 上传 → 验证服务器列表新增
2. 文件上传：选择服务器 → 拖拽文件到文件列表区 → 验证远程文件存在
3. 批量 Agent：选中多台服务器 → 点击「安装 Agent」→ 验证逐台结果

## 浏览器验证结果 (2026-05-26)

| 功能 | 验证项 | 结果 |
|------|--------|------|
| CSV 导入 | 「↓ 导入」按钮 + 弹窗 | ✅ |
| CSV 导入 | 模板下载 API (200, text/csv) | ✅ |
| CSV 导入 | 导入 2 台服务器 (created=2) | ✅ |
| CSV 导入 | 重复地址跳过 (skipped=1) | ✅ |
| 文件上传 | 「↑ 上传」按钮 | ✅ |
| 文件上传 | 上传 API 端点响应正常 | ✅ |
| 批量 Agent | 选中后显示「安装 Agent」「升级 Agent」 | ✅ |
| 批量 Agent | batch/install-agent API 正确响应 | ✅ |
| 批量 Agent | batch/upgrade-agent API 正确响应 | ✅ |
| 路由修复 | 静态路径不再被 /{id} 捕获 | ✅ |
