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

192 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:**
```json
{
"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
```json
{
"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
```json
[
{
"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
```python
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
- 前端实现