【考勤】考勤管理
考勤管理覆盖考勤规则、节假日、打卡记录、月度统计和请假审批。管理端由 yudao-module-hrm 的 attendance 包实现,员工端由 portal.attendance 包实现。
- 考勤设置:按部门或员工配置班次、特殊日期、打卡条件和扣款规则,并维护全局节假日。
- 打卡与统计:HR 可补录手工打卡,系统根据班次、节假日、打卡和有效请假实时计算日/月考勤。
- 请假审批:员工从 HRM 员工端提交请假,审批复用 BPM;管理端只查询、查看流程和导出。
本文涉及表如下图所示:
# 1. 考勤组
考勤组由 HrmAttendanceGroupController 提供接口。班次、特殊日期、地点、WiFi 和扣款规则都随考勤组整体保存,不建立独立业务表。
# 1.1 表结构
省略
creator/create_time/updater/update_time/deleted/tenant_id等通用字段。JSON 字段由 TypeHandler 完成对象转换。
CREATE TABLE `hrm_attendance_group` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '考勤组编号',
`name` varchar(50) NOT NULL COMMENT '考勤组名称',
`dept_ids` varchar(4000) DEFAULT NULL COMMENT '适用部门编号列表',
`employee_ids` varchar(4000) DEFAULT NULL COMMENT '适用员工编号列表',
`open_wifi_card` bit NOT NULL DEFAULT 0 COMMENT '是否启用 WiFi 打卡',
`open_point_card` bit NOT NULL DEFAULT 0 COMMENT '是否启用定位打卡',
`shifts` varchar(10000) NOT NULL COMMENT '班次配置 JSON',
`rest` bit NOT NULL DEFAULT 1 COMMENT '法定节假日是否休息',
`special_dates` varchar(4000) NOT NULL COMMENT '特殊日期 JSON',
`points` varchar(10000) NOT NULL COMMENT '打卡地点 JSON',
`wifis` varchar(10000) NOT NULL COMMENT '打卡 WiFi JSON',
`deduct_rule` varchar(4000) NOT NULL COMMENT '扣款规则 JSON',
`default_status` bit NOT NULL DEFAULT 0 COMMENT '是否默认考勤组',
PRIMARY KEY (`id`)
) COMMENT='HRM 考勤组';
① dept_ids 关联 system_dept.id,employee_ids 关联 hrm_employee.id。保存适用范围时,系统会从其它考勤组移除冲突的部门和员工。
② 员工按“显式员工 → 当前部门及最近父部门 → 默认考勤组”的顺序匹配。默认考勤组可以修改,但不能删除。
③ shifts 保存星期、上下班时点、允许打卡窗口和休息区间,支持跨日班次;special_dates 可把指定日期设为上班或休息。
④ deduct_rule 保存迟到、早退、旷工和缺卡的扣款方式。迟到、早退可按月、分钟或次数计算,旷工按天、缺卡按次数计算。
# 1.2 管理后台
对应 [HRM 人力资源 -> 考勤管理 -> 考勤设置 -> 考勤组设置] 菜单。
# 列表
列表由 @/views/hrm/attendance/config/group/index.vue 实现,通过 HrmAttendanceGroupController 的 GET /hrm/attendance/group/page 查询考勤组,展示名称、适用范围、打卡方式和是否默认组。页面可按名称筛选,并提供新增、修改和删除入口;默认考勤组的删除按钮不可用。

# 新增 / 修改
点击“新增”或“修改”打开同目录的 AttendanceGroupForm.vue。表单在一个 Dialog 中依次配置基本信息、适用部门/员工、班次、法定节假日、特殊日期、定位、WiFi 和扣款规则;班次与特殊日期使用表单内的编辑弹窗,不需要跳转其它菜单。

