第 44 课:任务详情抽屉里的评论输入与操作记录联动

这一课我们继续沿着"任务管理页主线"往前推进。

前面你已经做到:

  • 在任务详情抽屉里查看操作记录、评论和附件
  • 在详情里快捷改状态
  • 在详情里上一条 / 下一条切换
  • 在详情里直接驱动筛选
  • 在详情里建立批量上下文
  • 在详情里直接批量改状态、批量删除

但到第 43 课为止,详情抽屉里的"协作评论"仍然只是只读展示。

也就是说:

  • 你能看已有评论
  • 但还不能在当前任务上下文里直接补一条新评论

所以这一课要补上的核心能力是:

让任务详情抽屉从"只读业务区块展示",升级成"可直接协作输入"的入口。

而且评论提交后,不只评论区要更新:

  • 操作记录区也要同步追加一条"评论协作"记录

这才更像真实后台。


这一课一句话在做什么?

这一课本质上是在做:

把详情抽屉里的评论区从只读列表,升级成"可输入、可提交、可联动"的协作区块。

重点不是简单加一个 textarea。

重点是把下面这条链路真正接起来:

  1. 用户在详情抽屉里输入评论
  2. 页面层校验并接住提交意图
  3. 评论区立即出现新评论
  4. 操作记录区同时追加一条评论协作记录

为什么这个能力很像真实后台?

因为真实后台里的详情抽屉,通常不只是"查看资料"。

它更常承担两类工作:

  1. 看当前记录上下文
  2. 顺手补一条协作信息

比如:

  • 给任务补一条最新判断
  • 记录当前阻塞点
  • 说明下一步准备怎么做
  • 留一条评审意见

如果每次都要:

  • 先离开当前任务详情
  • 再去别的地方找评论入口

体验就很割裂。

所以这一课做的事情非常真实:

让用户在"正在看这条任务"的那个地方,直接把协作输入补进去。


这节课最关键的设计结论

1. 基础详情数据和运行时新增数据要分层

这节课没有直接去改:

  • src/mock/taskDetail.ts

里那份基础 mock 数据。

而是把详情协作数据拆成两层:

  1. 基础层
    • 继续由 getTaskDetailBusinessData(task) 生成
  2. 运行时增量层
    • 当前用户在本次页面会话里新提交的评论
    • 当前用户在本次页面会话里新追加的活动记录

最后再在页面层把两层合并。

这非常重要。

因为你要开始学会区分:

  • "系统初始给我的上下文"
  • "用户当前操作临时追加的上下文"

2. 评论输入框本身可以是展示组件的一部分,但草稿状态最好由页面层托管

这一课里,TaskDetailDrawer.vue 新增了:

  • commentDraft
  • commentAuthor
  • update:comment-draft
  • submit-comment

也就是说:

  • 输入框 UI 在抽屉组件里
  • 但草稿值和真正提交逻辑仍然在页面层

这是一种很经典的写法:

展示组件负责呈现输入入口,页面层负责托管跨区域业务状态。

3. 评论提交后不只评论区变,操作记录区也要同步变

这一课最关键的不是"评论出现了"。

而是:

评论提交本身也应该被视为一条后台操作。

所以提交评论后,页面层会同时创建两份数据:

  1. 一条新的评论记录
  2. 一条新的活动记录

这让详情抽屉里两块区块形成了联动:

  • 评论区展示讨论内容
  • 操作记录区展示"刚刚发生了什么"

4. 这节课先做"当前会话内可见",暂时不做后端持久化

这一课故意没有把评论持久化到后端,也没有写进 localStorage。

这是有意设计,不是没做完。

因为当前更重要的是先让你彻底理解:

  1. 详情基础数据从哪里来
  2. 运行时协作增量放在哪里
  3. 页面层如何统一协调展示层和业务层

如果这三步还没理清,就直接上接口或持久化,代码很容易乱。

所以这一课的范围是:

先把页面内协作输入闭环做对。


这次主要改了哪些文件?

