Skip to main content

考勤管理系统设计

📌 重要说明:对标企业微信/钉钉考勤标准

本系统参考企业微信钉钉的考勤管理标准,实现企业级考勤管理解决方案。

系统核心特点

  • 标准化流程:对标主流平台的审批流程和规则
  • 智能统计:自动化考勤统计和月度汇总
  • 多端支持:Web端 + 移动端(预留接口)
  • 灵活配置:考勤规则、节假日、审批流程可配置
  • 完善报表:个人/部门/异常多维度报表

技术栈

  • 后端:Spring Boot 2.7.x + MyBatis-Plus 3.5.x + Spring Security + JWT
  • 前端:Vue 3 + Element Plus + TypeScript + Pinia
  • 数据库:MySQL 8.0 + Redis 6.0
  • 定时任务:Quartz 2.3.x
  • 工具库:Hutool、Lombok、MapStruct

补卡规则说明(参考钉钉/企业微信):

  • 每月最多补卡3次(可配置2-5次)
  • 只能补最近7天内的打卡
  • 补卡次数按月统计,每月1号重置

一、项目概述

1.1 项目背景

随着企业信息化建设的深入,传统的人工考勤方式已无法满足现代企业管理需求。本系统旨在提供一套完整的、自动化的考勤管理解决方案,对标企业微信和钉钉的考勤标准,实现考勤打卡、请假出差、审批流转、统计报表等全流程管理。

1.2 设计目标

业务目标

  • 智能化:自动计算考勤统计,智能识别异常
  • 标准化:对标企业微信/钉钉审批流程标准
  • 可视化:直观的日历视图和图表展示
  • 移动化:支持多端打卡(预留接口)

技术目标

  • 高性能:支持千人级并发打卡
  • 高可用:7×24小时稳定运行
  • 易扩展:模块化设计,便于功能扩展
  • 易维护:清晰的代码结构和文档

1.3 核心功能

功能模块核心功能用户角色
考勤打卡上下班打卡、位置记录、异常标记全员
请假管理请假申请、审批流转、自动扣除考勤全员、审批人
出差管理出差申请、审批流转、出差期间免打卡全员、审批人
补卡管理补卡申请、审批后自动更新打卡记录全员、审批人
考勤统计日/月统计、自动计算工作时长全员
考勤报表个人报表、部门报表、异常报表管理员、部门主管
规则配置考勤规则、工作时间、节假日配置管理员

1.4 用户角色

1.5 核心价值

价值点说明预期效果
🎯 提升效率自动化考勤统计,减少HR工作量人力成本降低 50%
📊 数据准确实时打卡记录,避免人工错误数据准确率达 99.9%
🔄 流程规范标准化审批流程,透明可追溯审批效率提升 60%
📈 决策支持多维度报表,辅助管理决策决策效率提升 40%

二、系统架构设计

2.1 总体架构

2.2 技术选型

后端技术栈

技术版本用途
Spring Boot2.7.x应用框架
Spring Security5.7.x安全认证
MyBatis-Plus3.5.xORM框架
MySQL8.0+关系数据库
Redis6.0+缓存/分布式锁
Quartz2.3.x定时任务
MapStruct1.5.5对象映射
JWT-Token认证
Druid1.2.x数据库连接池

前端技术栈

技术版本用途
Vue.js3.x前端框架
Element Plus2.xUI组件库
Axios1.xHTTP客户端
Pinia2.x状态管理
Vue Router4.x路由管理
ECharts5.x图表展示

2.3 分层架构设计

表现层(Presentation Layer)

  • 职责:用户交互、数据展示、表单验证
  • 组件:Vue组件、Element Plus
  • 特点:响应式设计、前后端分离

业务逻辑层(Business Logic Layer)

  • 职责:业务规则、流程控制、数据校验
  • 组件:Service服务、业务逻辑处理
  • 特点:事务管理、异常处理

数据访问层(Data Access Layer)

  • 职责:数据CRUD、SQL执行
  • 组件:Mapper接口、MyBatis XML
  • 特点:SQL优化、连接池管理

数据转换层(Converter Layer)

  • 职责:对象转换、数据映射
  • 组件:MapStruct接口
  • 特点:编译时生成、高性能

2.4 核心设计原则

  1. 分层解耦:严格按照MVC模式分层,降低耦合度
  2. 单一职责:每个类/方法只负责一个功能
  3. 开闭原则:对扩展开放,对修改关闭
  4. 依赖倒置:面向接口编程,而非具体实现
  5. 里氏替换:子类可以替换父类
  6. 最少知识:类之间减少依赖关系

三、功能模块设计

3.1 考勤打卡模块

功能描述

员工通过系统进行上下班打卡,系统自动记录打卡时间、地点、方式,并判断是否正常。

业务规则

流程设计

数据流向

1员工打卡 → 打卡记录表 → 实时统计 → 考勤统计表 → 月度汇总

3.2 请假管理模块

功能描述

员工提交请假申请,审批人审批,审批通过后自动计算考勤统计,扣除相应考勤天数。

请假类型

类型代码扣除考勤需要证明
事假1
病假2建议提供病假条
年假3
调休4
婚假5需要结婚证
产假6需要医院证明
丧假7需要相关证明

审批流程

业务规则

  1. 状态流转

    • 只有"待审批"状态才能审批或撤回
    • 审批后不可修改
    • 撤回后不可恢复
  2. 权限控制

    • 只有申请人本人可以撤回
    • 只有指定审批人可以审批
    • 管理员可以查看所有申请
  3. 考勤影响

    • 审批通过后次日自动校准考勤
    • 请假期间不计入迟到/早退
    • 扣除相应的应出勤天数

3.3 出差管理模块

功能描述

员工提交出差申请,审批通过后出差期间免打卡,不影响考勤统计。

业务规则

3.4 补卡管理模块

功能描述

员工因特殊原因忘记打卡,可提交补卡申请,审批通过后自动创建打卡记录。

