4.1 KiB
4.1 KiB
Design: Schedule Items API
Date: 2026-02-27 Status: Approved
Overview
实现日历事项(Schedule Items)的后端 CRUD API,支持用户创建、查询、更新、删除日历事项。
Scope
- 仅后端 API,不涉及前端
- 全量 CRUD
- 查询按时间范围筛选
- 暂不支持重复日程(recurrence_rule 留空)
API Endpoints
1. 创建日历事项
POST /api/v1/schedule-items
Request:
{
"title": "string (1-255 chars, required)",
"description": "string? (max 2000 chars)",
"start_at": "string (ISO 8601 datetime, required)",
"end_at": "string? (ISO 8601 datetime, must be after start_at)",
"timezone": "string? (default: UTC)",
"metadata": {
"color": "#FF6B6B",
"location": "会议室A",
"notes": "记得带身份证",
"attachments": [],
"version": 1
}
}
Response: 201 Created
{
"id": "uuid",
"title": "string",
"description": "string?",
"start_at": "string",
"end_at": "string?",
"timezone": "string",
"metadata": {...},
"status": "active",
"source_type": "manual",
"created_at": "string",
"updated_at": "string"
}
2. 查询日历事项列表
GET /api/v1/schedule-items?start_at=2026-02-01&end_at=2026-02-28
Query Parameters:
start_at: ISO 8601 date/datetime(查询范围起始)end_at: ISO 8601 date/datetime(查询范围结束)
Response: 200 OK
[
{
"id": "uuid",
"title": "string",
"start_at": "string",
"end_at": "string?",
"timezone": "string",
"status": "active"
}
]
3. 获取单个事项
GET /api/v1/schedule-items/{id}
Response: 200 OK(完整字段,同创建响应)
4. 更新事项
PATCH /api/v1/schedule-items/{id}
Request: 支持 title/description/start_at/end_at/timezone/metadata/status 部分更新
Response: 200 OK
5. 删除事项
DELETE /api/v1/schedule-items/{id}
Response: 204 No Content(软删除)
Data Models
Metadata 结构(Pydantic)
from enum import Enum
from pydantic import BaseModel
from uuid import UUID
class AttachmentType(str, Enum):
DOCUMENT = "document"
REMINDER = "reminder"
class ScheduleItemMetadataAttachment(BaseModel):
name: str
type: AttachmentType
visible_to: list[UUID] = []
# document 类型
url: str | None = None
note: str | None = None
# reminder 类型
content: str | None = None
class ScheduleItemMetadata(BaseModel):
color: str | None = None
location: str | None = None
notes: str | None = None
attachments: list[ScheduleItemMetadataAttachment] = []
version: int = 1
数据库模型(已有)
参见 backend/src/models/schedule_items.py:
id: UUIDowner_id: UUIDtitle: String(255)description: Textstart_at: DateTime(timezone=True)end_at: DateTime(timezone=True)timezone: String(50)extra_metadata: JSONB (mapped as "metadata")recurrence_rule: String(255)source_type: Enum (MANUAL/IMPORTED/AGENT_GENERATED)status: Enum (ACTIVE/COMPLETED/CANCELED/ARCHIVED)created_by: UUID
Architecture
遵循项目 schemas / repository / service / router 分层模式:
backend/src/v1/schedule_items/
├── __init__.py
├── schemas.py # Pydantic 请求/响应模型
├── repository.py # CRUD 操作(无 auth,无 commit)
├── service.py # 业务逻辑 + 授权 + 事务边界
├── router.py # FastAPI 路由定义
└── dependencies.py # DI(如有)
Security
- 所有端点需要认证(JWT)
owner_id从 JWTsub提取,不从请求体读取- 用户只能操作自己的日历事项(
owner_id过滤) - RLS 已在数据库层启用(防御边界)
Error Handling
使用 RFC 7807 application/problem+json 格式:
- 400: 请求参数无效
- 401: 未认证
- 404: 事项不存在或无权限访问
- 422: 验证失败
Out of Scope
- 重复日程(recurrence_rule)
- 日程订阅与协作(schedule_subscriptions)
- 待办事项联动(todos/todo_sources)
- 前端实现