第 33 课:任务看板视图(按状态分列)与本地持久化

第 33 课:任务看板视图(按状态分列)与本地持久化

这一课我们继续沿着"任务管理页个人工作台偏好"主线往下推进。

上一课我们已经让任务列表支持:

  • 表格视图
  • 卡片视图
  • 卡片视图下按状态分组

这一课继续把任务页推进到更接近真实后台系统的一步:

让任务列表支持看板视图,并把全部筛选结果按状态分列展示,同时把这份视图偏好持久化到 localStorage。


这节课一句话在做什么?

这一课我们完成了 7 件事:

  1. 给任务页新增了第三种主视图模式:看板视图
  2. 把当前任务按 待开始 / 进行中 / 待评审 / 已完成 分成稳定列。
  3. 看板列基于 全部筛选结果 + 当前排序结果 生成,而不是基于当前分页切片。
  4. 切到看板后会隐藏批量操作栏和分页栏,避免交互语义互相打架。
  5. 把看板视图偏好保存到了 localStorage
  6. 刷新任务页后,看板视图会自动恢复。
  7. 补上了单元测试、E2E 测试和课程文档。

这一课最重要的设计结论

这一课最重要的结论是:

看板视图不是"另一种分页列表",而是"当前筛选结果的流程总览"。


为什么看板不应该继续沿用分页切片?

这节课最值得你真正想清楚的点,就是:

表格 / 卡片 和 看板,虽然都在展示任务,但它们的产品语义并不完全一样。


1. 表格和卡片更像"列表阅读"

前两种模式里,我们一直在强调一条稳定数据流:

  1. 原始任务
  2. 筛选
  3. 排序
  4. 分页切片
  5. 渲染当前页

因为表格和卡片本质上都还是:

  • 一页一页地看数据
  • 当前页展示一段切片
  • 批量选择和分页器都仍然成立

所以它们天然适合:

  • 基于 paginatedTasks

2. 看板更像"流程全景图"

但看板不是为了回答:

  • 当前第几页有哪些任务

而是为了回答:

  • 现在各个流程阶段各有多少任务
  • 哪一列有积压
  • 哪个状态最值得优先关注

所以它更适合基于:

  • filteredTasks
  • sortedTasks

也就是:

  • 先筛选
  • 再排序
  • 然后把全部结果按状态分列

这就是为什么这一课里:

  • 看板继续遵守筛选和排序
  • 但不再使用分页切片

3. 一旦切到看板,就该把分页语义先收起来

如果你一边显示看板,一边还保留:

  • 分页栏
  • 本页全选
  • 批量操作栏

那页面语义会很混乱。

因为用户会产生两个冲突认知:

  • 这是完整流程总览
  • 还是这只是当前页的一小段?

所以这一课我们明确做了两个决定:

  1. 看板模式下隐藏批量操作栏
  2. 看板模式下隐藏分页栏

这不是"功能少了",而是:

先把语义做清楚。


这一课在 useTasksPage 里做了什么?

文件:

  • src/composables/useTasksPage.ts

这一课新增的核心状态仍然放在任务页组合式函数里,因为:

  • 主视图模式属于页面级偏好
  • 要持久化
  • 要同时影响多个展示组件

1. 扩展了任务列表视图模式类型

这次我们把:

  • TaskListViewMode

从原来的:

  • table | card

扩展成了:

  • table | card | kanban

同时也补了对应的:

  • 看板视图 选项文案
  • description 说明

这一步看起来只是多了一个字符串,但它实际上是在告诉整个项目:

  • 页面允许存在第三种主视图
  • 所有使用这个类型的地方都必须显式认识它

这就是 TypeScript 在工程里的价值:

当你扩展产品能力时,类型系统会逼你把所有受影响位置都补完整。


2. 新增了 isTaskKanbanView

除了原来的:

  • isTaskTableView

这次还新增了:

  • isTaskKanbanView