核心流程

业务规则

  1. 补卡限制(参考钉钉/企业微信标准)

    • 补卡次数:每月最多补卡3次(可配置为2-5次)
    • 补卡时效:只能补最近7天内的打卡
    • 补卡类型:可以补上班卡或下班卡
    • 补卡场景
      • ✅ 忘记打卡(缺卡)
      • ✅ 打卡失败(系统故障)
      • ✅ 位置异常打卡(需要修正)
      • ❌ 已有正常打卡记录,不能重复补卡
    • 次数统计:补卡次数按月统计,每月1号重置
  2. 补卡校验规则

    java
    1// 补卡前置校验
    21. 检查当月已补卡次数 < 3次(或配置值)
    32. 检查补卡日期在最近7天内
    43. 检查该时段是否已有正常打卡记录
    54. 检查是否在工作日(节假日不允许补卡)
    65. 检查是否有请假/出差记录(有则不能补卡)
  3. 审批后处理

    • ✅ 自动创建打卡记录
    • ✅ 标记打卡来源为"补卡"
    • ✅ 累加当月补卡次数
    • ✅ 重新计算当日考勤统计
    • ✅ 更新月度汇总数据

3.5 考勤统计模块

功能描述

自动统计员工每日、每月考勤数据,包括出勤天数、迟到次数、工作时长等。

统计维度

计算规则

应出勤天数计算

1应出勤天数 = 当月总天数 - 周末天数 - 法定节假日天数 + 调休补班天数

实际出勤天数计算

1实际出勤天数 = 正常打卡天数 + 出差天数 + 年假天数 + 其他不扣除考勤的假期

出勤率计算

1出勤率 = (实际出勤天数 / 应出勤天数) × 100%

工作时长计算

1日工作时长 = 下午打卡时间 - 上午打卡时间 - 午休时间
2月工作时长 = ∑ 日工作时长

定时任务设计

任务名称执行时间执行内容
每日统计任务每天 01:00统计昨日所有员工考勤数据
每月汇总任务每月1号 01:00生成上月考勤月报
数据清理任务每月1号 02:00清理6个月前的详细数据

统计SQL实现

1. 每日考勤统计SQL

sql
1-- 统计某一天的考勤数据(插入或更新统计表)
2INSERT INTO attendance_statistics (
3 user_id,
4 stat_date,
5 am_in_time,
6 pm_out_time,
7 is_late,
8 late_minutes,
9 is_early,
10 early_minutes,
11 is_absence,
12 absence_times,
13 work_hours,
14 status
15)
16SELECT
17 u.user_id,
18 DATE('2025-01-28') AS stat_date,
19
20 -- 上午上班时间(取当天最早的上班打卡)
21 MIN(CASE WHEN r.check_type = '1' THEN r.check_time END) AS am_in_time,
22
23 -- 下午下班时间(取当天最晚的下班打卡)
24 MAX(CASE WHEN r.check_type = '2' THEN r.check_time END) AS pm_out_time,
25
26 -- 是否迟到(上班时间晚于8:30)
27 CASE
28 WHEN MIN(CASE WHEN r.check_type = '1' THEN r.check_time END) > DATE_ADD(DATE('2025-01-28'), INTERVAL 8*60+30 MINUTE)
29 THEN '1'
30 ELSE '0'
31 END AS is_late,
32
33 -- 迟到分钟数
34 CASE
35 WHEN MIN(CASE WHEN r.check_type = '1' THEN r.check_time END) > DATE_ADD(DATE('2025-01-28'), INTERVAL 8*60+30 MINUTE)
36 THEN TIMESTAMPDIFF(MINUTE, DATE_ADD(DATE('2025-01-28'), INTERVAL 8*60+30 MINUTE),
37 MIN(CASE WHEN r.check_type = '1' THEN r.check_time END))
38 ELSE 0
39 END AS late_minutes,
40
41 -- 是否早退(下班时间早于18:00)
42 CASE
43 WHEN MAX(CASE WHEN r.check_type = '2' THEN r.check_time END) < DATE_ADD(DATE('2025-01-28'), INTERVAL 18*60 MINUTE)
44 THEN '1'
45 ELSE '0'
46 END AS is_early,
47
48 -- 早退分钟数
49 CASE
50 WHEN MAX(CASE WHEN r.check_type = '2' THEN r.check_time END) < DATE_ADD(DATE('2025-01-28'), INTERVAL 18*60 MINUTE)
51 THEN TIMESTAMPDIFF(MINUTE, MAX(CASE WHEN r.check_type = '2' THEN r.check_time END),
52 DATE_ADD(DATE('2025-01-28'), INTERVAL 18*60 MINUTE))
53 ELSE 0
54 END AS early_minutes,
55
56 -- 是否缺卡(上班或下班打卡缺失)
57 CASE
58 WHEN MIN(CASE WHEN r.check_type = '1' THEN r.check_time END) IS NULL
59 OR MAX(CASE WHEN r.check_type = '2' THEN r.check_time END) IS NULL
60 THEN '1'
61 ELSE '0'
62 END AS is_absence,
63
64 -- 缺卡次数
65 CASE
66 WHEN MIN(CASE WHEN r.check_type = '1' THEN r.check_time END) IS NULL THEN 1 ELSE 0
67 END +
68 CASE
69 WHEN MAX(CASE WHEN r.check_type = '2' THEN r.check_time END) IS NULL THEN 1 ELSE 0
70 END AS absence_times,
71
72 -- 工作时长(下班-上班-午休1.5小时)
73 CASE
74 WHEN MIN(CASE WHEN r.check_type = '1' THEN r.check_time END) IS NOT NULL
75 AND MAX(CASE WHEN r.check_type = '2' THEN r.check_time END) IS NOT NULL
76 THEN ROUND(
77 TIMESTAMPDIFF(MINUTE,
78 MIN(CASE WHEN r.check_type = '1' THEN r.check_time END),
79 MAX(CASE WHEN r.check_type = '2' THEN r.check_time END)
80 ) / 60.0 - 1.5, 2
81 )
82 ELSE 0
83 END AS work_hours,
84
85 -- 状态判断
86 CASE
87 -- 优先判断请假
88 WHEN EXISTS (
89 SELECT 1 FROM attendance_leave l
90 WHERE l.user_id = u.user_id
91 AND l.status = '1'
92 AND DATE('2025-01-28') BETWEEN DATE(l.start_time) AND DATE(l.end_time)
93 ) THEN '请假'
94
95 -- 判断出差
96 WHEN EXISTS (
97 SELECT 1 FROM attendance_trip t
98 WHERE t.user_id = u.user_id
99 AND t.status = '1'
100 AND DATE('2025-01-28') BETWEEN DATE(t.start_time) AND DATE(t.end_time)
101 ) THEN '出差'
102
103 -- 判断缺卡
104 WHEN MIN(CASE WHEN r.check_type = '1' THEN r.check_time END) IS NULL
105 OR MAX(CASE WHEN r.check_type = '2' THEN r.check_time END) IS NULL
106 THEN '缺卡'
107
108 -- 判断迟到
109 WHEN MIN(CASE WHEN r.check_type = '1' THEN r.check_time END) > DATE_ADD(DATE('2025-01-28'), INTERVAL 8*60+30 MINUTE)
110 THEN '迟到'
111
112 -- 判断早退
113 WHEN MAX(CASE WHEN r.check_type = '2' THEN r.check_time END) < DATE_ADD(DATE('2025-01-28'), INTERVAL 18*60 MINUTE)
114 THEN '早退'
115
116 ELSE '正常'
117 END AS status
118
119FROM sys_user u
120LEFT JOIN attendance_record r ON u.user_id = r.user_id
121 AND DATE(r.check_time) = DATE('2025-01-28')
122WHERE u.status = '0' -- 只统计在职员工
123GROUP BY u.user_id
124ON DUPLICATE KEY UPDATE
125 am_in_time = VALUES(am_in_time),
126 pm_out_time = VALUES(pm_out_time),
127 is_late = VALUES(is_late),
128 late_minutes = VALUES(late_minutes),
129 is_early = VALUES(is_early),
130 early_minutes = VALUES(early_minutes),
131 is_absence = VALUES(is_absence),
132 absence_times = VALUES(absence_times),
133 work_hours = VALUES(work_hours),
134 status = VALUES(status);

