taskwatch 0.2.4__tar.gz → 0.2.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. taskwatch-0.2.5/PKG-INFO +411 -0
  2. taskwatch-0.2.5/README.md +383 -0
  3. {taskwatch-0.2.4 → taskwatch-0.2.5}/pyproject.toml +1 -1
  4. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/templates/tasks.html +25 -24
  5. taskwatch-0.2.5/taskwatch.egg-info/PKG-INFO +411 -0
  6. taskwatch-0.2.4/PKG-INFO +0 -838
  7. taskwatch-0.2.4/README.md +0 -810
  8. taskwatch-0.2.4/taskwatch.egg-info/PKG-INFO +0 -838
  9. {taskwatch-0.2.4 → taskwatch-0.2.5}/setup.cfg +0 -0
  10. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/__init__.py +0 -0
  11. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/cli/__init__.py +0 -0
  12. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/cli/log.py +0 -0
  13. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/cli/main.py +0 -0
  14. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/cli/report.py +0 -0
  15. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/cli/run.py +0 -0
  16. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/cli/task.py +0 -0
  17. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/core/__init__.py +0 -0
  18. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/core/executor.py +0 -0
  19. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/core/models.py +0 -0
  20. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/core/notifier.py +0 -0
  21. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/core/reporter.py +0 -0
  22. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/core/scheduler.py +0 -0
  23. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/utils/__init__.py +0 -0
  24. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/utils/config.py +0 -0
  25. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/utils/logger.py +0 -0
  26. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/utils/process.py +0 -0
  27. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/__init__.py +0 -0
  28. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/api/__init__.py +0 -0
  29. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/api/reports.py +0 -0
  30. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/api/runs.py +0 -0
  31. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/api/settings.py +0 -0
  32. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/api/stats.py +0 -0
  33. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/api/tasks.py +0 -0
  34. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/app.py +0 -0
  35. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/routes/__init__.py +0 -0
  36. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/routes/dashboard.py +0 -0
  37. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/routes/logs.py +0 -0
  38. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/routes/reports.py +0 -0
  39. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/routes/settings.py +0 -0
  40. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/routes/tasks.py +0 -0
  41. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/static/css/style.css +0 -0
  42. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/templates/base.html +0 -0
  43. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/templates/dashboard.html +0 -0
  44. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/templates/logs.html +0 -0
  45. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/templates/reports.html +0 -0
  46. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/templates/settings.html +0 -0
  47. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch/web/templates/task_detail.html +0 -0
  48. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch.egg-info/SOURCES.txt +0 -0
  49. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch.egg-info/dependency_links.txt +0 -0
  50. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch.egg-info/entry_points.txt +0 -0
  51. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch.egg-info/requires.txt +0 -0
  52. {taskwatch-0.2.4 → taskwatch-0.2.5}/taskwatch.egg-info/top_level.txt +0 -0
