# 审计 — 调度执行周期可视化(2026-06-08) **Changelog**: `docs/changelog/2026-06-08-schedule-cycle-picker.md` **设计**: `docs/design/specs/2026-06-08-schedule-cycle-picker-design.md` ## 审计范围 | 模块 | 文件 | |------|------| | 周期工具 | `frontend/src/utils/scheduleCycle.ts` | | 选择器 | `frontend/src/components/schedules/ScheduleCyclePicker.vue` | | 调度页 | `frontend/src/pages/SchedulesPage.vue` | | 后端镜像 | `server/utils/schedule_cycle.py` | | 单测 | `tests/test_schedule_cycle.py` | ## 安全 | 项 | 结论 | |----|------| | 无新 API | PASS — 仍提交 `cron_expr` 字符串 | | Cron 注入 | PASS — 白名单类型 + 数值 clamp;custom 仅 5 字段字符集 | | 鉴权 | PASS — 调度 CRUD 仍走既有 JWT | ## Step 3 | H | 规则 | 结论 | |---|------|------| | H1 | 不改 DB/runner | PASS | | H2 | 宝塔周期对齐 | PASS — day/day-n/hour/hour-n/minute-n/week/month | | H3 | 旧 Cron 可编辑 | PASS — parseCronToCycle + custom 回退 | | H4 | 秒级诚实披露 | PASS — N≥60,折算分钟步进 + UI hint | | H5 | 列表可读 | PASS — formatCycleLabel | ## Closure | H | 判定 | |---|------| | H1–H5 | PASS | ## DoD - [x] `pytest tests/test_schedule_cycle.py tests/test_schedule_next_run.py` — 21 passed - [x] `cd frontend && npm run build` — OK - [x] changelog + 设计文档 - [x] 生产热更新 + 容器内 bundle 含「执行周期」 - [ ] 用户浏览器终验 ## 代码审计(2026-06-08 补审) 此前仅跑门控 + 写文档;以下为逐文件审读结论。 ### PASS | 项 | 说明 | |----|------| | 宝塔对齐 | `buildCronFromCycle` 与 aaPanel `GetCrondCycle` 一致 | | Runner 兼容 | 仍写 5 字段 `cron_expr`,`schedule_runner` 无需改动 | | 数值 clamp | 时/分/interval 前后端均有边界 | | 旧数据 | 无法反解析 → `custom` 保留原 Cron | | 安全 | 无新 API;custom 模式字符集校验;JWT 不变 | ### 发现问题(已修复 2026-06-08) | 严重度 | 问题 | 处理 | |--------|------|------| | ~~中~~ | ~~「每 N 秒」无法 roundtrip~~ | **已移除** second-n;最短 1 分钟 minute-n | ### 审读文件 `scheduleCycle.ts` · `ScheduleCyclePicker.vue` · `SchedulesPage.vue` · `schedule_cycle.py` · `test_schedule_cycle.py` · `schedule_runner.py`(未改,兼容性确认) ## Gate 7 说明 本变更仅前端 + 工具/单测。HEAD 已提交 sort 修复交叉引用:`useServerPagination.ts`、`DashboardPage.vue`、`ServersPage.vue`、`servers.py`、`server_list_sort.py`、`server_repo.py`、`test_server_list_sort.py`、`web/app/index.html`(见 `docs/audit/2026-06-08-servers-live-sort-fix.md`)。