docs: 更新 README 与 ADR-007
CI / verify (push) Canceled after 10s

- README 补充回收站、批量编辑、合并导入、标签管理与 schema v3 说明
- 新增 ADR-007,记录软删除、可见性矩阵与合并冲突策略的取舍
This commit is contained in:
chenshoulin
2026-10-19 18:33:00 +08:00
parent 65e98199ba
commit 777815704d
2 changed files with 89 additions and 11 deletions
+48
View File
@@ -155,3 +155,51 @@ MVP 有「启动快照 + 手动导出」两道保护,但两个整份覆盖的
- `persistent` 现在会随写入成功/失败翻转,UI 可据此判断「改动是否真的落盘」。
- 关闭详情抽屉的默认行为从「直接关闭」变为「有改动先确认」,相关组件测试已同步调整。
- 新增 `.gitea/workflows/ci.yml`,把 lint / typecheck / test / build 纳入推送与合并请求检查。
---
## ADR-007 · 删除改为软删除,导入提供覆盖 / 合并两种模式
**背景**
删除此前只有 5 秒内的 Toast 撤销,超过窗口后只能去自动备份里碰运气;而多设备、多次导出之后,
覆盖式导入又只能二选一,「把两份数据拼起来」需要手工处理。本批同时解决这两件事,并顺带把多选
从「批量删除工具」升级为「批量编辑器」。
**结论**
1. `Task` 增加 `deletedAt`,`schemaVersion` 升到 3;删除写 `deletedAt`(软删除),任务进入回收站,
30 天后在启动时自动清理。永久删除只允许作用于回收站里的任务,且需要二次确认。
2. 软删除是**数据状态**而不是筛选维度:store 提供 `activeTasks`,列、计数、统计、今日视图、
标签下拉、归档候选全部消费它;`matchesFilter` 仍然只负责归档可见性。回收站数据由 `trashTasks`
单独提供,按删除时间倒序。
3. 恢复只清除 `deletedAt`,保留原 `sortOrder` 与 `archivedAt`,因此位置和归档态都会还原。
导出仍包含已删除任务,保证换设备后回收站也能带走。
4. 批量编辑与单条编辑共用 `applyTaskPatch`(`src/utils/taskPatch.ts`),状态进出「已完成」、
`updatedAt` 刷新、标签去重、标题回退只有一份规则。批量标签采用**增 / 删**语义,
避免统一加标签时把每条任务原有的其它标签抹掉。
5. 导入增加合并模式:按 `id` 匹配,同 id 以 `updatedAt` 较新的一方为准;文件新增项追加到对应列末尾
并重算 `sortOrder`;本地独有任务保留;两种模式执行前都调用同一套快照逻辑。
6. 标签治理(重命名 / 合并 / 删除)放在 `src/utils/tags.ts` 的纯函数里,store 只负责找出真正变化的
任务、刷新 `updatedAt` 并一次落盘。回收站里的任务不参与改写。
**被否决的方案**
- _把 `deletedAt` 塞进 `TaskFilter`_:回收站不是「筛掉一部分」,而是一条独立的数据状态。
放进筛选会让每个调用点都要记得带上「排除已删除」,漏一处就会把删除项泄漏到看板或统计里。
改为在 `activeTasks` 层统一剔除,失败模式从「N 处可能漏」收敛为「一处必须对」。
- _给删除加二次确认_:删除是高频操作,弹窗会拖慢节奏;软删除 + 回收站已经提供了比确认框更好的退路。
- _批量改属性做 `[{id, before}]` 快照式撤销_:需要额外的内存态与 UI 语义,收益低于成本;
标签是增删语义,改错了再改回来即可。批量删除 / 归档仍有 Toast 撤销。
- _合并时对整列 `sortOrder` 做 normalize_:会悄悄重排用户已有数据。新增项追加列尾已经足够,
既有冲突留给后续显式整理。
- _给回收站做搜索 / 筛选_:列表按删除时间倒序已经能覆盖「刚删错」这个主场景,先不加。
**影响**
- 数据面变大:回收站会占用 localStorage 配额,靠 30 天自动清理与手动清空兜底;导出文件也会包含
已删除任务,体积略增。
- 所有「看板语义」的读取点必须走 `activeTasks`。新增读取点时若直接用 `tasks`,会把已删除任务
泄漏到 UI;可见性矩阵已写进测试(列、统计、标签、今日视图、归档候选)。
- 迁移链新增 `2 → 3`,且 `parsePersistedState` / 快照恢复共用同一套解析,旧备份仍可读。
- 详情抽屉的编辑对象改为在 `activeTasks` 里查找,删除后抽屉会立即关闭,而不是停留在一条已删除的任务上。