Files
social-app/docs/plans/2026-02-27-schedule-items-api-design.md
T

4.1 KiB
Raw Blame History

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: UUID
  • owner_id: UUID
  • title: String(255)
  • description: Text
  • start_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 从 JWT sub 提取,不从请求体读取
  • 用户只能操作自己的日历事项(owner_id 过滤)
  • RLS 已在数据库层启用(防御边界)

Error Handling

使用 RFC 7807 application/problem+json 格式:

  • 400: 请求参数无效
  • 401: 未认证
  • 404: 事项不存在或无权限访问
  • 422: 验证失败

Out of Scope

  • 重复日程(recurrence_rule
  • 日程订阅与协作(schedule_subscriptions
  • 待办事项联动(todos/todo_sources
  • 前端实现