Files
chenshoulin 4e064e82ea feat: 个人轻量看板工具 MVP
从零实现一个 local-first 的个人任务看板,数据只存在浏览器本地,不依赖后端。

功能
- 固定三列看板(待办 / 进行中 / 已完成),支持拖拽改状态与列内排序
- 快速新增、详情编辑、删除撤销、已完成归档
- 搜索与筛选(关键词 / 优先级 / 标签 / 今日到期 / 逾期)
- 今日视图:按紧急度分组(逾期 > 今天到期 > 进行中)+ 统计卡片
- 导出导入 JSON;启动时自动留快照,保留最近 3 份
- 键盘快捷键(N / 「/」/ ? / Esc)
- PWA:可安装、离线可用、更新提示

技术要点
- 持久化采用 TaskRepository 端口 + 整份快照读写,schemaVersion 迁移表
  显式登记升级规则(当前 v2,v1 -> v2 为归档功能补 archivedAt)
- 同列排序用相邻中点插入,间距不足时按列 normalize,避免浮点精度耗尽
- 拖拽只消费 Sortable 的事件,store 保持唯一数据源,不接管数据
- 数据损坏时先备份到 *.corrupt.<时间戳> 再报错,不覆盖用户数据
- 引入 vue-router 拆分看板与今日两个视图(见 docs/adr.md ADR-005)

验证
- 单元测试 437 个(33 个文件),行覆盖率 96.8%
- 端到端测试 23 个(Playwright),含真实拖拽与断网离线场景
- npm run build 通过,产物可静态托管

注:部署时需配置 SPA 回落,否则直接访问 /today 会 404(详见 README)。
2026-10-18 11:59:49 +08:00

12 KiB
Raw Permalink Blame History

个人看板工具 · MVP 开发任务卡

版本:v2(按评审修订) 决策前提:固定三列 · TaskRepository 接口 + localStorage 存储 · dueDate 仅存日期 · 不引入 vue-router

已定死的四项决策

决策 结论 理由
列是否可配置 否,固定 todo / doing / done 可配置列需引入 columns 表,成本翻倍,个人场景无收益
存储 TaskRepository 接口 + localStorage 起步 200 任务约 60KB,localStorage 足够;保留接口便于换 Dexie
dueDate 语义 仅日期 YYYY-MM-DD 个人看板不需要时刻,直接避开时区坑
路由 不引入 vue-router 单视图 + 抽屉/弹窗即可,减少依赖

总览

ID 任务 优先级 估时 依赖
T01 工程初始化与规范 P0 0.5d —
T02 技术决策记录(ADR) P0 0.25d —
T03 领域类型与常量 P0 0.25d T02
T04 TaskRepository 接口 + localStorage 实现(含 schema 迁移) P0 0.5d T03
T05 排序算法:sortOrder 中点插入 + normalize P0 0.5d T03
T06 Pinia store + 多标签页同步 P0 0.5d T04, T05
T07 看板三列骨架与空状态 P0 0.5d T06
T08 TaskCard 任务卡片组件 P0 0.5d T07
T09 UI 基础组件(Drawer / Toast / DatePicker / TagInput) P0 1d T01
T10 快速新增任务 P0 0.5d T07
T11 任务详情表单(创建 / 编辑 / 校验) P0 1d T09, T10
T12 删除与撤销 P0 0.5d T11
T13 拖拽改状态 + 列内排序(含筛选态保护) P0 1d T08, T11
T14 导出 / 导入 JSON + 启动自动快照 P0 0.5d T04
T15 搜索与筛选 P0.5 0.5d T07
T16 逾期提示 + 键盘快捷键 P1 0.5d T10
T17 已完成归档 + 长列表性能 P1 0.5d T13
T18 核心逻辑单元测试 P0 0.5d T05, T14
T19 E2E 关键路径测试 P1 0.5d T13, T14
T20 生产构建与部署 P0 0.5d T18

合计:11 人天(纯开发,不含缓冲)→ 实际排期按 ×1.4 计,约 15 天。

关键里程碑:T01–T13 完成后即「可用 MVP」;T14 是数据安全底线,不得后置。


任务卡明细

T01 · 工程初始化与规范

优先级 P0 估时 0.5d 依赖 —

描述 Vite + Vue3 + TS 工程初始化;接入 Tailwind(锁定 v4 + @tailwindcss/vite)、Pinia、Vitest;配置 ESLint + Prettier;统一目录结构。

验收标准

  • npm run dev 可启动,页面渲染正常
  • Tailwind 原子类生效(页面出现预期样式)
  • npm run lint 与 npm run format 均可执行且无报错
  • npm run test 可运行(哪怕只有 1 个示例用例)
  • 目录结构为 src/{components,composables,data,stores,types,utils,views}

