Files
omni-scheduler/PRD.md
home-PC 2a669bdfe7 feat(app): 初始化 OmniScheduler WPF 调度器
基于 PRD 搭建 .NET 8 WPF 桌面应用,包含主控制台、任务编辑、全局设置、系统托盘和应用图标集成。

实现本地任务模型、触发器规则、JSON 状态持久化、OmniNotify HTTP 推送、执行日志记录、动态变量替换以及基础 Cron 预览能力。

补充 .gitignore,排除构建产物和本地 IDE 文件。

BREAKING CHANGE: 首次提交,建立项目初始结构
2026-05-20 00:12:17 +08:00

123 lines
8.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OmniScheduler 产品需求与交互说明书 (PRD)
## 1. 产品概述
**OmniScheduler** 是一款专为 Windows 系统设计的本地高级任务调度与消息推送管理软件。其核心目标是允许用户创建高度灵活的定时/计时规则,并在规则触发时,向本地环境的 `OmniNotify` 软件标准 API 发送结构化的 JSON 消息(包含频道、标题、内容)。
产品风格定位为**技术工具型软件**,追求逻辑严密性、高信息密度、无干扰的后台运行体验以及所见即所得的日志反馈。
## 2. 核心术语
* **任务 (Task)**:一个完整的调度单元,包含基础信息、触发器和消息载荷。
* **触发器 (Trigger)**定义任务何时运行的时间规则如固定时间、间隔、Cron表达式等
* **消息载荷 (Payload)**:触发时向 OmniNotify 发送的具体内容,由 `channel`(频道)、`title`(标题)、`body`(内容)组成。
* **补偿策略 (Misfire Strategy)**:当系统休眠或关机导致错过了原定触发时间后,系统恢复时如何处理这些错过的触发。
---
## 3. 核心功能需求
### 3.1 任务管理 (Task Management)
* **任务属性**
* **任务名称**:必填,用于在列表中识别任务。
* **任务描述**:选填,用于记录任务用途的备忘。
* **状态开关**:启用 (Enabled) / 禁用 (Disabled)。禁用状态下的任务不会触发。
* **列表操作**:支持新建、编辑、删除、克隆(复制现有任务以便微调)、立即手动执行一次(用于测试)。
### 3.2 触发器配置引擎 (Trigger Engine)
为满足“丰富的可配置性”,一个任务允许配置**单个或多个**触发器。支持以下触发器类型:
1. **单次执行 (One-Time)**:指定未来的某一个具体日期和时间点。
2. **固定间隔 (Simple Interval)**
* 配置项:每隔 `X` [秒/分钟/小时/天] 执行一次。
* 附加项:可设置“起始生效时间”和“结束失效时间”。
3. **每日/每周/每月定时 (Calendar Scheduled)**
* 每日:每天 `HH:mm:ss` 执行(可添加多个时间点)。
* 每周:勾选周一至周日,在选定日的 `HH:mm:ss` 执行。
* 每月:每月的第 `X` 天 或 每月的“最后一个工作日”的 `HH:mm:ss` 执行。
4. **高级规则 (Cron Expression)** *(技术向特色功能)*
* 允许用户直接输入标准的 Cron 表达式(如 `0 0/5 14 * * ?`)。
* UI 需提供 Cron 表达式的“未来5次执行时间”的实时预览方便用户自测。
**高级调度设置(补偿策略)**
* 当系统从休眠中唤醒,发现错过了某次执行时,用户可配置:
* *忽略 (Do Nothing)*:当作没发生,等待下一个周期。
* *立即补偿 (Fire Once Now)*:立即补发一次消息,随后恢复正常计划。
### 3.3 消息载荷配置 (Payload Configuration)
任务触发后生成的 JSON 数据配置区:
* **频道 (Channel)**:单行文本输入框。提示用户“必须与 OmniNotify 控制面板中已创建的频道一致,否则将被 OmniNotify 拦截”。
* **标题 (Title)**:单行文本输入框。
* **内容 (Body)**:多行文本输入框,支持自动换行。
* **动态变量支持 (Dynamic Variables)** *(技术向特色功能)*
* 允许在 Title 和 Body 中使用预设变量,以丰富消息内容。
* 例如:`{CurrentTime}` (当前时间), `{TaskName}` (任务名称), `{TriggerType}` (触发类型)。在发送时自动替换为真实值。
### 3.4 运行日志与审计 (Execution Logs)
* **本地日志记录**:记录每一次任务触发的详细情况。
* **日志字段**:时间戳、任务名称、触发类型、目标 URL、HTTP 响应状态码(成功为 200失败/拒绝需标红)、响应耗时。
* **详情查阅**:点击单条日志可查看实际发出的完整 JSON 请求体及接收方的响应。
---
## 4. 界面与交互规范 (UI/UX)
整体 UI 风格向 Visual Studio、Postman 或 Windows 本地管理工具MMC靠拢。采用高对比度、紧凑的数据表格布局支持 Windows 系统的深色/浅色模式切换。
### 4.1 主窗口布局 (Main Dashboard)
主界面采用 **“上下分栏 (Split View)”** 布局:
* **顶部工具栏 (Toolbar)**
* 包含图标按钮:`新建任务``编辑``删除``克隆``手动触发``全局设置`
* **上半部分:任务列表区 (DataGrid)**
* 以数据表格形式展示。
* 列包含:状态 (Toggle Switch)、任务名称、频道、触发规则简述、上次运行时间、下次运行时间、最近一次状态 (成功/失败指示灯)。
* 支持按列头点击排序。
* **下半部分:执行日志区 (Log Console)**
* 类似控制台输出,按时间倒序滚动显示近期日志。
* 分为 `INFO` (正常发送) 和 `ERROR` (发送失败或 OmniNotify 未启动/拒收)。
* 提供“清空日志”按钮。
### 4.2 任务编辑窗口 (Task Editor Modal)
采用 **“左侧导航树 + 右侧属性面板”** 或 **“多标签页 (Tabs)”** 形式:
* **Tab 1: 常规 (General)**
* 输入任务名称、描述,以及启用/禁用状态开关。
* **Tab 2: 触发器 (Triggers)**
* 左侧列出该任务已添加的触发器,右侧为具体配置表单。
* 下拉菜单选择触发器类型间隔、每日、Cron等下方表单根据类型动态切换。
* 最底部折叠面板提供“错过触发补偿策略”设置。
* **Tab 3: 消息动作 (Action/Payload)**
* **目标地址**:默认只读显示 `http://127.0.0.1:19845/notify`(随全局设置变动)。
* **载荷表单**
* Channel (带输入历史记忆的下拉文本框)
* Title
* Body
* **测试按钮**:提供一个 `Send Test Message` 按钮,点击后立即使用当前填写的 Channel/Title/Body 向 OmniNotify 发送一次请求,并在旁边气泡提示成功或失败,无需保存任务即可验证频道是否合法。
### 4.3 托盘与后台交互 (System Tray)
* **最小化到托盘**:由于是定时软件,点击主窗口的“关闭”按钮默认不退出程序,而是隐藏到系统托盘 (System Tray)。
* **托盘右键菜单**
* 打开主界面 (Open Dashboard)
* 快速暂停所有任务 (Pause All Tasks)
* 退出 (Exit)
* **静默运行**:软件启动和运行时不应有任何强制弹窗打扰用户,所有通知全权交由 OmniNotify 处理。
---
## 5. 全局设置 (Global Settings)
在独立的“设置”弹窗中提供以下全局配置:
1. **开机自启动**:跟随 Windows 登录启动(最小化到托盘)。
2. **OmniNotify API 地址**:默认值为 `http://127.0.0.1:19845/notify`。提供修改入口,以防未来 OmniNotify 端口或地址发生变更。
3. **日志保留策略**:防止本地日志无限膨胀,例如“保留最近 30 天的日志”或“最多保留 10000 条记录”。
## 6. 异常流与边界说明 (Exception Flows)
1. **OmniNotify 未运行或端口被占用**
* 触发器正常到点执行,但网络请求失败。
* 系统不应弹窗报错(避免积压成百上千个弹窗导致死机),只需在“执行日志区”静默记录一条标红的 `ERROR` 日志(如 `Connection Refused`)。
2. **OmniNotify 频道校验失败 (`IllegalChannel`)**
* 触发器正常执行,网络请求发出。
* 收到 HTTP 状态异常(或特定拒收报文)。
* 日志区记录 `ERROR: IllegalChannel`,提示用户检查 OmniScheduler 中的频道名配置。
3. **并发触发 (Concurrent Execution)**
* 若用户配置了大量的任务在同一秒(如 `00:00:00`)触发,系统需具备并行发出网络请求的能力,不能因为单条消息的发送阻塞导致后续消息延迟。
4. **规则冲突检查**
* UI 层面在用户保存时,如果发现“固定间隔”被设置为 0 秒,需高亮报错并阻断保存。最低间隔建议限制为 1 秒。