2. 月度考勤汇总SQL

sql
1-- 生成某月的考勤汇总报表
2INSERT INTO attendance_monthly_summary (
3 user_id,
4 year_month,
5 work_days,
6 actual_days,
7 late_times,
8 early_times,
9 absence_times,
10 leave_days,
11 trip_days,
12 work_hours,
13 attendance_rate
14)
15SELECT
16 u.user_id,
17 '2025-01' AS year_month,
18
19 -- 应出勤天数 = 当月天数 - 周末天数 - 节假日天数 + 补班天数
20 (
21 DAY(LAST_DAY('2025-01-01')) -- 当月总天数
22 - (
23 -- 周末天数
24 SELECT COUNT(*)
25 FROM (
26 SELECT DATE_ADD('2025-01-01', INTERVAL seq DAY) AS d
27 FROM (
28 SELECT a.N + b.N * 10 AS seq
29 FROM
30 (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
31 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) a,
32 (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3) b
33 ) nums
34 WHERE DATE_ADD('2025-01-01', INTERVAL seq DAY) <= LAST_DAY('2025-01-01')
35 ) dates
36 WHERE DAYOFWEEK(d) IN (1, 7) -- 周日=1, 周六=7
37 )
38 - (
39 -- 法定节假日天数(排除补班日)
40 SELECT COUNT(*)
41 FROM attendance_holiday
42 WHERE holiday_date BETWEEN '2025-01-01' AND LAST_DAY('2025-01-01')
43 AND holiday_type = '0'
44 )
45 + (
46 -- 补班天数
47 SELECT COUNT(*)
48 FROM attendance_holiday
49 WHERE holiday_date BETWEEN '2025-01-01' AND LAST_DAY('2025-01-01')
50 AND holiday_type = '1'
51 )
52 ) AS work_days,
53
54 -- 实际出勤天数(正常+迟到+早退)
55 COALESCE((
56 SELECT COUNT(*)
57 FROM attendance_statistics s
58 WHERE s.user_id = u.user_id
59 AND s.stat_date BETWEEN '2025-01-01' AND LAST_DAY('2025-01-01')
60 AND s.status IN ('正常', '迟到', '早退')
61 ), 0) AS actual_days,
62
63 -- 迟到次数
64 COALESCE((
65 SELECT COUNT(*)
66 FROM attendance_statistics s
67 WHERE s.user_id = u.user_id
68 AND s.stat_date BETWEEN '2025-01-01' AND LAST_DAY('2025-01-01')
69 AND s.is_late = '1'
70 ), 0) AS late_times,
71
72 -- 早退次数
73 COALESCE((
74 SELECT COUNT(*)
75 FROM attendance_statistics s
76 WHERE s.user_id = u.user_id
77 AND s.stat_date BETWEEN '2025-01-01' AND LAST_DAY('2025-01-01')
78 AND s.is_early = '1'
79 ), 0) AS early_times,
80
81 -- 缺卡次数
82 COALESCE((
83 SELECT SUM(s.absence_times)
84 FROM attendance_statistics s
85 WHERE s.user_id = u.user_id
86 AND s.stat_date BETWEEN '2025-01-01' AND LAST_DAY('2025-01-01')
87 ), 0) AS absence_times,
88
89 -- 请假天数
90 COALESCE((
91 SELECT SUM(l.leave_days)
92 FROM attendance_leave l
93 WHERE l.user_id = u.user_id
94 AND l.status = '1'
95 AND (
96 (DATE(l.start_time) BETWEEN '2025-01-01' AND LAST_DAY('2025-01-01'))
97 OR (DATE(l.end_time) BETWEEN '2025-01-01' AND LAST_DAY('2025-01-01'))
98 OR (DATE(l.start_time) <= '2025-01-01' AND DATE(l.end_time) >= LAST_DAY('2025-01-01'))
99 )
100 ), 0) AS leave_days,
101
102 -- 出差天数
103 COALESCE((
104 SELECT SUM(t.trip_days)
105 FROM attendance_trip t
106 WHERE t.user_id = u.user_id
107 AND t.status = '1'
108 AND (
109 (DATE(t.start_time) BETWEEN '2025-01-01' AND LAST_DAY('2025-01-01'))
110 OR (DATE(t.end_time) BETWEEN '2025-01-01' AND LAST_DAY('2025-01-01'))
111 OR (DATE(t.start_time) <= '2025-01-01' AND DATE(t.end_time) >= LAST_DAY('2025-01-01'))
112 )
113 ), 0) AS trip_days,
114
115 -- 工作时长
116 COALESCE((
117 SELECT SUM(s.work_hours)
118 FROM attendance_statistics s
119 WHERE s.user_id = u.user_id
120 AND s.stat_date BETWEEN '2025-01-01' AND LAST_DAY('2025-01-01')
121 ), 0) AS work_hours,
122
123 -- 出勤率(实际出勤/应出勤*100)
124 ROUND(
125 COALESCE((
126 SELECT COUNT(*)
127 FROM attendance_statistics s
128 WHERE s.user_id = u.user_id
129 AND s.stat_date BETWEEN '2025-01-01' AND LAST_DAY('2025-01-01')
130 AND s.status IN ('正常', '迟到', '早退')
131 ), 0) * 100.0 /
132 GREATEST((
133 DAY(LAST_DAY('2025-01-01'))
134 - (SELECT COUNT(*) FROM (
135 SELECT DATE_ADD('2025-01-01', INTERVAL seq DAY) AS d
136 FROM (
137 SELECT a.N + b.N * 10 AS seq
138 FROM
139 (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
140 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) a,
141 (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3) b
142 ) nums
143 WHERE DATE_ADD('2025-01-01', INTERVAL seq DAY) <= LAST_DAY('2025-01-01')
144 ) dates WHERE DAYOFWEEK(d) IN (1, 7))
145 - COALESCE((SELECT COUNT(*) FROM attendance_holiday
146 WHERE holiday_date BETWEEN '2025-01-01' AND LAST_DAY('2025-01-01')
147 AND holiday_type = '0'), 0)
148 + COALESCE((SELECT COUNT(*) FROM attendance_holiday
149 WHERE holiday_date BETWEEN '2025-01-01' AND LAST_DAY('2025-01-01')
150 AND holiday_type = '1'), 0)
151 ), 1),
152 2
153 ) AS attendance_rate
154
155FROM sys_user u
156WHERE u.status = '0' -- 只统计在职员工
157ON DUPLICATE KEY UPDATE
158 work_days = VALUES(work_days),
159 actual_days = VALUES(actual_days),
160 late_times = VALUES(late_times),
161 early_times = VALUES(early_times),
162 absence_times = VALUES(absence_times),
163 leave_days = VALUES(leave_days),
164 trip_days = VALUES(trip_days),
165 work_hours = VALUES(work_hours),
166 attendance_rate = VALUES(attendance_rate);

