330 lines
6.6 KiB
Markdown
330 lines
6.6 KiB
Markdown
# Schedule Items 协议
|
||
|
||
本文档定义 `/api/v1/schedule-items` 的日历日程管理协议。
|
||
|
||
Base URL: `/api/v1/schedule-items`
|
||
|
||
---
|
||
|
||
## 端点
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|---|---|---|
|
||
| POST | `` | 创建日程 |
|
||
| GET | `` | 按日期范围查询日程 |
|
||
| GET | `/{item_id}` | 获取指定日程详情 |
|
||
| PATCH | `/{item_id}` | 更新日程 |
|
||
| DELETE | `/{item_id}` | 删除日程 |
|
||
| POST | `/{item_id}/share` | 分享日程给其他用户 |
|
||
| POST | `/{item_id}/accept` | 接受日程订阅 |
|
||
| POST | `/{item_id}/reject` | 拒绝日程订阅 |
|
||
|
||
---
|
||
|
||
## 枚举类型
|
||
|
||
### ScheduleItemStatus
|
||
|
||
| 值 | 说明 |
|
||
|---|---|
|
||
| `active` | 进行中 |
|
||
| `archived` | 已归档 |
|
||
|
||
兼容策略:历史数据中若存在 `completed` 或 `canceled`,服务端统一按 `archived` 语义处理;新写入仅允许 `active` 或 `archived`。
|
||
|
||
### ScheduleItemSourceType
|
||
|
||
| 值 | 说明 |
|
||
|---|---|
|
||
| `manual` | 手动创建 |
|
||
| `imported` | 导入 |
|
||
| `agent_generated` | Agent 生成 |
|
||
|
||
### AttachmentType
|
||
|
||
| 值 | 说明 |
|
||
|---|---|
|
||
| `document` | 文档 |
|
||
| `reminder` | 提醒 |
|
||
|
||
---
|
||
|
||
## 数据结构
|
||
|
||
### ScheduleItemMetadata
|
||
|
||
```json
|
||
{
|
||
"color": "#FF5733 | null",
|
||
"location": "string | null",
|
||
"notes": "string | null",
|
||
"attachments": [
|
||
{
|
||
"name": "string",
|
||
"type": "document | reminder",
|
||
"visible_to": ["uuid"],
|
||
"url": "string | null",
|
||
"note": "string | null",
|
||
"content": "string | null"
|
||
}
|
||
],
|
||
"reminder_minutes": "int (0-10080) | null",
|
||
"version": 1
|
||
}
|
||
```
|
||
|
||
### ScheduleItemCreateRequest
|
||
|
||
```json
|
||
{
|
||
"title": "string (1-255)",
|
||
"description": "string | null (max 2000)",
|
||
"start_at": "datetime (必须包含时区)",
|
||
"end_at": "datetime | null (必须包含时区)",
|
||
"timezone": "string (IANA 时区)",
|
||
"metadata": "ScheduleItemMetadata | null"
|
||
}
|
||
```
|
||
|
||
### ScheduleItemUpdateRequest
|
||
|
||
```json
|
||
{
|
||
"title": "string | null (1-255)",
|
||
"description": "string | null (max 2000)",
|
||
"start_at": "datetime | null (必须包含时区)",
|
||
"end_at": "datetime | null (必须包含时区)",
|
||
"timezone": "string | null (IANA 时区)",
|
||
"metadata": "ScheduleItemMetadata | null",
|
||
"status": "ScheduleItemStatus | null (active | archived)"
|
||
}
|
||
```
|
||
|
||
### ScheduleItemResponse
|
||
|
||
```json
|
||
{
|
||
"id": "uuid",
|
||
"owner_id": "uuid",
|
||
"title": "string",
|
||
"description": "string | null",
|
||
"start_at": "datetime",
|
||
"end_at": "datetime | null",
|
||
"timezone": "string",
|
||
"metadata": "ScheduleItemMetadata | null",
|
||
"status": "ScheduleItemStatus",
|
||
"source_type": "ScheduleItemSourceType",
|
||
"created_at": "datetime",
|
||
"updated_at": "datetime",
|
||
"permission": "int (位掩码: 1=view, 2=invite, 4=edit, 8=delete, 15=owner)",
|
||
"is_owner": "boolean (当前用户是否为日程所有者)",
|
||
"subscribers": ["SubscriberInfo"]
|
||
}
|
||
```
|
||
|
||
### SubscriberInfo
|
||
|
||
```json
|
||
{
|
||
"user_id": "uuid",
|
||
"username": "string | null",
|
||
"avatar_url": "string | null",
|
||
"phone": "string | null",
|
||
"permission": "int (位掩码: 1=view, 2=invite, 4=edit, 8=delete, 15=owner)",
|
||
"status": "string (active | pending | unsubscribed)",
|
||
"subscribed_at": "datetime"
|
||
}
|
||
```
|
||
|
||
说明:
|
||
- `subscribers` 列表仅包含状态为 `active` 的订阅者
|
||
- `phone` 字段来自 Supabase Auth,用于显示订阅者手机号
|
||
- 前端显示优先级:`phone ?? username ?? user_id`
|
||
|
||
### ScheduleItemShareRequest
|
||
|
||
```json
|
||
{
|
||
"phone": "+8613812345678",
|
||
"permission_view": "boolean (default: true)",
|
||
"permission_edit": "boolean (default: false)",
|
||
"permission_invite": "boolean (default: false)"
|
||
}
|
||
```
|
||
|
||
说明:
|
||
- 分享目标仅支持 `phone`(E.164 中国手机号,如 `+8613812345678`),不接受 `user_id` 作为分享入参。
|
||
- `permission_view`、`permission_edit`、`permission_invite` 为布尔值,内部会转换为位掩码整数:
|
||
- `permission_view = 1`
|
||
- `permission_invite = 2`
|
||
- `permission_edit = 4`
|
||
- `permission_delete = 8`
|
||
- `permission_owner = 15`
|
||
|
||
### ScheduleItemShareResponse
|
||
|
||
```json
|
||
{
|
||
"message": "string"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 1) POST `/`
|
||
|
||
创建日程。
|
||
|
||
### Request
|
||
|
||
`ScheduleItemCreateRequest` 对象。
|
||
|
||
### Response
|
||
|
||
`ScheduleItemResponse` 对象,状态码 201。
|
||
|
||
---
|
||
|
||
## 2) GET `/`
|
||
|
||
按日期范围查询日程。
|
||
|
||
### Query Parameters
|
||
|
||
- `start_at`: 开始时间(必须包含时区)
|
||
- `end_at`: 结束时间(必须包含时区)
|
||
|
||
### Response
|
||
|
||
`ScheduleItemResponse` 对象数组。
|
||
|
||
---
|
||
|
||
## 3) GET `/{item_id}`
|
||
|
||
获取指定日程详情。
|
||
|
||
### Path Parameters
|
||
|
||
- `item_id`: 日程 UUID
|
||
|
||
### Response
|
||
|
||
`ScheduleItemResponse` 对象。
|
||
|
||
---
|
||
|
||
## 4) PATCH `/{item_id}`
|
||
|
||
更新日程(部分更新)。
|
||
|
||
### Authorization
|
||
|
||
- **Owner**: 可更新所有字段
|
||
- **Subscriber (EDIT permission)**: 可更新所有字段(权限位掩码包含 `4`)
|
||
|
||
### Path Parameters
|
||
|
||
- `item_id`: 日程 UUID
|
||
|
||
### Request
|
||
|
||
`ScheduleItemUpdateRequest` 对象。
|
||
|
||
### Response
|
||
|
||
`ScheduleItemResponse` 对象。
|
||
|
||
### Error Responses
|
||
|
||
| Status | Code | 说明 |
|
||
|--------|------|------|
|
||
| 403 | `SCHEDULE_ITEM_FORBIDDEN` | 当前用户无权编辑此日程 |
|
||
| 404 | `SCHEDULE_ITEM_NOT_FOUND` | 日程不存在或用户既不是 owner 也没有订阅 |
|
||
|
||
---
|
||
|
||
## 5) DELETE `/{item_id}`
|
||
|
||
删除日程。
|
||
|
||
### Authorization
|
||
|
||
- **Owner**: 可删除日程(权限位掩码包含 `8`)
|
||
- **Subscriber (DELETE permission)**: 可删除日程(权限位掩码包含 `8`)
|
||
|
||
### Path Parameters
|
||
|
||
- `item_id`: 日程 UUID
|
||
|
||
### Response
|
||
|
||
204 No Content。
|
||
|
||
### Error Responses
|
||
|
||
| Status | Code | 说明 |
|
||
|--------|------|------|
|
||
| 403 | `SCHEDULE_ITEM_FORBIDDEN` | 当前用户无权删除此日程 |
|
||
| 404 | `SCHEDULE_ITEM_NOT_FOUND` | 日程不存在或用户既不是 owner 也没有订阅 |
|
||
|
||
---
|
||
|
||
## 6) POST `/{item_id}/share`
|
||
|
||
按手机号分享日程给已接受好友。
|
||
|
||
### Path Parameters
|
||
|
||
- `item_id`: 日程 UUID
|
||
|
||
### Request
|
||
|
||
`ScheduleItemShareRequest` 对象。
|
||
|
||
- `phone`: 分享目标手机号(E.164,中国号段,如 `+8613xxxxxxxxx`)
|
||
- `permission_view`: 是否授予查看权限
|
||
- `permission_edit`: 是否授予编辑权限
|
||
- `permission_invite`: 是否授予继续邀请权限
|
||
|
||
### Response
|
||
|
||
`ScheduleItemShareResponse` 对象。
|
||
|
||
### Error Responses
|
||
|
||
| Status | Code | 说明 |
|
||
|--------|------|------|
|
||
| 403 | `SCHEDULE_ITEM_SHARE_FORBIDDEN` | 当前用户无分享权限 |
|
||
| 403 | `SCHEDULE_ITEM_SHARE_PERMISSION_EXCEEDED` | 授权位超过当前用户可授予上限 |
|
||
| 403 | `SCHEDULE_ITEM_SHARE_TARGET_NOT_FRIEND` | 仅允许分享给已接受好友 |
|
||
| 404 | `SCHEDULE_ITEM_NOT_FOUND` | 日程不存在 |
|
||
|
||
---
|
||
|
||
## 7) POST `/{item_id}/accept`
|
||
|
||
接受日程订阅邀请。
|
||
|
||
### Path Parameters
|
||
|
||
- `item_id`: 日程 UUID
|
||
|
||
### Response
|
||
|
||
字典对象。
|
||
|
||
---
|
||
|
||
## 8) POST `/{item_id}/reject`
|
||
|
||
拒绝日程订阅邀请。
|
||
|
||
### Path Parameters
|
||
|
||
- `item_id`: 日程 UUID
|
||
|
||
### Response
|
||
|
||
字典对象。
|