@@ -0,0 +1,411 @@
1
+ Metadata-Version: 2.4
2
+ Name: taskwatch
3
+ Version: 0.2.5
4
+ Summary: A lightweight local task scheduler with CLI, web UI, and email reporting
5
+ Author-email: Chandler <275737875@qq.com>
6
+ License-Expression: MIT
7
+ Keywords: scheduler,task,cron,automation
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Python: >=3.9
16
+ Description-Content-Type: text/markdown
17
+ Requires-Dist: typer>=0.9.0
18
+ Requires-Dist: rich>=13.0.0
19
+ Requires-Dist: fastapi>=0.100.0
20
+ Requires-Dist: uvicorn>=0.23.0
21
+ Requires-Dist: jinja2>=3.1.0
22
+ Requires-Dist: apscheduler>=3.10.0
23
+ Requires-Dist: tomli>=2.0.0; python_version < "3.11"
24
+ Requires-Dist: tomli-w>=1.0.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
27
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
28
+
29
+ # TaskWatch
30
+
31
+ > 轻量级本地任务调度器:一条命令 + 一个调度表达式,即可定时执行任务、记录日志、统计结果,并通过邮件发送告警与日报/周报。
32
+
33
+ TaskWatch 面向个人与小团队的本地调度场景,集 **CLI 管理**、**Web 管理界面**、**邮件报告** 于一体,零外部服务依赖(无需 Redis / 数据库服务),安装即用。
34
+
35
+ ## 核心特性
36
+
37
+ - **定时调度** — 支持 cron 表达式、`30m`/`2h`/`1d` 间隔表达式、`YYYY-MM-DD HH:MM:SS` 一次性任务,自动识别
38
+ - **一次性任务** — 指定具体日期时间执行一次,执行后自动禁用,过期任务启动时自动跳过
39
+ - **任务星标** — 标记重要任务,一键筛选只看星标,随时添加或取消
40
+ - **悬浮抽屉** — 鼠标悬浮任务名即可右侧滑出详情面板,无需跳转即可运行/编辑/启用/星标/删除
41
+ - **手动触发** — CLI 或 Web UI 一键立即执行任意任务
42
+ - **重试机制** — 失败后自动重试,可配置重试次数与间隔
43
+ - **超时控制** — 超时自动终止任务进程(含进程树)
44
+ - **实时日志** — stdout/stderr 实时落盘,CLI 可 follow 跟踪,Web UI 运行中自动刷新
45
+ - **Web 管理界面** — 仪表盘、任务管理、运行日志、报告中心、系统设置
46
+ - **邮件通知** — 失败即时告警(带冷却机制)、日报/周报自动发送、多 SMTP 账号轮转
47
+ - **零配置存储** — SQLite 本地持久化(WAL 模式)+ TOML 配置文件
48
+
49
+ ## 目录
50
+
51
+ - [快速启动](#快速启动)
52
+ - [详细教程](#详细教程)
53
+ - [配置说明](#配置说明)
54
+ - [项目架构](#项目架构)
55
+ - [开发指南](#开发指南)
56
+ - [License](#license)
57
+
58
+ ---
59
+
60
+ ## 快速启动
61
+
62
+ ### 环境要求
63
+
64
+ - Python >= 3.9(支持 3.9 ~ 3.12)
65
+ - pip
66
+
67
+ ### 安装
68
+
69
+ ```bash
70
+ # 进入项目根目录(pyproject.toml 所在目录)
71
+ cd taskwatch
72
+
73
+ # 安装
74
+ pip install .
75
+
76
+ # 或开发模式安装(代码修改即时生效)
77
+ pip install -e .
78
+ ```
79
+
80
+ 安装后会注册两个等价的命令入口:`tw` 和 `taskwatch`。
81
+
82
+ ### 5 分钟跑起来
83
+
84
+ ```bash
85
+ # 1. 初始化:在当前目录生成 config.toml、taskwatch.db、logs/
86
+ tw init
87
+
88
+ # 2. 添加一个任务:每天早上 9 点执行
89
+ tw task add --name "hello" --command "echo Hello TaskWatch" --schedule "0 9 * * *"
90
+
91
+ # 3. 添加一个一次性任务:2026 年 12 月 31 日 23:59 执行一次
92
+ tw task add --name "year_end" --command "python cleanup.py" --schedule "2026-12-31 23:59:00"
93
+
94
+ # 4. 立即手动执行一次,验证是否工作
95
+ tw task run 1
96
+
97
+ # 5. 启动 Web 管理界面(内嵌调度器,任务会按计划自动运行)
98
+ tw web
99
+ ```
100
+
101
+ 浏览器访问 **http://127.0.0.1:8899**,即可在仪表盘查看统计、在「运行日志」页面查看刚才的输出。
102
+
103
+ > 如果只需要纯命令行调度:`tw run`(前台运行,Ctrl+C 停止)。
104
+ >
105
+ > ⚠️ `tw web` 已内嵌调度器,请勿与 `tw run` 同时运行,否则任务会被重复调度。
106
+
107
+ ---
108
+
109
+ ## 详细教程
110
+
111
+ ### CLI 常用命令
112
+
113
+ #### `tw init` — 初始化
114
+
115
+ 在当前目录创建数据目录、SQLite 数据库和默认配置文件,并可交互式配置 SMTP。
116
+
117
+ ```bash
118
+ tw init
119
+ ```
120
+
121
+ #### `tw task` — 任务管理
122
+
123
+ | 命令 | 说明 | 示例 |
124
+ |------|------|------|
125
+ | `tw task add` | 添加任务 | `tw task add -n "backup" -c "python backup.py" -s "0 2 * * *"` |
126
+ | `tw task list` | 列出任务 | `tw task list --status enabled --search etl` |
127
+ | `tw task show <ID>` | 任务详情与运行统计 | `tw task show 1` |
128
+ | `tw task edit <ID>` | 编辑任务 | `tw task edit 1 --schedule "30 8 * * *"` |
129
+ | `tw task rm <ID>` | 删除任务(`-f` 跳过确认) | `tw task rm 1 -f` |
130
+ | `tw task enable <ID>` | 启用任务 | `tw task enable 1` |
131
+ | `tw task disable <ID>` | 禁用任务 | `tw task disable 1` |
132
+ | `tw task run <ID>` | 手动触发一次运行 | `tw task run 1` |
133
+
134
+ `task add` / `task edit` 支持 `--schedule-type` 显式指定调度类型(`cron`/`interval`/`once`),未指定时自动识别。
135
+
136
+ #### `tw run` — 启动调度器
137
+
138
+ ```bash
139
+ tw run # 前台运行,Ctrl+C 停止
140
+ tw run --daemon # 后台守护进程(仅 Unix 系统)
141
+ ```
142
+
143
+ #### `tw log` — 查看日志
144
+
145
+ ```bash
146
+ tw log 1 # 查看任务 1 的最近运行记录 + 最新日志
147
+ tw log 1 --run-id 42 # 查看指定运行记录的日志
148
+ tw log 1 --tail 50 # 显示最近 50 行
149
+ tw log 1 --follow # 实时跟踪日志(类似 tail -f)
150
+ ```
151
+
152
+ #### `tw report` — 生成报告
153
+
154
+ ```bash
155
+ tw report daily # 生成今日日报
156
+ tw report daily 2026-07-22 --send # 生成指定日期日报并邮件发送
157
+ tw report weekly # 生成本周周报
158
+ tw report weekly 2026-07-14 2026-07-20 --send
159
+ ```
160
+
161
+ #### `tw config` — 配置管理
162
+
163
+ ```bash
164
+ tw config --list # 查看全部配置
165
+ tw config smtp.host # 查看单项
166
+ tw config smtp.host smtp.qq.com # 修改单项
167
+ ```
168
+
169
+ #### `tw mail` — 邮件测试
170
+
171
+ ```bash
172
+ tw mail test # 发送测试邮件,验证 SMTP 配置
173
+ ```
174
+
175
+ #### `tw web` — Web 管理界面
176
+
177
+ ```bash
178
+ tw web # 默认 127.0.0.1:8899,自动打开浏览器
179
+ tw web --host 0.0.0.0 --port 9000 # 自定义监听地址
180
+ tw web --no-browser # 不自动打开浏览器
181
+ ```
182
+
183
+ ### Web UI 功能说明
184
+
185
+ | 页面 | 路径 | 功能 |
186
+ |------|------|------|
187
+ | 仪表盘 | `/` | 任务总数、运行统计、成功率、近 7 天趋势图、最近运行记录 |
188
+ | 任务管理 | `/tasks` | 任务列表、搜索过滤、**星标标记与筛选**、**悬浮抽屉快速查看**、新建/编辑/删除、启用/禁用、手动运行 |
189
+ | 任务详情 | `/tasks/{id}` | 任务配置、运行统计(总次数/成功率/平均耗时)、最近运行记录 |
190
+ | 运行日志 | `/logs` | 多条件过滤(任务/状态/触发方式/时间范围/关键词)、分页、日志详情弹窗(运行中每 3 秒自动刷新)、终止运行中任务 |
191
+ | 报告中心 | `/reports` | 日报/周报历史、手动生成、查看详情、重新发送邮件 |
192
+ | 系统设置 | `/settings` | SMTP 配置、报告时间、告警配置、发送测试邮件、清理日志 |
193
+
194
+ **任务管理页面交互:**
195
+
196
+ - **星标**:每行任务可点击 ★/☆ 切换星标,顶部"仅看星标"开关可一键筛选星标任务
197
+ - **悬浮抽屉**:鼠标悬浮任务名 400ms 后,右侧滑出详情面板,展示任务基础信息与统计,可直接运行/编辑/启用禁用/星标/删除,Esc 或鼠标移出关闭
198
+
199
+ ### 任务配置项说明
200
+
201
+ | 配置项 | CLI 参数 | 说明 |
202
+ |--------|----------|------|
203
+ | `name` | `--name` / `-n` | 任务名称(必填) |
204
+ | `command` | `--command` / `-c` | 执行命令,通过 shell 执行(必填) |
205
+ | `schedule` | `--schedule` / `-s` | 调度表达式,见下方说明(必填) |
206
+ | `schedule_type` | `--schedule-type` | 调度类型:`cron`/`interval`/`once`,不传则自动识别 |
207
+ | `working_dir` | `--working-dir` / `-w` | 工作目录,默认为当前目录 |
208
+ | `env` | `--env` | 环境变量,格式 `KEY1=val1,KEY2=val2` |
209
+ | `timeout` | `--timeout` / `-t` | 超时秒数,默认 36000 |
210
+ | `retry` | `--retry` / `-r` | 失败最大重试次数,默认 0(不重试) |
211
+ | `retry_interval` | `--retry-interval` | 重试间隔秒数,默认跟随 `retry.default_retry_interval` |
212
+ | `interpreter` | `--interpreter` | Python 解释器路径(写入 `TASKWATCH_INTERPRETER` 环境变量) |
213
+ | `tags` | `--tags` | 标签,逗号分隔,用于搜索分组 |
214
+ | `notify` | `--notify` | 通知策略:`on_failure`(默认)/ `always` / `never` |
215
+
216
+ **调度表达式(自动识别类型):**
217
+
218
+ | 类型 | 格式 | 示例 | 说明 |
219
+ |------|------|------|------|
220
+ | cron | 5 位标准表达式:`分 时 日 月 周` | `0 9 * * *` | 每天 9:00 |
221
+ | cron | 6 位带秒:`秒 分 时 日 月 周` | `30 0 9 * * *` | 每天 9:00:30 |
222
+ | interval | 数字 + 单位(m/h/d) | `30m`、`2h`、`1d` | 每 30 分钟 / 2 小时 / 1 天 |
223
+ | **once** | `YYYY-MM-DD HH:MM:SS` | `2026-12-31 23:59:00` | 指定时刻执行一次,完成后自动禁用 |
224
+
225
+ **一次性任务(once)行为:**
226
+ - 在指定时刻触发执行一次,执行完成后自动禁用(`enabled=0`),不再重复
227
+ - 调度器重启后,未执行的 once 任务仍能按时触发
228
+ - 启动时若指定时间已过,自动标记为禁用并跳过(不补跑,避免惊群)
229
+ - 可随时编辑目标时间后重新启用
230
+
231
+ ---
232
+
233
+ ## 配置说明
234
+
235
+ ### 配置文件位置与格式
236
+
237
+ 配置文件为工作目录下的 **`config.toml`**(TOML 格式),首次运行 `tw init` 时自动生成。可通过 `tw config` 命令或 Web UI「系统设置」页面修改,也可以直接编辑文件(修改后重启服务生效)。
238
+
239
+ ### 完整配置示例(带注释)
240
+
241
+ 以下为 `tw init` 生成的默认配置及各项说明:
242
+
243
+ ```toml
244
+ [core]
245
+ database_path = "./taskwatch.db" # SQLite 数据库文件路径
246
+ log_dir = "./logs" # 任务日志目录
247
+ pid_file = "./taskwatch.pid" # 调度器 PID 文件路径
248
+ force_utf8_codepage = true # Windows 下自动为命令添加 chcp 65001 前缀,
249
+ # 解决 CMD 中文/emoji 乱码;不需要可设为 false
250
+
251
+ [smtp]
252
+ enabled = false # 是否启用邮件通知
253
+ host = "smtp.gmail.com" # SMTP 服务器
254
+ port = 587 # SMTP 端口
255
+ use_tls = true # 是否使用 TLS
256
+ username = "" # SMTP 用户名
257
+ password = "" # SMTP 密码(推荐用环境变量 TASKWATCH_SMTP_PASSWORD 代替)
258
+ from_addr = "" # 发件人地址
259
+ to_addrs = [] # 收件人列表
260
+
261
+ [retry]
262
+ default_retry = 0 # 任务未指定时的默认重试次数(0 表示不重试)
263
+ default_retry_interval = 60 # 默认重试间隔(秒)
264
+
265
+ [timeout]
266
+ default_timeout = 36000 # 任务未指定时的默认超时(秒),即 10 小时
267
+
268
+ [logging]
269
+ max_log_files = 100 # 日志文件保留数量上限
270
+ max_log_age_days = 30 # 日志保留天数
271
+
272
+ [web]
273
+ host = "127.0.0.1" # Web 监听地址
274
+ port = 8899 # Web 监听端口
275
+ auto_open_browser = true # 启动 tw web 时自动打开浏览器
276
+
277
+ [report]
278
+ daily_enabled = true # 是否启用日报
279
+ daily_time = "10:00" # 日报发送时间
280
+ weekly_enabled = true # 是否启用周报
281
+ weekly_day = "monday" # 周报发送星期
282
+ weekly_time = "11:00" # 周报发送时间
283
+
284
+ [alert]
285
+ enabled = true # 是否启用任务失败告警
286
+ cooldown_minutes = 10 # 同一任务的告警冷却时间(分钟),防止邮件轰炸
287
+ ```
288
+
289
+ > 多 SMTP 账号轮转:可在 `[smtp]` 下配置 `accounts` 账号列表,发信时自动轮转,规避单账号频率限制。
290
+
291
+ ---
292
+
293
+ ## 项目架构
294
+
295
+ ### 目录结构
296
+
297
+ ```
298
+ taskwatch/
299
+ ├── pyproject.toml # 项目元数据、依赖、命令入口(tw / taskwatch)
300
+ ├── docs/ # 设计文档(spec / design / add_spec)
301
+ └── taskwatch/ # 主包
302
+ ├── cli/ # 命令行层(Typer + Rich)
303
+ │ ├── main.py # 主应用:init / config / mail / web
304
+ │ ├── task.py # 任务管理:add/list/show/edit/rm/enable/disable/run
305
+ │ ├── run.py # 启动调度器:tw run [--daemon]
306
+ │ ├── log.py # 日志查看:tw log [--tail/--follow/--run-id]
307
+ │ └── report.py # 报告生成:daily / weekly
308
+ ├── core/ # 核心业务层(不依赖任何 UI 框架)
309
+ │ ├── models.py # SQLite 数据层(tasks / runs / reports,Schema 版本化迁移)
310
+ │ ├── scheduler.py # APScheduler 调度引擎(cron/interval/once 触发、孤儿运行清理)
311
+ │ ├── executor.py # 子进程执行器(超时/重试、实时日志捕获、once 执行后自动禁用)
312
+ │ ├── notifier.py # SMTP 通知(失败告警、日报/周报发送、多账号轮转、冷却)
313
+ │ └── reporter.py # 日报/周报 HTML 生成引擎
314
+ ├── utils/ # 工具层
315
+ │ ├── config.py # TOML 配置管理(全局单例,默认值 + 用户覆盖深合并)
316
+ │ ├── logger.py # 日志工具
317
+ │ └── process.py # 进程工具(按 PID 终止进程、存活检测)
318
+ └── web/ # Web 展示层(FastAPI)
319
+ ├── app.py # 应用工厂 create_app(),启动时内嵌调度器
320
+ ├── api/ # REST API(/api/stats、tasks、runs、reports、settings)
321
+ ├── routes/ # 页面路由(Jinja2 服务端渲染)
322
+ ├── static/css/ # 自定义样式
323
+ └── templates/ # HTML 模板(Tailwind CSS + HTMX + Chart.js,CDN 引入)
324
+ ```
325
+
326
+ ### 核心数据流
327
+
328
+ ```
329
+ tw run / tw web(内嵌调度器)
330
+ │ cron / interval / once 定时触发,或 CLI / Web 手动触发
331
+ ▼
332
+ TaskExecutor 子进程执行(shell 执行命令)
333
+ │ 实时捕获 stdout/stderr,逐行智能解码(UTF-8 优先,系统编码回退)
334
+ │ once 任务执行完成后自动禁用
335
+ ▼
336
+ 日志文件 logs/<task_id>/*.log + SQLite runs 表(状态/退出码/输出摘要)
337
+ │
338
+ ├──▶ Web UI:/logs 页面通过 /api/runs/{id}/stream 实时查看
339
+ ├──▶ CLI:tw log / tw task show
340
+ └──▶ 邮件:失败告警(Notifier)+ 日报/周报(Reporter)
341
+ ```
342
+
343
+ ### 技术栈
344
+
345
+ | 技术 | 用途 |
346
+ |------|------|
347
+ | Typer + Rich | CLI 框架与终端美化输出(表格、颜色) |
348
+ | FastAPI + Uvicorn | Web 框架与 ASGI 服务器 |
349
+ | Jinja2 | HTML 模板引擎(服务端渲染) |
350
+ | Tailwind CSS / HTMX / Chart.js | 前端样式、交互增强、趋势图表(全部 CDN 引入,零构建) |
351
+ | APScheduler | 调度引擎(BackgroundScheduler,cron/interval/date 触发器) |
352
+ | SQLite(WAL 模式) | 数据持久化,零配置、支持并发读写 |
353
+ | tomllib / tomli-w | TOML 配置读写(Python < 3.11 使用 tomli) |
354
+ | smtplib | 邮件发送(标准库) |
355
+
356
+ ### 数据库 Schema 版本演进
357
+
358
+ | 版本 | 变更 |
359
+ |------|------|
360
+ | v1-v2 | tasks / runs / reports 三表建立 |
361
+ | v3 | runs 表增加 pid 列 |
362
+ | v4 | tasks.schedule_type 放宽 CHECK 约束,增加 `'once'` 一次性任务类型 |
363
+ | v5 | tasks 表增加 starred 列,支持任务星标功能 |
364
+
365
+ 迁移在启动时自动执行,事务化保证安全,向后兼容。
366
+
367
+ ---
368
+
369
+ ## 开发指南
370
+
371
+ ### 本地开发环境
372
+
373
+ ```bash
374
+ # 1. 克隆项目并进入目录
375
+ cd taskwatch
376
+
377
+ # 2. 以开发模式安装(含 pytest 等开发依赖)
378
+ pip install -e ".[dev]"
379
+
380
+ # 3. 验证安装
381
+ tw --help
382
+ ```
383
+
384
+ 开发时数据文件(`config.toml`、`taskwatch.db`、`logs/`)生成在**当前工作目录**,建议在项目外单独建一个工作目录运行 `tw init`,避免污染源码目录。
385
+
386
+ ### 运行测试
387
+
388
+ 项目使用 pytest 作为测试框架(已包含在 `dev` 可选依赖中):
389
+
390
+ ```bash
391
+ pytest
392
+ ```
393
+
394
+ > 当前仓库未内置 `tests/` 目录;新增测试文件后 pytest 会自动收集执行。
395
+ > 修改代码后可先用 `python -m py_compile <文件>` 做语法快速检查。
396
+
397
+ ---
398
+
399
+ ## 免责声明
400
+
401
+ - 本项目为**本地轻量工具**,设计用于个人或小团队的本地任务调度场景,**不适用于生产环境高可用、高并发场景**。
402
+ - 任务执行依赖本地系统环境(Shell、Python 解释器等),项目**不对用户命令的执行结果负责**。
403
+ - 邮件发送功能依赖用户自行配置的 SMTP 服务,项目**不保证邮件一定能成功送达**。
404
+ - 数据存储为本地 SQLite 文件,**用户需自行做好数据备份**,项目不对数据丢失承担责任。
405
+ - 本项目按 **"原样"(AS IS)** 提供,不附带任何明示或暗示的保证。
406
+
407
+ ---
408
+
409
+ ## License
410
+
411
+ [MIT](https://opensource.org/licenses/MIT)