# 2026-06-08 — 调度执行周期可视化（对齐宝塔）

## 摘要

新建/编辑循环调度时，将「Cron 表达式（5 字段）」改为「执行周期」选择窗口：每天、每 N 天、每小时、每 N 小时、每 N 分钟、每 N 秒、每周、每月；一次性调度改为「指定日期（年-月-日 时:分）」。底层仍写入 `cron_expr`，与 `schedule_runner` 兼容。

## 动机

- 手工 Cron 门槛高、易错
- 宝塔 aaPanel 计划任务已验证该交互模式（`crontab.py` GetCrondCycle）

## 涉及文件

| 层 | 文件 |
|----|------|
| 前端工具 | `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` |
| 设计 | `docs/design/specs/2026-06-08-schedule-cycle-picker-design.md` |

## 是否需迁移/重启

- **否** — 仅前端 UI + 工具函数；`cron_expr` 字段不变
- 前端需 `vite build` 后部署

## 验证方式

```bash
pytest tests/test_schedule_cycle.py tests/test_schedule_next_run.py -q
cd frontend && npm run build
```

- 新建调度 → 选「每天 02:00」→ 列表显示「每天 02:00」
- 编辑 `0 2 * * *` 旧任务 → 表单反解析为每天
- 无法识别 Cron → 自定义模式保留原表达式

## 行为说明

- **每 N 秒**：调度引擎 60 秒轮询，N 秒折算为 `ceil(N/60)` 分钟 Cron 步进
- **每 N 天**：与宝塔一致，使用 `*/N` 日字段（从每月 1 日起算）