它的作用不是"省几行判断",而是:

  • 让页面模板更清晰
  • 让批量栏和分页栏的显隐条件更明确
  • 让测试更容易表达意图

这也是一个很典型的小型页面建模动作:

把"重要状态的业务含义"提前计算出来,而不是在模板里到处写字符串比较。


3. 新增了 kanbanTaskColumns

这一课最核心的新计算结果是:

  • kanbanTaskColumns

它的输入不是:

  • paginatedTasks

而是:

  • sortedTasks

也就是:

  • 看板列会继承当前筛选结果
  • 看板列会继承当前排序结果
  • 但不会被分页切成一小段

这样做后:

  • 列数量和卡片数量更符合"总览"语义
  • 每列内部任务顺序仍然稳定
  • E2E 也更容易验证真实结果

4. 切到看板时主动清空选择

这一课还在:

  • handleTaskListViewModeChange()

里补了一条非常实用的规则:

当视图切到 kanban 时,主动 clearTaskSelection()。

为什么这样做?

因为看板模式下我们已经决定:

  • 不展示批量操作栏

如果这时候还保留之前在表格/卡片里的选择,就会出现:

  • 页面上看不到选择入口
  • 却暗中保留了一堆旧选择

这就是典型的"隐藏状态污染"。

所以这一步本质上是在做:

  • 状态清理
  • 语义收口

这一课在界面层做了什么?

文件:

  • src/views/TasksView.vue
  • src/components/tasks/TaskKanbanBoard.vue
  • src/components/tasks/TaskListViewModeSwitch.vue
  • src/components/tasks/TaskColumnSettings.vue

1. TasksView.vue 继续承担页面级编排职责

这次页面层做了 4 件关键事情:

  1. 引入新的 TaskKanbanBoard
  2. 根据 taskListViewMode 在三种主视图之间切换
  3. 只在卡片视图下显示 TaskListGroupingSettings
  4. 在看板视图下隐藏批量栏和分页栏

这说明页面层最核心的职责依然是:

  • 条件编排
  • 状态分发
  • 多个功能块之间的协调

它不是"把组件堆在一起",而是在定义:

  • 什么时候该显示什么
  • 哪些能力能共存
  • 哪些能力应该互斥

2. 新增 TaskKanbanBoard.vue

这个组件负责:

  • 渲染状态列
  • 渲染每列里的任务卡片
  • 处理 loading / error / empty
  • 把编辑、删除操作继续抛给页面层

它没有处理:

  • 本地存储
  • 主视图状态
  • 分页
  • 批量选择

这说明它依然只是一个:

  • 展示组件

而不是页面状态中心。


3. 看板卡片继续复用字段显隐偏好

这节课没有重新发明一套"看板字段设置",而是继续复用:

  • visibleTaskColumnKeys

所以当前你在列配置面板里关闭:

  • 负责人
  • 截止日期
  • 优先级
  • 任务说明

这些偏好也会影响看板卡片。

这背后对应的工程思想是:

用户偏好尽量共享,不要在每种视图里各造一套相互割裂的配置系统。


这一课最值得你学会的前端思想

1. 同样是"列表展示",不同视图也可能有不同数据语义

很多初学者会觉得:

  • 既然都是展示任务,那就共用同一套分页逻辑

但真实项目里不能这么机械。

你更应该先问:

  • 这个视图到底想让用户看到什么?

这节课里:

  • 表格 / 卡片:强调"当前页读哪几条"
  • 看板:强调"全部筛选结果怎么按流程阶段分布"

所以它们虽然共用同一批原始数据,却不一定共用完全一样的处理顺序。


2. 视图切换不仅是"换组件",还常常伴随状态协调

这一课你要特别注意一件事:

我们做的不是简单的:

  • v-if 切一下组件

而是同时处理了:

  • 视图模式持久化
  • 批量栏显隐
  • 分页栏显隐
  • 选择状态清理

这说明真实前端里的"视图切换"通常都是:

  • UI 切换
  • 状态切换
  • 交互规则切换

三件事一起发生。


