培训
培训课程(书面、PDF 或 YouTube 视频)、测验题、用户组分配、外部培训、按周期的完成跟踪,以及每周提醒摘要。
培训管理必修课程、员工组分配和完成记录。培训课程包含书面内容、PDF 或 YouTube 视频,以及测验。在 Carbon 之外完成的培训是只有名称的外部培训分配,由管理员标记完成。Carbon 跟踪每位员工在每个周期的完成情况,为未完成的分配发送每周提醒,并允许经理记录手工完成。培训属于资源区域,使用 resources 权限。
例如,创建一项类型为 "Mandatory"(必修)、频率为 "Annual"(每年) 的「上锁挂牌」培训,然后分配给「机加工」组。组内每名成员在当年完成前都保持 "Pending"(待完成),未完成期间每周日收到提醒。
培训目录
每项培训是 training 表中的一行(packages/database/supabase/migrations/20251205021915_training.sql:18)。创建表单只要求名称(apps/erp/app/modules/resources/ui/Training/TrainingForm.tsx:76)。其余字段在属性面板中配置(apps/erp/app/modules/resources/ui/Training/TrainingProperties.tsx),每次更改通过批量更新操作保存。
content)。员工在回答问题前阅读。状态枚举是培训记录上的简单线性生命周期——不要与下文员工的完成状态混淆。
从页面页头更改状态:草稿培训显示 Publish(发布),已启用显示 Archive(归档),在 ⋯ 菜单中选择 Reopen(重新打开) 会移回草稿。每一步都会要求确认。
只有草稿培训可以修改
内容、PDF、视频和问题仅在培训为 "Draft" 时可编辑;服务器拒绝在任何其他状态更改 PDF 或视频(apps/erp/app/routes/x+/training+/update.tsx)。员工只能打开并完成 "Active" 培训。要修改已发布培训,请先重新打开。
书面内容、PDF 或视频
培训内容有三种之一,通过 Content(内容) 卡片上的 Write | Upload PDF | YouTube Video(编写 | 上传 PDF | YouTube 视频) 切换选择:
- 编写: 在编辑器中输入材料。
- 上传 PDF: 上传一个 PDF,适合培训材料已是文档的工厂。Replace(替换) 可更换(
apps/erp/app/modules/resources/ui/Training/TrainingGuide.tsx)。 - YouTube 视频: 粘贴一个 YouTube 视频链接(
youtube.com/watch、youtu.be、Shorts 或直播链接)。Carbon 保存为视频观看链接;Change(更换) 可替换(apps/erp/app/modules/resources/ui/Training/TrainingVideo.tsx)。Carbon 不托管视频文件。
培训有 PDF 时员工在查看器中看到 PDF,有视频时在 YouTube 播放器中看到视频,两者都没有时看到书面内容。要切换到另一种类型,在切换器中选择;Carbon 在移除 PDF 或视频前会询问。三者都只在培训为草稿时才能更改。
测验问题
培训可以带测验。每个问题是 trainingQuestion 中的一行(20251205021915_training.sql:229),归属于一个培训,按 sortOrder 排序,并标记是否 required(必答)。Carbon 支持五种题型(apps/erp/app/modules/resources/resources.models.ts:343):
correctBoolean。correctNumber 在 tolerance 范围内判分。问题在培训详情页编写,可以重新排序。存储的答案键列因类型而异:选择题使用 options 和 correctAnswers,判断题使用 correctBoolean,配对题使用 matchingPairs,数值题使用 correctNumber / tolerance(20251205021915_training.sql:229)。
向用户组分配培训
培训分配给用户组,而不是单个员工。一条 trainingAssignment(20251205021915_training.sql:93)把一个 trainingId 链接到 groupIds 数组。这些组中的所有员工都会收到分配。
新分配分为内部或外部。内部分配从目录中选择培训。外部分配只有名称,如下所述。
分配针对用户组,再展开到人
分配存储 groupIds,而不是员工 ID。Carbon 在计算谁欠这项培训时把组展开为成员,因此向组中添加人员会自动纳入——无需重新分配。
在列表中点击分配可打开其名册:每名成员及其当前状态、完成日期(如已完成)和 "Mark Complete"(标记完成) 按钮(apps/erp/app/routes/x+/resources+/assignments.$assignmentId.tsx)。行菜单中的 Edit Assignment(编辑分配) 可修改名称或用户组。分配内部培训还会向新覆盖的员工发送通知(参见通知)。
外部培训
有些培训在 Carbon 之外进行,例如外部供应商的叉车课程。创建外部分配,填写课程名称和所属用户组。Carbon 不为其存储培训记录(trainingAssignment.name,20261014164752_external-training-assignments.sql),因此没有内容、测验或频率。它是一次性的:每名员工为 "Pending" 或 "Completed"。
- 没有员工页面,也没有通知。 员工不会收到通知或提醒,也无法打开它。
- 由管理员完成: 在名册上,Mark Complete 可以附上员工的证书(一个 10 MB 以内的 PDF、PNG 或 JPG)。证书可选。HEIC 格式的手机照片会在上传时转换为 JPEG。
- 凭证: 带证书的已完成行会在名册和该人员的培训卡片上显示 View Certificate(查看证书)。
分配列表在这些行上显示 External(外部) 标记。
完成与状态
完成记录保存在 trainingCompletion 中(20251205021915_training.sql:156)——每名员工、每个分配、每个周期一行,带 completedAt 时间戳和 completedBy。对于循环培训,该行还带 period 字符串,唯一约束防止同一员工同一周期被重复记录。
周期是循环逻辑的核心(20251206000000_training_assignments.sql)。Carbon 根据培训频率推导当前周期:
NULL)。完成一次即永久完成。Q1-2026 的字符串。一个季度的完成不会带入下一季度。2026 的字符串。每年开始时重置。员工状态是计算出来的,不是存储的——Carbon 根据当前周期是否存在完成记录以及员工入职时间求值。共有四种可能值(apps/erp/app/modules/resources/resources.models.ts:318):
新员工不会被追溯为逾期
循环培训会把员工入职日期与周期比较。在过去的周期关闭后入职的人,该周期显示 "Not Required"(无需完成),而不是 "Overdue"(已逾期)——因此新员工入职时不会立刻被标红。
经理从分配名册点击 "Mark Complete" 标记完成;Carbon 在服务器端计算当前周期(recordTrainingCompletion,apps/erp/app/modules/resources/resources.server.ts)。已 "Completed" 或 "Not Required" 的员工没有按钮——没有可标记的内容。
要撤销错误的完成,名册上的 "Remove Completion"(移除完成) 会删除记录,员工回到 "Pending"(或 "Overdue")。它需要 resources_delete 权限,并会删除附加的证书文件。培训授予的任何能力仍保留在员工身上;如需要,请在其能力页面移除。
每周提醒
每周日 21:00 UTC,定时任务查找未完成的培训(packages/jobs/src/inngest/functions/scheduled/weekly.ts,cron 0 21 * * 0)。它选择 "Pending" 和 "Overdue" 分配,并向每名员工发送一份摘要。
通知是 Training 主题下的 TrainingReminder 事件(training-reminder)。其邮件标题为 "Training reminder"(培训提醒),行动按钮为 "View training"(查看培训)(packages/notifications/src/index.ts)。这是 Carbon 中唯一循环的通知事件——因此需要防止永远打扰。
每个周期发送五次后提醒停止
循环提醒有上限:某项未完成培训在当前周期成功投递五封提醒邮件后,Carbon 停止再发。季度和年度培训的计数按周期建键,因此新周期开始时上限重置。如果提醒「突然不来了」,通常就是这个上限。
两个一次性事件会通知分配:"Training assigned to you"(分配给你的培训)(training-assignment)和 "New training available"(有新培训)(resource-training-assignment)。投递方式和偏好参见通知。
培训可以授予能力
能力是员工对某道工艺的资格。培训可以授予一项能力:在属性中设置 Grants Ability(授予能力),完成培训会把该能力添加到员工(grant_ability_on_training_completion,packages/database/supabase/migrations/20260720121629_capacity-planning.sql:264)。排程器和车间使用能力决定谁可以运行该工艺。
培训是授予能力的一种方式;经理也可以在人员的能力页面手工添加。移除培训完成记录不会移除能力。
每道要求能力的工艺决定无能力操作员在车间只是被警告还是被阻止;参见要求能力。