Bills 模块 API 文档

基础信息

  • Base URL: /api/bills
  • 认证方式: JWT Bearer Token

数据库表

bills 表

字段类型必填说明
idtext (PK)必填UUID(v4)
nametext必填账单名称
descriptiontext选填描述
owner_idtext (FK→users)必填创建者用户ID
is_archivedinteger必填0=正常, 1=归档
is_activeinteger必填0=停用, 1=启用(默认1)
created_atdatetime必填创建时间
updated_atdatetime必填更新时间

bill_members 表

字段类型必填说明
idtext (PK)必填UUID(v4)
bill_idtext (FK→bills)必填账单ID
user_idtext (FK→users)必填用户ID
roletext必填owner / editor / viewer
custom_prompttext选填用户在该账单的 AI 自定义提示词
joined_atdatetime必填加入时间
updated_atdatetime必填更新时间
唯一约束: (bill_id, user_id) 组合唯一

categories 表

字段类型必填说明
idtext (PK)必填UUID前缀截断(12位)+序号,如 a1b2c3d4e5f60
bill_idtext (FK→bills)必填所属账单
nametext必填分类名称
icontext选填图标名称
colortext选填颜色(hex)
typetext必填expense(支出)/ income(收入)
parent_idtext (FK→categories)选填父分类(支持二级分类)
is_defaultinteger必填0=自定义, 1=默认创建
is_archivedinteger必填0=正常, 1=归档
created_atdatetime必填创建时间
updated_atdatetime必填更新时间

bill_invitations 表

字段类型必填说明
idtext (PK)必填UUID
bill_idtext (FK→bills)必填账单ID
invited_bytext (FK→users)必填邀请人
invitee_phonetext必填被邀请人手机号
invitee_user_idtext (FK→users)选填被邀请人用户ID(同意后填充)
roletext必填owner / editor / viewer
statustext必填pending / accepted / rejected / expired
expires_atdatetime必填过期时间(邀请后24h)
created_atdatetime必填创建时间
updated_atdatetime必填更新时间

接口列表


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
请求参数:
参数类型必填说明
namestring必填账单名称(trim后非空)
descriptionstring选填账单描述,默认空字符串
后端处理: 1. 校验 name 非空 2. 生成 UUID(10次碰撞检测) 3. 事务: - 插入 billsowner_id = 当前用户) - 插入 bill_members(角色 owner) - 插入7个默认分类
重要: 新账单无交易数据,首次使用需上传 CSV
Schema 注意: 描述字段 description 允许空字符串,但不接受 undefined

PUT/api/bills/:id

4. 更新账单信息

触发时机: 在 账单设置弹窗 修改账单名称后点击保存
BillPage → 打开账单详情 → 点击"编辑" → 修改名称 → 点击保存 → PUT /bills/:id
权限: ownereditor 可调用,viewer 返回 403 请求参数:
参数类型必填说明
namestring必填新账单名称(trim后非空)
descriptionstring选填新描述
后端处理: 更新 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 可操作 请求参数:
参数类型必填说明
rolestring选填新角色(editor / viewer
custom_promptstring选填自定义提示词
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_promptstring必填自定义提示词(可传 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/income

POST/api/bills/:id/invite

11. 邀请成员加入账单

触发时机: 在 成员管理面板 输入手机号后点击「邀请」按钮
BillPage → 成员管理 → 输入手机号 → 点击"邀请" → POST /bills/:id/invite
权限: 仅 owner 可邀请 请求参数:
参数类型必填说明
phonestring必填被邀请人手机号(带或不带 +86 前缀)
rolestring选填角色,默认 viewer
后端处理: 1. 校验手机号格式 2. 在 users 表中查找该手机号(必须已注册) 3. 确认不是账单成员 4. 确认无 pending 邀请 5. 插入 bill_invitations(24小时有效)
重要问题:见 P02
Schema 注意: invitee_user_id 在邀请创建时为 NULL,只有在被邀请人接受时才会填充

默认分类(创建账单/注册时)

nameiconcolortype
餐饮Utensils#FF9500expense
交通Car#007AFFexpense
购物ShoppingBag#FF2D55expense
居住Home#5856D6expense
娱乐Gamepad#AF52DEexpense
医疗Heart#FF3B30expense
工资DollarSign#34C759income