3. "总览视图"适合减少局部操作,先保留核心阅读能力

这节课我们故意没有在看板里继续支持:

  • 勾选
  • 批量改状态
  • 批量删除

不是因为做不出来,而是因为当前阶段更重要的是:

  • 先把总览语义做清楚
  • 先把页面边界理顺
  • 先把功能做成稳定可测试的能力

这就是很典型的工程取舍:

先做正确,再做更多。


这一课补了哪些测试?

1. 单元测试

文件:

  • src/composables/__tests__/useTasksPage.spec.ts

新增覆盖:

  • localStorage 恢复合法看板视图模式
  • 非法视图模式自动回退成 table
  • 切到 kanban 后清空选择状态
  • kanbanTaskColumns 是否基于全部筛选结果生成
  • 看板列内部是否继续保留排序后的相对顺序

这一层主要验证:

  • 页面级状态是否正确
  • 看板的数据边界是否正确
  • 视图切换是否做了必要的状态清理

2. E2E 测试

文件:

  • e2e/pages/TasksPage.ts
  • e2e/app.spec.ts

新增覆盖:

  • 切到看板视图
  • 断言状态列标题真实出现
  • 断言看板里真实出现目标任务卡片
  • 断言批量栏和分页栏被隐藏
  • 刷新页面
  • 再次断言看板视图和状态列仍然保留

这一层主要验证:

  • 不只是状态值变了
  • 页面结构也真的切成了看板
  • 本地持久化在真实浏览器里确实可恢复

这一课改了哪些文件?

  • src/types/task.ts
  • src/composables/useTasksPage.ts
  • src/views/TasksView.vue
  • src/components/tasks/TaskKanbanBoard.vue
  • src/components/tasks/TaskListViewModeSwitch.vue
  • src/components/tasks/TaskColumnSettings.vue
  • src/composables/__tests__/useTasksPage.spec.ts
  • e2e/pages/TasksPage.ts
  • e2e/app.spec.ts
  • docs/33-task-kanban-view-and-persistence.md
  • docs/README.md

这一课最值得你真正记住什么?

如果你只记住"多了一个看板视图按钮",那还不够。

你更应该记住下面这 6 点:

  1. 看板不是普通分页列表,它更像全部筛选结果的流程总览。
  2. 同样的数据,在不同视图里可以有不同的数据处理顺序。
  3. 视图切换不仅会换组件,还会影响分页、批量操作和选择状态。
  4. 页面级偏好仍然应该放在 composable,而不是塞进最终渲染组件里。
  5. 用户字段显隐偏好尽量跨视图共享,不要为每种视图各造一套配置。
  6. 真正像后台系统的能力,不只是能显示,还要语义清晰、状态干净、可持久化、可测试。

这一课的验证命令

完成后至少应该验证:

bash 复制代码
npm run test:unit -- --run
npm run type-check
npm run lint
npm run test:e2e -- --project=chromium
相关推荐
A_aspectJ2 小时前
【Java基础开发】 基于Swing GUI 组件实现图书管理系统
java·开发语言
GISer_Jing2 小时前
Dify可视化编排:技术架构与实战指南
前端·人工智能·ai编程
宇宙realman_9992 小时前
DSP28335-FlashAPI使用
linux·前端·python
xyq20242 小时前
Font Awesome 加载中图标
开发语言
Accerlator2 小时前
MCP vs Function Calling
学习
踩着两条虫2 小时前
VTJ 平台六大设计模式落地实战指南
开发语言·前端·人工智能·低代码·设计模式·重构·架构
Yeats_Liao2 小时前
后台 Sidebar 伸缩交互(PC + 移动端)实现
前端·javascript·css·html5
夜瞬2 小时前
从后端到 RAG 再到 Agent:一份可执行的大模型应用开发学习路线
学习·语言模型
MXN_小南学前端2 小时前
computed 计算属性详解:触发时机、实战场景、Vue2 与 Vue3 对比
前端·javascript·vue.js