3. 查询个人月度统计

sql
1-- 查询某用户某月的考勤统计
2SELECT
3 user_id,
4 year_month,
5 work_days AS '应出勤天数',
6 actual_days AS '实际出勤天数',
7 late_times AS '迟到次数',
8 early_times AS '早退次数',
9 absence_times AS '缺卡次数',
10 leave_days AS '请假天数',
11 trip_days AS '出差天数',
12 work_hours AS '工作时长(小时)',
13 attendance_rate AS '出勤率(%)'
14FROM attendance_monthly_summary
15WHERE user_id = 1
16 AND year_month = '2025-01';

4. 查询部门考勤报表

sql
1-- 查询某部门某月的考勤汇总
2SELECT
3 u.user_id,
4 u.user_name,
5 u.nick_name,
6 d.dept_name,
7 s.work_days AS '应出勤',
8 s.actual_days AS '实际出勤',
9 s.attendance_rate AS '出勤率(%)',
10 s.late_times AS '迟到',
11 s.early_times AS '早退',
12 s.absence_times AS '缺卡',
13 s.leave_days AS '请假',
14 s.work_hours AS '工时'
15FROM attendance_monthly_summary s
16INNER JOIN sys_user u ON s.user_id = u.user_id
17INNER JOIN sys_dept d ON u.dept_id = d.dept_id
18WHERE d.dept_id = 1
19 AND s.year_month = '2025-01'
20ORDER BY s.attendance_rate DESC;

5. 查询异常考勤明细

sql
1-- 查询某月迟到明细
2SELECT
3 u.user_id,
4 u.user_name,
5 u.nick_name,
6 d.dept_name,
7 s.stat_date AS '日期',
8 s.am_in_time AS '上班打卡时间',
9 s.late_minutes AS '迟到分钟数',
10 s.remark AS '备注'
11FROM attendance_statistics s
12INNER JOIN sys_user u ON s.user_id = u.user_id
13INNER JOIN sys_dept d ON u.dept_id = d.dept_id
14WHERE s.stat_date BETWEEN '2025-01-01' AND LAST_DAY('2025-01-01')
15 AND s.is_late = '1'
16ORDER BY s.stat_date DESC, s.late_minutes DESC;

3.6 考勤报表模块

功能描述

提供多维度的考勤报表,支持导出Excel,方便管理层决策。

报表类型

数据展示

  1. 表格展示:详细的数据列表
  2. 图表展示:柱状图、折线图、饼图
  3. 日历展示:直观的日历视图
  4. 导出功能:支持Excel导出

3.7 规则配置模块

功能描述

