1. 项目背景与核心价值
这个28960小型企业员工考勤管理系统,是我去年为本地一家30人规模的广告公司开发的实战项目。当时他们正面临三个典型痛点:手工签到表经常丢失、加班时长统计混乱、月度报表制作耗时长达2天。市面上成熟的考勤系统要么功能过剩(80%功能用不上),要么价格超出预算(年费普遍在5000元以上)。
这个系统的设计哲学很明确:用最精简的功能解决最核心的考勤问题。开发周期控制在一周内,最终实现的功能模块包括:
- 员工基础信息管理(含部门树形结构)
- 人脸识别打卡(支持移动端GPS定位)
- 异常考勤自动标记(迟到/早退/缺勤)
- 可视化报表导出(支持按部门/个人筛选)
关键设计决策:放弃复杂的排班功能,采用"默认工作日+特殊日期设置"的轻量级方案。实测证明,这种设计能满足90%小型企业的基本需求。
2. 技术架构解析
2.1 前端选型方案
采用Vue2+ElementUI的组合而非Vue3,主要考虑两点:
- 企业办公电脑普遍配置较低,Vue2的兼容性更好
- ElementUI的表格和表单组件成熟稳定,开发效率高
特别优化点:
javascript复制// 考勤表格的虚拟滚动优化
<el-table
:data="attendanceData"
style="width: 100%"
height="calc(100vh - 180px)"
row-key="id"
:row-height="50"
:virtual-scroll="true">
2.2 后端技术栈
使用SpringBoot+MyBatis经典组合,但做了三个针对性优化:
- 考勤记录表采用分区表设计(按月份物理隔离)
- 人脸特征值单独加密存储(非图片存储)
- 引入Redis缓存常用部门数据
数据库关键字段设计:
sql复制CREATE TABLE `attendance` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT '员工ID',
`clock_in` datetime DEFAULT NULL COMMENT '打卡时间',
`clock_out` datetime DEFAULT NULL COMMENT '签退时间',
`status` tinyint DEFAULT '0' COMMENT '0正常 1迟到 2早退 3缺勤',
`location` varchar(100) DEFAULT NULL COMMENT 'GPS坐标',
`photo_url` varchar(255) DEFAULT NULL COMMENT '打卡照片',
`create_date` date NOT NULL COMMENT '分区字段'
) ENGINE=InnoDB PARTITION BY RANGE (TO_DAYS(create_date)) (
PARTITION p202301 VALUES LESS THAN (TO_DAYS('2023-02-01')),
PARTITION p202302 VALUES LESS THAN (TO_DAYS('2023-03-01'))
);
3. 核心业务逻辑实现
3.1 人脸识别考勤流程
- 员工打开微信小程序(降低安装门槛)
- 调用手机摄像头进行活体检测
- 提取人脸特征值与预存模型比对
- 记录打卡时的GPS位置(防代打卡)
- 自动判断是否迟到(对比公司预设时间)
关键算法优化点:
- 采用MTCNN+FaceNet组合方案
- 特征比对阈值设为0.75(平衡误识率)
- 同一设备5分钟内禁止重复打卡
3.2 异常考勤处理机制
系统会自动标记三类异常:
- 迟到:打卡时间 > 上班时间+10分钟
- 早退:签退时间 < 下班时间-30分钟
- 缺勤:当日无任何打卡记录
处理流程包含自动申诉通道:
mermaid复制graph TD
A[系统标记异常] --> B{是否申诉?}
B -->|是| C[填写申诉理由]
B -->|否| D[计入月度统计]
C --> E[主管审批]
E -->|通过| F[修正状态]
E -->|拒绝| D
4. 部署与运维实践
4.1 硬件配置建议
- 服务器:2核4G云主机(实测支持50人并发打卡)
- 人脸识别终端:300万像素摄像头(推荐罗技C920)
- 网络要求:上行带宽≥5Mbps(多人同时上传照片)
4.2 常见问题排查
-
照片上传失败:
- 检查Nginx的client_max_body_size配置(需≥5M)
- 验证OSS存储桶的跨域设置
-
打卡延迟高:
bash复制# 查看服务器TCP连接状态 ss -ant | awk '{print $1}' | sort | uniq -c建议优化方案:
- 增加Redis连接池大小
- 开启SpringBoot的Gzip压缩
-
报表生成慢:
sql复制-- 为常用查询添加索引 ALTER TABLE attendance ADD INDEX idx_user_date (user_id, create_date);
5. 二次开发建议
对于想基于此系统扩展的开发者,推荐三个实用方向:
-
企业微信/钉钉集成
- 通过OAuth2.0实现单点登录
- 对接消息通知接口
-
薪资模块对接
java复制// 计算加班费的示例逻辑 public BigDecimal calculateOvertimePay(Long userId, LocalDate month) { List<Attendance> overtimes = attendanceMapper.selectOvertime(userId, month); return overtimes.stream() .map(a -> { Duration duration = Duration.between(a.getClockOut(), company.getClosingTime()); return payRate.multiply(new BigDecimal(duration.toHours())); }) .reduce(BigDecimal.ZERO, BigDecimal::add); } -
体温监测扩展(后疫情时代需求)
- 蓝牙体温枪数据对接
- 异常体温自动预警
这个项目的完整源码包(含数据库初始化脚本)已经上传到我的GitHub仓库,需要的小伙伴可以私信获取。在实际部署时,建议特别注意员工照片等敏感信息的存储加密问题,我们采用了AES-256加密+访问日志审计的方案来满足合规要求。
