# Daily Todo 功能设计文档

## 概述

每日待办（Daily Todo）是一个以"天"为维度的任务管理模块，与现有的看板（以项目/多天为维度）形成互补。

**核心价值：** AI 每天早上自动预生成今日待办（基于前一天未完成的看板任务 + 前一天对话记录），用户可手动增删改。

## 时区说明

- 所有日期相关字段均使用**用户本地日期**（后端统一用 `datetime.date.today()` 计算，不依赖 UTC）
- `todo_date` 格式：`YYYY-MM-DD`（本地日期字符串），便于按天查询

## 数据模型

### DailyTodo 表

| 字段 | 类型 | 说明 |
|------|------|------|
| id | String(36) | 主键，UUID |
| user_id | String(36) | 所属用户，索引 |
| title | String(500) | 待办标题 |
| is_completed | Boolean | 是否完成，默认 false |
| source | Enum | `ai_kanban` / `ai_chat` / `manual`，来源 |
| source_detail | String(500) | 展示用说明文本，如"看板：完成用户登录功能" |
| source_ref_id | String(36) | 来源原始ID（看板TaskID或对话ConversationID），可空 |
| todo_date | String(10) | 所属日期，格式 YYYY-MM-DD，复合索引 (user_id, todo_date) |
| completed_at | DateTime | 完成时间，可空 |
| created_at | DateTime | 创建时间 |
| updated_at | DateTime | 更新时间 |

**索引：** `INDEX (user_id, todo_date)`，查询今日待办的主要路径

### DailyTodoHistory 归档表

归档时机：每天凌晨 1:00，APScheduler 清理 7 天前的记录

| 字段 | 类型 | 说明 |
|------|------|------|
| id | String(36) | 主键，UUID |
| original_id | String(36) | 原记录ID（原记录归档后可能已删除） |
| user_id | String(36) | 所属用户 |
| title | String(500) | 待办标题 |
| is_completed | Boolean | 最终完成状态 |
| source | Enum | 来源 |
| source_detail | String(500) | 展示用说明文本 |
| todo_date | String(10) | 所属日期 |
| completed_at | DateTime | 完成时间 |
| created_at | DateTime | 创建时间 |
| archived_at | DateTime | 归档时间 |

**保留策略：** 归档记录保留 7 天，到期自动删除（APScheduler 每日清理）

## 核心功能

### F1: 今日待办列表
- 展示当天的所有待办事项
- 每条可勾选完成状态（勾选后划线 + 变灰）
- 支持新增、编辑、删除
- 按创建时间倒序排列
- 分页：每页 50 条，支持 `page` + `page_size` 参数

### F2: 历史记录
- 可查看昨天、前天等历史日期的待办
- 切换日期查看，**只读**（历史不允许修改/删除）
- 历史数据来自 `DailyTodo` 表（按 todo_date 过滤）
- 注：不从 `DailyTodoHistory` 表读取——归档表仅作备份保留

### F3: AI 自动预生成
- 触发时机：每天早上 8:00（APScheduler 定时任务），也可手动触发
- 数据来源：
  1. **看板任务**：前一天创建的、状态 ≠ done 的任务，取前 20 条（按 created_at 倒序）
  2. **对话记录**：前一天创建的对话，取其消息内容前 2000 字发给 LLM
- AI 处理流程：
  1. 查询上述数据，拼装为分析文本
  2. 发送给 LLM，Prompt 要求输出 JSON 数组：`[{ "title": "...", "reason": "..." }]`
  3. 解析 LLM 返回，若返回为空或解析失败则跳过对话分析
  4. 批量写入 DailyTodo 表（source=ai_kanban / ai_chat）
- **幂等处理（关键）**：使用事务 + 插入前检查，确保同一天不会重复生成
  ```
  BEGIN TRANSACTION
  IF EXISTS (SELECT 1 FROM daily_todos WHERE user_id=? AND todo_date=? AND source IN ('ai_kanban','ai_chat')):
      ROLLBACK  -- 已有AI生成，跳过
  ELSE:
      INSERT ...  -- 批量写入
      COMMIT
  ```
- **容错**：LLM 不可用时记录日志，跳过该部分，不阻塞整体流程
- 看板任务上限 20 条，对话分析最多提取 3 条

### F4: AI 来源说明
- 每条 AI 生成的待办，显示其来源说明
- `source=ai_kanban`：`source_detail` = "看板：{任务标题}"，`source_ref_id` = 原始 Task ID
- `source=ai_chat`：`source_detail` = "对话：{reason 摘要（截取前60字）}"

## API 设计

### GET /api/todos
查询待办列表（支持分页）
- Query: `?date=2026-03-20&page=1&page_size=50`（date 默认当天）
- Response:
```json
{
  "items": [DailyTodoOut],
  "total": 12,
  "page": 1,
  "page_size": 50
}
```

### POST /api/todos
新增待办（手动）
- Body: `{ title: string }`
- source 固定为 `manual`，todo_date 为当天

### PATCH /api/todos/{id}
更新待办（完成状态 / 标题）
- Body: `{ is_completed?: boolean, title?: string }`
- 仅当日待办可修改，历史日期返回 403

### DELETE /api/todos/{id}
删除待办
- 仅当日待办可删除，历史日期返回 403

### POST /api/todos/ai-generate
手动触发 AI 预生成
- 检查今日是否已有 AI 生成记录，有则返回 200（幂等，不重复生成）
- 无则执行 AI 分析流程，返回生成结果

### GET /api/todos/summary
获取今日待办摘要
- Response: `{ date: "2026-03-20", total: 5, completed: 2, pending: 3 }`

## 响应 Schema

### DailyTodoOut
```json
{
  "id": "uuid",
  "title": "完成用户登录功能",
  "is_completed": false,
  "source": "ai_kanban",
  "source_detail": "看板：完成用户登录功能",
  "todo_date": "2026-03-20",
  "completed_at": null,
  "created_at": "2026-03-20T08:00:00Z"
}
```

## 定时任务

| 任务 | 时间 | 说明 |
|------|------|------|
| AI预生成 | 每天 08:00 | 为所有活跃用户执行 AI 预生成 |
| 历史归档清理 | 每天 01:00 | 删除 7 天前已归档的 DailyTodo 记录 |

## 前端页面

### TodoView.vue
- 路径：`/todo`
- 布局：顶部日期导航 + 下方待办列表
- 日期导航：今天、昨天、前天快捷按钮 + 日期选择器
- 今日视图：输入框新增 + 列表 + "AI 规划今日"按钮
- 历史视图：只读列表，无新增/删除按钮，灰色禁用样式
- 交互细节：
  - 勾选完成：Motion 动画划线效果
  - 加载状态：骨架屏
  - 空状态：终端风格空提示
- 风格：sci-fi 全息终端，cyan (#00f5d4) + #03050a，与 AgentView 一致

### 侧边栏
- 新增菜单项：`{ name: '待办', path: '/todo', icon: CheckSquare }`

## 技术依赖

- 后端：FastAPI + SQLAlchemy + APScheduler + LLM Service
- 前端：Vue 3 Composition API + 复用 api/index 的 axios 实例
- 数据库：新表 DailyTodo + DailyTodoHistory（迁移 Alembic 或手动 CREATE TABLE）
