Bills 模块 API 文档
基础信息
- Base URL:
/api/bills - 认证方式: JWT Bearer Token
数据库表
bills 表
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | text (PK) | 必填 | UUID(v4) |
| name | text | 必填 | 账单名称 |
| description | text | 选填 | 描述 |
| owner_id | text (FK→users) | 必填 | 创建者用户ID |
| is_archived | integer | 必填 | 0=正常, 1=归档 |
| is_active | integer | 必填 | 0=停用, 1=启用(默认1) |
| created_at | datetime | 必填 | 创建时间 |
| updated_at | datetime | 必填 | 更新时间 |
bill_members 表
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | text (PK) | 必填 | UUID(v4) |
| bill_id | text (FK→bills) | 必填 | 账单ID |
| user_id | text (FK→users) | 必填 | 用户ID |
| role | text | 必填 | owner / editor / viewer |
| custom_prompt | text | 选填 | 用户在该账单的 AI 自定义提示词 |
| joined_at | datetime | 必填 | 加入时间 |
| updated_at | datetime | 必填 | 更新时间 |
(bill_id, user_id) 组合唯一
categories 表
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | text (PK) | 必填 | UUID前缀截断(12位)+序号,如 a1b2c3d4e5f60 |
| bill_id | text (FK→bills) | 必填 | 所属账单 |
| name | text | 必填 | 分类名称 |
| icon | text | 选填 | 图标名称 |
| color | text | 选填 | 颜色(hex) |
| type | text | 必填 | expense(支出)/ income(收入) |
| parent_id | text (FK→categories) | 选填 | 父分类(支持二级分类) |
| is_default | integer | 必填 | 0=自定义, 1=默认创建 |
| is_archived | integer | 必填 | 0=正常, 1=归档 |
| created_at | datetime | 必填 | 创建时间 |
| updated_at | datetime | 必填 | 更新时间 |
bill_invitations 表
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | text (PK) | 必填 | UUID |
| bill_id | text (FK→bills) | 必填 | 账单ID |
| invited_by | text (FK→users) | 必填 | 邀请人 |
| invitee_phone | text | 必填 | 被邀请人手机号 |
| invitee_user_id | text (FK→users) | 选填 | 被邀请人用户ID(同意后填充) |
| role | text | 必填 | owner / editor / viewer |
| status | text | 必填 | pending / accepted / rejected / expired |
| expires_at | datetime | 必填 | 过期时间(邀请后24h) |
| created_at | datetime | 必填 | 创建时间 |
| updated_at | datetime | 必填 | 更新时间 |
接口列表
GET/api/bills
1. 查询当前用户的所有账单
触发时机: 应用启动登录后(DataContext 初始化时),或切换用户时
登录成功 → DataContext 初始化 → GET /bills → 获取用户全部账单列表
后端处理:
1. JOIN bills + bill_members + users(owner信息)
2. 筛选 bm.user_id = 当前用户
3. 返回:bills 全部字段 + owner_phone/nickname + 当前用户角色 + custom_prompt
4. 按 updated_at 倒序
响应:
{
"bills": [
{
"id": "uuid",
"name": "我的账单",
"description": "",
"owner_id": "user_id",
"is_archived": 0,
"is_active": 1,
"created_at": "ISO8601",
"updated_at": "ISO8601",
"owner_phone": "string",
"owner_nickname": "string",
"role": "owner | editor | viewer",
"custom_prompt": "string | null"
}
]
}
GET/api/bills/:id
2. 获取单个账单详情
触发时机: 切换到某个账单时(点击账单切换器选择账单)DataContext.selectBill(billId) → GET /bills/:id
同时触发: GET /transactions/:id + GET /bills/:id/categories
权限: 账单任意成员均可访问(owner/editor/viewer 都能获取详情)
后端处理:
1. 校验账单存在
2. 校验当前用户是账单成员
3. 获取成员列表(JOIN users)
4. 获取分类列表
5. 计算当前用户权限
响应:
{
"bill": { /* bills 表全部字段 */ },
"members": [ /* bill_members + users 字段 */ ],
"categories": [ /* categories 数组 */ ],
"myRole": "owner | editor | viewer",
"myPerms": {
"can_edit": true | false,
"can_delete": true | false
}
}
Schema 注意:见 P14
POST/api/bills
3. 创建新账单
触发时机: 在 账单页面(BillPage) 点击「+ 新建账单」按钮,填写账单名称后确认BillPage → 点击"新建账单" → 输入账单名 → 点击确认 → POST /bills
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 必填 | 账单名称(trim后非空) |
| description | string | 选填 | 账单描述,默认空字符串 |
bills(owner_id = 当前用户)
- 插入 bill_members(角色 owner)
- 插入7个默认分类
重要: 新账单无交易数据,首次使用需上传 CSV
Schema 注意: 描述字段 description 允许空字符串,但不接受 undefined
PUT/api/bills/:id
4. 更新账单信息
触发时机: 在 账单设置弹窗 修改账单名称后点击保存BillPage → 打开账单详情 → 点击"编辑" → 修改名称 → 点击保存 → PUT /bills/:id
权限: owner 或 editor 可调用,viewer 返回 403
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 必填 | 新账单名称(trim后非空) |
| description | string | 选填 | 新描述 |
bills 表 + updated_at
DELETE/api/bills/:id
5. 删除账单
触发时机: 在 账单详情页 点击「删除账单」,二次确认账单名称后提交BillPage → 打开账单详情 → 点击"删除" → 输入账单名称确认 → DELETE /bills/:id
权限: 仅 owner 可删除
后端处理: 级联删除 bills 记录(依赖外键 CASCADE 删除 members/transactions/categories 等)
GET/api/bills/:id/members
6. 查询账单成员列表
触发时机: 获取账单详情时由fetchBillDetails 一起获取(与 /bills/:id 一起请求)
权限: 任意成员可查看
PUT/api/bills/:id/members/:memberId
7. 修改成员角色
触发时机: 在 成员管理面板 点击某成员右侧的「角色」下拉框,选择新角色后自动触发BillPage → 成员列表 → 点击某成员角色下拉框 → 选择新角色 → PUT /bills/:id/members/:memberId
权限: 仅 owner 可操作
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| role | string | 选填 | 新角色(editor / viewer) |
| custom_prompt | string | 选填 | 自定义提示词 |
Schema 注意:
custom_prompt 存在 bill_members 表,不是 users 表(每个用户在每个账单有独立 prompt)DELETE/api/bills/:id/members/:memberId
8. 移除账单成员
触发时机: 在 成员管理面板 点击某成员右侧的「移除」按钮,二次确认成员昵称后提交BillPage → 成员列表 → 点击"移除" → 输入成员昵称确认 → DELETE /bills/:id/members/:memberId
权限规则:
owner可移除任何人(但不能移除自己)editor/viewer只能移除自己
PUT/api/bills/:id/prompt
9. 更新当前用户在账单的 Prompt
触发时机: 在 账单设置 或 AI 配置区域 修改该账单的 AI 提示词后自动保存BillPage → 打开账单AI设置 → 修改 custom_prompt → PUT /bills/:id/prompt
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| custom_prompt | string | 必填 | 自定义提示词(可传 null 清空) |
⚠️ 前后端不一致 bug:见 P13
Schema 注意: custom_prompt 属于
bill_members 记录,而非 bills 表(每个用户在每个账单有独立 prompt)GET/api/bills/:id/categories
10. 查询账单分类列表
触发时机: 通常与GET /bills/:id 一起由 fetchBillDetails 并行请求(Promise.all)
fetchBillDetails → Promise.all([
GET /bills/:id,
GET /transactions/:id,
GET /bills/:id/categories
])
Schema 注意: 分类按
name 升序返回,不区分 expense/incomePOST/api/bills/:id/invite
11. 邀请成员加入账单
触发时机: 在 成员管理面板 输入手机号后点击「邀请」按钮BillPage → 成员管理 → 输入手机号 → 点击"邀请" → POST /bills/:id/invite
权限: 仅 owner 可邀请
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| phone | string | 必填 | 被邀请人手机号(带或不带 +86 前缀) |
| role | string | 选填 | 角色,默认 viewer |
users 表中查找该手机号(必须已注册)
3. 确认不是账单成员
4. 确认无 pending 邀请
5. 插入 bill_invitations(24小时有效)
重要问题:见 P02
Schema 注意:
invitee_user_id 在邀请创建时为 NULL,只有在被邀请人接受时才会填充默认分类(创建账单/注册时)
| name | icon | color | type |
|---|---|---|---|
| 餐饮 | Utensils | #FF9500 | expense |
| 交通 | Car | #007AFF | expense |
| 购物 | ShoppingBag | #FF2D55 | expense |
| 居住 | Home | #5856D6 | expense |
| 娱乐 | Gamepad | #AF52DE | expense |
| 医疗 | Heart | #FF3B30 | expense |
| 工资 | DollarSign | #34C759 | income |