Files
omni-scheduler/DEVELOPMENT.md
gamewhale 45d3ca2f83 docs: 补充用户与开发者文档
- 新增 README.md,面向用户说明功能、运行要求、快速开始、触发器和常见问题。
- 新增 DEVELOPMENT.md,面向开发者说明项目结构、构建运行、发布流程、提交规范和检查清单。
- 将 artifacts/ 加入忽略规则,避免误提交本地发布产物。
- 修正托盘图标加载方式,改为读取 exe 内嵌图标,匹配不包含外置 app.ico 的发布包结构。
2026-05-21 11:44:38 +08:00

281 lines
6.6 KiB
Markdown
Raw 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 开发指导
本文档面向参与 OmniScheduler 开发、构建和发布的维护者。
## 技术栈
- 语言C#
- 运行时:.NET 8
- 框架WPF
- 目标平台Windows
- 项目类型WinExe
- 项目文件:`OmniScheduler/OmniScheduler.csproj`
项目启用了:
- `UseWPF`
- `UseWindowsForms`
其中 Windows Forms 主要用于系统托盘 `NotifyIcon`
## 目录结构
```text
.
├── OmniScheduler/
│ ├── App.xaml
│ ├── MainWindow.xaml
│ ├── MainWindow.xaml.cs
│ ├── Models.cs
│ ├── Services.cs
│ ├── SettingsWindow.xaml
│ ├── SettingsWindow.xaml.cs
│ ├── TaskEditorWindow.xaml
│ ├── TaskEditorWindow.xaml.cs
│ └── OmniScheduler.csproj
├── app.ico
├── README.md
├── DEVELOPMENT.md
└── PRD.md
```
## 主要模块
### `Models.cs`
定义核心数据模型:
- `SchedulerState`:应用整体状态,包含任务、日志和设置。
- `AppSettings`:全局设置,例如 OmniNotify API 地址和日志保留策略。
- `ScheduledTask`:单个调度任务。
- `TaskTrigger`:任务触发器。
- `ExecutionLog`:执行日志。
触发器类型由 `TriggerKind` 定义:
- `OneTime`
- `Interval`
- `Daily`
- `Weekly`
- `Monthly`
- `Cron`
### `Services.cs`
包含应用服务层:
- `StateStore`:负责读取和保存 `%LOCALAPPDATA%\OmniScheduler\state.json`
- `NotifyClient`:负责向 OmniNotify API 发送 JSON 请求。
- `SchedulerService`:调度循环、任务触发、手动触发和补偿策略处理。
- `NextRunCalculator`:计算下次执行时间和未来执行预览。
### `MainWindow`
主界面,负责:
- 任务列表展示
- 日志列表展示
- 新建、编辑、删除、克隆、手动触发任务
- 全局暂停/恢复
- 托盘菜单与隐藏窗口行为
### `TaskEditorWindow`
任务编辑窗口,包含三个页签:
- 常规
- 触发器
- 消息动作
触发器页会根据 `TriggerKind` 动态切换配置区域。时间输入应优先使用日期选择器、下拉框、按钮等结构化控件,避免要求用户手写时间格式。
### `SettingsWindow`
全局设置窗口。当前支持:
- OmniNotify API 地址
- 日志保留天数
- 最大日志条数
为了降低对用户系统的影响,项目不提供开机自启功能,也不写入 Windows 启动项。
## 本地开发
### 环境要求
- Windows
- .NET 8 SDK
- 支持 WPF 的开发环境,例如 Visual Studio、Rider 或 VS Code + .NET SDK
### 还原与构建
```powershell
dotnet restore .\OmniScheduler\OmniScheduler.csproj
dotnet build .\OmniScheduler\OmniScheduler.csproj
```
如果本地正在运行 `OmniScheduler.exe`,构建可能因为 `bin` 目录文件被锁定而失败。可以先退出应用,或临时输出到其他目录:
```powershell
dotnet build .\OmniScheduler\OmniScheduler.csproj -p:OutDir=.\obj\codex-verify\
```
### 运行
```powershell
dotnet run --project .\OmniScheduler\OmniScheduler.csproj
```
也可以直接运行构建后的 exe。
## 数据存储
运行时数据保存在:
```text
%LOCALAPPDATA%\OmniScheduler\state.json
```
`StateStore` 会在文件不存在或读取失败时创建默认状态。默认任务用于 OmniNotify 连通性测试,并保持禁用,避免首次启动自动发送消息。
## 调度规则开发注意事项
- 所有下次执行时间计算应集中在 `NextRunCalculator`
- UI 里的触发器摘要来自 `TaskTrigger.Summary`
- 修改触发器模型时,需要同步检查:
- 克隆逻辑:`TaskTrigger.Clone`
- 摘要逻辑:`TaskTrigger.Summary`
- 下次执行计算:`NextRunCalculator.NextRun`
- 任务编辑窗口加载与保存:`TaskEditorWindow`
- 对用户可见的时间输入,优先使用结构化控件,不新增要求用户记忆格式的文本输入。
## OmniNotify API 约定
`NotifyClient` 发送 `POST` 请求Content-Type 为 `application/json`
```json
{
"channel": "default",
"title": "标题",
"body": "内容"
}
```
发送前会替换以下变量:
- `{CurrentTime}`
- `{TaskName}`
- `{TriggerType}`
响应状态码非 2xx 时,日志级别记为 `ERROR`。如果响应中包含 `IllegalChannel`,错误消息会提示检查频道名。
## 托盘图标
项目图标由根目录 `app.ico` 提供:
- `ApplicationIcon` 用于嵌入 exe 图标。
- `Resource Include="..\app.ico"` 用于 WPF 窗口图标资源。
- 托盘图标从当前进程 exe 的关联图标读取,不依赖发布目录中的独立 `app.ico` 文件。
发布包中不应包含外置 `app.ico`
## 发布构建
首次发布使用 framework-dependent、多文件包不内置运行时不启用 single-file
```powershell
dotnet publish .\OmniScheduler\OmniScheduler.csproj `
-c Release `
-r win-x64 `
--self-contained false `
-p:PublishSingleFile=false `
-p:PublishReadyToRun=false `
-p:DebugType=none `
-p:DebugSymbols=false `
-p:PublishDir=..\artifacts\OmniScheduler-v0.1.0-win-x64\
```
压缩包命名建议遵循 GitHub Release 常见格式:
```text
OmniScheduler-v0.1.0-win-x64.zip
```
压缩:
```powershell
Compress-Archive `
-Path .\artifacts\OmniScheduler-v0.1.0-win-x64 `
-DestinationPath .\artifacts\OmniScheduler-v0.1.0-win-x64.zip
```
计算校验值:
```powershell
Get-FileHash .\artifacts\OmniScheduler-v0.1.0-win-x64.zip -Algorithm SHA256
```
发布包预期包含:
```text
OmniScheduler.exe
OmniScheduler.dll
OmniScheduler.deps.json
OmniScheduler.runtimeconfig.json
```
## Git 与提交规范
提交信息使用 Conventional Commits
```text
<type>[optional scope]: <description>
[optional body]
```
示例:
```text
feat: 优化触发器配置体验
- 根据触发器类型动态展示对应配置区域。
- 增加单次执行的延后快捷设置。
```
常用 type
- `feat`:新增功能
- `fix`:修复问题
- `docs`:文档变更
- `refactor`:重构
- `chore`:构建、发布、工具或维护性变更
## 版本标签
创建版本标签:
```powershell
git tag -a v0.1.0 -m "v0.1.0"
git push origin v0.1.0
```
如果发布内容修正后需要移动尚未正式发布的标签,应明确确认后再执行:
```powershell
git tag -fa v0.1.0 -m "v0.1.0"
git push --force origin v0.1.0
```
## 质量检查清单
提交前建议确认:
- `dotnet build` 通过。
- 触发器编辑窗口能正常切换各触发类型。
- 单次执行快捷设置能正确回填日期时间。
- Cron 预览可显示未来执行时间或明确错误提示。
- 发送测试消息不会要求保存任务。
- 发布包不包含 `app.ico`、PDB、运行时目录或其他多余文件。
- 程序关闭后能隐藏到托盘,托盘菜单可打开、暂停和退出。