← 返回导航
API 设计
Spring Boot 风格
基础路径:`https://timesake-api.shihesuian.cn/api/v1`
认证:`Authorization: Bearer `(登录后下发,有效期 30 天)
统一响应:`{"code": 0, "message": "ok", "data": {...}}`(code=0 成功,非 0 见 message)
v0.2(2026-08-11 迭代二):记录支持图片(imageUrl 可空、content 可空,双空报 4001);自定义里程碑 `PUT /projects/{id}/milestones`;分享 records 带 `image_url`;文件上传接口归档
1. 认证(手机号验证码)
| 方法 | 路径 | 说明 |
|---|
| POST | /auth/sms/send | 发送验证码 {phone, scene} → 60s 限频,5 分钟有效 |
| POST | /auth/login | 登录/注册 {phone, code} → {token, user} |
| POST | /auth/wx-login | 微信小程序一键登录 {code}(免登录)→ code2session 换 openid → 已有账号直接登录/无则自动注册;未配置 AppID/Secret 返回 5001 |
| POST | /auth/bind-phone | 绑定手机号 {phone, code}(需登录):手机号未注册→直接绑定;已注册→自动合并(微信账号的项目/成员/记录/邀请/待办/分享迁入手机号账号后删除),返回新 token |
| GET | /auth/me | 获取当前用户信息 |
| PUT | /auth/me | 更新昵称/头像 |
2. 项目
| 方法 | 路径 | 说明 |
|---|
| POST | /projects | 创建项目 {name, type, target_time?, start_time?, repeat_rule, icon, color} |
| GET | /projects | 我的项目列表(创建 + 加入),支持 ?status=1 过滤 |
| GET | /projects/{id} | 项目详情(含成员数、我的角色) |
| PUT | /projects/{id} | 编辑项目(管理员) |
| DELETE | /projects/{id} | 删除项目(管理员,物理删除连带成员/记录) |
| PUT | /projects/{id}/status | 转珍藏/封存(仅支持 status=2:期待 1→2 转珍藏 / 坚持 1→2 封存;重复转返回 4105) |
| PUT | /projects/{id}/milestones | 自定义里程碑整体替换(管理员){milestones:[{name,days}]}:≤5 个、name 非空、days≥1,超限/null 报 4001;空列表=清空;项目详情响应带 milestones |
3. 邀请与加入
| 方法 | 路径 | 说明 |
|---|
| POST | /projects/{id}/invite | 生成邀请 {expire_days=7} → {token, qr_payload} |
| POST | /projects/join | 加入项目 {token} → 项目详情 |
| GET | /projects/{id}/members | 成员列表 |
| DELETE | /projects/{id}/members/{uid} | 移除成员(管理员) |
4. 记录条目(共同维护)
| 方法 | 路径 | 说明 |
|---|
| POST | /projects/{id}/records | 添加记录 {content?, imageUrl?, value_json?, record_date?}:content 与 imageUrl 至少一项(双空报 4001),支持图文/纯图/纯文字 |
| GET | /projects/{id}/records | 记录列表(含 image_url),支持 ?record_date=2026-08-01 或 ?limit=50&offset=0 |
| DELETE | /projects/{id}/records/{rid} | 删除记录(本人或管理员) |
6. 文件上传
| 方法 | 路径 | 说明 |
|---|
| POST | /upload/image | multipart 上传图片 file → {url}(服务端统一压缩:最长边 >1920px 等比缩放 + JPEG 80%;≤1920px 原样直存;HEIC/解码失败兜底原图直存;支持 jpg/png/webp/heic/heif,限 10MB;失败 4002) |
5. 待办(期待筹备期,一期)
| 方法 | 路径 | 说明 |
|---|
| POST | /projects/{id}/todos | 添加待办 {content}(仅期待项目) |
| GET | /projects/{id}/todos | 待办列表 |
| PUT | /todos/{id} | 勾选/取消完成(记录 done_by/done_at 留痕) |
7. 分享(珍藏只读)
| 方法 | 路径 | 说明 |
|---|
| POST | /projects/{id}/share | 生成只读分享(仅珍藏项目+管理员;已有有效分享则复用)→ {token, url} |
| DELETE | /projects/{id}/share | 作废分享(管理员) |
| GET | /share/{token} | 只读内容 {project, records, todos, wish}(无需登录;records 含 image_url 支持媒体版时间线;坚持封存额外返回 days_elapsed/sealed_at 冻结值;曾是一念的珍藏额外返回 wish——一念描述 + 参与档案 + 建议(附议数/被采纳/留言嵌套),供分享页展示「这一念的旅程」) |
8. 实时同步(WebSocket)
连接:wss://timesake-api.shihesuian.cn/ws/projects/{id}?token=<jwt>
鉴权(2026-08-16 评审 P0 修复):握手校验 JWT + 项目权限——进行中/珍藏需为正式成员;
一念(status=0)需为成员或已「看见」(参与档案 seen=1)。无权限连接被拒(1008 Policy Violation)。
消息(服务端→客户端):
{"type": "record_added", "data": {...record}}
{"type": "record_deleted", "data": {"id": 123}}
{"type": "member_joined", "data": {...user}}
{"type": "project_updated","data": {...project}}
{"type": "todo_added", "data": {...todo}} // 待办新增(2026-08-13)
{"type": "todo_toggled", "data": {...todo}} // 待办勾选(2026-08-13)
{"type": "wish_updated", "data": null} // 一念:表态/建议/附议变化
{"type": "suggestion_commented", "data": null} // 一念:留言/回复变化
客户端心跳:每 30s 发送 {"type": "ping"}(H5 发字符串,小程序发 {data})
9. 关键字段示例
创建项目请求:
{
"name": "宝宝成长倒计时",
"type": 2,
"start_time": "2026-03-15T00:00:00+08:00",
"repeat_rule": 0,
"icon": "baby",
"color": "#FFB6C1"
}
项目详情响应:
{
"code": 0,
"data": {
"id": 1,
"name": "宝宝成长倒计时",
"type": 2,
"start_time": "2026-03-15T00:00:00+08:00",
"target_time": null,
"repeat_rule": 0,
"icon": "baby",
"color": "#FFB6C1",
"role": 1,
"member_count": 3,
"days_elapsed": 139,
"milestones": [{"name": "会走路了", "days": 365}]
}
}
记录列表响应(含图片):
{
"code": 0,
"data": [
{
"id": 88,
"content": "今天会叫妈妈了!",
"image_url": "https://timesake-api.shihesuian.cn/uploads/2026/08/xxxx.jpg",
"record_date": "2026-08-11",
"created_by": 1
}
]
}
上传图片响应:
{"code": 0, "data": {"url": "https://timesake-api.shihesuian.cn/uploads/2026/08/xxxx.jpg"}}
10. 错误码
| code | 含义 |
|---|
| 0 | 成功 |
| 1001 | 验证码错误/过期 |
| 1002 | 发送太频繁(60s) |
| 1003 | 短信服务未配置 |
| 1004 | 短信发送失败 |
| 1005 | 登录状态失效,请重新登录(TOKEN_INVALID,2026-08-16 起独立码,原与 1003 重号) |
| 1006 | 验证码错误次数过多,已锁定 15 分钟(2026-08-16 防爆破) |
| 2001 | 未登录/令牌缺失 |
| 2002 | 无权限(非管理员操作 / 用户被禁用) |
| 3001 | 项目不存在 |
| 3002 | 邀请无效/过期 |
| 3003 | 你不是该项目成员(含一念未「看见」) |
| 4001 | 参数错误(含:记录 content 与 imageUrl 双空;里程碑 >5 个或字段非法) |
| 4002 | 图片上传失败 |
| 4003 | 仅支持 jpg/png/webp/heic 图片 |
| 4004 | 图片不能超过 10MB |
| 4005 | 背景不存在 |
| 4101 | 待办不存在 |
| 4102 | 分享不存在或已失效 |
| 4103 | 仅珍藏的项目可生成分享 |
| 4104 | 仅进行中的项目可转为珍藏 |
| 4105 | 该项目已珍藏 |
| 4106 | 仅一念(status=0)可进行此操作(vote/confirm/suggestions/support/留言) |
| 4107 | 已珍藏的记忆不可修改(珍藏态 update 封禁) |
| 5001 | 微信登录未配置(缺 TIMESAKE_WX_APPID/SECRET) |
| 5002 | 微信登录失败(code2session 异常) |
一念接口:`POST /projects/{id}/vote`(表态)、`/confirm`(敲定转正)、`/suggestions`(提建议)、`/suggestions/{sid}/support`(附议)、`/suggestions/{sid}/comments`(留言/回复/删除)——完整契约见 `spec-iteration-a.md`;建议 type 枚举已扩展至 1-7(交通/集合/预算/分工,迭代 B),见 `spec-iteration-b.md`。
`/confirm` 敲定时再选类型:请求体加 `type`(1=转期待 填 `targetTime` / 2=转坚持 填 `startTime`,默认 1)——采纳时间建议按 type 分流写入 `target_time` 或 `start_time`,详见 `spec-iteration-c.md`。
11. 备注
- 二维码内容 =
COUNTDOWN_JOIN:,鸿蒙端用 Scan Kit 扫描解析 - 推送:服务端调 Push Kit API 发通知(到期提醒、新成员加入)
- 游客→登录后的本地项目同步:App 端先建云端项目再复制本地记录,或提供"上传本地项目"接口