HRMS(Human Resource Management System)是一套功能完整的人资管理系统,覆盖员工"入-转-调-离"的全生命周期管理,同时集成考勤管理、薪资核算、审批流程、系统管理等核心业务功能。系统采用前后端分离架构,前端使用 React + TypeScript + Ant Design,后端使用 Spring Boot 3 + MyBatis + Spring Security,数据库使用 MySQL 8。
| 技术 | 版本 | 说明 |
|---|---|---|
| Java | 21 | 编程语言 |
| Spring Boot | 3.4.1 | 微服务框架 |
| Spring Security | 6.x | 安全认证框架 |
| MyBatis | 3.0.3(spring-boot-starter) | ORM 持久层框架 |
| MySQL | 8.0+ | 关系型数据库 |
| Redis | 7.x | 缓存(存储 JWT Token) |
| RabbitMQ | 3.x | 消息队列 |
| JWT | 0.12.6 | 无状态 Token 认证 |
| Spring AI | 1.0.0 | AI 集成(通义千问 Qwen3.7) |
| Lombok | ~ | 代码简化 |
| Jackson | ~ | JSON 序列化(含 JSR310 时间支持) |
| Maven | ~ | 构建工具 |
| 技术 | 版本 | 说明 |
|---|---|---|
| React | 18.3.1 | UI 框架 |
| TypeScript | 5.5.4 | 类型安全 |
| Vite | 5.4.14 | 构建工具 |
| Ant Design | 5.22.7 | UI 组件库 |
| React Router | 6.28.2 | 路由管理 |
| Axios | 1.7.9 | HTTP 请求库 |
| Zustand | 5.0.3 | 状态管理 |
| Day.js | 1.11.13 | 日期处理 |
| Ant Design Charts | 2.2.4 | 图表组件 |
| Lodash-es | 4.17.21 | 工具库 |
- MySQL 数据库:
jdbc:mysql://39.97.251.102:3306/hrms - Redis 缓存:
39.97.251.102:6379 - RabbitMQ 消息队列:
39.97.251.102:5672
系统共包含 30+ 张数据库表,按业务域分为以下几类:
| 表名 | 说明 | 核心字段 |
|---|---|---|
| sys_user | 用户表(登录账号) | id, username(手机号), password(BCrypt加密), employee_id(关联员工), role_id(关联角色), status, force_change_pwd, last_login_time, deleted(逻辑删除) |
| sys_role | 角色表 | id, role_name, role_key(ADMIN/HR/MANAGER/FINANCE/EMPLOYEE), status |
| sys_permission | 权限菜单表 | id, permission_name, permission_key, parent_id(树形结构), type(1-菜单/2-按钮/3-接口), sort_order |
| sys_user_role | 用户角色关联表 | user_id, role_id(联合唯一) |
| sys_role_permission | 角色权限关联表 | role_id, permission_id(联合唯一) |
| sys_operation_log | 操作日志表 | user_id, username, operation, method(请求方法), params(请求参数), ip, status(成功/失败), error_msg |
| sys_login_log | 登录日志表 | user_id, username, ip, location(IP定位), browser(浏览器), status(成功/失败), message, login_time |
| 表名 | 说明 | 核心字段 |
|---|---|---|
| department | 部门表 | id, department_name, department_code(字母编码), dept_code(2位数字编码用于工号), parent_id(树形结构), leader_id(关联员工负责人), sort_order, status, deleted |
| position | 职位表 | id, position_name, job_level(1-老总/2-部门负责人/3-普通员工), department_id(所属部门), default_probation(默认试用期月数), status, deleted |
| 表名 | 说明 | 核心字段 |
|---|---|---|
| employee | 员工表(核心表) | id, employee_no(工号), name, gender, phone, email, id_card, birthday, address, department_id, position_id, job_level, supervisor_id(直接汇报人), previous_position_id(卸任恢复用), employment_status(1-试用期/2-正式/3-待离职/4-已离职), hire_date, hire_type, contract_type, base_salary, bank_account, emergency_contact |
| 表名 | 说明 | 核心字段 |
|---|---|---|
| onboarding | 入职申请表 | id, name, gender, phone, department_id, position_id, expected_hire_date, probation_months, status(0-草稿/1-审批中/2-已批准/3-已拒绝/4-已入职), employee_id(入职后关联员工ID), created_by |
| regularization | 转正申请表 | id, employee_id, probation_start_date(DEFAULT NULL,已不再使用), probation_end_date(生效日期), evaluation(评价), result(1-通过/2-延长/3-不通过), status(0-待发起/1-审批中/2-已通过/3-已拒绝) |
| transfer | 调岗申请表 | id, employee_id, old_department_id/old_position_id/old_job_level/old_supervisor_id(原信息), new_department_id/new_position_id/new_job_level/new_supervisor_id(新信息), transfer_reason, transfer_date, status(0-草稿/1-审批中/2-已通过/3-已拒绝/4-已生效) |
| resignation | 离职申请表 | id, employee_id, resignation_date, resignation_reason(1-主动/2-被动/3-协商), resignation_type(1-辞职/2-辞退/3-合同到期), handover_employee_id(工作交接人), status(0-草稿/1-审批中/2-已通过/3-已拒绝/4-待离职/5-已离职) |
| 表名 | 说明 | 核心字段 |
|---|---|---|
| attendance_group | 考勤组表 | id, group_name, shift_type(1-固定班/2-弹性班/3-排班制), work_start_time/work_end_time(工作时间), break_start_time/break_end_time(午休), late_threshold/early_leave_threshold(迟到/早退阈值分钟数) |
| attendance_group_member | 考勤组成员表 | group_id, employee_id(联合唯一) |
| attendance_group_department | 考勤组适用部门表 | group_id, department_id(联合唯一) |
| clock_record | 打卡记录表 | id, employee_id, clock_date, clock_type(1-上班/2-下班), clock_time, status(1-正常/2-迟到/3-早退/4-旷工半天/5-上班缺卡/6-下班缺卡/7-缺勤/8-补卡) |
| leave_application | 请假申请表 | id, employee_id, leave_type(1-年假/2-病假/3-事假/4-婚假/5-产假/6-丧假/7-调休), start_time/end_time, leave_days(支持0.5), reason, handover_employee_id, attachment_url, status(0-待审批/1-审批中/2-已通过/3-已拒绝/4-已取消) |
| leave_balance | 假期余额表 | id, employee_id, leave_type, year, total_days, used_days, remaining_days(按员工+类型+年份联合唯一) |
| clock_supplement | 补卡申请表 | id, employee_id, clock_date, clock_type(1-上班/2-下班), clock_time, reason, status(0-待审批/1-审批中/2-已通过/3-已拒绝) |
| attendance_monthly_stats | 月度考勤统计表 | id, employee_id, year_month, work_days, normal_days, late_count, early_leave_count, absent_half_day/absent_full_day, missing_card_count, supplement_count, overtime_days(按员工+月份联合唯一) |
| holiday | 法定节假日表 | id, holiday_name, holiday_date, holiday_type(1-法定假日/2-调休上班), year |
| overtime_application | 加班申请表 | id, employee_id, overtime_date, start_time/end_time, overtime_hours, overtime_type(1-工作日/2-休息日/3-法定节假日), reason, status |
| comp_time_balance | 调休余额表 | id, employee_id, year, month, total_hours, used_hours, remaining_hours, expire_date(加班当月+2个月末), source_overtime_id |
| 表名 | 说明 | 核心字段 |
|---|---|---|
| salary_template | 薪资账套表 | id, template_name, description, effective_date, status |
| salary_template_item | 薪资账套项目表 | id, template_id, item_name, item_type(1-固定收入/2-变动收入/3-考勤扣款/4-社保/5-公积金/6-个税), calc_method(fixed/formula/rule), calc_formula, sort_order |
| employee_salary | 员工薪资档案表 | id, employee_id(唯一), template_id, base_salary, post_allowance(岗位津贴), performance_base(绩效基数), social_insurance_base(社保基数), housing_fund_base(公积金基数), effective_date |
| salary_batch | 薪资核算批次表 | id, batch_name, year_month(唯一), total_employees, total_gross(应发总额), total_deduction(扣除总额), total_net(实发总额), status(0-草稿/1-计算中/2-待确认/3-审批中/4-已通过/5-已发放/6-已驳回), created_by |
| salary_record | 薪资明细表 | id, batch_id, employee_id, base_salary, post_allowance, performance_bonus, overtime_pay, attendance_deduction(考勤扣款), leave_deduction(请假扣款), pension/medical_insurance/unemployment_insurance/housing_fund(社保公积金), income_tax(个税), gross_salary(应发), total_deduction(扣除合计), net_salary(实发)(按批次+员工联合唯一) |
| salary_adjustment | 调薪记录表 | id, employee_id, old_salary/new_salary, adjust_reason, effective_date, created_by |
| 表名 | 说明 | 核心字段 |
|---|---|---|
| approval_instance | 审批流程实例表 | id, business_type(1-入职/2-转正/3-调岗/4-离职/5-请假/6-补卡/7-薪资批次), business_id(关联业务表ID), title, applicant_id(申请人), status(0-进行中/1-已通过/2-已拒绝/3-已撤回), current_node, deleted |
| approval_node | 审批节点表 | id, instance_id, node_order, approver_id(审批人用户ID), node_name, status(0-待审批/1-已通过/2-已拒绝/3-已转交), opinion(审批意见), approved_at |
| approval_delegation | 审批委托表 | id, delegator_id(委托人), delegate_id(被委托人), start_date/end_date, status(0-已取消/1-生效中) |
| notification | 通知消息表 | id, user_id, title, content, type(clock_reminder/approval/system), is_read(0-未读/1-已读) |
employee (员工) ──┬── department (部门,多对一)
├── position (职位,多对一)
├── sys_user (用户,一对一)
├── employee_salary (薪资档案,一对一)
├── attendance_group_member (考勤组成员,多对多)
├── leave_balance (假期余额,一对多)
├── clock_record (打卡记录,一对多)
├── salary_record (薪资记录,一对多)
├── regularization (转正,一对多)
├── transfer (调岗,一对多)
└── resignation (离职,一对多)
sys_user (用户) ──┬── sys_user_role (关联表,多对多) ── sys_role (角色)
├── sys_role_permission (关联表,多对多) ── sys_permission (权限)
├── approval_instance (审批实例,一对多)
└── notification (通知,一对多)
salary_batch (批次) ──── salary_record (明细,一对多)
approval_instance (审批) ──── approval_node (节点,一对多)
attendance_group (考勤组) ──┬── attendance_group_member (成员关联)
└── attendance_group_department (部门关联)
hrms-backend/
├── pom.xml # Maven 依赖配置
├── src/main/java/com/hrms/
│ ├── HrmsApplication.java # Spring Boot 启动类
│ ├── aspect/
│ │ └── OperationLogAspect.java # 操作日志切面(AOP记录操作日志)
│ ├── common/ # 公共枚举、常量、工具类
│ │ ├── Result.java / ResultCode.java # 统一响应结果封装
│ │ ├── PageRequest.java / PageResult.java # 分页请求/响应
│ │ ├── BusinessType.java # 业务类型枚举(入职/转正/调岗/离职/请假/补卡/薪资)
│ │ ├── ClockStatus.java # 打卡状态枚举
│ │ ├── SalaryBatchStatus.java # 薪资批次状态枚举
│ │ ├── ApprovalStatus.java # 审批状态枚举
│ │ ├── EmploymentStatus.java # 在职状态枚举
│ │ ├── OperationLog.java # 操作日志注解
│ │ └── ...(其他枚举)
│ ├── config/ # 配置类
│ │ ├── SecurityConfig.java # Spring Security 安全配置
│ │ ├── JwtAuthenticationFilter.java # JWT 认证过滤器(从Header提取Token)
│ │ ├── LoginUser.java # 当前登录用户上下文
│ │ ├── RedisConfig.java # Redis 配置
│ │ ├── RabbitMQConfig.java # RabbitMQ 消息队列配置
│ │ ├── AiConfig.java # Spring AI 配置(通义千问)
│ │ ├── RestTemplateConfig.java # HTTP 客户端配置
│ │ ├── WebMvcConfig.java # Web MVC 配置
│ │ └── UserDetailsServiceImpl.java # Spring Security 用户详情加载
│ ├── controller/ # 控制器层(REST API)
│ │ ├── AuthController.java # 认证接口
│ │ ├── EmployeeController.java # 员工管理接口
│ │ ├── DepartmentController.java # 部门管理接口
│ │ ├── PositionController.java # 职位管理接口
│ │ ├── OnboardingController.java # 入职管理接口
│ │ ├── RegularizationController.java# 转正管理接口
│ │ ├── TransferController.java # 调岗管理接口
│ │ ├── ResignationController.java # 离职管理接口
│ │ ├── AttendanceController.java # 考勤管理接口
│ │ ├── AttendanceGroupController.java# 考勤组管理接口
│ │ ├── LeaveController.java # 请假管理接口
│ │ ├── ClockSupplementController.java# 补卡管理接口
│ │ ├── SalaryController.java # 薪资管理接口
│ │ ├── ApprovalController.java # 审批中心接口
│ │ ├── ApprovalDelegationController.java # 审批委托接口
│ │ ├── DashboardController.java # 工作台仪表盘接口
│ │ ├── NotificationController.java # 通知消息接口
│ │ ├── HolidayController.java # 节假日管理接口
│ │ ├── OvertimeApplicationController.java # 加班管理接口
│ │ ├── SystemController.java # 系统管理接口
│ │ └── CustomerServiceController.java # AI智能客服接口
│ ├── dto/ # 数据传输对象(请求参数)
│ │ ├── LoginDTO.java # 登录参数(username, password)
│ │ ├── EmployeeDTO.java # 员工创建/更新参数
│ │ ├── EmployeeQueryDTO.java # 员工查询参数
│ │ ├── EmployeeSalaryUpdateDTO.java # 薪资调整参数(baseSalary, postAllowance)
│ │ ├── OnboardingDTO.java # 入职申请参数
│ │ ├── RegularizationDTO.java # 转正申请参数
│ │ ├── TransferDTO.java # 调岗申请参数
│ │ ├── ResignationDTO.java # 离职申请参数
│ │ ├── DepartmentDTO.java # 部门创建/更新参数
│ │ ├── PositionDTO.java # 职位创建/更新参数
│ │ ├── LeaveApplicationDTO.java # 请假申请参数
│ │ └── ApprovalActionDTO.java # 审批操作参数(instanceId, action, opinion)
│ ├── entity/ # 实体类(对应数据库表)
│ │ ├── Employee.java / SysUser.java / Department.java / Position.java
│ │ ├── Onboarding.java / Regularization.java / Transfer.java / Resignation.java
│ │ ├── ClockRecord.java / LeaveApplication.java / LeaveBalance.java
│ │ ├── ClockSupplement.java / AttendanceGroup.java / AttendanceGroupMember.java
│ │ ├── AttendanceMonthlyStats.java / Holiday.java / OvertimeApplication.java
│ │ ├── SalaryBatch.java / SalaryRecord.java / SalaryTemplate.java
│ │ ├── SalaryTemplateItem.java / EmployeeSalary.java / SalaryAdjustment.java
│ │ ├── ApprovalInstance.java / ApprovalNode.java / ApprovalDelegation.java
│ │ ├── Notification.java
│ │ └── SysLoginLog.java / SysOperationLog.java / SysPermission.java / SysRole.java / SysUserRole.java / SysRolePermission.java
│ ├── exception/ # 异常处理
│ │ ├── BusinessException.java # 业务异常
│ │ └── GlobalExceptionHandler.java # 全局异常处理器(@ControllerAdvice)
│ ├── mapper/ # MyBatis Mapper 接口
│ │ ├── EmployeeMapper.java / DepartmentMapper.java / PositionMapper.java
│ │ ├── OnboardingMapper.java / RegularizationMapper.java
│ │ ├── TransferMapper.java / ResignationMapper.java
│ │ ├── ClockRecordMapper.java / LeaveApplicationMapper.java / LeaveBalanceMapper.java
│ │ ├── ClockSupplementMapper.java / AttendanceGroupMapper.java
│ │ ├── AttendanceMonthlyStatsMapper.java / HolidayMapper.java / OvertimeApplicationMapper.java
│ │ ├── SalaryBatchMapper.java / SalaryRecordMapper.java / SalaryTemplateMapper.java
│ │ ├── EmployeeSalaryMapper.java / SalaryAdjustmentMapper.java
│ │ ├── ApprovalInstanceMapper.java / ApprovalNodeMapper.java / ApprovalDelegationMapper.java
│ │ ├── NotificationMapper.java / SysUserMapper.java / SysRoleMapper.java
│ │ └── SysPermissionMapper.java / SysOperationLogMapper.java / SysLoginLogMapper.java
│ ├── service/ # 业务服务接口
│ │ └── impl/ # 服务实现类
│ │ ├── AuthServiceImpl.java # 认证服务(登录/登出/改密)
│ │ ├── EmployeeServiceImpl.java # 员工管理
│ │ ├── DepartmentServiceImpl.java # 部门管理
│ │ ├── PositionServiceImpl.java # 职位管理
│ │ ├── OnboardingServiceImpl.java # 入职(创建员工+生成工号+创建账号)
│ │ ├── RegularizationServiceImpl.java # 转正(更新员工状态为正式)
│ │ ├── TransferServiceImpl.java # 调岗(更新部门/职位/上司)
│ │ ├── ResignationServiceImpl.java # 离职(禁用账号)
│ │ ├── AttendanceServiceImpl.java # 考勤(打卡判定/统计/缺卡补充)
│ │ ├── AttendanceGroupServiceImpl.java # 考勤组管理
│ │ ├── LeaveServiceImpl.java # 请假(余额校验/工作日计算/扣减余额)
│ │ ├── ClockSupplementServiceImpl.java # 补卡审批(更新打卡记录)
│ │ ├── SalaryServiceImpl.java # 薪资核算(考勤汇总→薪资计算→个税)
│ │ ├── ApprovalServiceImpl.java # 审批流程(通过/驳回→执行业务逻辑)
│ │ ├── ApprovalDelegationServiceImpl.java # 审批委托
│ │ ├── NotificationServiceImpl.java # 通知消息
│ │ ├── DashboardServiceImpl.java # 仪表盘统计
│ │ ├── SystemServiceImpl.java # 系统管理
│ │ ├── HolidayServiceImpl.java # 节假日
│ │ ├── OvertimeApplicationServiceImpl.java # 加班审批
│ │ ├── ClockReminderServiceImpl.java # 打卡提醒(RabbitMQ延迟消息)
│ │ └── MonthlyAttendanceSummaryTask.java # 考勤月度汇总定时任务
│ ├── tool/
│ │ └── HrTools.java # 自定义提示词工具(AI客服)
│ ├── util/
│ │ ├── JwtUtil.java # JWT 生成/解析工具
│ │ └── ApprovalUtil.java # 审批工具(审批人自动确定逻辑)
│ └── vo/ # 视图对象(返回给前端的数据)
│ ├── LoginVO.java # 登录返回(token, userId, roles, permissions)
│ ├── UserInfoVO.java # 用户信息(含员工详情+部门+职位+角色权限)
│ ├── EmployeeVO.java # 员工视图(含部门名/职位名/汇报人)
│ ├── DepartmentVO.java # 部门视图(含负责人名/员工数/子部门树)
│ ├── PositionVO.java # 职位视图
│ ├── OnboardingVO.java / RegularizationVO.java / TransferVO.java / ResignationVO.java
│ ├── LeaveApplicationVO.java # 请假申请视图
│ ├── SalaryRecordVO.java # 薪资记录视图(所有薪资项目明细)
│ ├── ApprovalVO.java / ApprovalNodeVO.java # 审批实例/节点视图
│ ├── DashboardStatsVO.java # 仪表盘统计视图
│ └── EmployeeSalaryConfigVO.java # 员工薪资配置视图
└── src/main/resources/
├── application.yml # 应用配置文件
└── mapper/ # MyBatis XML Mapper 文件
├── EmployeeMapper.xml / DepartmentMapper.xml / ... (每个Mapper对应一个XML)
└── ...(共30+个XML文件)
hrms-frontend/
├── package.json # 依赖配置
├── vite.config.ts # Vite 构建配置(代理 /api 到后端8080)
├── tsconfig.json # TypeScript 配置
├── index.html # 入口HTML
├── src/
│ ├── main.tsx # 应用入口(ReactDOM.createRoot)
│ ├── App.tsx # 根组件(BrowserRouter)
│ ├── router.tsx # 路由配置(所有页面路由 + 权限守卫)
│ ├── api/ # API 接口封装
│ │ ├── auth.ts # 登录/登出/改密/个人信息
│ │ ├── employee.ts # 员工CRUD
│ │ ├── department.ts # 部门管理
│ │ ├── position.ts # 职位管理
│ │ ├── onboarding.ts # 入职管理
│ │ ├── regularization.ts # 转正管理
│ │ ├── transfer.ts # 调岗管理
│ │ ├── resignation.ts # 离职管理
│ │ ├── attendance.ts # 考勤打卡/记录/统计
│ │ ├── attendanceGroup.ts # 考勤组管理
│ │ ├── leave.ts # 请假管理
│ │ ├── clockSupplement.ts # 补卡管理
│ │ ├── overtime.ts # 加班管理
│ │ ├── salary.ts # 薪资管理
│ │ ├── approval.ts # 审批中心
│ │ ├── approvalDelegation.ts # 审批委托
│ │ ├── dashboard.ts # 工作台
│ │ ├── notification.ts # 通知消息
│ │ ├── system.ts # 系统管理
│ │ └── customerService.ts # AI客服
│ ├── pages/ # 页面组件
│ │ ├── login/index.tsx # 登录页
│ │ ├── dashboard/index.tsx # 工作台仪表盘
│ │ ├── organization/
│ │ │ ├── DepartmentList.tsx # 部门管理页
│ │ │ └── PositionList.tsx # 职位管理页
│ │ ├── employee/
│ │ │ └── EmployeeList.tsx # 员工列表页(含新增/编辑/查看/删除)
│ │ ├── onboarding/
│ │ │ └── OnboardingList.tsx # 入职申请页(创建/提交/删除)
│ │ ├── regularization/
│ │ │ └── RegularizationList.tsx # 转正申请页
│ │ ├── transfer/
│ │ │ └── TransferList.tsx # 调岗申请页
│ │ ├── resignation/
│ │ │ └── ResignationList.tsx # 离职申请页
│ │ ├── attendance/
│ │ │ ├── AttendanceStats.tsx # 考勤统计页
│ │ │ ├── AttendanceGroupList.tsx # 考勤组管理页
│ │ │ ├── LeaveList.tsx # 请假管理页
│ │ │ └── OvertimeList.tsx # 加班管理页
│ │ ├── salary/
│ │ │ ├── SalaryTemplateList.tsx # 薪资账套页
│ │ │ ├── SalaryBatchList.tsx # 薪资核算页(核心)
│ │ │ ├── PaySlipList.tsx # 工资条页
│ │ │ └── SalaryAdjust.tsx # 薪资调整页
│ │ ├── approval/
│ │ │ ├── PendingApprovals.tsx # 待办审批
│ │ │ ├── DoneApprovals.tsx # 已办审批
│ │ │ └── DelegationList.tsx # 审批委托
│ │ ├── personal/
│ │ │ ├── MyProfile.tsx # 个人信息
│ │ │ ├── MyAttendance.tsx # 我的考勤
│ │ │ ├── MyLeave.tsx # 我的请假
│ │ │ ├── MySalary.tsx # 我的薪资
│ │ │ ├── MySupplement.tsx # 我的补卡
│ │ │ └── AccountSecurity.tsx # 账号安全
│ │ ├── system/
│ │ │ ├── UserList.tsx # 用户管理
│ │ │ ├── RoleList.tsx # 角色管理
│ │ │ └── LogList.tsx # 日志管理
│ │ └── notification/
│ │ └── NotificationList.tsx # 通知列表
│ ├── layouts/
│ │ └── MainLayout.tsx # 主布局(侧边栏菜单 + 顶栏通知 + 面包屑)
│ ├── stores/ # Zustand 状态管理
│ │ ├── authStore.ts # 认证状态(用户信息/权限/登录/登出)
│ │ ├── appStore.ts # 应用状态(侧边栏折叠)
│ │ └── notificationStore.ts # 通知状态(未读数/列表)
│ ├── types/
│ │ └── index.ts # 所有 TypeScript 类型定义
│ ├── utils/
│ │ ├── request.ts # Axios 封装(拦截器/Token注入/错误处理)
│ │ └── auth.ts # Token 存储工具
│ ├── constants/
│ │ └── enums.ts # 枚举常量
│ └── styles/ # 样式文件
用户通过手机号/账号和密码登录系统,系统验证身份后颁发 JWT Token,后续所有请求通过 Token 进行身份认证。支持密码修改、密码验证、个人资料更新、登录历史查看等功能。
- sys_user:验证用户名和密码(BCrypt加密存储),获取用户状态
- sys_role:获取用户的角色信息
- sys_permission:获取用户的权限集合
- sys_login_log:记录每次登录的IP、浏览器、地点、状态
- employee:获取员工详情用于个人信息展示(通过 employee_id 关联)
前端请求(POST /api/auth/login):
// 请求体 (LoginDTO)
{
"username": "13800000001", // 登录账号(手机号)
"password": "Admin123" // 密码
}后端逻辑:
AuthServiceImpl.login()接收LoginDTO,通过sysUserMapper.selectByUsername()从sys_user表查询用户- 检查用户是否存在 → 不存在则抛出异常并记录失败日志到
sys_login_log表 - 检查用户状态是否启用 → 已禁用则抛出异常
- 使用
BCryptPasswordEncoder.matches()校验密码 → 密码错误记录失败日志 - 检查用户角色是否被禁用
- 验证通过后,使用
JwtUtil.generateToken()生成 JWT Token - 将 Token 存入 Redis(有效期24小时),key格式:
hrms:token:{username} - 更新
sys_user表的last_login_time - 记录登录成功日志到
sys_login_log表,包含IP地址、浏览器信息、IP定位(通过 ip-api.com 接口获取地理位置) - 查询用户的角色标识集合和权限标识集合
后端返回(LoginVO):
{
"token": "eyJhbGciOiJIUzI1NiJ9...", // JWT Token
"userId": 1,
"username": "13800000001",
"employeeId": 1, // 关联的员工ID
"roles": ["ADMIN", "HR"], // 角色标识集合
"permissions": ["dashboard", "employee", "salary:batch", ...], // 权限标识集合
"forceChangePwd": 1 // 是否需要强制修改密码
}JwtAuthenticationFilter 在每个请求前执行:
- 从请求头
Authorization: Bearer {token}中提取 Token - 使用
JwtUtil解析 Token,获取用户 ID 和用户名 - 从 Redis 中验证 Token 是否有效(对比
hrms:token:{username}) - 从
sys_user表加载用户信息,封装成LoginUser对象设置到SecurityContextHolder - 放行
/api/auth/**和/api/public/**路径
前端调用 POST /api/auth/logout,后端从 Redis 中删除该用户的 Token。
前端请求(PUT /api/auth/change-password):
{
"oldPassword": "Admin123",
"newPassword": "NewPass456"
}后端逻辑:
- 校验旧密码是否正确(
passwordEncoder.matches()) - 新密码经过 BCrypt 加密后更新
sys_user表的 password 字段 - 将
force_change_pwd字段置为 0(表示不再需要强制修改) - 从 Redis 中删除旧 Token,强制用户重新登录
前端请求(GET /api/auth/user-info):
后端逻辑:通过 SecurityContextHolder 获取当前登录用户,从 sys_user 表查询基本信息,用 employee_id 关联 employee 表查询员工详情(姓名、部门、职位等),从 department 表获取部门名称,从 position 表获取职位名称。
后端返回(UserInfoVO):
{
"userId": 1,
"username": "13800000001",
"employeeId": 1,
"employeeNo": "202200001",
"name": "刘备",
"gender": 1,
"phone": "13800000001",
"email": "liubei@hrms.com",
"departmentId": 1,
"departmentName": "总公司",
"positionName": "老总",
"jobLevel": 1,
"employmentStatus": 2,
"currentAddress": "...",
"emergencyContact": "...",
"emergencyContactPhone": "...",
"hireDate": "2022-01-01",
"roles": ["ADMIN"],
"permissions": ["dashboard", "employee", ...]
}前端请求(PUT /api/auth/update-profile):可更新 email、currentAddress、emergencyContact、emergencyContactPhone 四个字段。
后端通过当前用户关联的 employee_id,更新 employee 表中的对应字段。
前端请求(GET /api/auth/login-history):从 sys_login_log 表查询当前用户最近10条登录记录。
展示系统核心统计数据,包括员工总数、今日考勤人数、待审批数量、本月薪资概况等。
- employee:统计员工总数、试用期人数、正式员工人数
- attendance_group_member / clock_record:统计今日考勤
- approval_instance:统计待审批数量
- salary_batch / salary_record:统计本月薪资
前端请求(GET /api/dashboard/stats):
后端逻辑(DashboardServiceImpl):
employeeMapper.countByStatus()→ 统计试用期人数、正式人数、待离职人数- 统计今日打卡人数、待审批数量
- 查询最近一条薪资记录的应发总额
后端返回(DashboardStatsVO):
{
"totalEmployees": 30,
"todayAttendance": 25,
"pendingApprovals": 3,
"monthlySalary": 500000,
"probationCount": 2,
"regularCount": 25,
"pendingResignation": 1
}- department:部门数据(树形结构,通过 parent_id 自关联)
- employee:统计各部门员工数,关联 leader_id 获取部门负责人姓名
查询部门树:GET /api/departments
- 后端从
department表查询所有未删除的部门(deleted=0) - 按照
parent_id组装成树形结构 - 每个部门返回时统计该部门员工数量
- 通过
employee表关联查询部门负责人名称
创建部门(POST /api/departments):
// 请求体 (DepartmentDTO)
{
"departmentName": "测试部",
"departmentCode": "TEST",
"deptCode": "09",
"parentId": 1,
"leaderId": 2,
"sortOrder": 6,
"description": "测试部门"
}更新部门(PUT /api/departments/{id}):更新部门基本信息,修改负责人时同时更新 department.leader_id。
删除部门(DELETE /api/departments/{id}):逻辑删除(deleted=1),限制只有无子部门且无员工的部门才能删除。
更换部门负责人(PUT /api/departments/{id}/leader):
{"newLeaderId": 5}更新 department.leader_id 字段。
查看部门员工(GET /api/departments/{id}/employees):从 employee 表查询指定部门的员工列表。
- position:职位数据,含职级(1-老总/2-部门负责人/3-普通员工)、所属部门、默认试用期
- department:关联查询部门名称
职位CRUD:GET/POST/PUT/DELETE /api/positions
- 查询所有职位(含部门名称)
- 创建时指定名称、职级、所属部门、默认试用期月数
- 支持按部门筛选:GET
/api/positions/department/{departmentId}
对在职员工进行增删改查,支持多维度筛选查询,查看员工详情。
- employee:员工主表(所有员工数据)
- department:部门名称
- position:职位名称
- employee_salary:薪资档案信息
分页查询(GET /api/employees):
// 请求参数 (EmployeeQueryDTO)
{
"keyword": "张", // 姓名/手机号模糊搜索
"departmentIds": [2, 7], // 部门筛选
"positionIds": [4], // 职位筛选
"employmentStatusList": [1, 2], // 在职状态筛选
"jobLevels": [3], // 职级筛选
"hireDateStart": "2024-01-01",
"hireDateEnd": "2024-12-31",
"pageNum": 1,
"pageSize": 10
}后端逻辑:EmployeeServiceImpl 通过 MyBatis Mapper 执行多条件动态查询,使用 <where> 标签动态拼接 SQL。
后端返回(PageResult):
{
"list": [
{
"id": 8,
"employeeNo": "202306001",
"name": "赵子龙",
"gender": 1,
"phone": "13800000008",
"departmentId": 7,
"departmentName": "前端组",
"positionId": 5,
"positionName": "前端开发工程师",
"jobLevel": 3,
"supervisorId": 2,
"supervisorName": "吕布",
"employmentStatus": 2,
"baseSalary": 14000.00,
"hireDate": "2023-03-15",
...
}
],
"total": 30,
"pageNum": 1,
"pageSize": 10
}创建员工(POST /api/employees):将数据插入 employee 表,自动生成工号(年份+部门编码+序号)。
更新员工(PUT /api/employees/{id}):更新员工基本信息。
删除员工(DELETE /api/employees/{id}):逻辑删除。
查看详情(GET /api/employees/{id}):返回完整的员工信息,含部门名、职位名、汇报人姓名等。
HR填写新员工入职信息 → 提交审批 → 审批通过后自动创建员工记录和系统账号(支持入职→创建员工→创建账号完整流程)。
- onboarding:入职申请数据(状态流转: 0-草稿 → 1-审批中 → 2-已批准 → 4-已入职)
- employee:审批通过后在此表创建员工记录
- sys_user:审批通过后在此表创建系统登录账号
- sys_user_role:关联用户角色
- department:获取部门编码用于生成工号
- position:获取职位信息用于确定角色和职级
- approval_instance:创建审批实例
- approval_node:创建审批节点
- notification:发送通知给审批人
前端请求体(OnboardingDTO):
{
"name": "张新员工",
"gender": 1,
"phone": "13800000031",
"email": "new@hrms.com",
"idCard": "110101199001011234",
"expectedHireDate": "2026-08-01",
"departmentId": 8,
"positionId": 4,
"hireType": 1,
"probationMonths": 3,
"supervisorId": 2
}注意:
probationMonths在前端表单中固定为3个月(禁用输入框),所有部门统一试用期3个月。probationSalaryRatio已从提交载荷中移除,试用期薪资统一按固定薪资的80%计算,且无岗位津贴。
后端逻辑:
OnboardingServiceImpl.createOnboarding()将数据插入onboarding表- 状态置为
DRAFT(0)(草稿状态) - 如果未指定 supervisorId,自动从
department表获取部门负责人的 ID
后端逻辑:
- 将
onboarding表状态更新为PENDING(1)(审批中) - 在
approval_instance表创建审批实例(business_type=1, business_id=入职ID, title="入职审批 - 姓名", status=0) - 根据职位的职级确定审批人:
- 普通员工职位(job_level=3)→ 部门负责人
- 部门负责人职位(job_level=2)→ 老总
- 老总职位(job_level=1)→ 无需审批
- 在
approval_node表创建第一个审批节点 - 通过
notification表发送通知给审批人
当审批中心处理完流程后回调此方法:
- 验证入职申请状态为
PENDING - 生成工号:调用
generateEmployeeNo(),格式为 年份(4位) + 部门编码(2位) + 序号(3位) = 9位- 例:赵子龙的工号为
202306001(2023年,前端组dept_code=06,序号001) - 从
department表获取dept_code(2位数字编码) - 从
employee表查询该年份+部门下的最大工号序号,+1后生成
- 例:赵子龙的工号为
- 将数据插入
employee表(雇佣状态=试用期),薪资按职位固定薪资设置 - 根据职位自动确定角色的规则:
- "部门大哥"职位 → 部门主管角色(role_id=3)
- "老总"职位 → 系统管理员角色(role_id=1)
- 职位名含"HR"或"人力" → HR专员角色(role_id=2)
- 职位名含"财务" → 财务专员角色(role_id=4)
- 其他 → 普通员工角色(role_id=5)
- 创建系统账号(用户名=手机号,初始密码=123456,
force_change_pwd=1)- 如果该手机号的账号已存在(可能是离职员工重新入职):恢复账号启用,重新关联新员工ID
- 更新
onboarding表状态为APPROVED(2),设置employee_id字段
更新 onboarding 表状态为 REJECTED(3)。
只允许删除草稿(0)或已驳回(3)状态的记录,物理删除。
为试用期员工发起转正申请 → 审批通过后更新员工为正式员工状态。
- regularization:转正申请数据(状态: 0-待发起 → 1-审批中 → 2-已通过 → 3-已拒绝)
- employee:审批通过后更新 employment_status 为正式(2)
- approval_instance / approval_node:审批流程
- notification:通知
前端请求体(RegularizationDTO):
{
"employeeId": 8,
"probationEndDate": "2023-06-15",
"evaluation": "该员工工作表现优秀,..."
}注意:
probationEndDate在前端表单中标签为"生效日期"(即转正生效日期)。试用期开始日期已移除,试用期固定为3个月(由入职时确定)。薪资调整字段已移除,转正后薪资按职位固定薪资自动生效。
后端逻辑:
- 校验员工当前状态必须是试用期(PROBATION)
- 数据插入
regularization表,状态为 DRAFT(0)
与入职类似的流程:更新状态→创建审批实例→确定审批人→发送通知。
- 更新
regularization表的 status 为 APPROVED(2),result 为 PASSED(1) - 更新
employee表的employment_status为 REGULAR(2)(正式员工) - 转正后薪资自动按职位固定薪资生效(基本工资=职位固定薪资,岗位津贴=职位固定津贴),不再享受试用期80%折扣
更新 regularization 表状态为 REJECTED(3)。
为员工发起调岗申请(变更部门、职位、职级、汇报人)→ 审批通过后自动更新员工信息。
- transfer:调岗申请(保存原和新部门/职位/职级/汇报人)
- employee:审批通过后更新员工的 department_id, position_id, job_level, supervisor_id
- approval_instance / approval_node / notification:审批流程
前端请求体(TransferDTO):
{
"employeeId": 8,
"newDepartmentId": 3,
"newPositionId": 6,
"newJobLevel": 3,
"newSupervisorId": 3,
"transferReason": "根据业务发展需要...",
"transferDate": "2026-08-01"
}注意:薪资调整字段已从调岗表单中移除。调岗后薪资按新职位的固定薪资自动生效(由职位表中的默认薪资决定)。 后端逻辑:
- 校验员工状态(试用期或正式才可调岗)
- 查询
employee表获取原部门/职位/职级/汇报人信息,填入transfer表 - 如果未指定新汇报人,自动从
department表获取新部门负责人 - 状态为 DRAFT(0)
- 更新
transfer表状态为 APPROVED(2) - 更新
employee表的department_id,position_id,job_level,supervisor_id - 调岗后薪资自动按新职位的固定薪资生效(由薪资调整页面统一管理)
为员工发起离职申请 → 审批通过后更新员工为已离职状态并禁用系统账号。
- resignation:离职申请
- employee:审批通过后更新 employment_status 为已离职(4)
- sys_user:审批通过后禁用账号(status=0)
- approval_instance / approval_node / notification:审批流程
前端请求体(ResignationDTO):
{
"employeeId": 9,
"resignationDate": "2026-08-15",
"resignationReason": 1,
"resignationType": 1,
"reasonDetail": "个人发展原因...",
"handoverEmployeeId": 8
}resignationReason: 1-主动离职, 2-被动, 3-协商 resignationType: 1-辞职, 2-辞退, 3-合同到期不续签, 4-其他
- 更新
resignation表状态为 APPROVED(2) - 更新
employee表的employment_status为 RESIGNED(4) - 查询
sys_user表中关联该员工的账号,禁用账号(status=0)
- attendance_group:考勤组(含上下班时间、迟到/早退阈值)
- attendance_group_member:成员关联
- attendance_group_department:适用部门关联
CRUD(GET/POST/PUT/DELETE /api/attendance-groups):
- 创建时设置考勤组名称、班次类型(固定班/弹性班/排班制)、上下班时间、午休时间、迟到/早退阈值
- 成员管理:GET/PUT
/attendance-groups/{id}/members设置考勤组包含的员工 - 部门管理:GET/PUT
/attendance-groups/{id}/departments设置考勤组适用的部门
系统默认两个考勤组:
- 标准工时组(09:00-18:00):除人力资源部外所有部门
- 非标准工时组(10:00-20:00):人力资源部专用
- clock_record:打卡记录
- attendance_group:考勤组规则
- holiday:法定节假日
- leave_application:请假校验
- overtime_application:加班校验
上班打卡(POST /api/attendance/clock):
{"clockType": 1} // 1-上班打卡, 2-下班打卡后端打卡判定逻辑(AttendanceServiceImpl.clock()):
- 权限校验:仅允许指定员工(吕布 employeeId=2、貂蝉=4、赵子龙=8)打卡
- 日期校验:
- 检查是否为周末(周六/周日)→ 如是则检查是否有已通过的加班申请,无则抛出"休息日无需打卡"
- 通过
holidayService.isHoliday()检查是否为法定节假日 → 逻辑同上
- 请假校验:从
leave_application表查询当日是否有已通过的请假 → 如有则"今日正在请假中,无需打卡" - 重复打卡校验:检查当日是否已打过卡(上班/下班)
- 考勤组规则:获取员工所属考勤组,根据上下班时间和迟到阈值计算打卡状态
打卡状态计算逻辑(calculateClockStatus):
上班打卡判定:
| 打卡时间 | 状态 |
|---|---|
| ≤ 规定上班时间 | 正常(1) |
| 规定上班时间 ~ 规定时间+阈值 | 迟到(2) |
| 规定时间+阈值 ~ 12:00 | 上班缺卡/旷工半天(5) |
| > 12:00 | 缺勤(7) |
下班打卡判定:
| 打卡时间 | 状态 |
|---|---|
| ≥ 规定下班时间 | 正常(1) |
| 规定时间-阈值 ~ 规定时间 | 早退(3) |
| 13:00 ~ 规定时间-阈值 | 下班缺卡/旷工半天(6) |
| < 13:00 | 缺勤(7) |
后端的缺卡状态补充(fillMissingClockStatus): 在查询打卡记录时自动检查工作日的打卡情况:
- 工作日无任何记录 → 插入一条缺勤(7)记录
- 只有上班打卡无下班打卡 → 插入下班缺卡(6)记录(仅在下班时间后触发)
- 只有下班打卡无上班打卡 → 插入上班缺卡(5)记录
- clock_record:原始打卡记录
- attendance_monthly_stats:月度统计汇总表
- employee / department:关联员工和部门信息
查询考勤统计(GET /api/attendance/stats):
请求参数: yearMonth=2026-07, departmentId=2(可选), employeeId=8(可选)
权限控制:
- ADMIN/HR → 可查全公司/指定部门/指定员工
- 部门主管(MANAGER) → 可查本部门及子部门
- 普通员工 → 只能查自己
数据来源:从 clock_record 表按员工+月份分组统计
- 正常天数、迟到次数、早退次数、缺卡次数、旷工次数等
个人考勤查询(GET /api/attendance/my-attendance):
一次返回打卡记录和统计数据:
{
"records": [...], // 当月每日打卡记录
"stats": {} // 当月统计汇总
}每天 23:00 自动执行,将当月的原始打卡记录汇总到 attendance_monthly_stats 表。
- clock_record:读取原始打卡数据
- attendance_monthly_stats:写入统计数据(DELETE旧→INSERT新,支持幂等)
- overtime_application:读取已通过的加班天数
@Scheduled(cron = "0 0 23 * * ?") // 每天23:00执行- 计算当前月份(格式 yyyy-MM)
- 删除
attendance_monthly_stats表中该月份的旧数据 - 从
clock_record表和overtime_application表重新聚合生成新的月度统计- 统计每个员工的应出勤天数、正常天数、迟到次数、早退次数、旷工次数、缺卡次数、补卡次数、加班天数
- 批量插入
attendance_monthly_stats表
MyBatis 聚合 SQL(batchInsertFromClockRecords):
INSERT INTO attendance_monthly_stats (employee_id, year_month, work_days, normal_days, late_count, ...)
SELECT
employee_id, '2026-07' as year_month,
COUNT(DISTINCT clock_date) as work_days,
SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) as normal_days,
SUM(CASE WHEN status = 2 THEN 1 ELSE 0 END) as late_count,
...
FROM clock_record
WHERE clock_date BETWEEN '2026-07-01' AND '2026-07-31'
GROUP BY employee_id该定时任务为薪资核算提供数据基础——薪资核算时会重新调用此逻辑确保数据最新。
- leave_application:请假申请
- leave_balance:假期余额(按员工+类型+年份唯一)
- approval_instance / approval_node / notification:审批流程
- employee / department:关联信息
创建请假申请(POST /api/leaves):
// 前端请求体 (LeaveApplicationDTO)
{
"leaveType": 1,
"startTime": "2026-07-20 09:00",
"endTime": "2026-07-21 18:00",
"reason": "身体不适",
"handoverEmployeeId": 8,
"attachmentUrl": ""
}后端逻辑(LeaveServiceImpl.createLeave()):
-
仅允许指定员工(吕布、赵子龙、貂蝉)请假
-
解析起止时间,校验前者不能晚于后者
-
计算请假天数:工作日计算法,排除周末(周六日)
// countWorkingDays() 方法 // 遍历startDate到endDate,只计算周一到周五
-
从
leave_balance表查询该员工该类型该年份的剩余假期余额 -
余额不足则抛出异常
-
数据插入
leave_application表(状态=待审批) -
自动发起审批:创建审批实例 + 审批节点(审批人通过 ApprovalUtil 自动确定)
-
发送通知给审批人
-
注意:创建时不扣减余额,审批通过后才扣减
审批通过后(ApprovalServiceImpl 回调 LeaveServiceImpl.deductLeaveBalance()):
- 更新
leave_application状态为已通过(2) - 扣减假期余额:更新
leave_balance表的 used_days(+请假天数)和 remaining_days(-请假天数)
取消请假(PUT /api/leaves/{id}/cancel):
- 更新状态为已取消(4)
- 如果之前已进入审批中,恢复假期余额(used_days - 请假天数,remaining_days + 请假天数)
删除请假(DELETE /api/leaves/{id}):仅允许删除已通过或已拒绝的记录。
查询假期余额(GET /api/leaves/balance):返回当前用户的年假、病假、事假、调休等余额。
- clock_supplement:补卡申请
- clock_record:补卡审批通过后更新打卡状态
- approval_instance / approval_node / notification:审批流程
创建补卡申请(POST /api/clock-supplements):填写缺卡日期、打卡类型(上班/下班)、补卡时间、原因,自动发起审批。
审批通过:ClockSupplementService.approve() 更新 clock_supplement 状态为已通过,并更新对应日期的 clock_record 表状态为补卡(8)。
辅助查询(用于前端补卡页面):
GET /clock-supplements/absent-employees?yearMonth=2026-07:查指定月份有旷工记录的员工GET /clock-supplements/absent-dates?employeeId=8&yearMonth=2026-07:查指定员工指定月份的旷工日期GET /clock-supplements/my-count?yearMonth=2026-07:当前用户补卡次数GET /clock-supplements/my-absent-dates?yearMonth=2026-07:当前用户缺卡日期列表
- overtime_application:加班申请
- attendance_monthly_stats:加班审批通过后重新统计
- comp_time_balance:调休余额(加班可转调休)
创建加班申请(POST /api/overtime):
{
"employeeId": 8,
"overtimeDate": "2026-07-20",
"overtimeType": 2,
"reason": "项目上线",
...
}overtimeType: 1-工作日加班, 2-休息日加班, 3-法定节假日加班
加班审批通过:
- 更新
overtime_application状态为已通过(2) - 重新统计该员工当月的考勤数据:调用
attendanceMonthlyStatsMapper.batchInsertFromClockRecords()重新生成attendance_monthly_stats表数据
可用加班日期查询:GET /api/overtime/available-dates 返回当月可加班的日期(工作日+周末均可)。
薪资管理是本系统的核心模块,实现了完整的薪资核算流程:薪资账套配置 → 创建批次 → 自动核算 → 确认 → 提交审批 → 审批通过 → 标记发放。
- salary_template:薪资账套(模板)
- salary_template_item:账套项目明细
- employee_salary:员工薪资档案
查询账套(GET /api/salary/templates):从 salary_template 表查询所有启用状态的账套。
查询账套项目(GET /api/salary/templates/{id}/items):从 salary_template_item 表查询指定账套的工资项目,包括:
- 固定收入:基本工资、岗位津贴(calc_method=fixed)
- 变动收入:绩效奖金(formula: performance_base * coefficient)
- 考勤扣款:迟到扣款(rule: 50 * late_count)
- 社保:养老保险(social_insurance_base * 0.08)、医疗保险(0.02)、失业保险(0.005)
- 公积金(housing_fund_base * 0.12)
- 个税(formula: cumulative_withholding)
薪资档案查询(GET /api/salary/employee-configs):从 employee_salary 表查询所有员工的薪资配置(含基础薪资、岗位津贴、社保公积金基数等),返回 EmployeeSalaryConfigVO。
创建批次(草稿) → 计算(自动核算) → 待确认 → 提交审批 → 审批中 → 通过/驳回 → 标记发放
↑ |
└──────── 重新核算 ────────────────┘
- salary_batch:薪资批次(状态流转)
- salary_record:薪资明细(每个员工一条记录)
- employee_salary:薪资档案(取基本工资、岗位津贴、社保公积金基数)
- attendance_monthly_stats:月度考勤统计(取迟到/早退/缺卡/旷工数据)
- leave_application:请假数据(计算请假扣款)
- employee:员工信息(试用期判断)
- sys_user:发通知用
前端请求(POST /api/salary/batches):
{
"batchName": "2026年7月薪资",
"yearMonth": "2026-07"
}后端逻辑(SalaryServiceImpl.createBatch()):
- 校验 yearMonth 格式(yyyy-MM)
- 从
salary_batch表检查该月份是否已存在批次(yearMonth 唯一约束) - 插入
salary_batch表,状态为 DRAFT(0),created_by 设为当前用户
前端调用(POST /api/salary/batches/{id}/calculate):
后端逻辑(SalaryServiceImpl.calculateBatch()):
第一步:重新统计考勤数据
// 重新计算该月份的考勤统计数据(确保补卡等变更已同步)
attendanceMonthlyStatsMapper.deleteByYearMonth(yearMonth);
attendanceMonthlyStatsMapper.batchInsertFromClockRecords(yearMonth);先删除该月考勤统计,再从 clock_record 表重新汇总到 attendance_monthly_stats 表。
第二步:仅核算指定员工的薪资
系统目前配置了3名可核算员工:吕布(2)、赵子龙(8)、貂蝉(4)。从 employee 表筛选状态为试用期或正式的员工。
第三步:对每个员工调用 calculateEmployeeSalary() 逐项计算
| 计算步骤 | 数据来源 | 计算逻辑 |
|---|---|---|
| ① 基本工资 | employee_salary.base_salary |
试用期:基本工资×80%,且无岗位津贴;正式:取档案值 |
| ② 岗位津贴 | employee_salary.post_allowance |
试用期为0,正式员工取档案值 |
| ③ 加班费 | attendance_monthly_stats.overtime_days |
加班天数 × 200元/天 |
| ④ 绩效奖金 | 手动调整 | 默认0,可在核算预览中手动修改 |
| ⑤ 考勤扣款 | attendance_monthly_stats |
迟到50元/次 + 早退50元/次 + 缺卡100元/次 + 旷工半天100元/次 + 旷工整天200元/次 |
| ⑥ 请假扣款 | leave_application |
日工资(基本工资/22天) × 请假天数 |
| ⑦ 养老保险 | employee_salary.social_insurance_base |
社保基数 × 8% |
| ⑧ 医疗保险 | 同上 | 社保基数 × 2% |
| ⑨ 失业保险 | 同上 | 社保基数 × 0.5% |
| ⑩ 住房公积金 | employee_salary.housing_fund_base |
公积金基数 × 12% |
| ⑪ 个人所得税 | 简化版累计预扣法 | (应发-社保公积金-5000起征点) × 税率-速算扣除数 |
| ⑫ 应发工资 | = 基本工资 + 岗位津贴 + 绩效奖金 + 加班费 | |
| ⑬ 实发工资 | = 应发工资 - 考勤扣款 - 请假扣款 - 社保公积金 - 个税 |
个税计算(简化版累计预扣法):
应纳税所得额 = 应税收入 - 5000(起征点)
税率表:
不超过3000元 → 3%
3000~12000元 → 10% - 210
12000~25000元 → 20% - 1410
25000~35000元 → 25% - 2660
35000~55000元 → 30% - 4410
55000~80000元 → 35% - 7160
超过80000元 → 45% - 15160
计算完成后:
- 每名员工的薪资明细插入
salary_record表 - 更新
salary_batch表的总人数、应发总额、扣除总额、实发总额 - 批次状态更新为 PENDING_CONFIRM(2)(待确认)
前端请求(PUT /api/salary/records/{id}):在待确认状态下,允许手动调整绩效奖金、加班费、考勤扣款、请假扣款、备注,系统自动重新计算应发和实发。
将批次状态从 PENDING_CONFIRM(2) 更新为 PENDING_APPROVAL(3)(审批中)。进入审批中心后可进行审批操作。
后端逻辑:
- 校验批次状态为 PENDING_APPROVAL(3)
- 更新
salary_batch表状态为 APPROVED(4)(已通过)
后端逻辑(SalaryServiceImpl.markAsPaid()):
- 校验批次状态为 APPROVED(4)
- 更新
salary_batch表状态为 PAID(5)(已发放) - 遍历该批次的所有薪资记录,查询每个员工的
sys_user账号 - 向每个员工发送系统通知:
"您 2026-07 的工资已发放,实发金额: ¥xxxx",插入notification表
批次状态回退为 REJECTED(6),之后可修改后重新核算。
仅允许删除草稿、待确认或已驳回的批次,同时删除关联的 salary_record 记录。
提供薪资数据的可视化展示,包括月度趋势和薪资构成分析。
查询(GET /api/salary/stats?yearMonth=2026-07):
后端逻辑:
- 月度趋势:从
salary_batch表查询所有已通过或已发放的批次,按月汇总应发和实发总额 - 薪资构成:从
salary_record表聚合所有记录的基本工资、岗位津贴、绩效奖金、加班费,用于饼图展示
返回:
{
"monthlyTrend": [
{"month": "2026-06", "grossSalary": 500000, "netSalary": 380000, "totalEmployees": 3}
],
"compositionData": [
{"type": "基本工资", "value": 210000},
{"type": "岗位津贴", "value": 35000}
]
}调整员工的基本工资和岗位津贴,记录调薪历史。
- employee_salary:更新薪资档案
- salary_adjustment:记录调薪历史
查询员工薪资配置(GET /api/salary/employee-configs):从 employee_salary 表返回所有员工薪资配置的分页列表(含员工姓名、部门、职位、薪资模板等信息)。
调整薪资(PUT /api/salary/employee-configs/{id}):
{
"baseSalary": 18000,
"postAllowance": 2000
}后端校验不可为负数,更新 employee_salary 表对应字段。
员工可查看自己的历史薪资记录。
- salary_record:薪资明细
员工查看本人(GET /api/salary/my-records):
后端从 salary_record 表查询当前登录用户关联的员工的所有薪资记录。
管理员查看批次明细(GET /api/salary/batches/{id}/records):查询指定批次所有员工的薪资明细。
统一管理系统中所有业务(入职/转正/调岗/离职/请假/补卡/薪资批次)的审批流程,包括待办审批、已办审批、我的申请、审批委托。
- approval_instance:审批流程实例(记录业务类型、业务ID、状态、当前节点)
- approval_node:审批节点(审批人、状态、意见、时间)
- approval_delegation:审批委托设置
- 各个业务表:审批通过/驳回后更新对应业务状态(onboarding/regularization/transfer/resignation/leave_application/clock_supplement/salary_batch/overtime_application)
- notification:审批通知
创建申请 → 自动创建审批实例 → 通知审批人 → 审批人通过/驳回
│
┌──────┴──────┐
▼ ▼
审批通过 审批驳回
(执行业务逻辑) (更新业务状态)
普通员工(job_level=3) → 部门负责人(job_level=2)
部门负责人(job_level=2) → 老总(job_level=1)
老总(job_level=1) → 无需审批
- 从
approval_instance表获取审批实例(使用 FOR UPDATE 行锁防并发) - 获取当前审批节点(
approval_node),校验审批人身份 - 更新当前节点状态为通过(1)
- 检查是否有下一节点:
- 有 → 流转到下一节点,通知下一审批人
- 无 → 审批实例状态更新为已通过(1),执行业务逻辑
- 业务逻辑执行(handleBusinessApproval):
- 入职→创建员工和账号
- 转正→更新员工为正式
- 调岗→更新部门职位
- 离职→禁用账号
- 请假→扣减假期余额
- 补卡→更新打卡状态
- 加班→重算考勤统计
- 薪资批次→更新批次状态
- 发送审批结果通知给申请人
- 更新当前节点状态为驳回(2)
- 审批实例状态更新为已拒绝(2)
- 执行业务回滚逻辑(handleBusinessRejection)更新业务表状态为已拒绝
- 发送驳回通知给申请人
- ADMIN/HR → 查看所有待办审批
- 部门主管/普通员工 → 查看自己是审批人的待办审批
- 分页返回
ApprovalVO列表,含业务标题、申请人等信息
- ADMIN/HR → 查看所有已完成的审批
- 其他人 → 查看自己处理过的审批
查询当前用户发起的所有审批申请。
返回审批实例详情 + 所有审批节点 + 业务数据(businessData 根据 business_type 动态加载不同业务表的详情)。
{
"instanceId": 1,
"action": 1, // 1-通过, 2-驳回
"opinion": "同意"
}功能:审批人可将自己的审批权限临时委托给他人。
涉及的表:approval_delegation
- POST
/api/approval-delegations:创建委托 - POST
/api/approval-delegations/{id}/cancel:取消委托 - GET
/api/approval-delegations/my:查询我发起的委托 - GET
/api/approval-delegations/to-me:查询委托给我的
个人中心提供员工自助服务,包含个人信息查看编辑、个人考勤、个人请假、个人薪资、个人补卡、账号安全等功能。
- GET
/api/auth/user-info:展示个人信息 - PUT
/api/auth/update-profile:编辑邮箱、地址、紧急联系人
- GET
/api/attendance/my-attendance?yearMonth=2026-07:合并接口,一次返回当月打卡记录和统计数据 - 含上班/下班打卡按钮(POST
/api/attendance/clock)
- GET
/api/leaves:分页查询本人的请假申请 - POST
/api/leaves:提交请假申请 - PUT
/api/leaves/{id}/cancel:取消申请 - GET
/api/leaves/balance:查看假期余额
- GET
/api/salary/my-records:查看本人的工资条记录 - 展示各薪资项目明细(基本工资、岗位津贴、考勤扣款、社保公积金、个税、实发等)
- GET
/api/clock-supplements/my-absent-dates:查看本人当月缺卡日期 - GET
/api/clock-supplements/my-count:查看本人当月补卡次数 - POST
/api/clock-supplements:提交补卡申请
- POST
/api/auth/verify-password:验证当前密码 - PUT
/api/auth/change-password:修改密码 - GET
/api/auth/login-history:查看登录历史
- 查询和提交本人的加班申请
- 查看加班记录
- sys_user:系统用户
- sys_role:角色
- sys_user_role:用户角色关联
- 分页查询系统用户列表,显示用户名、关联员工、角色、状态、最后登录时间
- 创建用户:选择角色(支持多角色)
- 重置密码:PUT
/api/system/users/{id}/reset-password - 切换状态:PUT
/api/system/users/{id}/status(启用/禁用账号)
- sys_role:角色
- sys_permission:权限菜单
- sys_role_permission:角色权限关联
- CRUD 角色(ADMIN/HR/MANAGER/FINANCE/EMPLOYEE)
- 权限分配:GET/PUT
/api/system/roles/{id}/permissions返回/设置角色拥有的权限ID列表 - 所有权限以树形结构展示(菜单/按钮/接口三级)
- sys_operation_log:操作日志(通过 AOP 切面自动记录)
- sys_login_log:登录日志
- 操作日志:GET
/api/system/operation-logs记录每次业务操作的操作用户、操作描述、请求方法、请求参数、IP地址、执行状态 - 登录日志:GET
/api/system/login-logs记录每次登录的用户名、IP、浏览器、地点、登录时间、状态 - 操作日志通过
@OperationLog("创建薪资批次")注解 + AOP切面自动记录
系统内通知消息,包括审批通知、打卡提醒、系统通知等。
- notification:通知消息
- 分页查询当前用户的通知列表,按时间倒序
{"count": 5}- 单条已读:POST
/api/notifications/{id}/read - 全部已读:POST
/api/notifications/read-all
- 审批请求通知:新审批需要处理时通知审批人
- 审批结果通知:审批通过/驳回时通知申请人
- 薪资发放通知:薪资批次标记发放时通知所有员工
- 打卡提醒(通过 RabbitMQ 延迟消息,
ClockReminderService)
利用 Spring AI 集成通义千问(Qwen3.7)大模型,提供智能 HR 问答服务。
- POST
/api/customer-service/chat:用户输入问题,AI 模型返回回答 - 配置:
application.yml中配置阿里云 DashScope 的 API Key 和模型名称(qwen3.7-plus) - 自定义提示词在
HrTools.java中定义,限定 AI 回答 HR 相关领域知识
本项目由四人团队协作完成,采用模块化分工与统一接口规范的开发模式。以下重点阐述各模块间的依赖关系、核心业务链路集成以及协作规范。
| 成员 | 负责模块 | 核心职责 |
|---|---|---|
| 成员 A | 组织架构管理、员工档案管理 | 部门/职位 CRUD、员工信息维护、工号生成规则、薪资档案初始化 |
| 成员 B | 权限体系、个人中心 | RBAC 权限模型设计、JWT 认证流程、用户角色分配、个人信息管理 |
| 成员 C (我) | 考勤管理、薪资管理 | 打卡状态判定引擎、考勤统计定时任务、薪资核算公式与流程 |
| 成员 D | 入转调离流程、审批中心 | 通用审批流程引擎、业务状态机流转、消息通知推送 |
系统各模块并非孤立存在,而是通过数据流和事件驱动紧密耦合:
-
基础支撑层:
- 权限体系 (成员 B) 贯穿所有模块,通过
JwtAuthenticationFilter拦截请求,提供身份认证与接口级权限校验。 - 组织架构 (成员 A) 提供基础数据,所有业务数据(考勤、薪资、审批)均关联
employee_id和department_id。
- 权限体系 (成员 B) 贯穿所有模块,通过
-
业务驱动层:
- 审批中心 (成员 D) 是业务流转的枢纽。入职、转正、调岗、离职、请假等申请,审批通过后通过回调机制触发其他模块的状态变更。
-
数据应用层:
- 考勤与薪资 (成员 C) 处于业务下游。考勤数据依赖员工排班与打卡记录;薪资核算则依赖考勤统计结果与员工薪资档案。
入职流程是系统中最复杂的链路,涉及档案创建、权限分配与薪资初始化。
- 发起与审批 (成员 D):HR 提交入职申请,审批中心创建实例。
- 档案创建 (成员 A):审批通过后,回调
OnboardingServiceImpl.approve()。- 调用
generateEmployeeNo()生成唯一工号。 - 插入
employee表,状态设为"试用期"。
- 调用
- 权限开通 (成员 B):
- 调用
SysUserService.createUser()创建登录账号。 - 根据职位职级自动分配角色(如"部门大哥"分配 MANAGER 角色)。
- 调用
- 薪资初始化 (成员 C):
- 接收员工 ID,在
employee_salary表创建档案,写入该职位的固定基本工资与岗位津贴。
- 接收员工 ID,在
关键接口协作:
POST /api/onboardings/{id}/approve(成员 D)→ POST /api/employees(成员 A)→ POST /api/system/users(成员 B)→ POST /api/salary/employee-configs(成员 C)
薪资核算的准确性完全依赖于考勤数据的完整性。
- 数据采集 (成员 C):员工每日打卡,数据写入
clock_record。 - 数据聚合 (成员 C):
- 定时任务:每日 23:00 自动运行
MonthlyAttendanceSummaryTask,将原始打卡记录聚合为attendance_monthly_stats(月度统计表)。 - 实时触发:薪资核算执行前,会强制重新运行一次聚合逻辑,确保补卡、请假等最新变更已同步。
- 定时任务:每日 23:00 自动运行
- 薪资计算 (成员 C):核算引擎读取月度统计表,自动计算迟到/早退/缺卡扣款,并结合社保公积金公式生成最终工资条。
审批中心采用策略模式处理不同业务的审批结果:
- 转正审批通过 → 更新员工状态为"正式" (成员 A) + 薪资档案生效 (成员 C)。
- 调岗审批通过 → 更新部门/职位信息 (成员 A) + 调整薪资标准 (成员 C)。
- 离职审批通过 → 更新员工状态为"离职" (成员 A) + 禁用系统账号 (成员 B)。
- 请假审批通过 → 扣减假期余额表
leave_balance(成员 C)。
为了保证四人开发的代码能够无缝集成,团队制定了以下规范:
- 统一字段命名:主键统一为
id,逻辑删除统一为deleted(0/1),时间字段统一为created_at/updated_at。 - 关联约束:所有业务表必须包含
employee_id或department_id以便关联查询。
- RESTful 风格:统一使用
GET/POST/PUT/DELETE对应查/增/改/删。 - 权限标识:所有接口必须配置
@PreAuthorize,权限 Key 遵循模块:操作格式(如attendance:clock,salary:calculate)。
- 采用 Feature Branch 模式,每人独立分支开发。
- 合并前必须进行 Code Review,重点检查跨模块调用的接口定义是否一致。
| 问题描述 | 原因分析 | 解决方案 |
|---|---|---|
| 部门筛选数据不全 | 成员 A 的 SQL 仅查询直接子部门 | 改为 WITH RECURSIVE 递归查询,支持无限层级 |
| 转正后薪资未变动 | 审批回调未触发薪资档案更新 | 在 RegularizationServiceImpl 中增加薪资生效逻辑 |
| 定时任务编译失败 | Javadoc 注释中包含 */ 导致语法错误 |
修改注释格式,移除特殊字符 |
在本项目中,我们深度使用 AI 工具提升开发效率,主要体现在以下三个场景:
百宝箱是我们团队的核心开发工具,它提供了以下能力:
| 能力 | 说明 |
|---|---|
| 免费使用 | 零成本接入,无需额外购买商业 IDE 插件 |
| 代码级操作 | 直接读取、编辑、创建项目文件,无需手动复制粘贴 |
| 远程仓库集成 | 自动连接 Git 仓库,支持 commit、push 等操作 |
| 上下文理解 | 能理解整个项目结构,提供精准的代码建议 |
实际收益:
- 日常开发中,通过自然语言描述需求,AI 直接生成可运行的代码
- 修复 bug 时,AI 能快速定位问题文件并给出修复方案
- 代码审查阶段,AI 自动检查潜在问题(如 null 值处理、SQL 注入风险)
在开发审批中心模块时,最初每个业务(入职、转正、调岗、离职、请假等)都重复编写了相同的审批逻辑:
// 每个 Service 中都有类似的重复代码
ApprovalInstance instance = new ApprovalInstance();
instance.setBusinessType(businessType);
instance.setBusinessId(businessId);
instance.setApplicantId(loginUser.getUserId());
instance.setStatus(1); // 待审批
approvalInstanceMapper.insert(instance);
// 创建审批节点...
ApprovalNode node = new ApprovalNode();
node.setInstanceId(instance.getId());
node.setNodeOrder(1);
node.setApproverId(approverId);
node.setStatus(1);
approvalNodeMapper.insert(node);问题:代码重复度高,维护成本大,新增业务类型需要复制粘贴。
AI 优化方案:
让 AI 分析所有审批相关代码后,提取出通用的 ApprovalUtil 工具类:
@Component
@RequiredArgsConstructor
public class ApprovalUtil {
private final ApprovalInstanceMapper instanceMapper;
private final ApprovalNodeMapper nodeMapper;
private final EmployeeMapper employeeMapper;
/**
* 通用审批实例创建
*/
public ApprovalInstance createInstance(Integer businessType, Long businessId,
String title, Long applicantId) {
ApprovalInstance instance = new ApprovalInstance();
instance.setBusinessType(businessType);
instance.setBusinessId(businessId);
instance.setTitle(title);
instance.setApplicantId(applicantId);
instance.setStatus(1);
instanceMapper.insert(instance);
return instance;
}
/**
* 根据员工职级自动确定审批人
*/
public Long determineApproverId(Long employeeId) {
Employee employee = employeeMapper.selectEntityById(employeeId);
if (employee == null) return null;
// 根据职级和部门自动匹配审批人
if (employee.getJobLevel() == 1) {
return null; // 老总无需审批
}
// ... 其他审批人匹配逻辑
}
}优化效果:
- 代码量减少约 60%
- 新增业务类型只需调用工具类方法,无需重复编写
- 审批人匹配逻辑统一管理,修改一处全局生效
开发过程中遇到不熟悉的技術点时,我们采用 "AI 实现 + AI 讲解" 的学习模式:
案例:考勤状态判定算法
需求:根据打卡时间、排班规则、请假/加班数据,自动判定每天的考勤状态(正常/迟到/早退/旷工/缺卡)
AI 实现过程:
- 描述需求 → AI 生成初始代码框架
- 提供业务规则 → AI 完善判定逻辑
- 边界情况测试 → AI 补充异常处理
AI 讲解收获:
AI 不仅给出代码,还详细解释了设计思路:
考勤状态判定采用"优先级链"模式:
1. 旷工(最高优先级):无任何打卡记录
2. 缺卡:只有上班卡或只有下班卡
3. 迟到+早退:上班卡超时 + 下班卡提前
4. 迟到:仅上班卡超时
5. 早退:仅下班卡提前
6. 正常(最低优先级):其他情况
这种设计确保每个员工每天只有一个最终状态,避免状态冲突。
学习收益:
- 不仅"知其然",更"知其所以然"
- 快速掌握复杂业务逻辑的实现思路
- 积累可复用的设计模式(如优先级链、状态机)
需求分析 → AI 辅助理解业务
↓
代码实现 → AI 生成初始代码 + 讲解原理
↓
代码优化 → AI 识别重复代码 → 提取工具类
↓
Bug 修复 → AI 定位问题 → 给出修复方案
↓
代码审查 → AI 检查潜在风险 → 提升代码质量
核心体会:
AI 不是替代开发者,而是放大开发者的能力。
它让我们能够:
- 专注于业务逻辑而非语法细节
- 快速学习不熟悉的技術栈
- 保持代码的高质量和可维护性
在 HRMS 项目中,AI 工具帮助我们以 4 人团队在有限时间内完成了原本需要 6-8 人才能完成的工作量。
HRMS 人力资源管理系统实现了员工全生命周期管理,主要功能模块包括:
- 组织架构管理:部门和职位的树形管理
- 员工管理:员工档案的增删改查
- 入转调离流程:入职→转正→调岗→离职的完整流程管理,每次变更关联审批
- 考勤管理:打卡(含状态自动判定)、考勤统计(定时任务自动汇总)、请假(余额校验)、补卡、加班
- 薪资管理:薪资账套→批次核算(自动从考勤数据计算扣款)→审批→发放的完整流程
- 审批中心:统一审批流程引擎,7种业务类型共用
- 系统管理:用户、角色、权限、日志管理
- 个人中心:员工自助查看个人信息、考勤、薪资等
系统特色:
- 前后端分离,RESTful API 设计
- JWT + Redis 无状态认证
- Spring Security 权限控制(角色+权限双维度)
- 统一的审批流程引擎,支持业务扩展
- 自动考勤统计定时任务
- 完整的薪资核算引擎(含社保公积金个税计算)
- AOP 操作日志自动记录
- AI 智能客服集成