系统管理员配置考勤规则、工作时间、节假日等基础数据。

配置项


四、业务流程设计

4.1 考勤打卡完整流程

4.2 请假审批完整流程

4.3 补卡审批与考勤更新流程

4.4 月度考勤统计流程

4.5 异常考勤处理流程


五、数据库设计

5.1 数据库架构

5.2 核心表设计

5.2.1 打卡记录表 (attendance_record)

表说明:记录员工每次打卡的详细信息

sql
1CREATE TABLE `attendance_record` (
2 `record_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
3 `user_id` BIGINT NOT NULL COMMENT '用户ID',
4 `check_time` DATETIME NOT NULL COMMENT '打卡时间',
5 `check_type` VARCHAR(10) NOT NULL COMMENT '打卡类型(1上班2下班)',
6 `check_source` VARCHAR(20) NOT NULL COMMENT '打卡来源(移动端/PC端/补卡)',
7 `location` VARCHAR(200) DEFAULT NULL COMMENT '打卡位置',
8 `latitude` DECIMAL(10,7) DEFAULT NULL COMMENT '纬度',
9 `longitude` DECIMAL(10,7) DEFAULT NULL COMMENT '经度',
10 `is_normal` CHAR(1) NOT NULL DEFAULT '1' COMMENT '是否正常(0否1是)',
11 `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注',
12 `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
13 PRIMARY KEY (`record_id`),
14 KEY `idx_user_time` (`user_id`, `check_time`),
15 KEY `idx_check_time` (`check_time`)
16) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='打卡记录表';

5.2.2 考勤统计表 (attendance_statistics)

表说明:每日考勤统计数据,用于快速查询

sql
1CREATE TABLE `attendance_statistics` (
2 `stat_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
3 `user_id` BIGINT NOT NULL COMMENT '用户ID',
4 `stat_date` DATE NOT NULL COMMENT '统计日期',
5 `am_in_time` DATETIME DEFAULT NULL COMMENT '上午上班时间',
6 `am_out_time` DATETIME DEFAULT NULL COMMENT '上午下班时间',
7 `pm_in_time` DATETIME DEFAULT NULL COMMENT '下午上班时间',
8 `pm_out_time` DATETIME DEFAULT NULL COMMENT '下午下班时间',
9 `is_late` CHAR(1) NOT NULL DEFAULT '0' COMMENT '是否迟到(0否1是)',
10 `late_minutes` INT DEFAULT NULL COMMENT '迟到分钟数',
11 `is_early` CHAR(1) NOT NULL DEFAULT '0' COMMENT '是否早退(0否1是)',
12 `early_minutes` INT DEFAULT NULL COMMENT '早退分钟数',
13 `is_absence` CHAR(1) NOT NULL DEFAULT '0' COMMENT '是否缺卡(0否1是)',
14 `absence_times` INT DEFAULT 0 COMMENT '缺卡次数',
15 `work_hours` DECIMAL(5,2) DEFAULT NULL COMMENT '工作时长(小时)',
16 `status` VARCHAR(20) NOT NULL COMMENT '状态(正常/迟到/早退/缺卡/请假/出差)',
17 `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注',
18 PRIMARY KEY (`stat_id`),
19 UNIQUE KEY `uk_user_date` (`user_id`, `stat_date`),
20 KEY `idx_stat_date` (`stat_date`)
21) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='考勤统计表';

5.2.3 月度汇总表 (attendance_monthly_summary)

表说明:每月考勤汇总数据

sql
1CREATE TABLE `attendance_monthly_summary` (
2 `summary_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
3 `user_id` BIGINT NOT NULL COMMENT '用户ID',
4 `year_month` VARCHAR(7) NOT NULL COMMENT '年月(YYYY-MM)',
5 `work_days` INT NOT NULL COMMENT '应出勤天数',
6 `actual_days` INT NOT NULL COMMENT '实际出勤天数',
7 `late_times` INT NOT NULL DEFAULT 0 COMMENT '迟到次数',
8 `early_times` INT NOT NULL DEFAULT 0 COMMENT '早退次数',
9 `absence_times` INT NOT NULL DEFAULT 0 COMMENT '缺卡次数',
10 `leave_days` DECIMAL(5,1) DEFAULT 0 COMMENT '请假天数',
11 `trip_days` DECIMAL(5,1) DEFAULT 0 COMMENT '出差天数',
12 `work_hours` DECIMAL(8,2) DEFAULT NULL COMMENT '工作时长(小时)',
13 `attendance_rate` DECIMAL(5,2) DEFAULT NULL COMMENT '出勤率(%)',
14 PRIMARY KEY (`summary_id`),
15 UNIQUE KEY `uk_user_month` (`user_id`, `year_month`)
16) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='月度汇总表';

5.2.4 请假记录表 (attendance_leave)

表说明:员工请假申请记录

sql
1CREATE TABLE `attendance_leave` (
2 `leave_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
3 `user_id` BIGINT NOT NULL COMMENT '用户ID',
4 `leave_type` VARCHAR(10) NOT NULL COMMENT '请假类型(1事假2病假3年假4调休5婚假6产假7丧假)',
5 `start_time` DATETIME NOT NULL COMMENT '开始时间',
6 `end_time` DATETIME NOT NULL COMMENT '结束时间',
7 `leave_days` DECIMAL(5,1) NOT NULL COMMENT '请假天数',
8 `reason` VARCHAR(500) NOT NULL COMMENT '请假原因',
9 `proof_url` VARCHAR(500) DEFAULT NULL COMMENT '证明材料URL',
10 `status` CHAR(1) NOT NULL DEFAULT '0' COMMENT '审批状态(0待审批1通过2拒绝3撤销)',
11 `approver_id` BIGINT DEFAULT NULL COMMENT '审批人ID',
12 `approve_time` DATETIME DEFAULT NULL COMMENT '审批时间',
13 `approve_remark` VARCHAR(500) DEFAULT NULL COMMENT '审批备注',
14 `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
15 `update_time` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
16 PRIMARY KEY (`leave_id`),
17 KEY `idx_user_status` (`user_id`, `status`),
18 KEY `idx_start_time` (`start_time`)
19) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='请假记录表';

