103 lines
2.2 KiB
Markdown
103 lines
2.2 KiB
Markdown
# 数据与同步
|
||
|
||
## 核心实体
|
||
|
||
- `user`:用户。
|
||
- `device`:设备。
|
||
- `ledger`:账本。
|
||
- `ledger_member`:账本成员。
|
||
- `ledger_invitation`:账本邀请。
|
||
- `category`:分类。
|
||
- `entry`:账目。
|
||
- `sync_operation`:同步操作。
|
||
|
||
## 账本字段
|
||
|
||
- `id`
|
||
- `name`
|
||
- `visibility`:`private` 或 `shared`。
|
||
- `owner_id`
|
||
- `created_at`
|
||
- `updated_at`
|
||
- `deleted_at`
|
||
|
||
## 成员字段
|
||
|
||
- `ledger_id`
|
||
- `user_id`
|
||
- `role`:`owner` 或 `member`。
|
||
- `joined_at`
|
||
- `removed_at`
|
||
|
||
## 邀请字段
|
||
|
||
- `id`
|
||
- `ledger_id`
|
||
- `token`
|
||
- `created_by`
|
||
- `expires_at`
|
||
- `accepted_by`
|
||
- `accepted_at`
|
||
- `revoked_at`
|
||
|
||
## 权限规则
|
||
|
||
- 用户只能同步自己有成员关系的账本。
|
||
- 独享账本只有 owner 一名成员。
|
||
- 共享账本可以有多名成员。
|
||
- `owner` 可以邀请和移除成员。
|
||
- `member` 可以查看和记账。
|
||
- 首版不做单条账目权限。
|
||
|
||
## 账目字段
|
||
|
||
- `id`:客户端生成 UUID。
|
||
- `ledger_id`
|
||
- `type`:`expense` 或 `income`。
|
||
- `amount`:金额,整数分。
|
||
- `category_id`
|
||
- `occurred_at`
|
||
- `note`
|
||
- `created_by`
|
||
- `updated_by`
|
||
- `created_at`
|
||
- `updated_at`
|
||
- `deleted_at`
|
||
- `version`
|
||
|
||
## 同步原则
|
||
|
||
- 客户端先写 IndexedDB,界面立即成功。
|
||
- 每次本地变更生成一个 `operation_id`。
|
||
- 同步 API 必须幂等。
|
||
- 服务端保存账本变更日志。
|
||
- 客户端用游标拉取增量。
|
||
- 同步范围必须按账本成员权限过滤。
|
||
|
||
## 同步流程
|
||
|
||
1. 用户新增、编辑或删除账目。
|
||
2. 客户端写 IndexedDB。
|
||
3. 客户端写本地同步队列。
|
||
4. 网络可用时推送队列。
|
||
5. 服务端按 `operation_id` 去重并应用。
|
||
6. 客户端拉取远端增量。
|
||
7. 客户端合并到 IndexedDB。
|
||
|
||
## 冲突策略
|
||
|
||
- 新增记录基本无冲突,ID 由客户端生成。
|
||
- 删除使用软删除。
|
||
- 同一条账目被多人离线修改时,首版最后写入胜出。
|
||
- 不做字段级合并。
|
||
- 冲突历史和人工选择版本后置。
|
||
|
||
冲突示例:
|
||
|
||
- 手机 A 和手机 B 都同步过同一笔账:`午餐 100 元`。
|
||
- 两台手机同时离线。
|
||
- 手机 A 改成 `120 CNY`。
|
||
- 手机 B 改成 `110 CNY` 或修改分类。
|
||
- 两台手机恢复网络后上传。
|
||
- 服务端必须决定最终版本。
|