Metadata-Version: 2.4
Name: taskwatch
Version: 0.1.1
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

轻量级本地任务调度器，集 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