这一课主要涉及这些文件:

  1. src/components/tasks/TaskDetailDrawer.vue
  2. src/views/TasksView.vue
  3. src/utils/taskDetailCollaboration.ts
  4. src/utils/__tests__/taskDetailCollaboration.spec.ts
  5. src/components/tasks/__tests__/taskDetailDrawer.spec.ts
  6. e2e/pages/TasksPage.ts
  7. e2e/app.spec.ts
  8. docs/README.md

另外新增了本节文档:

  • docs/44-task-detail-comment-composer-and-activity-sync.md

TaskDetailDrawer.vue 里学什么?

这一课里,评论区不再只是"评论列表 + 空状态提示"。

它前面新增了一块评论输入区。

1. 评论输入区本质上是新的详情工作流入口

这块输入区不是一个普通表单。

它是在告诉你:

详情抽屉可以同时承担"查看上下文"和"补充上下文"两种职责。

这和前面几课是一脉相承的:

  • 快捷改状态,是"就地处理"
  • 快速筛选,是"从详情切回列表上下文"
  • 批量处理,是"从详情发起一批任务动作"
  • 评论输入,是"从详情补充协作信息"

2. 组件继续只抛意图,不自己直接改评论列表

这一课里,抽屉组件新增了:

  • update:comment-draft
  • submit-comment

但它依然没有直接去改:

  • detailData.comments
  • detailData.activityLog

这说明一个很重要的原则:

详情抽屉可以变得更强,但它依然不应该直接接管页面业务数据。

3. "评论人是谁"也应该在界面上明确展示

输入区不是只有一个 textarea。

还额外展示了:

  • 当前评论人标签

这是一种很真实的后台细节。

因为用户在协作系统里通常会关心:

  • 这条评论最终会以谁的身份发出

TasksView.vue 里学什么?

这一课真正的业务协调核心仍然在页面层。

1. 页面层新增了"运行时评论增量"和"运行时活动记录增量"

页面层这次新增了三组状态:

  • taskDetailCommentDraft
  • taskDetailRuntimeComments
  • taskDetailRuntimeActivityLog

这三组状态分别负责:

  1. 当前评论输入框草稿
  2. 本次会话里新增的评论
  3. 本次会话里新增的评论活动记录

它们都不属于基础任务数据本身。

这就是分层设计。

2. 当前详情业务数据不再只是"直接取 mock"

以前是:

  • getTaskDetailBusinessData(activeTaskDetail)

现在变成:

  1. 先拿基础 mock 详情数据
  2. 再读取当前任务对应的运行时评论增量
  3. 再读取当前任务对应的运行时活动记录增量
  4. 最后合并成真正给抽屉展示的数据

这里你要学会一个很关键的思维:

页面真正展示的数据,常常不是某一个来源,而是多个来源合并后的结果。

3. 评论提交流程要先校验,再创建两类数据

handleSubmitTaskDetailComment 做了几件事:

  1. 检查当前是否有有效详情任务
  2. 检查页面是否正在加载
  3. 检查评论内容是否为空
  4. 生成统一时间文案
  5. 创建评论记录
  6. 创建活动记录
  7. 追加到当前任务对应的运行时增量里
  8. 清空草稿

这说明一个后台动作通常不是"点一下就完了"。

它背后通常是一个小型工作流。

4. 删除任务时要顺手清理这条任务对应的运行时详情协作状态

这一课我还顺手补了一个非常重要的清理动作:

  • 单条删除时清理这条任务的运行时评论 / 活动记录增量
  • 批量删除时批量清理这些增量

这说明一个工程层面的习惯:

你新增了某种按任务 id 挂载的运行时状态,就要同时考虑它的销毁时机。


taskDetailCollaboration.ts 里学什么?

这一课新增了一个纯工具文件:

  • src/utils/taskDetailCollaboration.ts

它负责三类事情:

  1. 格式化详情区时间文案
  2. 创建评论记录
  3. 创建评论活动记录
  4. 合并基础详情数据和运行时增量