修改时先调用 GET /hrm/attendance/group/get 回显完整聚合;保存时分别调用 POST /hrm/attendance/group/create、PUT /hrm/attendance/group/update。表单要求至少启用定位或 WiFi 一种打卡方式,并校验地点、半径、SSID 和 MAC。保存成功后关闭弹窗并刷新列表。
# 删除
非默认考勤组可在确认后调用 DELETE /hrm/attendance/group/delete 逻辑删除。默认考勤组承担未匹配员工的兜底规则,因此后端也会拒绝删除。
# 2. 节假日
节假日由 HrmAttendanceHolidayController 提供接口,用于维护全局上班日和休息日。
# 2.1 表结构
CREATE TABLE `hrm_attendance_holiday` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`date` datetime NOT NULL COMMENT '日期',
`type` tinyint DEFAULT 2 COMMENT '日期类型:1 上班、2 休息',
PRIMARY KEY (`id`)
) COMMENT='HRM 考勤节假日';
实际班次按“考勤组特殊日期 → 全局节假日 → 每周班次”的优先级解析。补班日没有命中星期班次时,使用考勤组第一条班次。
# 2.2 管理后台
对应 [HRM 人力资源 -> 考勤管理 -> 考勤设置 -> 节假日设置] 菜单。
# 列表
列表由 @/views/hrm/attendance/config/holiday/index.vue 实现,通过 HrmAttendanceHolidayController 的 GET /hrm/attendance/holiday/page 查询数据,可按日期范围和日期类型筛选。
# 新增 / 修改
点击“新增”或“修改”打开同目录的 AttendanceHolidayForm.vue,维护日期和“上班/休息”类型。修改时调用 GET /hrm/attendance/holiday/get 回显,保存时分别调用 POST /hrm/attendance/holiday/create、PUT /hrm/attendance/holiday/update。
# 删除
确认后调用 DELETE /hrm/attendance/holiday/delete 删除节假日。删除后,该日期重新按考勤组的特殊日期或每周班次解析。
# 3. 打卡记录
打卡记录由 HrmAttendanceClockController 提供接口,保存员工实际打卡、应打卡时点、来源和考勤结果。
# 3.1 表结构
CREATE TABLE `hrm_attendance_clock` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '打卡记录编号',
`employee_id` bigint DEFAULT NULL COMMENT '员工编号',
`clock_time` datetime NOT NULL COMMENT '实际打卡时间',
`type` tinyint NOT NULL COMMENT '打卡类型:1 上班、2 下班',
`attendance_time` datetime NOT NULL COMMENT '应打卡时间',
`source_type` tinyint DEFAULT 2 COMMENT '来源:1 手机端、2 手工录入',
`status` tinyint DEFAULT 0 COMMENT '状态:0 正常、1 迟到、2 早退、3 缺卡',
`stage` int DEFAULT 1 COMMENT '打卡阶段,当前仅第一段',
`address` varchar(255) DEFAULT NULL COMMENT '打卡地址',
`longitude` decimal(10,6) DEFAULT NULL COMMENT '经度',
`latitude` decimal(10,6) DEFAULT NULL COMMENT '纬度',
`ssid` varchar(50) DEFAULT NULL COMMENT 'WiFi 名称',
`mac` varchar(50) DEFAULT NULL COMMENT 'WiFi MAC 地址',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`)
) COMMENT='HRM 打卡记录';
① employee_id 关联 hrm_employee.id;attendance_time 是班次应打卡时点,也是判断迟到、早退和跨日归属的依据。
② 管理端补录时,后端固定 source_type = 2、stage = 1,并根据 clock_time 和 attendance_time 计算状态,前端不能自行指定这些生命周期字段。
③ 只有手工录入记录允许修改和删除;来源为手机端的历史记录在管理端只读。
# 3.2 管理后台
对应 [HRM 人力资源 -> 考勤管理 -> 打卡记录] 菜单。
# 打卡概况
@/views/hrm/attendance/clock/AttendanceClockOverview.vue 以员工和日期矩阵展示月度打卡概况。点击日期单元格打开 AttendanceClockDailyDetail.vue,查看当天应打卡时点、实际打卡和考勤状态。
概况数据来自 HrmAttendanceStatisticsController 的 GET /hrm/attendance/statistics/month-daily-page 和 GET /hrm/attendance/statistics/daily-detail,因此与月度汇总使用同一套实时统计口径。

# 打卡明细与导出
@/views/hrm/attendance/clock/AttendanceClockRecordList.vue 调用 GET /hrm/attendance/clock/page 查询明细,可按员工、部门和打卡时间等条件筛选;点击“导出”调用 GET /hrm/attendance/clock/export-excel 导出当前条件下的数据。
# 补录 / 修改
点击“新增”或手工记录的“修改”打开 AttendanceClockForm.vue。选择员工、打卡类型和日期后,表单调用 GET /hrm/attendance/clock/get-shift 获得当天应打卡时点及允许窗口;没有有效班次,或打卡时间不在允许窗口内时不能提交。

新增调用 POST /hrm/attendance/clock/create,修改先由 GET /hrm/attendance/clock/get 回显,再调用 PUT /hrm/attendance/clock/update。修改时员工不可更换,保存后月度统计会按新记录实时重算。
# 删除
单条删除和批量删除分别调用 DELETE /hrm/attendance/clock/delete、DELETE /hrm/attendance/clock/delete-list。只有手工录入的数据允许删除,删除后对应日期和月份的统计结果随之变化。
# 4. 月度考勤统计
月度统计由 HrmAttendanceStatisticsController 提供接口,不建立月度结果表。系统按月份加载员工、考勤组、节假日、打卡和审批通过的请假,实时计算出勤、迟到、早退、缺卡、旷工、请假和扣款。
# 4.1 管理后台
对应 [HRM 人力资源 -> 考勤管理 -> 月度汇总] 菜单。
# 月度汇总
列表由 @/views/hrm/attendance/month/index.vue 实现,通过 GET /hrm/attendance/statistics/month-record-page 按月份、员工、工号、部门和是否全勤筛选。点击“导出”调用 GET /hrm/attendance/statistics/month-record-export-excel。

# 员工月度详情
点击员工姓名进入 @/views/hrm/attendance/month/detail/index.vue。页面调用 GET /hrm/attendance/statistics/month-detail 展示出勤概况和每日状态日历;点击具体日期后,再调用 GET /hrm/attendance/statistics/daily-detail 查看班次、打卡和请假明细。
实时计算
统计不是归档快照。修改考勤组、节假日、手工打卡或请假审批结果后,重新查询历史月份也可能得到不同结果。
# 5. 请假与 BPM 审批
请假由 HrmAttendanceLeaveController 提供管理端查询接口,员工申请由 HrmPortalAttendanceLeaveController 提供接口,审批任务和流程记录复用 BPM。
# 5.1 表结构
CREATE TABLE `hrm_attendance_leave` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '请假记录编号',
`employee_id` bigint NOT NULL COMMENT '员工编号',
`type` varchar(64) DEFAULT NULL COMMENT '请假类型',
`start_time` datetime DEFAULT NULL COMMENT '开始时间',
`end_time` datetime DEFAULT NULL COMMENT '结束时间',
`day` decimal(10,2) DEFAULT NULL COMMENT '请假天数',
`reason` varchar(300) DEFAULT NULL COMMENT '请假理由',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
`approval_status` tinyint NOT NULL COMMENT 'BPM 流程状态',
`process_instance_id` varchar(64) DEFAULT NULL COMMENT 'BPM 流程实例编号',
`approval_time` datetime DEFAULT NULL COMMENT '审批结束时间',
`approval_reason` varchar(500) DEFAULT NULL COMMENT '审批或取消原因',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_hrm_attendance_leave_process_instance_id` (`process_instance_id`)
) COMMENT='HRM 请假记录';
① employee_id 关联员工;id 同时作为 BPM businessKey,流程定义 Key 固定为 hrm_attendance_leave。
② approval_status 直接使用 BPM 状态:1 审批中、2 审批通过、3 审批不通过、4 已取消。只有审批通过的时间段参与考勤统计。
③ 发起前会拒绝与本人审批中或已通过申请重叠的时间;创建顺序为写入 HRM 记录、发起 BPM、回写流程实例编号。
状态流转
员工提交 -> 审批中(1) -> 审批通过(2) -> 参与考勤统计
\-> 审批不通过(3)
\-> 本人取消(4)
HrmAttendanceLeaveStatusListener 只监听 hrm_attendance_leave 流程,并将终态和审批意见回写业务表。
# 5.2 管理后台
对应 [HRM 人力资源 -> 考勤管理 -> 请假记录] 菜单。管理后台只提供查询、流程详情和导出,不提供新增、修改或删除。
# 查询与导出
列表由 @/views/hrm/attendance/leave/index.vue 实现,通过 HrmAttendanceLeaveController 的 GET /hrm/attendance/leave/page 按月份、员工、部门、请假类型和审批状态查询;点击“导出”调用 GET /hrm/attendance/leave/export-excel。

