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

6.6 KiB
Raw Blame History

OmniScheduler 开发指导

本文档面向参与 OmniScheduler 开发、构建和发布的维护者。

技术栈

  • 语言C#
  • 运行时:.NET 8
  • 框架WPF
  • 目标平台Windows
  • 项目类型WinExe
  • 项目文件:OmniScheduler/OmniScheduler.csproj

项目启用了:

  • UseWPF
  • UseWindowsForms

其中 Windows Forms 主要用于系统托盘 NotifyIcon

目录结构

.
├── 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

还原与构建

dotnet restore .\OmniScheduler\OmniScheduler.csproj
dotnet build .\OmniScheduler\OmniScheduler.csproj

如果本地正在运行 OmniScheduler.exe,构建可能因为 bin 目录文件被锁定而失败。可以先退出应用,或临时输出到其他目录:

dotnet build .\OmniScheduler\OmniScheduler.csproj -p:OutDir=.\obj\codex-verify\

运行

dotnet run --project .\OmniScheduler\OmniScheduler.csproj

也可以直接运行构建后的 exe。

数据存储

运行时数据保存在:

%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

{
  "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

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 常见格式:

OmniScheduler-v0.1.0-win-x64.zip

压缩:

Compress-Archive `
  -Path .\artifacts\OmniScheduler-v0.1.0-win-x64 `
  -DestinationPath .\artifacts\OmniScheduler-v0.1.0-win-x64.zip

计算校验值:

Get-FileHash .\artifacts\OmniScheduler-v0.1.0-win-x64.zip -Algorithm SHA256

发布包预期包含:

OmniScheduler.exe
OmniScheduler.dll
OmniScheduler.deps.json
OmniScheduler.runtimeconfig.json

Git 与提交规范

提交信息使用 Conventional Commits

<type>[optional scope]: <description>

[optional body]

示例:

feat: 优化触发器配置体验

- 根据触发器类型动态展示对应配置区域。
- 增加单次执行的延后快捷设置。

常用 type

  • feat:新增功能
  • fix:修复问题
  • docs:文档变更
  • refactor:重构
  • chore:构建、发布、工具或维护性变更

版本标签

创建版本标签:

git tag -a v0.1.0 -m "v0.1.0"
git push origin v0.1.0

如果发布内容修正后需要移动尚未正式发布的标签,应明确确认后再执行:

git tag -fa v0.1.0 -m "v0.1.0"
git push --force origin v0.1.0

质量检查清单

提交前建议确认:

  • dotnet build 通过。
  • 触发器编辑窗口能正常切换各触发类型。
  • 单次执行快捷设置能正确回填日期时间。
  • Cron 预览可显示未来执行时间或明确错误提示。
  • 发送测试消息不会要求保存任务。
  • 发布包不包含 app.ico、PDB、运行时目录或其他多余文件。
  • 程序关闭后能隐藏到托盘,托盘菜单可打开、暂停和退出。