为什么值得抽?

因为这些逻辑都属于:

  • 规则明确
  • 不依赖组件实例
  • 很适合单元测试

这正是纯函数最适合承接的部分。


单元测试这次补了什么?

1. taskDetailCollaboration.spec.ts

这一课给新纯函数补了四类验证:

  • 时间文案格式化是否正确
  • 评论记录创建是否正确
  • 评论活动记录创建是否正确
  • 业务数据合并是否正确

这让"评论输入联动"里最容易写错的规则部分先被锁住。

2. taskDetailDrawer.spec.ts

这一课继续补了展示层组件测试:

  • 评论输入区是否渲染出来
  • 是否会抛出 update:comment-draft
  • 是否会抛出 submit-comment
  • 空草稿时是否不会误触发提交

这很适合帮助你区分:

  • 展示层应该测什么
  • 页面层应该测什么

E2E 这次补了什么?

1. Page Object 新增了评论输入语义方法

文件:

  • e2e/pages/TasksPage.ts

新增方法:

  • fillTaskDetailCommentDraft
  • submitTaskDetailComment

同时还顺手把两个已有定位器收紧了:

  • 详情里的"改为某状态"按钮现在按精确文案点
  • 详情评论断言现在只在评论正文节点里找

这说明一个很重要的测试经验:

当页面能力变多时,Page Object 的语义定位也要跟着变精确。

2. 新增了一条完整的评论提交流程 E2E

文件:

  • e2e/app.spec.ts

新增测试:

  • user can add a collaboration comment inside task detail drawer

它验证了:

  1. 打开第 4 条任务详情
  2. 填写一条新评论
  3. 提交评论
  4. 评论区立即出现这条评论
  5. 操作记录区同步出现一条评论协作记录
  6. 关闭再打开同一条任务详情后,这条评论在当前会话内仍然保留

这已经是一个很完整的小闭环了。


你现在真正应该学会什么?

学完这一课,你最应该记住的是下面 6 件事:

1. 详情抽屉里的业务区块不一定只能只读

它完全可以逐步升级成真正可操作的工作区。

2. "基础详情数据"和"运行时新增数据"最好分层

不要一上来就直接改基础 mock 或把所有东西搅在一起。

3. 输入框可以在展示组件里,但草稿状态不一定要放在展示组件里

这就是"受控组件"思路。

4. 一次评论提交,可能会同时影响多个区块

评论区和操作记录区这次就是联动关系。

5. 新增按任务挂载的运行时状态时,一定要考虑删除清理

否则后面页面会越来越脏。

6. 页面越复杂,测试定位器越要语义清晰、范围明确

否则稍微多一个按钮、多一段重复文案,E2E 就会开始误命中。

相关推荐
雪芽蓝域zzs3 小时前
vue解构平铺VS对象包裹
前端·javascript·vue.js
风骏时光牛马4 小时前
从零到实战,完整AI学习路线
前端
三十而立洋4 小时前
深入理解 Monorepo:子包安装依赖
前端·前端工程化
IT_陈寒4 小时前
Java Stream处理大集合,我的内存怎么就炸了
前端·人工智能·后端
Captaincc5 小时前
AI 用量桌面端-桌面宠物自定义指南
前端·人工智能
OpenTiny社区5 小时前
码力全开,智启前端新生态|OpenTiny 登陆华为全联接大会2026
前端·github
妙码生花5 小时前
利用AI从零学Go并完成实战项目,完工总结:目录结构
前端·后端·go
妙码生花5 小时前
利用AI从零学Go并完成实战项目,完工总结:商业级开源产品定位和核心特性介绍
前端·后端·go
Captaincc6 小时前
掘金AI用量统计v0.1.0大更新-支持桌面宠物自定义和订阅额度卡片
前端·后端
默_笙6 小时前
🚲 从写信到打电话:WebSocket 双工通信与跨域方案的"通信进化史"
前端·javascript