4.9 KiB
4.9 KiB
2026-05-29 推送页面迭代 Round 3 — 技术文档
涉及文件清单
| 文件 | 改动类型 | 涉及功能 |
|---|---|---|
server/application/services/sync_engine_v2.py |
修改 | G1 取消检查 |
server/api/sync_v2.py |
新增端点 | G1 取消端点 |
server/api/schemas.py |
新增模型 | G1 取消请求 |
server/api/servers.py |
修改参数 | G4 历史筛选分页 |
web/app/push.html |
修改 | G1-G6 全部前端 |
docs/changelog/2026-05-29-push-round3.md |
新增 | changelog |
实现步骤
Step 1: G1 推送取消(后端+前端)
后端:
-
server/api/schemas.py— 新增:class SyncCancel(BaseModel): batch_id: str = Field(..., min_length=1, max_length=32) -
server/api/sync_v2.py— 新增POST /api/sync/cancel:- Redis
SET sync:cancel:{batch_id} 1 EX 3600 - 审计日志
- 返回
{"cancelled": true, "batch_id": ...}
- Redis
-
server/application/services/sync_engine_v2.py:_rsync_push(): 执行前检查sync:cancel:{batch_id},存在则返回{"exit_code": -1, "stderr": "推送已取消"}sync_files():_sync_one()任务启动前(async with sem之后、rsync 之前)检查取消标记- 取消的服务器 status=
"cancelled",不创建 retry job
前端:
doPush()执行期间显示"取消推送"按钮cancelPush()— 调用POST /api/sync/cancelupdateProgressFromWS()— 处理status=cancelled- 取消后按钮隐藏,已完成的服务器结果保留
Step 2: G6 拖拽上传 ZIP(纯前端)
文件: web/app/push.html
- 将
#sourceUpload区域改为拖拽区:<div>加dragover/dragleave/drop事件dragover: 高亮边框border-branddrop: 取ev.dataTransfer.files[0],调用uploadZip()逻辑
- 保留
<input type="file">隐藏,拖拽区 click 触发zipFile.click() - 文件类型校验:仅
.zip
Step 3: G5 浏览器推送完成通知(纯前端)
文件: web/app/push.html
doPush()开始时请求Notification.requestPermission()- 推送完成(
doPush()finally 块前)发送通知:if (Notification.permission === 'granted') { new Notification('Nexus 推送完成', {body: `${completed} 成功, ${failed} 失败`}); } - 降级:授权拒绝时
document.title闪烁(3 次交替🔔 Nexus/Nexus — 推送)
Step 4: G2 推送页面直接调度(纯前端)
文件: web/app/push.html
- "开始推送"按钮旁加"⏰ 定时推送"按钮
- 点击弹出简单模态框:
datetime-local选择器 + 确认按钮 - 确认后调用
POST /api/schedules/,body 包含:name: "手动推送-{时间}"schedule_type: "push"run_mode: "once"fire_at: 选择的时间source_path,server_ids,sync_mode: 从当前表单取
- 成功后 toast 提示 + 链接到调度页面
Step 5: G3 推送模板/收藏(纯前端)
文件: web/app/push.html
- localStorage key:
nexus_push_templates— JSON 数组 - 模板结构:
{name, source_path, target_path, sync_mode, server_ids[]} - UI:
- 表单上方"模板"下拉框 + "保存当前配置"按钮
- 选择模板 → 自动填充 source_path/target_path/sync_mode/server_ids
- 下拉旁"删除"按钮删除模板
saveTemplate(): 弹出 prompt 输入名称 → 存入 localStorageloadTemplate(): 从 localStorage 读取模板列表 → 渲染下拉框applyTemplate(): 填充表单字段deleteTemplate(): 从 localStorage 移除
Step 6: G4 推送历史筛选(后端+前端)
后端:
server/api/servers.py—list_sync_logs():- 新增参数:
status: Optional[str],server_id: Optional[int],page: int = 1 - 增加过滤条件到 SQLAlchemy 查询
- 增加
COUNT(*)查询获取总数 - 返回增加:
total,page,pages
- 新增参数:
前端:
- 历史区增加筛选控件:
- 状态下拉: 全部/成功/失败
- 服务器搜索输入框
loadHistory()增加参数传递- 分页控件: 上一页/下一页 + 页码显示
依赖与配置变更
无新依赖。无数据库 schema 迁移。 G1 需要已有的 Redis 连接。
测试要点
- G1: 推送 10 台 → 取消 → 仅已完成的有结果,其余显示"已取消"
- G1: 推送完成后再取消 → 无效果(batch_id 已失效)
- G2: 定时推送 → 调度页出现对应任务 → 到时间自动执行
- G3: 保存模板 → 刷新 → 选择模板 → 表单填充正确
- G3: 删除模板 → 下拉框更新
- G4: 筛选"失败" → 仅显示失败记录 → 分页翻页
- G5: 推送完成 → 浏览器通知弹出 → 点击通知回到页面
- G6: 拖拽 ZIP → 上传解压成功 → 文件管理器显示
- G6: 拖拽非 ZIP → 提示仅支持 .zip
回滚方式
所有改动均为增量(新增端点/前端元素),回滚只需:
git revert提交supervisorctl restart nexus