Metadata-Version: 2.4
Name: taskwatch
Version: 0.2.3
Summary: A lightweight local task scheduler with CLI, web UI, and email reporting
Author-email: Chandler <275737875@qq.com>
License-Expression: MIT
Keywords: scheduler,task,cron,automation
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: typer>=0.9.0
Requires-Dist: rich>=13.0.0
Requires-Dist: fastapi>=0.100.0
Requires-Dist: uvicorn>=0.23.0
Requires-Dist: jinja2>=3.1.0
Requires-Dist: apscheduler>=3.10.0
Requires-Dist: tomli>=2.0.0; python_version < "3.11"
Requires-Dist: tomli-w>=1.0.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"

# TaskWatch

> 轻量级本地任务调度器：一条命令 + 一个 cron 表达式，即可定时执行任务、记录日志、统计结果，并通过邮件发送告警与日报/周报。

TaskWatch 面向个人与小团队的本地调度场景，集 **CLI 管理**、**Web 管理界面**、**邮件报告** 于一体，零外部服务依赖（无需 Redis / 数据库服务），安装即用。

## 核心特性

- **定时调度** — 支持标准 cron 表达式与 `30m` / `2h` / `1d` 间隔表达式，自动识别
- **手动触发** — CLI 或 Web UI 一键立即执行任意任务
- **重试机制** — 失败后自动重试，可配置重试次数与间隔
- **超时控制** — 超时自动终止任务进程（含进程树）
- **实时日志** — stdout/stderr 实时落盘，CLI 可 follow 跟踪，Web UI 运行中自动刷新
- **Web 管理界面** — 仪表盘、任务管理、运行日志、报告中心、系统设置
- **邮件通知** — 失败即时告警（带冷却机制）、日报/周报自动发送、多 SMTP 账号轮转
- **零配置存储** — SQLite 本地持久化（WAL 模式）+ TOML 配置文件

## 目录

