# 2026-05-29 推送页面 Round 4 迭代

## 变更摘要
1. H2: 服务器搜索过滤 — 目标服务器下拉列表上方加搜索框，按名称/域名实时过滤
2. H3: 推送对比 Diff 视图 — 预览文件列表中加"📄 diff"按钮，点击后对比本地与远程文件内容差异
3. H4: 推送排错面板 — 失败行加"🔍 诊断"按钮，检查 SSH 连通/磁盘空间/目标路径权限/写入权限
4. H5: 源路径直接输入 — 除 ZIP 上传外，支持直接输入服务器本地路径推送
5. H6: 批量重试 — 推送完成后，一键重试所有失败服务器

## 动机
推送页面功能已较完善，但 5 个实际使用痛点：2000+ 服务器下拉无法搜索定位、推送前无法看到文件内容差异、推送失败后需手动 SSH 排查、已有文件需先下载再上传、批量失败需逐台点重试。

## 涉及文件

### 后端
- `server/api/schemas.py` — 新增 `ValidateSourcePath`, `SyncDiagnose`, `FileSyncDiff` 三个 Schema
- `server/api/sync_v2.py` — 新增 3 个端点
  - `POST /api/sync/validate-source-path`: 验证本地目录路径有效性（禁止 /etc /root /home 等敏感路径）
  - `POST /api/sync/diagnose`: 诊断推送失败原因（SSH 连通 → 磁盘空间 → 路径权限 → 写入测试）
  - `POST /api/sync/file-diff`: 对比本地文件与远程文件差异（difflib.unified_diff，限 100KB）
- `docs/design/specs/2026-05-29-push-round4-design.md` — 设计文档
- `docs/design/plans/2026-05-29-push-round4.md` — 技术文档

### 前端
- `web/app/push.html` — 5 项改动
  - H2: `<input id="serverSearch">` + `filterServerOptions()` 按 oninput 实时过滤
  - H3: 预览文件列表渲染 HTML 带 diff 按钮 + `showFileDiff()` + diff 模态框（新增绿/删除红/头部青）
  - H4: 服务器行加 `srv_diag_{id}` 按钮 + `diagnoseServer()` + 诊断模态框
  - H5: "或输入源路径" 输入框 + "验证路径" 按钮 + `validateSourcePath()`
  - H6: 进度条区域"🔄 重试全部失败"按钮 + `retryAllFailed()` 批量提交重试

## 安全影响
- H5 (源路径验证): `os.path.realpath()` 校验 + 禁止 `/etc` `/root` `/home` `/var` 等敏感路径前缀
- H3 (文件对比): realpath 校验 local_file 必须在 source_path 下，source_path 必须 `startswith("/tmp/nexus_upload_")`
- H4 (诊断): `shlex.quote()` 防注入，SSH 操作复用连接池
- 所有新端点需 JWT 认证 + 审计日志

## 需要迁移/重启
- 是：后端 Python 需重启（supervisorctl restart nexus）
- 否：无数据库 schema 迁移

## 验证方式
1. H2: 输入 "web" → 下拉只显示名称/域名含 "web" 的服务器
2. H3: 预览 → 文件列表 → 点 "📄 diff" → 显示逐行对比（新增绿/删除红）
3. H4: 推送失败 → 点"🔍 诊断" → SSH/磁盘/权限检查结果
4. H5: 输入 `/tmp/nexus_upload_xxx` → 验证成功 → 可推送
5. H6: 推送完成后有失败 → 显示"重试全部失败"按钮 → 点击批量重试

## 进度条
☑实现 ☑WSL验证 ☐审计8步 ☑部署 ☐健康检查 ☐浏览器验证 ☑changelog
