1. 任务 ⋯ 菜单 (列表行与看板卡片): 编辑 / 拷贝到其他项目 / 删除 (antd-mobile ActionSheet, 带任务名标题; 拷贝抽出为 CopyTaskPopup 复用) 2. 点击任务非按钮区域 = 打开编辑页 (原本即如此, ⋯ 不再误触为编辑) 3. 修复状态选择器堆成三行: 此前 .seg 只有 .pv-head 作用域样式, 详情弹层裸用导致纵向堆叠; 新增通用 .seg 分段样式, 当前项高亮点按即切 4. 移除任务的扩展信息 UI (T-TK-04~07 标注已取消, 决策 35): ExtrasCard 组件删除, DB extras 字段保留不再使用; 项目相关长文本由项目信息块 (T-PJ-13) 承载 5. 任务移动入口: 详情页新增「看板列」ActionSheet 换列(联动裁决不变) 与「层级」区(转为子任务=选父任务 / 转为顶层), 覆盖无法拖拽的场景 6. 列表页移除「+ 子任务」入口: 添加子任务只在详情页, 或经转子任务 已验证: 99 文件语法 0 错误、导入 0 缺失、文档 149 条/决策 35 连续
59 KiB
iBoard V0.2 任务模块 需求文档 — 轻量任务 / 项目管理
版本:V0.2 · 模块:任务(Task) · 日期:2026-10-24 适用范围:iBoard APP 内的任务模块(沿用现有项目框架、路由体系与登录态实现) 关联文档:《设计文档》《数据库设计文档》《界面设计》——接口清单在设计阶段重新设计,本文档不含接口定义
1. 总体需求
1.1 一句话描述
在 iBoard 现有 APP 内新增一个轻量级的项目与任务管理模块:界面交互参考 Todoist,以项目为隔离单位组织任务,提供列表 / 看板双视图,并允许每个项目独立配置看板列与任务状态的对应关系、以及每列已完成任务的保留选项,用最小认知成本覆盖「个人琐事记录」与「多人协作推进」两类场景。
「轻量」的含义:不做需求管理、工时、甘特图、工作流引擎、审批流;字段克制、结构最多两层(任务 + 一级子任务)、权限不做细分角色。目标是用最少的配置让用户"打开就能记、记完就能推进"。
1.2 核心概念
| 概念 | 定义 |
|---|---|
| 项目(Project) | 任务归属的隔离单位,也是权限单位。用户只能看到自己是成员的项目;项目内成员权限目前均等 |
| 个人默认项目(Personal Project) | 每个用户自动拥有且仅有一个的私有项目。不可删除、不可添加其他成员,名称以用户名开头且可自定义,用于个人琐碎事务 |
| 普通协作项目(Shared Project) | 用户新建的项目,可增删成员、可归档 |
| 项目成员(Member) | 用户与项目的多对多关联。成员的存在决定权限,「负责人 / 任务成员」字段只决定展示 |
| 任务(Task) | 一条事务记录。归属唯一项目;含基础字段 + 内置可折叠的扩展信息卡片;特例:子任务 |
| 一级子任务(Subtask) | 挂在父任务下的任务。最多一层,不可再嵌套;必须与父任务同项目;完成状态与父任务相互独立 |
| 负责人(Assignee) | 任务上的单人标记,字号更大、视觉突出。新建任务时默认填入创建者本人,可清空 |
| 任务成员(Task Members) | 任务上的多人标记,字号更小、弱化展示,位于卡片 / 条目下方 |
| 扩展信息卡片 | 任务内置的可折叠信息区,承载任意名称 / 值 / 链接的扩展信息(来源不限、字段不固定),默认收起、全部非必填 |
| 看板列(Column) | 项目级可配置的列,默认 4 列 Plan → Doing → Action → Done;可增删改、可调整顺序,数量不固定 |
| 任务状态(Status) | 任务的处理阶段,取值为 未开始 / 执行中 / 完成。与看板列是两个独立概念,二者的对应关系由项目配置决定 |
| 列-状态绑定(Column Status Binding) | 项目级配置:每一列独立选择"是否绑定任务状态"以及"绑定到哪个状态"。绑定后列与状态双向联动;不绑定时二者完全独立 |
| 已完成但未绑定状态 | 任务状态为「完成」、但其所在看板列未绑定到「完成」的情形——此时列保持不变 |
| 看板列保留选项(Column Retention) | 项目级配置:每一列独立设置已完成任务的保留时长,取值为「永不显示」/「当天」/「3 天」/「本周」/「本月」/「永久显示」六档,用于控制该列中已完成任务的可见性 |
| 视图记忆 | 设备端按项目独立保存"上次选择的视图(列表 / 看板)",进入项目自动恢复 |
| 上下文 | 用户当前所处的视图位置(某个项目 / 某个父任务的子任务列表 / 某个列表分区),用于解释"本次修改"相对哪些任务生效 |
1.3 完整功能
- 视图体系:列表视图、看板视图,可随时互相切换,同源数据、实时双向同步;每个项目独立记忆上次使用的视图。列表只是不按列分组,任务归属的看板列与看板视图完全一致。首屏上部为「最近项目」(3 个卡片 + 更多入口,卡片可手动排序),下部直接展示当前项目的任务管理视图,不必先进项目列表。
- 看板与任务状态的绑定配置:
- 看板列默认 4 列
Plan → Doing → Action → Done;列可增删改、可调整顺序,数量不固定。 - 每一列独立选择是否绑定任务状态,并可选择绑定到
未开始 / 执行中 / 完成中的任一个;允许多列绑定同一状态。 - 列决定状态:任务拖入某列时,该列绑定了状态则状态随之改变;该列未绑定则保留原状态。
- 状态与列不匹配时自动归位:状态改变后若当前所在列未绑定该状态,则按当前列顺序移入第一个绑定该状态的列;没有匹配列就不移动,保留当前位置。
- 默认:
Plan绑定「未开始」、Doing绑定「执行中」、Done绑定「完成」、Action不绑定。 - 配置是项目级的,项目内任意成员均可修改,不同项目互不影响。
- 子任务不受列-状态绑定约束,其状态可与父任务不一致。
- 看板列默认 4 列
- 已完成任务显示控制:按看板列独立配置保留选项——
永不显示/当天/3 天/本周/本月/永久显示六选一;超出保留选项的已完成任务在该列中自动隐藏。列表视图按其所属列的配置执行同样的显示控制。 - 任务字段体系:基础字段(标题必填,负责人默认本人)+ 内置可折叠扩展信息卡片(默认收起、全非必填);负责人(单人)与任务成员(多人)均为信息标记。
- 负责人 & 成员展示规则:负责人大字号突出、成员小字号弱化并置于下方;二者只能从当前项目成员中选择;不改变项目统一读写权限。
- 子任务体系:仅一级、必须同项目、父子完成状态互不联动;列表视图支持缩进与折叠展开;看板卡片内以简洁形式嵌套展示子任务并可直接勾选,完整详情在卡片弹窗内编辑;支持长按拖拽把任务降为另一个任务的一级子任务。
- 项目体系:个人默认项目(不可删、不可加成员、名称以用户名开头且可改名);普通协作项目(可增删成员);创建人可主动退出;成员清空后静默保留,交后台维护。成员管理、列设置与项目信息(改名 / 归档 / 删除 / 退出)统一收进「项目管理」入口。
- 项目权限:以项目为隔离单位,只能看到自己是成员的项目;项目内成员权限均等、全读写;预留权限分级入口但不实现细分角色;任意成员均可归档项目。
- 跨项目拷贝:是拷贝不是移动;完整复制全部字段、扩展信息、子任务、负责人、成员、状态、看板列、标签;新任务创建人为执行拷贝者;拷贝后新旧任务完全独立。
- UI 交互规范:参考 Todoist 的列表交互与子任务折叠风格;看板卡片轻量化;列表与看板同源、切换无刷新、数据一致;具备空状态 / 加载状态 / 数据异常状态。
- 模块入口:任务模块作为顶级 Tab 接入底部导航,位于**「打卡」之后**(顺序:打卡 → 任务 → 宏观 → 监控 → 我)。
1.4 典型用法
场景 A · 个人琐事(个人默认项目)
用户打开模块 → 进入自己的个人默认项目(如「张三的琐事」)→ 列表视图输入标题回车新增,负责人自动是本人,也可清空 → 需要推进时切到看板,把任务从 Plan 拖到 Doing。
因个人项目不能加成员,负责人 / 成员的可选范围只有自己,无需任何权限配置。
场景 B · 多人协作与列-状态绑定
用户新建普通项目「APP 改版」并加入 3 名同事。默认配置下:任务在 Plan=未开始、Doing=执行中、Done=完成;Action 不绑定状态,任务放进去后状态保持不变。
成员 A 把任务拖入 Done ⇒ 状态自动变为「完成」;成员 B 在列表视图把某任务状态改为「完成」⇒ 任务自动出现在 Done 列。
若任务停留在 Action(不绑定)里被改成「完成」,因当前列与状态不匹配,系统自动归位到第一个绑定「完成」的列(默认即 Done);若该项目把「完成」的绑定全部取消,则无匹配列,任务留在 Action 不动。若把 Action 也设为绑定「完成」,则按列序仍先进 Done——这是项目级配置,不影响其他项目。
场景 C · 扩展信息卡片 新增任务「登录接口返回 500」→ 展开默认收起的扩展信息卡片 → 按需添加任意条目,如「仓库 = gitlab/app」「分支 = fix/login-500」或一条相关链接(全部非必填,不填不影响任务本身)。
场景 D · 跨项目复用 把「APP 改版」里的某任务跨项目拷贝到「APP 二期」→ 生成一条全新任务,字段、扩展信息、子任务、负责人、成员、状态、看板列、标签全部复制,创建人记为执行拷贝的用户;此后两任务互不影响。
场景 E · 按列控制已完成任务显示
某项目的 Done 列已完成任务过多影响阅读 → 把该列保留选项设为「当天」→ 更早的已完成任务自动隐藏;同时把 Action 列设为「永不显示」,该列不再展示已完成任务;Plan 列保持「永久显示」不受影响。列表视图同样按各任务所属列的配置隐藏它们,与看板一致。切到另一个项目时,该项目各列配置保持自己的设置(互不干扰)。
场景 F · 拖拽调整层级 列表视图中长按任务卡片,向上拖动到另一个任务上并停留 → 该任务成为目标任务的一级子任务(缩进显示)。若目标任务本身已是子任务,或被拖任务已带子任务,则拒绝并给出提示(仅支持一级)。降为子任务后,它原有的看板列与状态保持不变。
场景 G · 看板卡片内的子任务 看板中某任务卡片下方以简洁样式嵌套显示其子任务 → 直接在卡片内勾选子任务完成,父任务状态不受影响,子任务状态也不受该列绑定规则约束;每个嵌套子任务带自身状态小标记,便于识别与父任务不一致的状态;需要编辑子任务标题或负责人时,点开卡片弹窗操作。
场景 H · 从底部 Tab 进入(首屏) 底部导航顺序为「打卡 → 任务 → 宏观 → 监控 → 我」→ 点击「任务」进入首屏:上部是最近使用的 3 个项目卡片 + 「更多项目」入口(点卡片即切换当前项目,长按卡片可调整顺序);下部直接是当前项目(上次访问的,记录在设备端;无记录则回到个人默认项目)的任务管理页,无需先进项目列表。点「更多项目」才进入完整的项目列表页。
场景 I · 项目管理 在项目页头部点「项目管理」→ 弹出统一管理页,内含三个分区:成员(查看 / 添加 / 移除)、列设置(列管理 / 状态绑定 / 保留选项)、项目信息(改名 / 归档 / 删除 / 退出,个人默认项目不出现删除与退出)。
1.5 不在本期范围(明确排除)
- 多层子任务(仅一级)。
- 角色 / 权限分级(只预留入口,本期全部成员权限均等)。
- 任务评论、@提及、附件上传、提醒通知、日历同步。
- 列内拖拽排序的精细规则(本期为简单位置值)。
- 甘特图、工时、报表统计。
- 项目成员清空后的数据清理(由后台维护,前端不做特殊处理)。
- 独立的 WebView / 登录态 / 返回键适配(沿用现有项目框架,不单独提出要求)。
2. 术语与概念定义
| 术语 | 定义 |
|---|---|
| 项目(Project) | 任务与权限的隔离单位;用户只能看到自己为成员的项目 |
| 个人默认项目 | 每个用户唯一、自动创建、不可删除、不可添加成员的私有项目;isPersonal = true |
| 普通协作项目 | 可增删成员、可归档的项目;isPersonal = false |
| 项目成员(Member) | ProjectMember 记录,决定读写权限 |
| 负责人(Assignee) | 任务上的单人标记(须为项目成员),决定列表 / 卡片视觉上的突出位置;新建时默认为创建者,可清空 |
| 任务成员(TaskMember) | 任务上的多成员标记(须为项目成员),弱化展示,可为空 |
| 任务状态(status) | todo(未开始)/ doing(执行中)/ done(完成),三值枚举 |
| 看板列(column) | 项目级可配置的列实体,默认 Plan / Doing / Action / Done 四列;可增删改、可排序,数量不固定 |
| 列-状态绑定(columnBindings) | 项目级配置:每列独立声明「是否绑定」及「绑定到哪个状态」;默认 plan→todo、doing→doing、done→done、action→不绑定 |
| 已完成但未绑定状态 | 状态为 done 但所在列未绑定到 done;此时拖拽/勾选只改状态不改列(见 T-EX-04) |
| 看板列保留选项(columnRetention) | 项目级配置:每列独立设置已完成任务的保留时长,never 永不显示 / today 当天 / 3d 3 天 / week 本周 / month 本月 / forever 永久显示 |
| 视图记忆(viewMode) | list / board,按项目独立记忆、保存在设备端 |
| 扩展信息卡片 | 任务的折叠信息区,存任意 [{label, value, url?}] 条目,默认收起、全部非必填 |
| 一级子任务 | parentId 非空的任务;其父任务必须为顶层任务,且同项目 |
| 上下文 | 本次操作所处位置(项目 / 父任务 / 列表分区),用于界定"从该列拖出"等相对语义的作用范围 |
| 拷贝(Copy) | 跨项目生成新任务并复制全部内容;原任务不受影响 |
3. 需求点
编号规则:T-模块-序号。前缀 T 表示本模块(Task / 任务)。模块:
| 模块码 | 模块名 | 对应 §1.3 条目 |
|---|---|---|
VW |
视图体系 | 第 1 条 |
COL |
看板列管理 | 第 2 条 |
BD |
看板与列-状态绑定 | 第 2 条 |
FL |
已完成任务显示控制(按列保留选项) | 第 3 条 |
TK |
任务字段体系(含扩展信息卡片) | 第 4 条 |
AS |
负责人与成员 | 第 5 条 |
ST |
子任务体系 | 第 6 条 |
PJ |
项目体系 | 第 7 条 |
PM |
项目权限与模块入口 | 第 8 条、第 11 条 |
CP |
跨项目拷贝 | 第 9 条 |
UI |
UI 交互规范 | 第 10 条 |
DT |
数据需求 | — |
NF |
非功能需求 | — |
EX |
异常与边界 | — |
优先级:P0 = 本期必须有;P1 = 本期应该有;P2 = 有则更好(可延后)。
验收要点写法:统一采用「给什么输入 / 做什么操作 → 期望得到什么可观察结果」,可直接转写为测试用例。
3.1 视图体系(T-VW)
| 编号 | 需求描述 | 验收要点 | 优先级 |
|---|---|---|---|
| T-VW-01 | 项目内提供列表视图与看板视图两种呈现方式 | 同一项目的同一批任务,两种视图均能完整呈现,条数一致 | P0 |
| T-VW-02 | 可在列表 / 看板之间互相切换,切换过程无整页刷新 | 切换不触发页面重载、不出现白屏,切换后滚动位置或回到顶部行为明确 | P0 |
| T-VW-03 | 视图记忆按单个项目独立保存:A 项目选列表、B 项目选看板互不影响 | 项目 A 切到看板 → 进入项目 B → B 仍为 B 上次选择的视图;回到 A → 仍为看板 | P0 |
| T-VW-04 | 进入项目时自动恢复该项目上次选择的视图 | 退出模块后重新进入某项目,视图与上次退出时一致 | P0 |
| T-VW-05 | 从未选择过视图的新项目,默认使用列表视图 | 新建项目首次进入为列表视图 | P1 |
| T-VW-06 | 视图记忆保存在设备端,不要求跨设备同步;本机跨会话保持 | 杀进程重进某项目,视图仍为上次选择;换设备登录不要求一致 | P0 |
| T-VW-07 | 上次访问的项目记录在设备端;无记录时一律回到个人默认项目 | 杀进程重进落在上次项目;首次使用或记录失效则进入个人默认项目 | P0 |
| T-VW-08 | 任务首屏上部展示最近使用的 3 个项目卡片,末尾放「更多项目」入口;点击「更多项目」进入完整项目列表页 | 最近项目按访问时间倒序取前 3;点卡片切换当前项目并高亮;点「更多」进入项目列表 | P0 |
| T-VW-09 | 任务首屏下部直接展示当前选中项目的任务管理视图(列表 / 看板,随该项目视图记忆);当前项目默认为上次访问的项目,无记录时为个人默认项目 | 进入任务 Tab 即见当前项目的任务,无需先进项目列表;切换首屏项目卡片后下部随之切换 | P0 |
| T-VW-10 | 首屏最近项目卡片支持手动排序(长按拖动调整顺序),排序结果存设备端;未手动排序时按最近使用时间自动排列 | 拖动后顺序持久化,杀进程重进保持;新近访问但未手动排序的项目不出现在固定卡位之外 | P1 |
3.2 看板列管理(T-COL)
看板列是项目级可配置实体:默认 4 列,允许增删改与排序。列与「状态绑定」「保留选项」是三条正交的配置。
| 编号 | 需求描述 | 验收要点 | 优先级 |
|---|---|---|---|
| T-COL-01 | 新建项目默认生成 4 列:Plan / Doing / Action / Done,顺序即此 |
新项目看板渲染 4 列且名称、顺序与默认一致 | P0 |
| T-COL-02 | 支持新增列(自定义名称),新列默认追加在末尾 | 新增后看板多一列,位于最后一列之后,可正常拖入任务 | P0 |
| T-COL-03 | 支持重命名列 | 改名后看板、列设置、任务归属处同步显示新名称 | P0 |
| T-COL-04 | 支持删除列;删除前需二次确认,并明确其中任务的处理方式 | 按 T-EX-16 约定迁移任务,不产生无归属任务 | P0 |
| T-COL-05 | 支持调整列顺序(拖动排序),顺序即看板显示顺序 | 拖动后顺序持久化,重新进入保持新顺序 | P0 |
| T-COL-06 | 列数量不固定,约束上下限:至少 1 列、至多 10 列(上限待确认) | 可增到多于 4 列;删到仅剩 1 列时禁止再删;达 10 列时禁止新增并提示 | P0 |
| T-COL-07 | 列名需非空且有长度上限,同一项目内不允许重名 | 提交空名 / 重名时拒绝保存并提示 | P0 |
| T-COL-08 | 删除列时,若该列绑定了状态,绑定关系随之解除 | 删除绑定「完成」的列后,该状态不再有该列可归位 | P1 |
| T-COL-09 | 列配置属项目级,项目内任意成员可修改,不影响其他项目 | 成员 A 改列名,成员 B 同步可见;其他项目列不受影响 | P0 |
| T-COL-10 | 列表视图不展示列分组,但任务仍归属某一列(列可被增删后依然成立) | 删除/新增列后,列表视图中任务的列归属正确 | P0 |
3.3 看板与列-状态绑定(T-BD)
| 编号 | 需求描述 | 验收要点 | 优先级 |
|---|---|---|---|
| T-BD-01 | 看板以列为单位组织任务,列由项目配置(默认 4 列,支持增删改与排序,详见 T-COL) | 看板按项目当前列配置渲染;调整列后任务归属随之正确呈现 | P0 |
| T-BD-02 | 每一列独立配置是否绑定任务状态;绑定时可选择绑定到 未开始 / 执行中 / 完成 中任一个 |
每列都有独立的绑定开关与状态选择器;各列配置独立保存 | P0 |
| T-BD-03 | 允许多列绑定到同一个状态(如 Done 与 Action 都绑定「完成」) |
同一项目配置两列均绑定「完成」后,两列均能触发完成联动 | P0 |
| T-BD-04 | 绑定列 → 拖入即改状态:任务落入绑定列时,任务状态改为该列所绑定的状态 | 把「未开始」任务拖入绑定「执行中」的列 → 状态变「执行中」;拖入绑定「完成」的列 → 状态变「完成」 | P0 |
| T-BD-05 | 状态 → 自动移入列:任务状态改为某状态时,任务自动移入绑定该状态的列 | 列表视图把状态改为「完成」→ 切到看板,任务位于绑定「完成」的列 | P0 |
| T-BD-06 | 同一状态被多列绑定时,自动移入按当前列顺序取第一个匹配列,规则确定且可预期 | 两列均绑定「完成」时,任务状态改为「完成」后仅出现在列序靠前的那个绑定列,不重复出现 | P0 |
| T-BD-07 | 列决定状态,不看来源列:拖动任务时,一律以「目标列的绑定配置」决定任务状态——目标列绑定了状态,则状态改为所绑定状态;目标列未绑定,则任务保留原状态 | ①从绑定「完成」的列拖到绑定「执行中」的列 → 状态变「执行中」;②从任意列拖到未绑定的 Action → 状态保持不变 |
P0 |
| T-BD-08 | 不绑定列与任务状态完全独立:拖入、拖出该列以及在其他位置改变状态,均不改变该列归属以外的行为 | 把「执行中」任务拖入未绑定的 Action → 状态仍为「执行中」,仅列变化 |
P0 |
| T-BD-14 | 状态与所在列不匹配时自动归位:任务状态改变后,若其当前所在列未绑定该状态,则自动查找绑定该状态的列并将其移入 | 在未绑定的 Action 中把任务改为「完成」→ 任务自动移入绑定「完成」的列 |
P0 |
| T-BD-15 | 自动归位时按当前列的实际显示顺序取第一个匹配列(列顺序可被用户调整) | 若两列都绑定「完成」,状态改为「完成」后移入排在前面那一列 | P0 |
| T-BD-16 | 无匹配列时任务不移动,保留在原列(状态照常改变) | 取消所有列对「完成」的绑定后,把任务改为「完成」→ 状态为完成,列保持不变 | P0 |
| T-BD-09 | 默认配置:Plan 绑定「未开始」、Doing 绑定「执行中」、Done 绑定「完成」、Action 不绑定 |
新建项目首次打开看板配置,四列取值与默认完全一致 | P0 |
| T-BD-10 | 绑定配置是项目级的,项目内任意成员均可修改,不同项目互不影响 | 成员 A 修改项目一配置成功;项目二配置不受影响;成员 B 也能修改 | P0 |
| T-BD-11 | 修改绑定配置不批量改写既有任务的状态与列,仅对之后的操作生效 | 把 Action 由不绑定改为绑定「完成」后,已在 Action 的任务状态保持原样 |
P1 |
| T-BD-12 | 绑定配置变更后,看板与列表即时一致,无需手动刷新 | 保存配置后,看板列徽标与完成态立即反映新规则 | P1 |
| T-BD-13 | 子任务不受看板列-状态绑定影响:子任务状态不因所在列而改写,也不触发「状态 → 移入列」 | 父任务在绑定「完成」的列,其子任务状态仍可为「执行中」且不被改写;修改子任务状态不使其离开当前列 | P0 |
3.4 已完成任务显示控制(T-FL)
本节的「保留选项」以看板列为单位配置,取代原先的「项目整体 5 档过滤」。
| 编号 | 需求描述 | 验收要点 | 优先级 |
|---|---|---|---|
| T-FL-01 | 每一列独立配置已完成任务的保留选项,配置项属于项目级 | 各列(含新增列)都有独立配置入口,修改一列不影响其他列 | P0 |
| T-FL-02 | 保留选项为固定 6 档:永不显示 / 当天 / 3 天 / 本周 / 本月 / 永久显示 |
下拉仅此六项,不提供自由输入天数 | P0 |
| T-FL-03 | 「永久显示」:该列已完成任务始终展示,不受时间限制 | 设为永久显示后,历史任意时间完成的任务均可见 | P0 |
| T-FL-04 | 「永不显示」:该列已完成任务始终不展示 | 设为永不显示后,该列无已完成任务卡片 | P0 |
| T-FL-05 | 「当天」:仅展示**完成于今天(自然日)**的已完成任务 | 今天完成的可见;昨天完成的次日即不显示 | P0 |
| T-FL-06 | 「3 天」:展示**完成于最近 3 个自然日(含今天)**的已完成任务 | 今天、昨天、前天完成可见,更早不显示 | P0 |
| T-FL-07 | 「本周」:展示**完成于本周(周一 00:00 起,至今天)**的已完成任务 | 周一起算;下周一进来看,上周完成的任务不再显示 | P0 |
| T-FL-08 | 「本月」:展示**完成于本月(当月 1 日起,至今天)**的已完成任务 | 当月 1 日起算;进入次月后,上月完成的任务不再显示 | P0 |
| T-FL-09 | 超出所选档位范围的已完成任务自动隐藏(无需手动操作) | 某列设为「当天」,次日进入该列,昨日完成的任务自动消失 | P0 |
| T-FL-10 | 保留判定以「该任务的完成时间」为准,与任务当前所在列无关 | 任务完成后再移动列,可见性仍按其完成时间与新列档位判定 | P0 |
| T-FL-11 | 列表视图与看板视图行为一致:列表只是不按看板列分组展示,任务归属哪一列仍是哪一列,显示控制同样按其所属列的配置执行 | 看板中某列已隐藏的已完成任务,在列表视图中同样不出现;两视图可见条数一致 | P0 |
| T-FL-12 | 该配置仅影响已完成任务;未完成任务始终展示,不受保留选项影响 | 未完成任务在任何保留选项配置下均可见 | P0 |
| T-FL-13 | 显示控制为展示层过滤,不改变任务数据与状态 | 修改保留选项后,任务数据、状态、计数口径不发生变化 | P0 |
| T-FL-14 | 过滤后每列的计数与展示条数一致 | 列头显示 N 条时,该列实际可见卡片同为 N 条 | P1 |
| T-FL-15 | 保留选项配置在项目内所有成员间共享(属项目配置,非个人偏好) | 成员 A 修改后,成员 B 进入即按新配置显示 | P0 |
3.5 任务字段体系(T-TK)
| 编号 | 需求描述 | 验收要点 | 优先级 |
|---|---|---|---|
| T-TK-01 | 任务包含基础字段:标题(必填)、描述、所属项目、看板列、任务状态、负责人、任务成员、标签、创建人、创建时间、更新时间 | 新建任务后上述字段均可正确保存与读取 | P0 |
| T-TK-02 | 标题为唯一必填字段,其余字段均可为空 | 仅填标题即可保存成功;仅清空标题时拒绝保存并提示 | P0 |
| T-TK-03 | 任务状态为三值枚举:未开始 / 执行中 / 完成 |
任一任务的状态只能取这三个值之一,不存在第四种取值 | P0 |
| T-TK-04 | — | 已取消 | |
| T-TK-05 | — | 已取消 | |
| T-TK-06 | — | 已取消 | |
| T-TK-07 | — | 已取消 | |
| T-TK-08 | 每条任务有负责人(单人) | 任务最多只有一个负责人,重复设置时以最后一次为准 | P0 |
| T-TK-09 | 新建任务时负责人默认填入创建者本人 | 新建任务后未手动修改时,负责人即为创建者 | P0 |
| T-TK-10 | 负责人允许清空为空 | 清空后任务可正常保存,展示为「未指派」 | P0 |
| T-TK-11 | 每条任务有任务成员(多人) | 可设置 0 ~ 多个成员,成员不重复 | P0 |
| T-TK-12 | 任务支持标签 | 可添加多个标签,展示于条目 / 卡片 | P1 |
| T-TK-13 | 任务的创建人、创建时间、更新时间由系统维护,用户不可直接编辑 | 编辑任务不改变创建人与创建时间;任何修改刷新更新时间 | P1 |
3.6 负责人 & 成员 UI 展示规则(T-AS)
| 编号 | 需求描述 | 验收要点 | 优先级 |
|---|---|---|---|
| T-AS-01 | 负责人字号更大、视觉突出,位于条目 / 卡片的主要信息区 | 同名负责人与成员并排时,负责人字号明显更大且位于主位 | P0 |
| T-AS-02 | 任务成员字号更小、弱化展示(低对比色),位于卡片 / 条目下方 | 成员信息渲染在负责人 / 标题之下,视觉层次弱于负责人 | P0 |
| T-AS-03 | 负责人只能从当前项目的成员中选择 | 选择器只列出本项目成员;项目外用户无法被选中 | P0 |
| T-AS-04 | 任务成员只能从当前项目的成员中选择 | 选择器只列出本项目成员,不提供项目外用户 | P0 |
| T-AS-05 | 负责人为空(已清空)时展示「未指派」占位,正常渲染 | 清空负责人后条目 / 卡片显示「未指派」,可再次指派 | P0 |
| T-AS-06 | 人员被移出项目后,其负责人 / 成员标记按约定处理且不报错 | 见 T-EX-06 | P1 |
| T-AS-07 | 负责人、任务成员仅为信息标记,不改变项目统一读写权限 | 仅为负责人或仅为成员的用户,对项目读写能力与其他成员完全相同 | P0 |
3.7 子任务体系(T-ST)
| 编号 | 需求描述 | 验收要点 | 优先级 |
|---|---|---|---|
| T-ST-01 | 仅支持一级子任务,不支持多层嵌套 | 子任务上无「添加子任务」入口;后端拒绝以子任务为父任务创建任务 | P0 |
| T-ST-02 | 子任务必须与父任务归属同一项目 | 尝试将子任务置于其他项目时被拒绝(含跨项目拷贝场景) | P0 |
| T-ST-03 | 父任务与子任务的完成状态相互独立、不自动联动 | 子任务全部完成,父任务状态不变;父任务完成,子任务状态不变 | P0 |
| T-ST-04 | 列表视图支持子任务缩进展示 | 子任务在父任务下方缩进渲染,层级一眼可辨 | P0 |
| T-ST-05 | 列表视图支持子任务折叠 / 展开 | 折叠后子任务不显示且不占位;展开后恢复;折叠状态可感知 | P0 |
| T-ST-06 | 看板卡片内嵌套展示子任务:含子任务的卡片中,子任务以简洁形式嵌套显示在任务卡片内 | 卡片内可见子任务列表(如紧凑单行:复选框 + 标题),样式轻量、不喧宾夺主 | P0 |
| T-ST-07 | 嵌套子任务可在卡片内直接勾选完成;完整详情(编辑标题 / 负责人 / 扩展信息等)在卡片弹窗内查看编辑 | 点击子任务复选框即切换其状态;点击卡片打开弹窗可编辑子任务全部字段 | P0 |
| T-ST-08 | 子任务状态与父任务状态可以不一致,且子任务不受看板列-状态绑定约束 | 父任务在 Done(绑定「完成」)时,其子任务可为「未开始」且不被改写 |
P0 |
| T-ST-09 | 卡片内嵌套的子任务显示自身状态小标记(区分「未开始 / 执行中 / 完成」),以便识别与其父任务不一致的状态 | 父任务为完成、子任务为执行中时,卡片内可见子任务带「执行中」小标记 | P0 |
| T-ST-10 | 子任务不可作为看板独立卡片出现,只在其父任务卡片内嵌套 | 看板上一个任务只占一张卡,子任务不会单独成卡 | P1 |
| T-ST-11 | 删除父任务时级联删除其子任务 | 删除父任务后子任务一并删除,不产生孤儿数据 | P0 |
| T-ST-12 | 支持长按拖拽把任务降为另一个任务的一级子任务 | 列表视图长按任务 A 拖到任务 B 上释放 → A 成为 B 的子任务并缩进显示 | P0 |
| T-ST-13 | 拖拽成为子任务时,若目标任务本身已是子任务,则拒绝操作并提示 | 把任务拖到某个子任务上 → 操作被拒绝,给出「仅支持一级子任务」提示,数据不变 | P0 |
| T-ST-14 | 拖拽成为子任务时,若被拖任务是有子任务的父任务,则拒绝并提示(父任务不可整体挂到别的任务下) | 拖动含子任务的任务到其他任务上 → 拒绝,避免形成二级嵌套 | P0 |
| T-ST-15 | 拖拽成为子任务时,子任务的看板列与状态保持自身原值,仅改变父子归属 | 按 T-EX-13 约定处理,保证子任务与父任务同项目且层级合法 | P1 |
3.8 项目体系(T-PJ)
| 编号 | 需求描述 | 验收要点 | 优先级 |
|---|---|---|---|
| T-PJ-01 | 每个用户自动拥有且仅有一个个人默认项目 | 新用户首次进入模块即已存在个人项目;不可再创建第二个 | P0 |
| T-PJ-02 | 个人默认项目不可删除 | 无删除入口;直接调用删除接口被拒绝 | P0 |
| T-PJ-03 | 个人默认项目不能添加其他成员 | 成员管理入口不存在或不可用;调用添加成员接口被拒绝 | P0 |
| T-PJ-04 | 个人默认项目名称以用户名开头,且整体名称可自定义修改 | 初始名称以用户名开头;改名后修改内容生效,仍保持「个人项目」性质 | P0 |
| T-PJ-05 | 支持新建普通协作项目 | 可创建多个普通项目,创建者为成员 | P0 |
| T-PJ-06 | 普通项目可以增删成员 | 添加 / 移除成员后,成员列表与可见性即时变化 | P0 |
| T-PJ-07 | 项目创建人可以主动退出项目 | 创建人退出后不再是成员,该项目不再对其可见 | P0 |
| T-PJ-08 | 项目成员清空后静默保留,交后台后续维护,前端不做特殊处理 | 成员全部退出后,前端不弹特殊提示、不出现错误;不可见 | P0 |
| T-PJ-09 | 项目可归档,归档项目与进行中项目区分展示 | 归档后从进行中列表移出,可在归档区找回 | P1 |
| T-PJ-10 | 项目列表按用户可见范围返回,仅含自己为成员的项目 | 非成员项目不出现在列表中 | P0 |
| T-PJ-11 | 项目的成员管理、成员新增、列设置统一收进「项目管理」入口;项目页头部不再散置多个功能入口 | 项目管理内含 成员 / 列设置 / 项目信息 三个分区;头部仅保留「项目管理」一个入口 | P0 |
| T-PJ-12 | 项目管理内提供项目信息管理:改名(T-PJ-04)、归档 / 取消归档(T-PJ-09)、删除项目(T-PJ-02,个人默认项目禁用)、退出项目(T-PJ-07,创建人可退) | 各操作在项目管理中可用且遵循既有约束;个人项目不出现删除与退出入口 | P0 |
| T-PJ-13 | 项目支持信息块:可自由添加任意多个长文本信息块(标题 + 多行内容,如 Readme / 项目说明),每块独立编辑与删除;属项目级数据,全体成员可见可编辑 | 可增删改任意块;内容支持多行长文本;所有成员看到同一份信息块 | P0 |
3.9 项目权限(T-PM)
| 编号 | 需求描述 | 验收要点 | 优先级 |
|---|---|---|---|
| T-PM-01 | 权限以项目为隔离单位:用户只能看到自己是成员的项目及其任务 | 非成员访问某项目接口返回 403 / 404,列表不出现该项目 | P0 |
| T-PM-02 | 项目内所有成员权限均等,具备全读写能力 | 任意成员均可新增 / 编辑 / 删除任务、管理成员、修改列-状态绑定与保留选项配置 | P0 |
| T-PM-03 | 预留权限分级入口,本期不实现细分角色 | 数据结构或接口层保留扩展位;界面无角色分配功能 | P1 |
| T-PM-04 | 项目内所有成员都可以归档项目 | 任意成员执行归档均成功 | P0 |
| T-PM-05 | 复用现有项目框架的登录态与鉴权,未登录访问被拒 | 无有效登录态访问返回 401 | P0 |
| T-PM-06 | 任务模块作为顶级 Tab 接入底部导航,位置在**「打卡」之后** | 底部 Tab 顺序为「打卡 → 任务 → 宏观 → 监控 → 我」;点击该 Tab 进入任务模块 | P0 |
| T-PM-07 | 进入任务模块后默认落在上次访问的项目(记录在设备端);无记录时一律回到个人默认项目 | 首次进入 / 记录失效 → 个人默认项目;再次进入 → 上次离开时的项目;换设备不继承 | P0 |
3.10 跨项目拷贝(T-CP)
| 编号 | 需求描述 | 验收要点 | 优先级 |
|---|---|---|---|
| T-CP-01 | 跨项目操作为拷贝,不是移动:源任务保留在原项目 | 拷贝后源任务仍存在于原项目且内容不变 | P0 |
| T-CP-02 | 拷贝时完整复制全部字段 | 标题、描述、负责人、成员、标签、任务状态、看板列、扩展信息卡片逐项比对一致 | P0 |
| T-CP-03 | 拷贝时完整复制子任务 | 子任务条数、标题、状态、列归属均与源任务一致 | P0 |
| T-CP-04 | 拷贝后新任务的创建人为本次执行拷贝操作的用户 | 新任务创建人 = 操作者,非源任务创建人 | P0 |
| T-CP-05 | 拷贝完成后新旧任务互相独立,后续修改互不影响 | 修改新任务标题 / 状态,源任务不变;反之亦然 | P0 |
| T-CP-06 | 拷贝目标必须是操作者有权限的项目 | 目标项目非本人成员时拒绝并提示 | P0 |
| T-CP-07 | 拷贝时负责人 / 成员若不属目标项目成员,按约定处理 | 按 T-EX-08 约定处理,不产生「项目外人」脏数据 | P1 |
| T-CP-08 | 拷贝包含子任务时,子任务与父任务同属目标项目 | 拷贝后子任务项目归属与父任务一致 | P0 |
| T-CP-09 | 拷贝时若目标任务项目的列-状态绑定规则不同,按 T-EX-14 约定处理 | 状态与列不出现互相矛盾的组合 | P1 |
3.11 UI 交互规范(T-UI)
| 编号 | 需求描述 | 验收要点 | 优先级 |
|---|---|---|---|
| T-UI-01 | 整体界面、列表交互、子任务折叠风格参考 Todoist | 列表条目结构、快速新增、勾选完成、子任务折叠的交互与 Todoist 同类操作一致 | P0 |
| T-UI-02 | 看板卡片轻量化,样式简洁 | 卡片仅承载必要信息,无多余装饰;信息层级清晰 | P0 |
| T-UI-03 | 列表与看板同源数据,修改实时双向同步 | 列表改标题 / 状态 → 切到看板立即可见;看板改 → 切到列表立即可见 | P0 |
| T-UI-04 | 视图切换无刷新、数据一致 | 切换过程中不发起整页加载,数据不发生丢失或错位 | P0 |
| T-UI-05 | 移动端适配:复用现有样式体系与底部导航,安全区不遮挡内容 | 375~430px 视口无横向滚动、无内容被遮挡 | P0 |
| T-UI-06 | 勾选完成有即时反馈(视觉状态变化),不阻塞后续操作 | 点击勾选后立即变化,无需等待接口返回才能继续操作 | P1 |
| T-UI-07 | 看板拖拽在移动端支持长按拖拽,并提供卡片「移动到」快捷项作为兜底 | 长按可拖起卡片;无法拖拽的场景可用「移动到」菜单完成同效果 | P0 |
| T-UI-08 | 具备空状态展示(无项目 / 无任务 / 无子任务等) | 各层级无数据时展示空态与引导入口,不出现空白页 | P0 |
| T-UI-09 | 具备加载状态展示 | 首屏与切换视图时展示加载态,不出现闪烁或错乱 | P0 |
| T-UI-10 | 具备数据异常状态展示,可重试 | 接口失败时展示异常态与重试入口,重试成功后恢复 | P0 |
| T-UI-11 | 弹层(任务详情等)底部按钮与屏幕底边保持安全距离,不被安全区 / 手势条遮挡 | 底部留白 ≥ 安全区高度 + 12px;小屏下弹层内容可滚动,删除等底部按钮始终完整可见可点 | P0 |
3.12 数据需求(T-DT)
| 编号 | 需求描述 | 验收要点 | 优先级 |
|---|---|---|---|
| T-DT-01 | 新增 Prisma 模型:Project(含 isPersonal、列-状态绑定配置、列保留选项配置、archived 等)、ProjectMember |
字段见附录 A | P0 |
| T-DT-02 | 列-状态绑定配置按列存储,每列独立保存「是否绑定 + 绑定状态」,支持多列指向同一状态 | 任意数量列的配置可独立读写;两列绑定同一状态可正确落库 | P0 |
| T-DT-03 | 列保留选项配置按列存储,取值覆盖六档:never / today / 3d / week / month / forever |
三档取值均可落库并正确读回 | P0 |
| T-DT-04 | 新增 Prisma 模型:Task(含 parentId 自关联、assigneeId、status、看板列、扩展信息卡片、sortOrder) |
字段见附录 A | P0 |
| T-DT-05 | 新增 Prisma 模型:TaskMember(任务成员关联)、扩展信息卡片结构、标签结构 |
字段见附录 A | P0 |
| T-DT-06 | 视图记忆按设备端存储,不要求落库 | 换设备登录不要求视图一致 | P0 |
| T-DT-07 | 建立必要索引:任务按项目查询、按父子关系查询、按状态查询 | 列表 / 看板 / 显示控制查询均走索引 | P0 |
| T-DT-08 | 提供迁移 SQL 并纳入 prisma migrate deploy 流程 |
与现有迁移流程一致 | P0 |
| T-DT-09 | 归档采用软删除语义,历史数据保留 | 归档不物理删除任务与项目数据 | P1 |
3.13 非功能需求(T-NF)
| 编号 | 需求描述 | 验收要点 | 优先级 |
|---|---|---|---|
| T-NF-01 | 项目内任务列表首屏加载 < 1.5s(正常网络),交互响应 < 300ms | 真机可感知流畅 | P0 |
| T-NF-02 | 兼容当前 APP 的 WebView 运行环境与移动端浏览器 | 真机验证通过 | P0 |
| T-NF-03 | 前端代码组织遵循现有约定:src/pages/task/* + src/components/* + server/routes/task*.js |
结构一致 | P0 |
| T-NF-04 | 路由与接口挂载沿用现有项目框架的组织方式 | 与现有模块的组织方式一致 | P0 |
| T-NF-05 | 数据量按「单项目千级任务 / 年」设计,无需分表 | 千级任务下列表与看板可用 | P1 |
3.14 异常与边界(T-EX)
| 编号 | 需求描述 | 处理约定 | 优先级 |
|---|---|---|---|
| T-EX-01 | 重复点击勾选 / 重复拖拽 | 前端防抖 + 后端幂等,状态最终一致 | P0 |
| T-EX-02 | 接口失败 / 断网 | 乐观更新回滚 + 提示,可重试 | P0 |
| T-EX-03 | 绑定配置被改为「不绑定」时,已在该列的已完成任务 | 保持当前列与状态不变,等待用户后续操作 | P0 |
| T-EX-04 | 任务状态与所在列绑定不一致(如在不绑定的 Action 中改为「完成」) |
触发自动归位:移入第一个绑定该状态的列;无匹配列则不移动,保留原列(见 T-BD-14~16) | P0 |
| T-EX-05 | 任务被拖到未绑定状态的列(如 Action),其原状态如何处理 |
原状态保持不变,不因离开原列而回退(不存在「拖出即回退」规则) | P0 |
| T-EX-06 | 项目成员被移除,其仍担任某任务负责人 / 成员 | 保留历史标记,展示为「已退出」样式;不报错、不清空 | P1 |
| T-EX-07 | 删除父任务 | 级联删除其子任务,确认弹窗提示「将一并删除 N 条子任务」 | P0 |
| T-EX-08 | 跨项目拷贝时负责人 / 成员不属于目标项目 | 仅保留属于目标项目成员者,其余丢弃并在结果中提示 | P1 |
| T-EX-09 | 个人默认项目尝试添加成员 / 尝试删除 | 接口返回明确错误,前端不提供入口 | P0 |
| T-EX-10 | 某列设为「当天」等档位且该列无符合条件的已完成任务 | 展示该列空态,不报错 | P0 |
| T-EX-11 | 项目成员清空后的项目 | 静默保留,前端不报错、不特殊提示 | P0 |
| T-EX-12 | 子任务所属项目与父任务不一致(绕过前端直接调用) | 后端拒绝并返回错误 | P0 |
| T-EX-13 | 拖拽成为子任务时,子任务的看板列与状态如何取值 | 保持自身原值不变,仅改变父子归属 | P1 |
| T-EX-14 | 跨项目拷贝时,源任务的状态 / 列在目标项目绑定规则下无对应关系 | 沿用源值落库,不强行纠正;由后续用户操作自然修正 | P1 |
| T-EX-15 | 拖拽将任务放到自身或其后代上 | 拒绝操作并提示,避免形成环形父子关系 | P0 |
| T-EX-16 | 删除仍有任务的列 | 二次确认后,该列任务迁移至相邻列(或由用户指定目标列),不产生无归属任务 | P0 |
| T-EX-17 | 删除唯一剩余的列 | 拒绝操作并提示「至少保留一列」 | P0 |
| T-EX-19 | 新增列时已达列数上限 | 拒绝新增并提示已达上限,不产生空列 | P1 |
| T-EX-18 | 已完成任务跨周期(周一零点 / 月初零点)后应隐藏 | 当场消失并带移除动画,其余任务平滑重排,不留空白 | P1 |
4. 优先级汇总(本期交付范围)
- P0(必须):T-VW-01
04、T-VW-0609;T-COL-0107、T-COL-09、T-COL-10;T-BD-0110、1316;T-FL-0113、15;T-TK-0111;T-AS-0105、07;T-ST-0109、1114;T-PJ-0108、1013;T-PM-01、02、0407;T-CP-0106、08;T-UI-0105、0711;T-DT-0108;T-NF-0104;T-EX-0105、07、0912、15~17。 - P1(应该):T-VW-05、10;T-COL-08;T-BD-11、12;T-FL-14;T-TK-12、13;T-AS-06;T-ST-10、15;T-PJ-09;T-PM-03;T-CP-07、09;T-UI-06;T-DT-09;T-NF-05;T-EX-06、08、13、14、18、19。
5. 已决策问题(评审记录)
以下问题已在 2026-10-24 评审中确认,作为实现依据:
| # | 问题 | 决策 |
|---|---|---|
| 1 | 列-状态绑定是单列还是多列? | 每列独立配置,允许多列绑定同一状态;默认 plan→未开始、doing→执行中、done→完成、action→不绑定(T-BD-02、03、09) |
| 2 | 保留档位的时间边界按自然日还是滚动小时? | 自然日(Asia/Shanghai,含今天 00:00 起);本周按周一起算、本月按 1 日起算 |
| 3 | 视图记忆 / 显示配置存在设备端还是服务端? | 视图记忆设备端、不跨设备;保留选项项目级共享(T-VW-06、T-FL-12、T-DT-06) |
| 4 | 删除父任务时子任务如何处理? | 级联删除,弹窗提示条数(T-EX-07) |
| 5 | 已完成任务在看板中的呈现? | 由该列的保留选项控制显示与隐藏(T-FL-01~10) |
| 6 | 看板拖拽的移动端交互? | 长按拖拽 + 「移动到」兜底;允许拖拽降为子任务(T-UI-07、T-ST-12) |
| 7 | 项目成员清空后是否需要本模块的管理入口? | 本期不承担,交后台;前端静默(T-PJ-08) |
| 8 | 扩展信息组的具体字段清单? | 不固定字段,改为任意扩展信息卡片(T-TK-04、05) |
| 9 | 已完成显示策略的粒度? | 改为按看板列独立的保留选项(T-FL-01、02) |
| 10 | 是否单独要求 WebView / 登录态 / 返回键? | 不单列,沿用现有项目框架(T-NF-04、T-PM-05) |
| 11 | 同一状态被多列绑定,状态变化时进哪一列? | 按当前列顺序取第一个匹配(T-BD-06、15、B-3) |
| 12 | 从绑定列拖出时状态是否回退? | 不设「拖出即回退」规则。只看目标列:目标列绑定了状态就按目标列改,未绑定则保留原状态(T-BD-07、B-4) |
| 13 | 列表视图如何处理「按列」的显示控制? | 列表只是不按列分组,任务归属仍是原看板列,行为与看板完全一致(T-FL-11、B-6) |
| 14 | 看板卡片如何展示子任务? | 在卡片内嵌套简洁展示,可直接勾选;完整详情在卡片弹窗(T-ST-06、07) |
| 15 | 子任务是否受列-状态绑定影响? | 不受。子任务状态可与父任务不一致,拖入列不改写其状态(T-BD-13、T-ST-08、B-7) |
| 16 | 父任务能否整体挂到别的任务下? | 不能。含子任务的父任务不可被拖拽为子任务(T-ST-14) |
| 17 | 保留选项的取值范围? | 固定 6 档:永不显示 / 当天 / 3 天 / 本周 / 本月 / 永久显示,不做自由输入(T-FL-02、B-5) |
| 18 | 任务状态与所在列绑定不一致时怎么处理? | 触发自动归位:查找绑定该状态的列并移入,按列序取第一个;无匹配列则不移动(T-BD-14~16、B-4b) |
| 19 | 卡片内嵌套的子任务是否显示自身状态? | 显示小状态标记,以区分与父任务不一致的状态(T-ST-09) |
| 20 | 任务模块入口放在哪里? | 作为顶级 Tab,位置在**「打卡」之后**(T-PM-06) |
| 21 | 5 个底部 Tab 是否影响既有布局与默认首页? | 暂无障碍;默认首页仍为打卡(T-PM-06) | | 22 | 任务状态为「完成」但所有列都未绑定「完成」时,列表视图按哪一列过滤? | 保留在当前列,按该列保留选项过滤。不存在「已完成统一用 Done 列」的强制规则,那只是默认配置下的自然效果,用户可完全自定义(T-FL-11) | | 23 | 「本周 / 本月」跨周跨月时是否要求实时隐藏? | 当场消失并带移除动画,其余任务平滑重排;以刷新方式实现也可接受(T-EX-18) | | 24 | 「上次访问的项目」记录在哪?无记录时如何? | 记录在设备端;无记录一律回个人默认项目(T-VW-07、T-PM-07) | | 25 | 看板列是否固定 4 列? | 非固定:默认 4 列,支持增删改与排序,数量可变,至少保留 1 列(T-COL-01~07) |
| 26 | 是否允许删除最后一个列? | 不允许。删除唯一剩余列时拒绝并提示,项目至少保留 1 列(T-COL-06、T-EX-17) |
| 27 | 新增列的默认设置? | 按默认值:保留选项 永久显示、不绑定状态,不继承相邻列设置(T-COL-02、B-18) |
| 28 | 看板列数量上限? | 暂定上限 10 列(待确认,见下) |
| 29 | 任务首屏结构? | 上部 = 最近使用的 3 个项目卡片 + 「更多项目」入口;下部 = 当前选中项目的任务管理视图,默认上次访问的项目(T-VW-08/09) |
| 30 | 首屏「任务卡片可以排序」的指代? | 指最近项目卡片可长按拖动排序,结果存设备端;任务卡片的列内排序维持既有口径(T-VW-10) |
| 31 | 成员 / 列设置入口的位置? | 统一收进「项目管理」入口(含成员、列设置、项目信息三区),项目页头部不再散置(T-PJ-11) |
| 32 | 项目信息管理包含什么? | 改名、归档 / 取消归档、删除(个人项目禁用)、退出(创建人可退),入口在项目管理内(T-PJ-12) |
| 33 | 任务详情底部按钮遮挡? | 弹层底部预留安全区 + 12px 距离;小屏下弹层可滚动,底部按钮完整可见(T-UI-11) |
| 34 | 项目相关长文本信息记录在哪? | 项目管理内新增信息块分区:任意多个 {标题, 长文本} 块,独立编辑,属项目级数据(T-PJ-13) |
| 35 | 任务级「扩展信息」的去留? | 移除 UI(2026-10-24 评审):任务不再带扩展信息,项目相关长文本由项目信息块(T-PJ-13)承载;DB 字段保留不用 |
仍待评审确认(影响实现口径):
| # | 问题 | 说明 |
|---|---|---|
| A | 列数量上限是否按 10 列? | 现按「至少 1 列、至多 10 列」写入(T-COL-06)。若无需上限,可去掉上限约束 |
附录 A:核心实体草案(供设计阶段参考,非最终表结构)
// 项目
model Project {
id Int @id @default(autoincrement())
name String
ownerId Int // 创建人 (可退出项目, 故与成员表分离)
isPersonal Boolean @default(false) // true = 个人默认项目: 不可删、不可加成员
archived Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
members ProjectMember[]
columns BoardColumn[]
tasks Task[]
@@index([archived])
}
// 看板列 (项目级实体: 默认 4 列, 可增删改与排序)
model BoardColumn {
id Int @id @default(autoincrement())
projectId Int
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
name String // 列名, 项目内唯一
sortOrder Int @default(0) // 显示顺序, 决定自动归位时的"第一个匹配列"
boundStatus String? // null = 不绑定; todo | doing | done
retention String @default("forever") // never | today | 3d | week | month | forever
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tasks Task[]
@@unique([projectId, name])
@@index([projectId, sortOrder])
}
// 项目成员 (权限单位: 在表内即全读写)
model ProjectMember {
id Int @id @default(autoincrement())
projectId Int
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
permission String @default("member") // 预留权限分级入口, 本期恒为 member
createdAt DateTime @default(now())
@@unique([projectId, userId])
@@index([userId])
}
// 任务 / 子任务 (parentId 为空 = 顶层任务)
model Task {
id Int @id @default(autoincrement())
projectId Int
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
parentId Int? // 非空 = 一级子任务 (最多一层)
parent Task? @relation("Subtask", fields: [parentId], references: [id], onDelete: Cascade)
children Task[] @relation("Subtask")
title String
description String @default("")
status String @default("todo") // todo | doing | done
columnId Int // 所属看板列 (BoardColumn), 列可增删改故用 id 而非固定名
column BoardColumn @relation(fields: [columnId], references: [id])
assigneeId Int? // 负责人 (可空; 新建默认 = 创建者)
assignee User? @relation("Assignee", fields: [assigneeId], references: [id], onDelete: SetNull)
creatorId Int // 创建人 (跨项目拷贝时 = 操作者)
creator User @relation("Creator", fields: [creatorId], references: [id])
// 扩展信息卡片: 任意条目, 默认收起
extras Json @default("[]") // [{ label: "仓库", value: "gitlab/app", url: "" }]
sortOrder Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
members TaskMember[]
tags TaskTag[]
@@index([projectId, columnId])
@@index([projectId, status])
@@index([parentId])
}
// 任务成员 (多人, 须为项目成员)
model TaskMember {
id Int @id @default(autoincrement())
taskId Int
task Task @relation(fields: [taskId], references: [id], onDelete: Cascade)
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([taskId, userId])
}
// 任务标签
model TaskTag {
id Int @id @default(autoincrement())
taskId Int
task Task @relation(fields: [taskId], references: [id], onDelete: Cascade)
name String
@@index([taskId])
}
说明:
status与columnId两个字段都落库(而非互相推导),因为未绑定的列需要二者彼此独立;联动仅在项目配置了绑定的列/状态之间发生,由服务端统一裁决。- 保留选项的判定依赖「在该列的完成时间」,建议在任务上记录完成时间或按列迁移时间计算,具体口径在设计阶段确定。
- 视图记忆存设备端(localStorage),不落库。
附录 B:实现约定(开发期补充,用于消除口径歧义)
| # | 约定 | 说明 |
|---|---|---|
| B-1 | 看板列 | 列是项目级实体(BoardColumn),含名称与顺序;默认 4 列 Plan/Doing/Action/Done;支持增删改与排序,至少保留 1 列 |
| B-2 | 列-状态绑定 | columnBindings 为「列 → 状态或 null」映射;null 表示不绑定;允许多列指向同一状态;状态枚举 todo / doing / done |
| B-3 | 多列绑定同一状态时的目标列 | 移入列时按当前列顺序取第一个绑定该状态的列(列顺序可被用户调整) |
| B-4 | 列决定状态 | 拖动任务时只看目标列:目标列绑定了状态 ⇒ 状态 = 所绑定状态(含从任意列拖入);目标列未绑定 ⇒ 状态保持原值。不存在「从某列拖出即回退」的规则 |
| B-4b | 状态与列不一致时的自动归位 | 状态改变后,若当前所在列未绑定该状态 ⇒ 按列序取第一个绑定该状态的列并移入;无匹配列则不移动,状态照常改变 |
| B-5 | 列保留选项 | columnRetention 为「列 → 选项」映射,选项为固定 6 档:never(永不显示)/ today(当天)/ 3d(3 天)/ week(本周)/ month(本月)/ forever(永久显示) |
| B-5b | 各档位口径 | 均按 Asia/Shanghai 自然日:today = 今天;3d = 含今天在内的最近 3 天;week = 本周一 00:00 起;month = 本月 1 日 00:00 起;判定依据为任务的完成时间 |
| B-6 | 显示控制作用域 | 列表视图与看板视图同样按任务当前所属列的保留选项执行过滤;列表只是不按列分组,归属不变;未完成任务不受影响 |
| B-7 | 子任务与绑定无关 | 子任务状态不受看板列-状态绑定影响:拖入列不改写子任务状态,修改子任务状态也不触发「移入列」 |
| B-8 | 子任务约束 | parentId 非空时:父任务 parentId 必须为空(禁止二级);projectId 必须与父任务一致;禁止指向自身或后代 |
| B-9 | 拖拽降为子任务 | 长按拖动任务 A 到任务 B 上释放 ⇒ A.parentId = B.id;要求 B 为顶层任务且 A 本身无子任务,否则拒绝 |
| B-10 | 负责人默认值 | 新建任务时若未显式指定,assigneeId 默认取创建者的 userId;显式传 null 表示清空 |
| B-11 | 个人默认项目 | isPersonal = true;服务端拒绝「添加成员」「删除项目」;名称初始为 {用户名}的任务,可改名 |
| B-12 | 成员清空 | 移除最后一名成员时不删除 Project,仅删除 ProjectMember 记录;前端不特判 |
| B-13 | 跨项目拷贝 | 新建任务(新 id)+ 复制全部字段、扩展卡片与子任务;creatorId = 操作者;负责人 / 成员按 T-EX-08 过滤;状态与列按 T-EX-14 沿用 |
| B-14 | 权限校验 | 所有项目 / 任务接口均先校验「请求者为该项目成员」,非成员返回 403 |
| B-15 | 偏好存储 | 视图记忆与「上次访问的项目」存设备端;列定义、列-状态绑定、列保留选项属项目配置,存服务端、项目内共享 |
| B-16 | 看板列实体 | 列为 BoardColumn(name / sortOrder / boundStatus / retention);默认 4 列由新建项目时初始化;至少保留 1 列;列名项目内唯一 |
| B-17 | 删除列的迁移 | 删除列前需二次确认;列内任务迁移至指定列(默认相邻列),迁移后任务状态按目标列绑定重新裁决;唯一剩余列不可删除 |
| B-18 | 新增列默认值 | 新增列取默认值:retention = forever、boundStatus = null,不继承相邻列配置;sortOrder 追加到末尾 |
| B-19 | 列数上限 | 至少 1 列、至多 10 列(上限待确认) |