ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Super Productivity 工时记录(Worklog)机制全解析:从时间追踪到历史视图、校正与 CSV 导出

Super Productivity 工时记录(Worklog)机制全解析:从时间追踪到历史视图、校正与 CSV 导出 Super Productivity 工时记录Worklog机制全解析从时间追踪到历史视图、校正与 CSV 导出【免费下载链接】super-productivitySuper Productivity is an advanced todo list app with integrated Timeboxing and time tracking capabilities. It also comes with integrations for Jira, GitLab, GitHub and Open Project.项目地址: https://gitcode.com/GitHub_Trending/su/super-productivityWorklog工时记录是 Super Productivity 中查看某天在某项任务上花了多长时间的统一视图它并非独立存储而是由任务上的每日耗时timeSpentOnDay数据实时重组生成。本文围绕 docs/wiki/4.21-Worklog.md 展开结合仓库源码src/app/features/history与src/app/features/worklog讲解其数据来源、层级构建、防重复计数、时区安全、刷新机制以及按项目/日期范围过滤的 CSV 导出与内联纠错读完即可熟练使用 History含旧版worklog、quick-history路由与每日摘要完成回顾、修正与导出。一个 Worklog 条目代表什么一条worklog 条目是工时记录中某一具体日期上的一行它将任务与该日花费的时间绑定。构建工时记录时任务上每日耗时timeSpentOnDay中的每一天都会变成一条或数条记录——即这个任务、在这一天、耗时多少。子任务可以关联到父任务使其在列表中紧跟在父任务之下显示应用还会记录某条目是否应从某些恢复操作中排除内部细节不影响日常使用。从用户视角看Worklog 就是一张任务—日期—时长行组成的列表按日分组再按月和年或按周展示。数据结构在 worklog.model.ts 中定义WorklogDay单日数据含timeSpent当日总耗时、logEntries条目列表、dateStr日期字符串、dayStr本地化日期标签、workStart/workEnd当日工作起止时间可选WorklogMonth含timeSpent、daysWorked工作天数、按日索引的ent以及weeks周数组WorklogYear含timeSpent、monthWorked有记录月份数、daysWorked及按月的entWorklog整个工时记录顶层结构按键为年份。Worklog 由时间追踪数据生成而非独立存储Worklog不是一套单独的时间存储。它由两部分数据计算而来活动任务——当前工作上下文中的任务列表以及每个任务上的timeSpentOnDay就是任务上显示今天 30m或2h的那份数据归档任务——被移入归档但仍保留时间追踪数据的任务。应用会为当前上下文同时加载活动任务与归档任务再从中构建工时记录因此你能看到完整历史而不仅限于当前任务。这一点在 worklog.service.ts 的_loadWorklogForWorkContext中体现它调用TaskArchiveService.load()加载归档读取任务特性状态再通过getCompleteStateForWorkContext将两者合并成一个完整状态后交给mapArchiveToWorklog变换。变换流程mapArchiveToWorklog核心实现位于 map-archive-to-worklog.ts其变换逻辑遍历每个任务及其timeSpentOnDay映射中的每一天构建层级——年 → 月 → 日周视图则为 年 → 周 → 日。每个日节点包含条目列表与当日总耗时放置子任务——当任务存在父任务时其条目被插入到父任务或兄弟任务之后使列表反映层级关系对应 history.component.html 中展开某天后逐条渲染logEntries的结构使用本地化与工作时间——日期标签使用你的 locale若配置了工作开始/结束时间在日级行会显示workStart/workEnd聚合且不重复计数——只有叶子任务无子任务的任务的耗时计入日/月/年合计。源码中if (task.subTaskIds.length 0)分支才累加day.timeSpent、month.timeSpent、year.timeSpent与totalTimeSpent父任务自身的每日耗时不会叠加在子任务时间之上因此总数不会被夸大。缺失数据的兜底默认值如果任务没有每日耗时如旧数据或边界情况map-archive-to-worklog.ts 的_getTimeSpentOnDay会施加默认值以保证任务仍出现在列表中子任务继承父任务timeSpentOnDay的第一个日期若父任务也无记录则回退到父任务的完成日期doneOn或创建日期created其他任务使用自身创建或完成日期配以 1最小时长单位的耗时。这样 Worklog 不会漏掉应当可见的任务。此外子任务仅在timeSpentForTask 0时才插入条目见mapArchiveToWorklog中if (task.parentId)分支避免零耗时子任务刷屏。时区安全日期比较使用日期字符串如YYYY-MM-DD由getDbDateStr生成而非原始时钟时间因此时区或夏令时变化不会把时间偏移到错误的日期。在 worklog.service.ts 的getTaskListForRange$中范围过滤同样使用rangeStartStr/rangeEndStr字符串比较dateStr也直接作为层级 key 参与mapArchiveToWorklog的年/月/日拆分。专门的时区测试位于 worklog.service.timezone.spec.ts 与 map-archive-to-worklog.tz.spec.ts。条目排序每日条目在构建后还会经过 sort-worklog-entries.ts 处理父任务按标题字母序忽略大小写排序子任务紧跟在各自父任务之后并按字母序排列若某日子任务存在但父任务当天没有条目孤儿子任务则统一追加在末尾。这样展开某天时任务按标题组织且父子关系清晰。何时刷新进入视图或手动触发Worklog不会在你计时过程中持续更新。它的刷新时机如下见 worklog.service.ts 的_archiveUpdateTrigger$导航到 History 视图或旧版worklog/quick-history路由时导航到每日摘要daily-summary或指标metrics页面时手动触发refreshWorklog()内联纠错后也会调用时。上述触发器通过合并导航事件与手动触发器archiveUpdateManualTrigger$驱动worklogData$重新加载。如果你刚结束计时想看到最新数据需要打开对应视图或手动刷新一次。源码注释也明确标注任务更新不会自动反映到已加载的 Worklog 中NOTE: task updates are not reflected。统一视图与旧路由History 视图是唯一入口旧版worklog与quick-history路由都指向同一组件。在 context.routes.ts 中history、worklog、quick-history三个路径均映射到HistoryComponentdata: { page: history }项目与标签上下文共享这套路由每日摘要daily-summary含daily-summary/:dayStr深链与metrics也在同一路由表内。界面形态年—月—周—日四级折叠history.component.html 展示了 History 视图的完整布局顶部为总耗时totalTimeSpent与导出全部按钮exportAllData()年份层显示有记录月数monthWorked、工作天数daysWorked与年度总耗时可展开各月月份层显示工作天数与月度总耗时每个月份带独立的导出按钮exportData(year.key, month.key)周层按月内周次weekNr列出显示周耗时与daysWorked每周也有导出按钮周的起止日期由getDateRangeForWeek与getWeeksInMonth计算日层显示本地化日期标签dayStr、工作区间workStart–workEnd按HH:mm格式化、条目数量与当日耗时展开后呈现history-day-meta当日简易计数器等元信息与任务汇总表。默认自动展开当前月expandedMonths初始化为当前年月且支持通过 URL 的dateStr查询参数深链定位并自动展开对应日与所在月见 history.component.ts 构造器中的effect。内联校正与父行只读叶子任务行可内联纠错history.component.ts 的updateTimeSpentTodayForTask通过TaskService.updateEverywhere更新该任务当天的timeSpentOnDay[dateStr]随后调用refreshWorklog()刷新视图。修正后的值会反映到 History、报告与指标中。父任务行只读父任务显示的是子任务合计不允许直接编辑从而避免重复计数。归档任务查看与恢复点击条目可打开归档任务详情DialogViewArchivedTaskComponent对未排除恢复的顶层归档任务可确认后通过TaskSharedActions.restoreTask恢复到今天并自动跳转到任务列表。导出全部历史、单月或单周导出入口有三个见 history.component.ts导出全部exportAllData收集 Worklog 中所有日期的dateStr取最早与最晚作为范围打开导出对话框导出单月exportData(year, month)由getDateRangeForMonth计算范围导出单周exportData(year, month, week)由getDateRangeForWeek计算范围。导出对话框由 dialog-worklog-export.component.ts 承载内置 worklog-export.component.ts 完成配置与生成。过滤选项项目过滤可限定单个项目projectId日期范围过滤按rangeStart/rangeEnd过滤排除范围外时间isFilterOutTimeSpentOnOtherDays选项会把任务timeSpentOnDay中落在范围之外的日期剔除后再导出确保只包含所选区间内的时间实现见 worklog.service.ts 的getTaskListForRange$。CSV 细节与安全处理CSV 输出使用分号作为分隔符并安全引号化含分号、引号或换行的字段worklog-export.util.ts 的escapeCsvField字段含;、、\r、\n时用双引号包裹内部引号以转义针对 CSV 注入做了防护以、、-、、TAB、CR、LF 开头的字段会被前缀避免 Excel/LibreOffice 将其当作公式执行源码注释明确引用 OWASP CSV injection而零时长占位符-保持原样表头固定为英文Date / Start / End / Titles / Parent Titles / Descriptions / Projects / Tags / Worked / Estimate不随界面语言变化便于脚本消费。列类型与分组方式可导出列WorklogColTypes包括DATE、START、END、TITLES父任务标题、TITLES_INCLUDING_SUB含子任务的完整标题、NOTES、PROJECTS、TAGS、TIME_MS/TIME_STR/TIME_CLOCK耗时毫秒/可读/时钟格式以及ESTIMATE_MS/ESTIMATE_STR/ESTIMATE_CLOCK估算时间。分组方式WorklogGroupingDATE按日期分组PARENT按父任务分组忽略子任务TASK按任务分组忽略父任务WORKLOG完全不分组每行即任务 日期 时长clearRepeatedWorklogDayTimes会清掉重复日期的开始/结束时间使其仅在每日首行出现。当按WORKLOG分组时任务的估算时间会按各日在总耗时中的占比摊分到每一天。默认导出配置默认设置定义在 work-context.const.ts 的WORKLOG_EXPORT_DEFAULTS配置项默认值cols[DATE, START, END, TIME_CLOCK, TITLES_INCLUDING_SUB]roundWorkTimeTonull不取整roundStartTimeTo/roundEndTimeTonullseparateTasksBy | 同一导出字段中多个任务值之间的分隔文本groupByDATE时间取整roundWorkTimeTo等通过roundDuration/roundTime实现可配置为精确或按 5/15/30 分钟等粒度取整开始/结束时间按HH:mm格式化输出。小结Worklog 按日期组织的视图年 → 月 → 日或年 → 周 → 日内容为任务的每日耗时每条记录 任务 日期 时长数据来源——由当前工作上下文的活动任务与归档任务构建无独立 Worklog 存储合计——只有叶子任务计入日/月/年合计避免重复计数刷新——进入 History或旧版worklog/quick-history路由、每日摘要或手动刷新时更新计时过程中不会实时刷新编辑——叶子任务时间可内联纠错父任务合计只读导出——可导出完整历史或单个月/周支持按项目与日期范围过滤并可选择排除范围外时间CSV 以分号分隔并安全转义默认配置见WORKLOG_EXPORT_DEFAULTS。延伸阅读4.14-How-Time-Is-Logged —— 每日耗时timeSpentOnDay如何被记录到任务上Worklog 数据的源头4.20-Task-Archiving —— 归档任务及其时间如何被纳入 Worklog 构建history.component.ts 与 history.component.html —— History 视图组件实现worklog.service.ts —— Worklog 加载、刷新与范围过滤服务map-archive-to-worklog.ts —— 层级构建、防重复计数与默认值核心变换worklog-export.util.ts —— 导出行列生成、CSV 转义与公式注入防护【免费下载链接】super-productivitySuper Productivity is an advanced todo list app with integrated Timeboxing and time tracking capabilities. It also comes with integrations for Jira, GitLab, GitHub and Open Project.项目地址: https://gitcode.com/GitHub_Trending/su/super-productivity创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进