5.2.5 出差记录表 (attendance_trip)

表说明:员工出差申请记录

sql
1CREATE TABLE `attendance_trip` (
2 `trip_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
3 `user_id` BIGINT NOT NULL COMMENT '用户ID',
4 `destination` VARCHAR(200) NOT NULL COMMENT '出差地点',
5 `start_time` DATETIME NOT NULL COMMENT '开始时间',
6 `end_time` DATETIME NOT NULL COMMENT '结束时间',
7 `trip_days` DECIMAL(5,1) NOT NULL COMMENT '出差天数',
8 `reason` VARCHAR(500) NOT NULL COMMENT '出差事由',
9 `proof_url` VARCHAR(500) DEFAULT NULL COMMENT '证明材料URL',
10 `status` CHAR(1) NOT NULL DEFAULT '0' COMMENT '审批状态(0待审批1通过2拒绝3撤销)',
11 `approver_id` BIGINT DEFAULT NULL COMMENT '审批人ID',
12 `approve_time` DATETIME DEFAULT NULL COMMENT '审批时间',
13 `approve_remark` VARCHAR(500) DEFAULT NULL COMMENT '审批备注',
14 `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
15 `update_time` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
16 PRIMARY KEY (`trip_id`),
17 KEY `idx_user_status` (`user_id`, `status`),
18 KEY `idx_start_time` (`start_time`)
19) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='出差记录表';

5.2.6 补卡申请表 (attendance_makeup)

表说明:员工补卡申请记录

sql
1CREATE TABLE `attendance_makeup` (
2 `makeup_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
3 `user_id` BIGINT NOT NULL COMMENT '用户ID',
4 `makeup_date` DATE NOT NULL COMMENT '补卡日期',
5 `makeup_time` TIME NOT NULL COMMENT '补卡时间',
6 `check_type` VARCHAR(10) NOT NULL COMMENT '打卡类型(1上班2下班)',
7 `reason` VARCHAR(500) NOT NULL COMMENT '补卡原因',
8 `status` CHAR(1) NOT NULL DEFAULT '0' COMMENT '审批状态(0待审批1通过2拒绝3撤销)',
9 `approver_id` BIGINT DEFAULT NULL COMMENT '审批人ID',
10 `approve_time` DATETIME DEFAULT NULL COMMENT '审批时间',
11 `approve_remark` VARCHAR(500) DEFAULT NULL COMMENT '审批备注',
12 `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
13 `update_time` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
14 PRIMARY KEY (`makeup_id`),
15 KEY `idx_user_status` (`user_id`, `status`),
16 KEY `idx_makeup_date` (`makeup_date`)
17) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='补卡申请表';

5.2.7 节假日配置表 (attendance_holiday)

表说明:法定节假日和调休补班日配置

sql
1CREATE TABLE `attendance_holiday` (
2 `holiday_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
3 `holiday_date` DATE NOT NULL COMMENT '日期',
4 `holiday_type` CHAR(1) NOT NULL COMMENT '类型(0节假日1补班日)',
5 `holiday_name` VARCHAR(100) NOT NULL COMMENT '节假日名称',
6 `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注',
7 `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
8 PRIMARY KEY (`holiday_id`),
9 UNIQUE KEY `uk_date` (`holiday_date`),
10 KEY `idx_type` (`holiday_type`)
11) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='节假日配置表';

5.2.8 考勤规则表 (attendance_rule)

表说明:考勤规则配置

sql
1CREATE TABLE `attendance_rule` (
2 `rule_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
3 `rule_name` VARCHAR(100) NOT NULL COMMENT '规则名称',
4 `am_start_time` TIME NOT NULL COMMENT '上午上班时间',
5 `am_end_time` TIME NOT NULL COMMENT '上午下班时间',
6 `pm_start_time` TIME NOT NULL COMMENT '下午上班时间',
7 `pm_end_time` TIME NOT NULL COMMENT '下午下班时间',
8 `late_threshold` INT DEFAULT 0 COMMENT '迟到阈值(分钟)',
9 `early_threshold` INT DEFAULT 0 COMMENT '早退阈值(分钟)',
10 `is_location_check` CHAR(1) DEFAULT '1' COMMENT '是否位置校验(0否1是)',
11 `location_range` INT DEFAULT 500 COMMENT '位置范围(米)',
12 `is_default` CHAR(1) DEFAULT '0' COMMENT '是否默认规则(0否1是)',
13 `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注',
14 `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
15 `update_time` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
16 PRIMARY KEY (`rule_id`)
17) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='考勤规则表';

5.3 数据关系图(ER图)

关系说明

关系说明类型
sys_user → attendance_record一个用户有多条打卡记录1:N
sys_user → attendance_statistics一个用户有多条日统计1:N
sys_user → attendance_monthly_summary一个用户有多条月汇总1:N
sys_user → attendance_leave/trip/makeup一个用户可以有多个申请1:N
sys_user(审批人) → attendance_leave/trip/makeup一个审批人可以审批多个申请1:N
attendance_record → attendance_statistics多条打卡记录生成一条日统计N:1
attendance_statistics → attendance_monthly_summary多条日统计汇总为一条月汇总N:1

5.4 数据字典

打卡类型 (check_type)

代码名称说明
1上班打卡上午上班、下午上班
2下班打卡上午下班、下午下班

打卡来源 (check_source)

代码名称说明
移动端手机APP移动设备打卡
PC端电脑网页电脑网页打卡
补卡补卡审批补卡审批通过后创建

考勤状态 (status)

代码名称说明
正常正常出勤按时打卡,无异常
迟到迟到上班打卡超时
早退早退下班打卡提前
缺卡缺卡缺少打卡记录
请假请假当天有请假
出差出差当天在出差