T02 · 技术决策记录(ADR)

优先级 P0 估时 0.25d 依赖 —

描述 将上述四项决策写入 docs/adr.md,含背景、结论、被否决的方案及原因。

验收标准

  • docs/adr.md 覆盖 4 项决策
  • 每项决策写明「否决了什么、为什么」

T03 · 领域类型与常量

优先级 P0 估时 0.25d 依赖 T02

描述 定义 Task、ColumnId、Priority 类型与列定义常量。

验收标准

  • Task 含 id/title/description/status/priority/tags/dueDate/sortOrder/createdAt/updatedAt/completedAt
  • status 为字面量联合类型 'todo' | 'doing' | 'done',不使用 enum
  • dueDate 类型为 string(YYYY-MM-DD)或 null
  • 列定义常量为只读,含 id / 标题 / 顺序
  • 无 any,vue-tsc 通过

T04 · TaskRepository 接口 + localStorage 实现

优先级 P0 估时 0.5d 依赖 T03

描述 定义 TaskRepository 接口,提供 localStorage 实现,含 schemaVersion 与迁移入口。

实现修订:接口最终定为 load() / save(tasks) 的整份快照读写,而非细粒度 CRUD。 原因:数据量小(约 60KB),整份写入不会产生「部分写入」的不一致状态;且排序、导入、 跨标签页同步本质上都是快照操作。接口与实现分离这一目标不变。

验收标准

  • 接口与实现分离,UI/Store 只依赖接口
  • 持久化结构含 schemaVersion 字段
  • 提供迁移入口(MIGRATIONS 表),未知/过高版本有明确报错而非静默降级
  • localStorage 不可用(隐私模式)时给出可读错误,不白屏
  • 写入失败(配额超限)抛出 StorageWriteError 并在界面提示
  • 数据损坏时先备份到 *.corrupt.<时间戳> 再报错,不覆盖用户原数据

T05 · 排序算法

优先级 P0 估时 0.5d 依赖 T03

描述 实现 sortOrder 相邻中点插入;间距小于 1e-6 时对该列执行 normalize 重排(间隔 1024)。

验收标准

  • 在任意两卡之间插入,顺序正确
  • 连续 100 次中间插入后,顺序仍正确(不出现精度崩坏)
  • normalize 后同列 sortOrder 严格递增且间距均匀
  • 纯函数实现,无副作用,可独立单测

T06 · Pinia store + 多标签页同步

优先级 P0 估时 0.5d 依赖 T04, T05

描述 Store 作为内存态唯一来源,读写走 repository;通过 BroadcastChannel 广播变更,使多标签页一致。

验收标准

  • 所有变更先写 repository 再更新内存态(或反之,但必须单一顺序)
  • 标签页 A 的修改,标签页 B 在 1 秒内自动反映
  • 跨列拖拽在一次事务内同时更新 status 与 sortOrder
  • 无「卡片已换列但顺序仍旧」的中间态

T07 · 看板三列骨架与空状态

优先级 P0 估时 0.5d 依赖 T06

描述 三列布局(待办 / 进行中 / 已完成),响应式;每列含标题、计数、空状态。

验收标准

  • ≥1024px 三列并排;<768px 纵向堆叠
  • 每列显示任务计数
  • 空列显示引导文案
  • 列内容区可独立滚动,页面不整体抖动

T08 · TaskCard 任务卡片组件

优先级 P0 估时 0.5d 依赖 T07

描述 卡片展示标题、优先级、标签、截止日期;逾期与已完成有区分样式。

验收标准

  • 三种优先级视觉可区分
  • 逾期(dueDate < 今天且未完成)显示警示色
  • 已完成卡片置灰 / 降饱和
  • 标签超过 3 个折叠为 +N
  • 长标题截断,不撑破卡片

T09 · UI 基础组件

优先级 P0 估时 1d 依赖 T01

描述 自建(或基于 headless 库)实现 Drawer/Modal、Toast、DatePicker、TagInput。注意:Tailwind 只提供样式,不提供行为。

验收标准

  • Drawer 支持 ESC 关闭、遮罩点击关闭、焦点陷阱(focus trap)
  • Toast 支持自动消失与手动关闭
  • DatePicker 输出 YYYY-MM-DD,可清空
  • TagInput 支持回车添加、退格删除、去重
  • 上述组件均有可访问性属性(role / aria-*)

T10 · 快速新增任务

优先级 P0 估时 0.5d 依赖 T07

描述 列顶部或全局输入框,回车即建卡,默认进入「待办」。

验收标准

  • 聚焦输入 → 输入标题 → 回车,卡片出现在列首
  • 空标题不可提交
  • 提交后输入框清空且保持聚焦(可连续录入)
  • 全流程 ≤3 秒可完成

