企业 Timesheet 前端

Odoo 企业版 Timesheet Grid 为什么不是“点个开始计时”:timer service、header field 与 UoM 同步讲透

Timesheet Grid 的计时能力并不是一个按钮,而是 timer service、响应式状态、字段元数据和工时单位显示一起配合的交互系统。

企业 前端
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 4 阅读

“开始计时”看起来像最简单的前端功能之一:点一下,开始跑秒;再点一下,提交结果。但企业版 Timesheet Grid 并不是这么做的。它用的是一套专门的 timesheet_timer 服务,把计时状态、字段元数据、项目/任务上下文和单位显示全部绑在一起。

主要参考:

  • enterprise/timesheet_grid/static/src/services/timesheet_timer_service.js
  • enterprise/timesheet_grid/static/src/hooks/use_timesheet_timer.js
  • enterprise/timesheet_grid/static/src/services/timesheet_grid_uom_service.js

一、timer service 的核心价值,是把状态提升为全局服务

timesheetTimerService 不是某个按钮组件内部的局部状态,而是注册到服务层的全局能力。它维护:

  • 当前是否有 running timer
  • 当前 timer 对应的 timesheet 数据
  • stepTimer
  • 相关 header fields 元数据
  • 事件总线 bus

这意味着无论计时按钮出现在 grid、kanban、list 还是顶部 header,大家都能消费同一份运行中状态。

二、开始/停止计时并不是纯前端行为

startTimer()stopTimer() 最终都会调 account.analytic.line 上的方法,比如 action_start_new_timesheet_timeraction_timer_stop。前端只是在包装调用与响应式更新。

这样设计的好处是:计时的真正事实仍在后端,前端只负责把它展示得连续、可操作。

三、header fields 元数据决定了计时表单能不能“懂业务”

服务里专门有 fetchTimerHeaderFields()getTimesheetTimerFieldInfo()。它会动态取 project_idtask_idname 等字段定义,再附加:

  • domain
  • placeholder
  • context
  • onChange
  • 是否必填

这让计时输入框不只是“把字段渲染出来”,而是能携带项目必须允许 timesheet、任务默认跟随项目、描述框给出业务语义提示等规则。

四、UoM 同步解决的是“同样一段时间,前端怎么显示”

Timesheet 系统里,用户可能看到小时、小数小时,甚至不同单位格式。如果没有专门的 UoM 服务,计时器、grid 单元格、header 显示就很容易口径不一致。

企业版把这件事抽出来,说明它非常重视“同一份计时事实,在不同组件里以一致单位表达”。

五、最容易踩坑的地方:不要把 running timer 当成页面内临时变量

如果你自己写一个组件,只在组件 state 里维护 timer,很快就会遇到:

  • 切视图后状态丢失
  • 另一个视图不知道计时已开始
  • 停止计时时上下文不一致
  • 工时单位显示不统一

官方服务化的做法,本质上就是在避免这些跨视图同步问题。

六、结论

Timesheet Grid 的计时体验之所以像“系统级功能”,不是因为按钮多漂亮,而是因为它把后端计时事实、前端响应式状态、字段元数据和单位显示整合到了同一个服务里。

所以它不是一个按钮,而是一套跨视图共享的前端计时基础设施。

DISCUSSION

评论区

想参与讨论?先 登录 再发表评论。
还没有评论,你可以成为第一个留言的人。