第 29 课:任务页筛选方案预设与快捷视图
第 29 课:任务页筛选方案预设与快捷视图
这一课,我们继续沿着任务管理页主线往下走,把它从“能筛选”推进到“能复用工作台”:
让用户把当前筛选条件保存成方案,以后可以一键切回。
这一步很像真实后台系统里常见的:
- 我的待处理
- 待评审优先处理
- 高优先级任务池
- 本周跟进项
很多初学者会把这类功能理解成“多存几组条件”,但真正重要的是:
- 哪些是当前页面的临时状态?
- 哪些是用户想长期复用的工作台?
- 它们应该怎么和 URL、localStorage 一起协同?
这一课一句话在做什么?
这一课我们完成了 6 件事:
- 给任务页增加“筛选方案预设”本地持久化。
- 允许把当前关键字、状态、优先级和排序保存成一条命名方案。
- 支持应用已保存方案,并自动回到第一页。
- 支持删除方案,并在删除最后一条时清空本地存储。
- 补了“回到默认工作视图”动作,让临时筛选能一键复位。
- 补上单元测试、E2E 和文档。
这一课最重要的设计结论
这一课最重要的结论是:
临时筛选状态,不等于可复用工作台。
为什么?
1. 临时筛选状态是“当前这次页面访问”
例如你现在临时把任务页切成:
- 状态:待开始
- 优先级:高
- 排序:截止日期从近到远
这更像:
- 当前页面状态
- 当前正在看的结果
- 适合写进 URL
因为它需要:
- 刷新恢复
- 链接分享
- 浏览器前进后退保留
2. 筛选方案是“以后还想反复使用的工作台”
如果你觉得这套筛选条件以后经常会用到,那它就不再只是当前场景,而是:
- 一个可复用视图
- 一个工作台入口
- 一个个人习惯
所以它更适合放进:
localStorage
而不是只停留在当前 URL 里。
3. 应用筛选方案后,当前真实页面状态仍然要同步回 URL
这也是这一课特别值得记住的一点。
筛选方案本身是本地偏好,
但一旦你点击“应用方案”,它就变成了:
- 当前页面真实生效的筛选状态
所以应用方案后,页面仍然要把:
keywordstatusprioritysort
继续同步进 URL。
这和上一课“默认排序偏好”的原则是完全一致的。
这一课在useTasksPage里做了什么?
文件:
src/composables/useTasksPage.ts
这一课的核心依然在任务页组合式函数里。
因为:
- 筛选方案本质上是页面级用户偏好
- 它依赖当前筛选状态
- 它还要和默认工作视图、分页、URL 同步一起配合
这些逻辑不适合丢进单个组件里各自维护。
新增了筛选方案的类型和本地存储 key
这次新增了:
TaskFilterPresetTASK_TABLE_FILTER_PRESETS_STORAGE_KEY
方案里保存的是一整套筛选快照:
keywordstatusFilterpriorityFiltersortOption
这里要注意:
- 没有把页码存进去
- 也没有把分页大小、显示列存进去
为什么?
因为这一课聚焦的是:
- 筛选与排序工作台
而:
- 页码是当前浏览位置
- 分页大小、显示列属于另外两种个人偏好
它们虽然都和“列表体验”有关,但不是同一层语义。
新增了标准化和比较函数
这一课补了几类重要辅助函数:
- 关键字标准化
- 状态筛选标准化
- 优先级筛选标准化
- 方案名称标准化
- 方案快照比较函数
- 本地方案恢复与写回函数
这类函数的意义不是“为了代码看起来高级”,而是:
不要直接相信 localStorage 里的数据永远干净。
只要是本地存储,就要默认考虑下面这些情况:
- 老版本数据结构
- 用户手动改过
- 异常写入
- 重复名称
- 空名称
所以这一课继续延续我们前面反复练的模式:
先读 -> 再校验 -> 再标准化 -> 再使用
把“当前筛选快照”和“已保存方案”明确分开
这一课新增了一个很关键的概念:
currentTaskFilterPresetSnapshot
它表示:
- 当前页面正在使用的这一组筛选条件
而:
taskFilterPresets
表示:
- 用户已经保存下来的可复用方案列表
这两者不能混在一起。
因为:
- 当前快照是实时状态
- 已保存方案是持久化工作台
只有分开,后面我们才能判断:
- 当前是不是命中了某条已保存方案
- 当前是不是默认工作视图
- 同名保存时应该更新还是新增
新增了几个真正有业务语义的动作函数
例如:
saveCurrentTaskFilterAsPreset()applyTaskFilterPreset()deleteTaskFilterPreset()resetTaskFiltersToDefaultView()
这几个函数非常值得你注意。
因为它们已经不是单纯的“改一个 ref”,而是在表达真实的业务动作:
- 保存一套工作台
- 切换到一套工作台
- 删除一套工作台
- 回到默认工作台
这说明你的composable已经越来越像:
- 页面领域层
而不只是“顺手抽几个函数”。
为什么“回到默认工作视图”很重要?
这一课除了筛选方案本身,还补了一个非常真实的后台动作:
- 回到默认工作视图
这个动作背后的设计是:
- 关键字清空
- 状态回到
全部 - 优先级回到
全部 - 排序恢复成当前
defaultSortOption - 页码回到第一页
这一步非常关键,因为它把第 28 课和第 29 课真正串起来了:
- 第 28 课定义了“默认工作视图”的排序偏好
- 第 29 课开始让页面具备“工作台切换”能力
这样一来,“默认工作视图”就不再只是说明文字,而是一个真实可回退的页面状态。
这一课在界面层做了什么?
文件:
src/components/tasks/TaskFilterPresetsPanel.vuesrc/views/TasksView.vue
这一课新增了一个独立组件:
TaskFilterPresetsPanel
为什么单独拆?
因为如果继续把这块逻辑塞进TaskFilterBar,它会越来越像一个“大而全”的超级组件。
而现在分开后:
TaskFilterBar负责临时筛选输入TaskFilterPresetsPanel负责工作台方案管理TasksView负责消息提示和确认框useTasksPage负责真正的状态和行为
这就是一套比较清晰的分层。
页面层负责什么?
这一课里,页面层主要负责:
- 弹出“保存筛选方案”输入框
- 弹出“删除筛选方案”确认框
- 给出成功/失败消息提示
这和我们前面处理删除任务、批量删除、恢复默认排序时的策略是一致的:
- 页面层负责交互反馈
- 组合式函数负责业务状态
这一课补了哪些测试?
1.useTasksPage.spec.ts
新增覆盖:
- 从
localStorage恢复筛选方案 - 非法和重复方案清理
- 保存当前筛选为方案
- 同名方案更新
- 应用方案后恢复筛选与排序
- 应用方案后页码回到第一页
- 回到默认工作视图
- 删除最后一条方案后清空本地存储
这一层测试主要在验证:
- 状态边界
- 本地持久化边界
- 方案比较与更新规则
2.e2e/app.spec.ts
新增覆盖:
- 设置状态筛选、优先级筛选和排序
- 保存筛选方案
- 回到默认工作视图
- 再次应用方案
- 验证 URL 查询参数同步
- 验证真实任务结果变化
- 重新进入干净任务页地址后方案仍然存在
- 删除方案后从界面中消失
这一层测试主要在验证:
- Element Plus 下拉框真实交互
- 方案面板真实点击流程
- localStorage 持久化是否真的生效
这一课改了哪些文件?
src/types/task.tssrc/composables/useTasksPage.tssrc/components/tasks/TaskFilterPresetsPanel.vuesrc/views/TasksView.vuesrc/composables/__tests__/useTasksPage.spec.tse2e/pages/TasksPage.tse2e/app.spec.tsdocs/29-task-filter-presets-and-quick-views.mddocs/README.md
这一课最值得你真正学会什么?
如果你只记住“多了一个保存筛选方案的按钮”,那还不够。
你更应该记住下面这 6 点:
- 当前页面筛选状态和可复用工作台不是一回事。
- 临时状态更适合进 URL,可复用方案更适合放在本地持久化。
- 方案保存的是“筛选快照”,不是所有列表偏好都往里塞。
- 同名方案更新、非法数据清理、重复项去重,都是本地持久化里很常见的真实工程问题。
- 应用方案后,当前真实页面状态仍然要同步到 URL。
- 页面层和组合式函数的职责分层,决定了这类复杂交互能不能长期维护。
这一课的验证结果
这一课相关改动完成后,应至少通过:
npm run test:unit -- --runnpm run type-checknpm run lintnpm run test:e2e -- --project=chromium