- [快速启动](#快速启动)
- [详细教程](#详细教程)
- [配置说明](#配置说明)
- [项目架构](#项目架构)
- [开发指南](#开发指南)
- [License](#license)

---

## 快速启动

### 环境要求

- Python >= 3.9（支持 3.9 ~ 3.12）
- pip

### 安装

```bash
# 进入项目根目录（pyproject.toml 所在目录）
cd taskwatch

# 安装
pip install .

# 或开发模式安装（代码修改即时生效）
pip install -e .
```

安装后会注册两个等价的命令入口：`tw` 和 `taskwatch`。

### 5 分钟跑起来

```bash
# 1. 初始化：在当前目录生成 config.toml、taskwatch.db、logs/
tw init

# 2. 添加一个任务：每天早上 9 点执行
tw task add --name "hello" --command "echo Hello TaskWatch" --schedule "0 9 * * *"

# 3. 立即手动执行一次，验证是否工作
tw task run 1

# 4. 启动 Web 管理界面（内嵌调度器，任务会按计划自动运行）
tw web
```

浏览器访问 **http://127.0.0.1:8899**，即可在仪表盘查看统计、在「运行日志」页面查看刚才的输出。

> 如果只需要纯命令行调度：`tw run`（前台运行，Ctrl+C 停止）。
>
> ⚠️ `tw web` 已内嵌调度器，请勿与 `tw run` 同时运行，否则任务会被重复调度。

---

## 详细教程

### CLI 常用命令

#### `tw init` — 初始化

在当前目录创建数据目录、SQLite 数据库和默认配置文件，并可交互式配置 SMTP。

```bash
tw init
```

#### `tw task` — 任务管理

| 命令 | 说明 | 示例 |
|------|------|------|
| `tw task add` | 添加任务 | `tw task add -n "backup" -c "python backup.py" -s "0 2 * * *"` |
| `tw task list` | 列出任务 | `tw task list --status enabled --search etl` |
| `tw task show <ID>` | 任务详情与运行统计 | `tw task show 1` |
| `tw task edit <ID>` | 编辑任务 | `tw task edit 1 --schedule "30 8 * * *"` |
| `tw task rm <ID>` | 删除任务（`-f` 跳过确认） | `tw task rm 1 -f` |
| `tw task enable <ID>` | 启用任务 | `tw task enable 1` |
| `tw task disable <ID>` | 禁用任务 | `tw task disable 1` |
| `tw task run <ID>` | 手动触发一次运行 | `tw task run 1` |

#### `tw run` — 启动调度器

```bash
tw run            # 前台运行，Ctrl+C 停止
tw run --daemon   # 后台守护进程（仅 Unix 系统）
```

#### `tw log` — 查看日志

```bash
tw log 1                  # 查看任务 1 的最近运行记录 + 最新日志
tw log 1 --run-id 42      # 查看指定运行记录的日志
tw log 1 --tail 50        # 显示最近 50 行
tw log 1 --follow         # 实时跟踪日志（类似 tail -f）
```

#### `tw report` — 生成报告

```bash
tw report daily                       # 生成今日日报
tw report daily 2026-07-22 --send     # 生成指定日期日报并邮件发送
tw report weekly                      # 生成本周周报
tw report weekly 2026-07-14 2026-07-20 --send
```

#### `tw config` — 配置管理

```bash
tw config --list                    # 查看全部配置
tw config smtp.host                 # 查看单项
tw config smtp.host smtp.qq.com     # 修改单项
```

#### `tw mail` — 邮件测试

```bash
tw mail test    # 发送测试邮件，验证 SMTP 配置
```

#### `tw web` — Web 管理界面

```bash
tw web                              # 默认 127.0.0.1:8899，自动打开浏览器
tw web --host 0.0.0.0 --port 9000   # 自定义监听地址
tw web --no-browser                 # 不自动打开浏览器
```

### Web UI 功能说明

| 页面 | 路径 | 功能 |
|------|------|------|
| 仪表盘 | `/` | 任务总数、运行统计、成功率、近 7 天趋势图、最近运行记录 |
| 任务管理 | `/tasks` | 任务列表、搜索过滤、新建/编辑/删除、启用/禁用、手动运行 |
| 任务详情 | `/tasks/{id}` | 任务配置、运行统计（总次数/成功率/平均耗时）、最近运行记录 |
| 运行日志 | `/logs` | 多条件过滤（任务/状态/触发方式/时间范围/关键词）、分页、日志详情弹窗（运行中每 3 秒自动刷新）、终止运行中任务 |
| 报告中心 | `/reports` | 日报/周报历史、手动生成、查看详情、重新发送邮件 |
| 系统设置 | `/settings` | SMTP 配置、报告时间、告警配置、发送测试邮件、清理日志 |

### 任务配置项说明

| 配置项 | CLI 参数 | 说明 |
|--------|----------|------|
| `name` | `--name` / `-n` | 任务名称（必填） |
| `command` | `--command` / `-c` | 执行命令，通过 shell 执行（必填） |
| `schedule` | `--schedule` / `-s` | 调度表达式，见下方说明（必填） |
| `working_dir` | `--working-dir` / `-w` | 工作目录，默认为当前目录 |
| `env` | `--env` | 环境变量，格式 `KEY1=val1,KEY2=val2` |
| `timeout` | `--timeout` / `-t` | 超时秒数，默认跟随 `config.toml` 的 `timeout.default_timeout` |
| `retry` | `--retry` / `-r` | 失败最大重试次数，默认跟随 `retry.default_retry` |
| `retry_interval` | `--retry-interval` | 重试间隔秒数，默认跟随 `retry.default_retry_interval` |
| `interpreter` | `--interpreter` | Python 解释器路径（写入 `TASKWATCH_INTERPRETER` 环境变量） |
| `tags` | `--tags` | 标签，逗号分隔，用于搜索分组 |
| `notify` | `--notify` | 通知策略：`on_failure`（默认）/ `always` / `never` |

**调度表达式（自动识别类型）：**

| 类型 | 格式 | 示例 |
|------|------|------|
| cron | 5 位标准表达式：`分 时 日 月 周` | `0 9 * * *`（每天 9:00） |
| cron | 6 位带秒：`秒 分 时 日 月 周` | `30 0 9 * * *`（每天 9:00:30） |
| interval | 数字 + 单位（m/h/d） | `30m`、`2h`、`1d`，等价于 `every 30m` 等 |

---

## 配置说明

### 配置文件位置与格式

配置文件为工作目录下的 **`config.toml`**（TOML 格式），首次运行 `tw init` 时自动生成。可通过 `tw config` 命令或 Web UI「系统设置」页面修改，也可以直接编辑文件（修改后重启服务生效）。

### 完整配置示例（带注释）

以下为 `tw init` 生成的默认配置及各项说明：

```toml
[core]
database_path = "./taskwatch.db"     # SQLite 数据库文件路径
log_dir = "./logs"                   # 任务日志目录
pid_file = "./taskwatch.pid"         # 调度器 PID 文件路径
force_utf8_codepage = true           # Windows 下自动为命令添加 chcp 65001 前缀，
                                     # 解决 CMD 中文/emoji 乱码；不需要可设为 false

[smtp]
enabled = false                      # 是否启用邮件通知
host = "smtp.gmail.com"              # SMTP 服务器
port = 587                           # SMTP 端口
use_tls = true                       # 是否使用 TLS
username = ""                        # SMTP 用户名
password = ""                        # SMTP 密码（推荐用环境变量 TASKWATCH_SMTP_PASSWORD 代替）
from_addr = ""                       # 发件人地址
to_addrs = []                        # 收件人列表

[retry]
default_retry = 0                    # 任务未指定时的默认重试次数（0 表示不重试）
default_retry_interval = 60          # 默认重试间隔（秒）

[timeout]
default_timeout = 3600               # 任务未指定时的默认超时（秒）

[logging]
max_log_files = 100                  # 日志文件保留数量上限
max_log_age_days = 30                # 日志保留天数

[web]
host = "127.0.0.1"                   # Web 监听地址
port = 8899                          # Web 监听端口
auto_open_browser = true             # 启动 tw web 时自动打开浏览器

[report]
daily_enabled = true                 # 是否启用日报
daily_time = "10:00"                 # 日报发送时间
weekly_enabled = true                # 是否启用周报
weekly_day = "monday"                # 周报发送星期
weekly_time = "11:00"                # 周报发送时间

[alert]
enabled = true                       # 是否启用任务失败告警
cooldown_minutes = 10                # 同一任务的告警冷却时间（分钟），防止邮件轰炸
```

> 多 SMTP 账号轮转：可在 `[smtp]` 下配置 `accounts` 账号列表，发信时自动轮转，规避单账号频率限制。

---

## 项目架构

### 目录结构

```
taskwatch/
├── pyproject.toml                  # 项目元数据、依赖、命令入口（tw / taskwatch）
├── docs/                           # 设计文档（变更规格与审查记录）
└── taskwatch/                      # 主包
    ├── cli/                        # 命令行层（Typer + Rich）
    │   ├── main.py                 # 主应用：init / config / mail / web
    │   ├── task.py                 # 任务管理：add/list/show/edit/rm/enable/disable/run
    │   ├── run.py                  # 启动调度器：tw run [--daemon]
    │   ├── log.py                  # 日志查看：tw log [--tail/--follow/--run-id]
    │   └── report.py               # 报告生成：daily / weekly
    ├── core/                       # 核心业务层（不依赖任何 UI 框架）
    │   ├── models.py               # SQLite 数据层（tasks / runs / reports 三表 CRUD）
    │   ├── scheduler.py            # APScheduler 调度引擎（cron/interval 触发、孤儿运行清理）
    │   ├── executor.py             # 子进程执行器（超时/重试、实时日志捕获、输出智能解码）
    │   ├── notifier.py             # SMTP 通知（失败告警、日报/周报发送、多账号轮转、冷却）
    │   └── reporter.py             # 日报/周报 HTML 生成引擎
    ├── utils/                      # 工具层
    │   ├── config.py               # TOML 配置管理（全局单例，默认值 + 用户覆盖深合并）
    │   ├── logger.py               # 日志工具
    │   └── process.py              # 进程工具（按 PID 终止进程、存活检测）
    └── web/                        # Web 展示层（FastAPI）
        ├── app.py                  # 应用工厂 create_app()，启动时内嵌调度器
        ├── api/                    # REST API（/api/stats、tasks、runs、reports、settings）
        ├── routes/                 # 页面路由（Jinja2 服务端渲染）
        ├── static/css/             # 自定义样式
        └── templates/              # HTML 模板（Tailwind CSS + HTMX + Chart.js，CDN 引入）
```

### 核心数据流

```
tw run / tw web（内嵌调度器）
      │  cron / interval 定时触发，或 CLI / Web 手动触发
      ▼
TaskExecutor 子进程执行（shell 执行命令）
      │  实时捕获 stdout/stderr，逐行智能解码（UTF-8 优先，系统编码回退）
      ▼
日志文件 logs/<task_id>/*.log  +  SQLite runs 表（状态/退出码/输出摘要）
      │
      ├──▶ Web UI：/logs 页面通过 /api/runs/{id}/stream 实时查看
      ├──▶ CLI：tw log / tw task show
      └──▶ 邮件：失败告警（Notifier）+ 日报/周报（Reporter）
```

### 技术栈

| 技术 | 用途 |
|------|------|
| Typer + Rich | CLI 框架与终端美化输出（表格、颜色） |
| FastAPI + Uvicorn | Web 框架与 ASGI 服务器 |
| Jinja2 | HTML 模板引擎（服务端渲染） |
| Tailwind CSS / HTMX / Chart.js | 前端样式、交互增强、趋势图表（全部 CDN 引入，零构建） |
| APScheduler | 调度引擎（BackgroundScheduler，cron/interval 触发器） |
| SQLite（WAL 模式） | 数据持久化，零配置、支持并发读写 |
| tomllib / tomli-w | TOML 配置读写（Python < 3.11 使用 tomli） |
| smtplib | 邮件发送（标准库） |

---

## 开发指南

### 本地开发环境

```bash
# 1. 克隆项目并进入目录
cd taskwatch

# 2. 以开发模式安装（含 pytest 等开发依赖）
pip install -e ".[dev]"

# 3. 验证安装
tw --help
```

开发时数据文件（`config.toml`、`taskwatch.db`、`logs/`）生成在**当前工作目录**，建议在项目外单独建一个工作目录运行 `tw init`，避免污染源码目录。

### 运行测试

项目使用 pytest 作为测试框架（已包含在 `dev` 可选依赖中）：

```bash
pytest
```

> 当前仓库未内置 `tests/` 目录；新增测试文件后 pytest 会自动收集执行。
> 修改代码后可先用 `python -m py_compile <文件>` 做语法快速检查。

---

## License

[MIT](https://opensource.org/licenses/MIT)
# TaskWatch

轻量级本地任务调度器，集 CLI 管理、Web 仪表盘和邮件报告于一体。

## 核心特性

- **CLI 管理**：基于 Typer + Rich 的命令行工具，支持任务增删改查、手动触发、日志查看
- **Web 仪表盘**：FastAPI 驱动的 Web 管理界面，实时查看任务状态与运行趋势
- **APScheduler 调度**：支持 cron 表达式和 interval 间隔两种调度方式
- **SQLite 持久化**：WAL 模式本地数据库，零配置、高可靠
- **SMTP 邮件通知/告警**：任务失败即时告警，支持多账号轮转与冷却机制
- **日报/周报自动生成**：定时汇总任务运行情况，自动生成 HTML 报告并邮件发送

---

## 快速启动（Quick Start）

### 环境要求

- Python >= 3.9
- pip（或其他兼容的包管理器）

### 安装步骤

```bash
# 克隆或进入项目目录
cd taskwatch-project

# 开发模式安装（推荐）
pip install -e .

# 或直接安装
pip install .
```

安装完成后，系统会注册两个命令入口：`tw` 和 `taskwatch`（功能相同）。

### 最小化使用示例

```bash
# 1. 初始化（创建数据库、配置文件、日志目录）
tw init

# 2. 添加一个任务：每天早上 9 点执行
tw task add --name "hello" --command "echo Hello TaskWatch" --schedule "0 9 * * *"

# 3. 启动调度器（前台运行）
tw run

# 4. 或者启动 Web 管理界面（内嵌调度器）
tw web
```

### 默认访问地址

启动 Web UI 后，默认监听地址为：

```
http://127.0.0.1:8899
```

可通过 `--host` 和 `--port` 参数自定义：

```bash
tw web --host 0.0.0.0 --port 9000
```

---

## 详细使用教程

### CLI 命令完整说明

#### `tw init`

初始化 TaskWatch 工作环境：创建数据目录、SQLite 数据库、默认配置文件，并可选配置 SMTP。

```bash
tw init
```

#### `tw task` — 任务管理

| 命令 | 说明 | 示例 |
|------|------|------|
| `tw task add` | 添加新任务 | `tw task add -n "backup" -c "python backup.py" -s "0 2 * * *"` |
| `tw task list` | 列出所有任务 | `tw task list --status enabled` |
| `tw task show <ID>` | 查看任务详情与统计 | `tw task show 1` |
| `tw task edit <ID>` | 编辑任务属性 | `tw task edit 1 --schedule "30 8 * * *"` |
| `tw task rm <ID>` | 删除任务 | `tw task rm 1 --force` |
| `tw task enable <ID>` | 启用任务 | `tw task enable 1` |
| `tw task disable <ID>` | 禁用任务 | `tw task disable 1` |
| `tw task run <ID>` | 手动触发一次运行 | `tw task run 1` |

**`task add` 完整参数：**

```bash
tw task add \
  --name "my_task" \           # 任务名称（必填）
  --command "python run.py" \  # 执行命令（必填）
  --schedule "0 9 * * *" \    # 调度表达式（必填）
  --timeout 3600 \             # 超时时间（秒），默认 3600
  --retry 3 \                  # 最大重试次数，默认 3
  --retry-interval 60 \        # 重试间隔（秒），默认 60
  --working-dir "/path" \      # 工作目录
  --env "KEY1=val1,KEY2=val2" \ # 环境变量
  --tags "daily,etl" \         # 标签（逗号分隔）
  --notify on_failure          # 通知策略：always / on_failure / never
```

#### `tw run` — 启动调度器

```bash
# 前台运行（Ctrl+C 停止）
tw run

# 后台守护进程模式（仅 Unix 系统）
tw run --daemon
```

#### `tw log` — 查看日志

```bash
# 查看任务最近运行记录及日志
tw log 1

# 查看指定运行记录的日志
tw log 1 --run-id 42

# 显示最近 50 行
tw log 1 --tail 50

# 实时跟踪日志输出
tw log 1 --follow
```

#### `tw report` — 生成报告

```bash
# 生成今日日报
tw report daily

# 生成指定日期的日报并发送邮件
tw report daily 2025-01-15 --send

# 生成本周周报
tw report weekly

# 生成指定周期的周报并发送
tw report weekly 2025-01-06 2025-01-12 --send
```

#### `tw config` — 配置管理

```bash
# 查看所有配置
tw config --list

# 查看某个配置项
tw config smtp.host

# 修改配置项
tw config smtp.host smtp.qq.com
tw config smtp.port 465
tw config alert.cooldown_minutes 30
```

#### `tw mail` — 邮件测试

```bash
# 发送测试邮件验证 SMTP 配置
tw mail test
```

#### `tw web` — Web 管理界面

```bash
# 默认启动（127.0.0.1:8899，自动打开浏览器）
tw web

# 自定义端口，不自动打开浏览器
tw web --port 9000 --no-browser
```

---

### Web UI 各页面功能说明

| 页面 | 路径 | 功能 |
|------|------|------|
| 仪表盘 | `/` | 任务总数、今日运行数、成功率、运行中数量；近 7 天趋势图；最近运行记录 |
| 任务管理 | `/tasks` | 任务列表、搜索过滤、新建/编辑/删除任务、启用/禁用开关、手动运行 |
| 任务详情 | `/tasks/{id}` | 任务配置信息、运行统计（总次数/成功率/平均耗时）、最近运行记录 |
| 运行日志 | `/logs` | 多条件过滤（任务/状态/触发方式/时间范围）、分页浏览、日志详情弹窗 |
| 报告中心 | `/reports` | 日报/周报历史列表、手动生成报告、查看报告详情、重新发送邮件 |
| 系统设置 | `/settings` | SMTP 配置、报告时间配置、告警配置、数据库/日志路径、日志清理 |

---

### 配置文件说明

配置文件为 `config.toml`（TOML 格式），位于工作目录下。首次运行 `tw init` 时自动创建。

```toml
[core]
database_path = "./taskwatch.db"    # 数据库文件路径
log_dir = "./logs"                  # 日志目录
pid_file = "./taskwatch.pid"        # PID 文件路径

[smtp]
enabled = false                     # 是否启用 SMTP
host = "smtp.gmail.com"            # SMTP 服务器
port = 587                          # 端口
use_tls = true                      # 是否使用 TLS
username = ""                       # 用户名
password = ""                       # 密码（也可通过环境变量 TASKWATCH_SMTP_PASSWORD 设置）
from_addr = ""                      # 发件人地址
to_addrs = []                       # 收件人列表

[retry]
default_retry = 3                   # 默认重试次数
default_retry_interval = 60         # 默认重试间隔（秒）

[timeout]
default_timeout = 3600              # 默认任务超时（秒）

[logging]
max_log_files = 100                 # 最大日志文件数
max_log_age_days = 30               # 日志保留天数

[web]
host = "127.0.0.1"                 # Web 监听地址
port = 8899                         # Web 监听端口
auto_open_browser = true            # 启动时自动打开浏览器

[report]
daily_time = "10:00"                # 日报发送时间
daily_enabled = true                # 是否启用日报
weekly_day = "monday"               # 周报发送星期
weekly_time = "11:00"               # 周报发送时间
weekly_enabled = true               # 是否启用周报

[alert]
enabled = true                      # 是否启用失败告警
cooldown_minutes = 10               # 告警冷却时间（分钟）
```

---

### 任务调度类型说明

TaskWatch 支持两种调度方式，系统会根据表达式格式自动识别：

| 类型 | 格式 | 示例 | 说明 |
|------|------|------|------|
| **cron** | 标准 5 位 cron 表达式 | `0 9 * * *` | 每天 9:00 执行 |
| **cron** | 带秒的 6 位表达式 | `30 0 9 * * *` | 每天 9:00:30 执行 |
| **interval** | 数字 + 单位 | `30m`、`2h`、`1d` | 每 30 分钟 / 2 小时 / 1 天执行一次 |

**cron 表达式字段说明：**

```
┌──────── 分钟 (0-59)
│ ┌────── 小时 (0-23)
│ │ ┌──── 日 (1-31)
│ │ │ ┌── 月 (1-12)
│ │ │ │ ┌ 星期 (0-6, 0=周日)
│ │ │ │ │
* * * * *
```

**interval 格式说明：**

- `30s` — 每 30 秒
- `5m` — 每 5 分钟
- `2h` — 每 2 小时
- `1d` — 每 1 天

---

### 邮件通知与告警机制

#### 通知策略

每个任务可独立设置通知策略（`--notify` 参数）：

| 策略 | 说明 |
|------|------|
| `on_failure` | 仅在任务失败时发送告警邮件（默认） |
| `always` | 每次运行完成后都发送通知 |
| `never` | 不发送任何通知 |

#### 多账号轮转

在配置文件中可配置多个 SMTP 账号（`smtp.accounts` 列表），系统发送邮件时会自动轮转使用，避免单账号发送频率限制。

#### 失败告警冷却

为防止同一任务频繁失败导致邮件轰炸，系统设有告警冷却机制：

- 默认冷却时间：10 分钟
- 同一任务在冷却期内不会重复发送告警
- 可通过 `alert.cooldown_minutes` 配置调整

---

## 项目架构

### 目录结构

```
taskwatch/
├── __init__.py                     # 包入口，版本定义
├── cli/                            # CLI 命令行层
│   ├── __init__.py
│   ├── main.py                     # Typer 主应用，注册所有子命令
│   ├── task.py                     # 任务管理命令 (add/list/show/edit/rm/enable/disable/run)
│   ├── run.py                      # 调度器启动命令
│   ├── log.py                      # 日志查看命令
│   └── report.py                   # 报告生成命令 (daily/weekly)
├── core/                           # 核心业务逻辑层
│   ├── __init__.py
│   ├── models.py                   # SQLite 数据层（tasks/runs/reports 表 CRUD）
│   ├── executor.py                 # 子进程任务执行器（超时控制、日志捕获）
│   ├── scheduler.py                # APScheduler 调度引擎（cron/interval 触发器）
│   ├── notifier.py                 # SMTP 邮件通知（多账号轮转、告警冷却）
│   └── reporter.py                 # 日报/周报生成引擎（HTML 报告）
├── utils/                          # 工具层
│   ├── __init__.py
│   ├── config.py                   # TOML 配置管理（全局单例）
│   └── logger.py                   # 日志工具
└── web/                            # Web 展示层
    ├── __init__.py
    ├── app.py                      # FastAPI 应用工厂 (create_app)
    ├── api/                        # REST API 路由
    │   ├── __init__.py
    │   ├── stats.py                # 统计数据接口
    │   ├── tasks.py                # 任务 CRUD 接口
    │   ├── runs.py                 # 运行记录接口
    │   ├── reports.py              # 报告生成/查看/重发接口
    │   └── settings.py             # 配置读写/测试邮件/日志清理接口
    ├── routes/                     # 页面路由（服务端渲染）
    │   ├── __init__.py
    │   ├── dashboard.py            # 仪表盘页面
    │   ├── tasks.py                # 任务管理 + 任务详情页面
    │   ├── logs.py                 # 运行日志页面
    │   ├── reports.py              # 报告中心页面
    │   └── settings.py             # 系统设置页面
    ├── static/
    │   └── css/
    │       └── style.css           # 自定义样式（滚动条、过渡动画）
    └── templates/                  # Jinja2 HTML 模板
        ├── base.html               # 基础布局（导航栏、Toast、API 工具函数）
        ├── dashboard.html          # 仪表盘（统计卡片 + Chart.js 趋势图）
        ├── tasks.html              # 任务列表（搜索/过滤/新建/编辑弹窗）
        ├── task_detail.html        # 任务详情（配置/统计/运行记录）
        ├── logs.html               # 日志（多条件过滤/分页/详情弹窗）
        ├── reports.html            # 报告中心（日报/周报/生成/重发）
        └── settings.html           # 设置（SMTP/报告/告警/数据库配置）
```

### 各模块职责说明

| 模块 | 职责 |
|------|------|
| `cli/` | 基于 Typer 的命令行入口，提供任务管理、调度器控制、日志查看、报告生成等命令 |
| `core/models.py` | SQLite 数据持久化层，管理 tasks、runs、reports 三张表的 CRUD 操作 |
| `core/executor.py` | 子进程任务执行器，负责命令执行、超时控制、stdout/stderr 捕获、日志文件写入 |
| `core/scheduler.py` | 基于 APScheduler BackgroundScheduler 的调度引擎，管理任务的注册/注销/触发 |
| `core/notifier.py` | SMTP 邮件发送模块，支持多账号轮转、失败告警冷却、测试邮件 |
| `core/reporter.py` | 报告生成引擎，汇总任务运行数据生成 HTML 格式日报/周报 |
| `utils/config.py` | TOML 配置文件管理，全局单例模式，支持深层嵌套读写 |
| `utils/logger.py` | 日志工具，提供统一的日志记录接口 |
| `web/app.py` | FastAPI 应用工厂，组装静态文件、模板、API 路由和页面路由 |
| `web/api/` | RESTful API 接口，供前端 AJAX 调用 |
| `web/routes/` | 服务端渲染页面路由，返回 Jinja2 模板响应 |
| `web/templates/` | HTML 模板，使用 Tailwind CSS + HTMX + Chart.js |

### 技术栈

| 技术 | 用途 |
|------|------|
| Typer | CLI 框架 |
| Rich | 终端美化输出（表格、颜色） |
| FastAPI | Web 框架 |
| Uvicorn | ASGI 服务器 |
| APScheduler | 任务调度引擎 |
| SQLite (WAL) | 数据持久化 |
| Jinja2 | HTML 模板引擎 |
| Tailwind CSS | 前端样式（CDN） |
| HTMX | 前端交互增强（CDN） |
| Chart.js | 数据可视化图表（CDN） |
| tomli / tomli_w | TOML 配置读写 |
| smtplib | 邮件发送（标准库） |

---

## 设计思路

### 分层架构设计

```
┌─────────────────────────────────────────────┐
│              CLI 层 (cli/)                    │  用户交互入口
├─────────────────────────────────────────────┤
│              Web 展示层 (web/)                │  可视化管理界面
├─────────────────────────────────────────────┤
│              Core 业务层 (core/)              │  核心逻辑：调度、执行、通知、报告
├─────────────────────────────────────────────┤
│              Utils 工具层 (utils/)            │  基础设施：配置、日志
└─────────────────────────────────────────────┘
```

- **CLI 层**和 **Web 层**作为两个独立的用户交互入口，共享底层 Core 业务逻辑
- **Core 层**不依赖任何 UI 框架，可被 CLI 和 Web 共同调用
- **Utils 层**提供配置管理和日志等基础能力，被所有上层模块引用

### 数据持久化方案

- 采用 **SQLite WAL（Write-Ahead Logging）模式**，支持并发读写，无需额外数据库服务
- 数据库文件默认位于工作目录下的 `taskwatch.db`
- 三张核心表：`tasks`（任务定义）、`runs`（运行记录）、`reports`（报告历史）
- 通过 `row_factory = sqlite3.Row` 实现字典式行访问

### 调度引擎选型

选用 **APScheduler BackgroundScheduler**：

- 纯 Python 实现，无外部依赖（无需 Redis/RabbitMQ）
- 原生支持 cron 和 interval 两种触发器
- 后台线程运行，不阻塞主进程
- 支持动态添加/移除/暂停任务
- 适合本地轻量调度场景

### Web 工厂模式

```python
def create_app() -> FastAPI:
    """应用工厂函数"""
    app = FastAPI(lifespan=lifespan)
    # 挂载静态文件、注册模板、注册 API 路由、注册页面路由
    return app
```

- 通过 `create_app()` 工厂函数创建应用实例，便于测试和 Uvicorn 加载
- API 路由（`/api/*`）与页面路由（`/`、`/tasks`、`/logs` 等）模块化分离
- 使用 `lifespan` 上下文管理器在应用启动时自动启动内嵌调度器

### 前端轻量方案

- **无需构建步骤**：所有前端依赖通过 CDN 引入（Tailwind CSS、HTMX、Chart.js）
- **服务端渲染**：Jinja2 模板直出 HTML，首屏加载快
- **渐进增强**：HTMX 处理动态交互，原生 JavaScript 处理复杂逻辑（分页、轮询）
- **零前端工程化**：无需 Node.js、npm、webpack 等工具链

---

## 免责声明

- 本项目为**本地轻量工具**，设计用于个人或小团队的本地任务调度场景，**不适用于生产环境高可用、高并发场景**。
- 任务执行依赖本地系统环境（Shell、Python 解释器等），项目**不对用户命令的执行结果负责**。
- 邮件发送功能依赖用户自行配置的 SMTP 服务，项目**不保证邮件一定能成功送达**。
- 数据存储为本地 SQLite 文件，**用户需自行做好数据备份**，项目不对数据丢失承担责任。
- 本项目按 **"原样"（AS IS）** 提供，不附带任何明示或暗示的保证，包括但不限于适销性、特定用途适用性和非侵权性的保证。

---

## 许可证

MIT License