# 查看审批进度
存在 process_instance_id 时,列表提供“审批进度”操作,进入 BPM 流程详情查看节点、处理人和意见。业务详情由 AttendanceLeaveProcessDetail.vue 展示,并通过 GET /hrm/attendance/leave/get 读取请假数据。
# 5.3 员工端
对应 [HRM 人力资源 -> HRM 员工端 -> 考勤报表] 菜单。
# 查看考勤
页面由 @/views/hrm/portal/attendance/report/index.vue 实现,使用 AttendanceCalendar.vue 展示本人月度汇总和每日打卡;数据分别来自 HrmPortalAttendanceStatisticsController 的 GET /hrm/portal/attendance/statistics/month-detail,以及 HrmPortalAttendanceClockController 的 GET /hrm/portal/attendance/clock/list。

# 提交请假
点击“请假申请”打开 @/views/hrm/portal/attendance/leave/AttendanceLeaveForm.vue,填写请假类型、开始时间、结束时间、天数、理由和备注。表单校验结束时间晚于开始时间后,调用 POST /hrm/portal/attendance/leave/create 发起 BPM 流程,成功后刷新考勤和申请列表。

# 查看 / 取消申请
AttendanceLeaveList.vue 调用 GET /hrm/portal/attendance/leave/list 查询本人申请,并可进入流程详情。只有“审批中”的申请显示取消按钮;填写取消原因并确认后,调用 PUT /hrm/portal/attendance/leave/cancel,BPM 和 HRM 记录同步变为已取消。
当前不提供在线打卡
员工端只查看已有打卡,没有创建打卡接口和打卡按钮。考勤组中的定位、WiFi 及允许窗口仍会完整保存,但当前只用于规则配置;source_type = 1 仅保留“手机端来源”的数据语义。