T11 · 任务详情表单

优先级 P0 估时 1d 依赖 T09, T10

描述 创建与编辑复用同一表单,置于 Drawer 内。

验收标准

  • 可编辑标题、描述、优先级、截止日期、标签
  • 标题必填,空值给出内联错误提示
  • 取消编辑不产生脏数据
  • 保存后看板与详情同步更新
  • updatedAt 正确刷新

T12 · 删除与撤销

优先级 P0 估时 0.5d 依赖 T11

描述 删除任务后提供 Toast 撤销入口(保留最近一次删除内容)。

验收标准

  • 删除后卡片立即消失
  • Toast 提供「撤销」,点击后卡片连同原顺序恢复
  • 撤销窗口结束后数据真正移除
  • 删除需二次确认(或依赖撤销兜底)

T13 · 拖拽改状态 + 列内排序

优先级 P0 估时 1d 依赖 T08, T11

描述 基于 vue-draggable-plus 实现跨列拖动与列内排序。

验收标准

  • 跨列拖动更新 status,刷新后保持
  • 列内拖动更新顺序,刷新后保持
  • 筛选/搜索激活时禁用列内排序(仅允许跨列改状态),避免顺序写坏
  • 拖拽中不触发卡片点击(区分 click 与 drag)
  • 触摸设备可拖动

T14 · 导出 / 导入 JSON + 自动快照

优先级 P0 估时 0.5d 依赖 T04

描述 一键导出全部任务为 JSON;支持覆盖式导入;启动时自动快照到独立 key。local-first 下这是唯一的数据安全网。

验收标准

  • 导出文件名含日期,内容含 schemaVersion
  • 导入前校验结构,非法文件给出明确错误且不破坏现有数据
  • 导入为覆盖式,执行前二次确认
  • 每次启动写入快照 key,保留最近 3 份
  • 导出 → 清空 → 导入,数据完全还原

T15 · 搜索与筛选

优先级 P0.5 估时 0.5d 依赖 T07

描述 关键词搜索(标题 + 描述)+ 按优先级/标签筛选。

验收标准

  • 中文搜索用 includes 即可,不引入分词库
  • 输入有防抖(≤300ms)
  • 多条件为「与」关系
  • 筛选后列计数反映筛选结果
  • 一键清空全部筛选条件

T16 · 逾期提示 + 键盘快捷键

优先级 P1 估时 0.5d 依赖 T10

描述 顶部统计条显示今日到期与逾期数量;提供常用快捷键。

验收标准

  • 顶部显示「今日到期 N / 逾期 N」,可点击直接筛选
  • N 聚焦快速新增;/ 聚焦搜索;Esc 关闭抽屉
  • 输入框内不劫持快捷键
  • 快捷键有可查看的帮助提示

T17 · 已完成归档 + 长列表性能

优先级 P1 估时 0.5d 依赖 T13

描述 已完成列支持归档;长列表不卡顿。

验收标准

  • 可一键归档「已完成」中超过 N 天的任务
  • 归档任务默认不显示,可切换查看
  • 单列 200 张卡片滚动仍流畅(必要时虚拟滚动)
  • 归档操作可撤销

T18 · 核心逻辑单元测试

优先级 P0 估时 0.5d 依赖 T05, T14

描述 只覆盖纯逻辑,UI 不强制测试。

验收标准

  • 排序:中间插入、normalize、边界值
  • 筛选:单条件、多条件组合、空结果
  • 状态流转:completedAt 的写入与清除
  • 导入校验:合法 / 缺字段 / 版本不匹配
  • 核心模块行覆盖率 ≥80%

T19 · E2E 关键路径测试

优先级 P1 估时 0.5d 依赖 T13, T14

描述 Playwright 覆盖一条主链路。

验收标准

  • 新增任务 → 拖到进行中 → 标记完成 → 刷新后状态仍正确
  • 导出 → 清空 → 导入 → 数据一致
  • 每个用例使用独立浏览器上下文,互不污染

T20 · 生产构建与部署

优先级 P0 估时 0.5d 依赖 T18

描述 生产构建、静态托管、基础可用性验证。

验收标准

  • npm run build 无 TS 错误、无警告阻断
  • 产物可静态托管,刷新不 404
  • 首屏加载 ≤2s(本地网络)
  • README.md 写明启动、构建、部署、数据备份方式

完成定义(DoD)

  • 功能可演示,有明确交互结果
  • 核心纯逻辑必须有单测;UI 组件不强制
  • 数据刷新后不丢失
  • 无阻断级 lint / type 错误
  • 涉及数据结构的变更,必须同步更新 schemaVersion 与迁移逻辑