审批状态 (status)

代码名称说明
0待审批已提交,等待审批
1已通过审批通过
2已拒绝审批拒绝
3已撤销申请人撤回

请假类型 (leave_type)

代码名称扣除考勤
1事假
2病假
3年假
4调休
5婚假
6产假
7丧假

六、接口设计

6.1 接口规范

请求规范

1基础URL: http://domain/api
2认证方式: JWT Token (Header: Authorization: Bearer {token})
3请求格式: application/json
4字符编码: UTF-8

响应规范

json
1{
2 "code": 200, // 状态码:200成功,其他失败
3 "msg": "操作成功", // 提示信息
4 "data": {} // 响应数据
5}

状态码定义

状态码说明场景
200成功操作成功
400参数错误请求参数不合法
401未认证未登录或Token过期
403无权限没有操作权限
404不存在资源不存在
500服务器错误系统内部错误

6.2 核心接口列表

6.2.1 考勤打卡接口

1. 打卡接口

http
1POST /attendance/record/checkIn
2Content-Type: application/json
3Authorization: Bearer {token}

请求参数

json
1{
2 "checkType": "1", // 打卡类型:1上班 2下班
3 "checkSource": "移动端", // 打卡来源
4 "location": "深圳市南山区...", // 打卡位置
5 "latitude": 22.5431, // 纬度
6 "longitude": 113.9520 // 经度
7}

响应数据

json
1{
2 "code": 200,
3 "msg": "打卡成功",
4 "data": {
5 "recordId": 12345,
6 "checkTime": "2025-01-28 09:00:00",
7 "isNormal": "1", // 是否正常
8 "lateMinutes": 0, // 迟到分钟数
9 "status": "正常" // 考勤状态
10 }
11}

2. 查询打卡记录

http
1GET /attendance/record/list?date=2025-01-28
2Authorization: Bearer {token}

响应数据

json
1{
2 "code": 200,
3 "msg": "查询成功",
4 "data": {
5 "list": [
6 {
7 "recordId": 12345,
8 "checkTime": "2025-01-28 09:00:00",
9 "checkType": "1",
10 "checkSource": "移动端",
11 "isNormal": "1"
12 }
13 ],
14 "total": 2
15 }
16}

6.2.2 请假管理接口

1. 提交请假申请

http
1POST /attendance/leave
2Content-Type: application/json
3Authorization: Bearer {token}

请求参数

json
1{
2 "leaveType": "1", // 请假类型
3 "startTime": "2025-01-29 09:00:00",
4 "endTime": "2025-01-30 18:00:00",
5 "leaveDays": 2, // 请假天数
6 "reason": "家中有事", // 请假原因
7 "proofUrl": "" // 证明材料URL
8}

响应数据

json
1{
2 "code": 200,
3 "msg": "提交成功",
4 "data": {
5 "leaveId": 1001,
6 "status": "0" // 待审批
7 }
8}

2. 撤回请假申请

http
1PUT /attendance/leave/cancel/{leaveId}
2Authorization: Bearer {token}

响应数据

json
1{
2 "code": 200,
3 "msg": "撤回成功"
4}

6.2.3 审批管理接口

1. 查询待审批列表

http
1GET /attendance/approve/pending
2Authorization: Bearer {token}

响应数据

json
1{
2 "code": 200,
3 "msg": "查询成功",
4 "data": {
5 "list": [
6 {
7 "id": 1001,
8 "type": "leave", // 类型:leave/trip/makeup
9 "typeName": "请假申请",
10 "userName": "zhangsan",
11 "nickName": "张三",
12 "deptName": "技术部",
13 "content": "事假,2天", // 申请内容
14 "reason": "家中有事",
15 "createTime": "2025-01-28 09:00:00",
16 "status": "0"
17 }
18 ],
19 "total": 5,
20 "leaveCount": 2, // 请假申请数
21 "tripCount": 1, // 出差申请数
22 "makeupCount": 2 // 补卡申请数
23 }
24}

2. 审批申请

http
1PUT /attendance/approve/{type}/{id}/{status}
2Content-Type: application/json
3Authorization: Bearer {token}

参数说明

  • type: leave/trip/makeup(申请类型)
  • id: 申请ID
  • status: 1通过 / 2拒绝

请求体

json
1{
2 "remark": "同意" // 审批备注
3}

响应数据

json
1{
2 "code": 200,
3 "msg": "审批成功"
4}

6.2.4 考勤统计接口

1. 查询个人月度统计

http
1GET /attendance/statistics/month?month=2025-01
2Authorization: Bearer {token}

响应数据

json
1{
2 "code": 200,
3 "msg": "查询成功",
4 "data": {
5 "workDays": 22, // 应出勤天数
6 "actualDays": 20, // 实际出勤天数
7 "lateTimes": 2, // 迟到次数
8 "earlyTimes": 0, // 早退次数
9 "absenceTimes": 0, // 缺卡次数
10 "leaveDays": 2, // 请假天数
11 "tripDays": 0, // 出差天数
12 "workHours": 160, // 工作时长
13 "attendanceRate": 90.91 // 出勤率
14 }
15}

2. 查询个人日统计列表

http
1GET /attendance/statistics/list?month=2025-01
2Authorization: Bearer {token}

响应数据

json
1{
2 "code": 200,
3 "msg": "查询成功",
4 "data": {
5 "list": [
6 {
7 "statDate": "2025-01-01",
8 "amInTime": "2025-01-01 08:55:00",
9 "pmOutTime": "2025-01-01 18:05:00",
10 "isLate": "0",
11 "isEarly": "0",
12 "workHours": 8.5,
13 "status": "正常"
14 }
15 ],
16 "total": 30
17 }
18}

6.2.5 报表接口

1. 部门考勤报表

http
1GET /attendance/report/department?month=2025-01&deptId=1
2Authorization: Bearer {token}

响应数据

json
1{
2 "code": 200,
3 "msg": "查询成功",
4 "data": {
5 "list": [
6 {
7 "userId": 1,
8 "userName": "zhangsan",
9 "nickName": "张三",
10 "deptName": "技术部",
11 "workDays": 22,
12 "actualDays": 20,
13 "attendanceRate": 90.91,
14 "lateTimes": 2,
15 "leaveDays": 2
16 }
17 ],
18 "total": 10
19 }
20}

2. 异常考勤报表

http
1GET /attendance/report/abnormal?month=2025-01&type=late
2Authorization: Bearer {token}

参数说明

  • type: late(迟到) / early(早退) / absence(缺卡)

响应数据

json
1{
2 "code": 200,
3 "msg": "查询成功",
4 "data": {
5 "list": [
6 {
7 "userId": 1,
8 "userName": "zhangsan",
9 "nickName": "张三",
10 "statDate": "2025-01-28",
11 "amInTime": "2025-01-28 09:05:00",
12 "lateMinutes": 5,
13 "reason": "堵车"
14 }
15 ],
16 "total": 15
17 }
18}

6.3 接口权限设计

接口路径权限标识角色要求
/attendance/record/checkInattendance:record:add全员
/attendance/leaveattendance:leave:add全员
/attendance/approve/pendingattendance:approve:list审批人
/attendance/approve/*attendance:approve:edit审批人
/attendance/report/departmentattendance:report:dept部门主管
/attendance/ruleattendance:rule:edit管理员

七、安全设计

7.1 认证与授权

认证机制

1采用JWT (JSON Web Token) 认证机制:
2
31. 用户登录
4
52. 验证用户名密码
6
73. 生成JWT Token (有效期2小时)
8
94. 返回Token给客户端
10
115. 客户端每次请求携带Token
12
136. 服务器验证Token有效性
14
157. 解析Token获取用户信息
16
178. 执行业务逻辑

Token结构

json
1{
2 "header": {
3 "alg": "HS256",
4 "typ": "JWT"
5 },
6 "payload": {
7 "userId": 1,
8 "userName": "zhangsan",
9 "roles": ["user", "dept_manager"],
10 "exp": 1706428800 // 过期时间戳
11 },
12 "signature": "..."
13}

权限控制

基于RBAC (Role-Based Access Control) 模型

7.2 数据安全

敏感数据加密

  • 密码加密:BCrypt算法,不可逆加密
  • 通信加密:HTTPS/TLS 1.2+
  • 数据库加密:敏感字段AES-256加密

SQL注入防护

  • 使用MyBatis预编译语句
  • 参数化查询
  • 输入验证和过滤

XSS防护

  • 前端输入过滤
  • 后端输出编码
  • CSP (Content Security Policy)

7.3 接口安全

接口限流

防重放攻击

  • 请求签名验证
  • 时间戳验证(5分钟内有效)
  • Nonce随机数验证

操作日志


八、性能设计

8.1 性能目标

指标目标值说明
打卡响应时间< 500ms99%请求
查询响应时间< 1s普通查询
报表生成时间< 3s月度报表
并发打卡1000人/分钟高峰期
系统可用性99.9%年度统计

8.2 性能优化策略

数据库优化

缓存策略

异步处理

8.3 监控告警

监控指标

  • 系统指标:CPU、内存、磁盘、网络
  • 应用指标:QPS、响应时间、错误率
  • 业务指标:打卡人数、审批数量、异常率

告警规则

  • CPU使用率 > 80%
  • 内存使用率 > 85%
  • 接口响应时间 > 3s
  • 错误率 > 1%
  • 数据库连接数 > 90

九、部署方案

9.1 部署架构

9.2 环境配置

生产环境

  • 应用服务器:3台,4核8G
  • 数据库服务器:1主2从,8核16G
  • Redis服务器:3节点集群,4核8G
  • 负载均衡:Nginx,2核4G

开发环境

  • 一体化服务器:1台,4核8G
  • 包含:应用、数据库、Redis

9.3 部署流程

9.4 备份策略

数据备份

  • 全量备份:每周日凌晨2点
  • 增量备份:每天凌晨2点
  • 保留策略:保留最近30天数据

日志备份

  • 应用日志:每天归档,保留30天
  • 操作日志:每周归档,保留90天
  • 异常日志:实时告警,保留180天

十、开发计划

10.1 开发周期

总周期:8周(2个月)

10.2 迭代计划

迭代时间目标交付物
Sprint 1Week 1-2考勤打卡 + 基础配置打卡功能、规则配置
Sprint 2Week 3-4审批流程(请假/出差/补卡)审批管理、流程流转
Sprint 3Week 5-6统计报表 + 定时任务考勤统计、报表展示
Sprint 4Week 7-8测试优化 + 上线部署测试报告、部署文档

10.3 团队配置

角色人数主要职责
后端开发2业务逻辑、接口开发
前端开发1页面开发、组件封装
测试工程师1测试用例、功能测试

10.4 里程碑

里程碑时间节点验收标准
M1: 核心功能Week 4打卡、审批功能完成
M2: 统计报表Week 6统计、报表功能完成
M3: 系统可用Week 7测试通过,性能达标
M4: 正式上线Week 8生产环境部署完成

十一、附录

11.1 术语表

术语英文说明
考勤Attendance员工上下班打卡及相关管理
打卡Check-in记录员工上下班时间
应出勤天数Work Days排除周末节假日后的工作日天数
实际出勤天数Actual Days实际到岗的天数
出勤率Attendance Rate实际出勤/应出勤的比率
缺卡Absence漏打卡
补卡Makeup补充漏打的卡

11.2 参考文档

11.3 更新日志

版本日期更新内容
V1.02025-01-28初始版本,完成基础功能设计

文档信息

文档编制:系统架构师
审核人员:技术总监
文档版本:V1.0
创建日期:2025年1月28日
最后更新:2025年11月10日

© 2025 考勤管理系统 | 基于若依Pro-Mini架构 | 保留所有权利


参与讨论