Java全栈项目 - 智能考勤管理系统

server/2024/12/26 13:08:04/

项目介绍

智能考勤管理系统是一个基于 Java 全栈技术开发的现代化企业考勤解决方案。该系统采用前后端分离架构,实现了员工考勤、请假管理、统计分析等核心功能,旨在帮助企业提高人力资源管理效率。

技术栈

后端技术

  • Spring Boot 2.6.x
  • Spring Security
  • MyBatis-Plus
  • MySQL 8.0
  • Redis
  • JWT

前端技术

  • Vue 3
  • Element Plus
  • Axios
  • Echarts
  • Vite

核心功能

1. 考勤管理

  • 上下班打卡
  • 加班申请
  • 外出登记
  • 考勤规则设置
  • 异常考勤处理

2. 请假管理

  • 请假申请
  • 请假审批
  • 请假类型配置
  • 假期余额查询

3. 统计分析

  • 考勤统计报表
  • 部门出勤率分析
  • 加班统计
  • 请假趋势分析

4. 系统管理

  • 用户管理
  • 角色权限
  • 部门管理
  • 系统配置

系统架构

├── smart-attendance-system
│   ├── attendance-admin        # 后台管理服务
│   ├── attendance-api         # 接口服务
│   ├── attendance-common      # 公共模块
│   ├── attendance-model       # 数据模型
│   └── attendance-web         # 前端项目

数据库设计

核心表结构

-- 员工表
CREATE TABLE sys_employee (id BIGINT PRIMARY KEY,emp_no VARCHAR(32),name VARCHAR(50),department_id BIGINT,position VARCHAR(50),status TINYINT,create_time DATETIME
);-- 考勤记录表
CREATE TABLE attendance_record (id BIGINT PRIMARY KEY,emp_id BIGINT,check_in_time DATETIME,check_out_time DATETIME,status TINYINT,type TINYINT,remark VARCHAR(255)
);-- 请假记录表
CREATE TABLE leave_record (id BIGINT PRIMARY KEY,emp_id BIGINT,leave_type TINYINT,start_time DATETIME,end_time DATETIME,reason VARCHAR(255),status TINYINT
);

项目亮点

1. 人脸识别打卡

  • 集成人脸识别SDK
  • 活体检测
  • 高精度识别算法

2. 智能定位打卡

  • 基于地理围栏技术
  • 支持移动端GPS定位
  • 异地打卡预警

3. 灵活的考勤规则

  • 多班次管理
  • 弹性工时
  • 节假日智能排班
  • 加班规则配置

4. 数据可视化

  • 直观的统计图表
  • 多维度数据分析
  • 自定义报表导出

性能优化

1. 缓存优化

java">@Cacheable(value = "attendance", key = "#empId")
public AttendanceDTO getAttendanceInfo(Long empId) {// 获取考勤信息逻辑
}

2. SQL优化

java">@Select("SELECT DATE_FORMAT(check_in_time,'%Y-%m-%d') as date, " +"COUNT(*) as count FROM attendance_record " +"WHERE emp_id = #{empId} " +"GROUP BY DATE_FORMAT(check_in_time,'%Y-%m-%d')")
List<StatisticsDTO> getAttendanceStatistics(Long empId);

3. 接口性能

  • 接口响应时间控制在200ms以内
  • 使用线程池处理异步任务
  • 批量操作优化

安全性设计

1. 身份认证

java">@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/api/auth/**").permitAll().anyRequest().authenticated().and().addFilter(new JwtAuthenticationFilter(authenticationManager()));}
}

2. 数据安全

  • 敏感数据加密
  • SQL注入防护
  • XSS防御

部署方案

1. 容器化部署

version: '3'
services:attendance-api:image: attendance-api:latestports:- "8080:8080"environment:- SPRING_PROFILES_ACTIVE=prod

2. 高可用方案

  • 服务器集群
  • 负载均衡
  • 数据库主从复制

项目总结

智能考勤管理系统采用现代化的技术栈和架构设计,实现了企业考勤管理的智能化和自动化。系统具有良好的可扩展性和维护性,为企业提供了一个高效、可靠的考勤解决方案。

未来展望

  • 引入机器学习算法,实现考勤预测
  • 集成企业微信等第三方平台
  • 开发移动端应用
  • 支持多租户架构

智能考勤系统 - 考勤与请假管理模块详解

一、考勤管理模块

1. 上下班打卡

1.1 打卡记录表设计
CREATE TABLE attendance_record (id BIGINT PRIMARY KEY,emp_id BIGINT COMMENT '员工ID',check_type TINYINT COMMENT '打卡类型:1-上班,2-下班',check_time DATETIME COMMENT '打卡时间',check_location VARCHAR(255) COMMENT '打卡地点',device_info VARCHAR(100) COMMENT '设备信息',face_image VARCHAR(255) COMMENT '人脸照片URL',status TINYINT COMMENT '状态:1-正常,2-迟到,3-早退',remark VARCHAR(255) COMMENT '备注',create_time DATETIME,FOREIGN KEY (emp_id) REFERENCES sys_employee(id)
);
1.2 打卡服务实现
java">@Service
@Slf4j
public class CheckInService {@Autowiredprivate AttendanceRuleService ruleService;@Autowiredprivate FaceRecognitionService faceService;@Autowiredprivate LocationService locationService;@Transactionalpublic CheckInResult doCheckIn(CheckInDTO checkInDTO) {// 1. 人脸识别验证boolean faceValid = faceService.verify(checkInDTO.getEmpId(), checkInDTO.getFaceImage());if (!faceValid) {throw new BusinessException("人脸识别失败");}// 2. 位置验证boolean locationValid = locationService.verifyLocation(checkInDTO.getLocation(),checkInDTO.getEmpId());if (!locationValid) {throw new BusinessException("不在打卡范围内");}// 3. 判断打卡类型和状态AttendanceRule rule = ruleService.getEmployeeRule(checkInDTO.getEmpId());CheckInStatus status = calculateStatus(checkInDTO.getCheckTime(), rule);// 4. 保存打卡记录AttendanceRecord record = new AttendanceRecord();record.setEmpId(checkInDTO.getEmpId());record.setCheckType(checkInDTO.getCheckType());record.setCheckTime(checkInDTO.getCheckTime());record.setStatus(status.getCode());attendanceMapper.insert(record);// 5. 返回打卡结果return new CheckInResult(status, record.getId());}private CheckInStatus calculateStatus(LocalDateTime checkTime, AttendanceRule rule) {LocalTime time = checkTime.toLocalTime();if (isCheckIn) {if (time.isAfter(rule.getLateTime())) {return CheckInStatus.LATE;}} else {if (time.isBefore(rule.getEarlyLeaveTime())) {return CheckInStatus.EARLY_LEAVE;}}return CheckInStatus.NORMAL;}
}
1.3 打卡界面实现
<template><div class="check-in-container"><div class="camera-container"><video ref="video" class="camera-preview"></video><canvas ref="canvas" style="display: none;"></canvas></div><div class="check-in-info"><div class="time-display">{{ currentTime }}</div><el-button type="primary" size="large" @click="handleCheckIn":loading="checking">{{ checkType === 1 ? '上班打卡' : '下班打卡' }}</el-button><div class="location-info">当前位置:{{ location }}</div></div><!-- 打卡结果弹窗 --><el-dialogtitle="打卡结果":visible.sync="showResult"width="300px"center><div class="check-result"><i :class="resultIcon"></i><span>{{ resultMessage }}</span><div class="check-time">{{ checkTime }}</div></div></el-dialog></div>
</template><script>
export default {data() {return {checking: false,currentTime: '',location: '',checkType: this.getCheckType(),showResult: false,resultMessage: '',stream: null}},methods: {async initCamera() {try {this.stream = await navigator.mediaDevices.getUserMedia({video: true});this.$refs.video.srcObject = this.stream;} catch (error) {this.$message.error('摄像头启动失败');}},getCheckType() {const now = new Date();const hour = now.getHours();return hour < 12 ? 1 : 2; // 12点前为上班打卡},async handleCheckIn() {try {this.checking = true;// 1. 获取人脸图片const faceImage = this.captureFace();// 2. 获取位置信息const location = await this.getCurrentLocation();// 3. 提交打卡const result = await this.$api.attendance.checkIn({checkType: this.checkType,faceImage,location,checkTime: new Date()});// 4. 显示结果this.showCheckResult(result);} catch (error) {this.$message.error(error.message);} finally {this.checking = false;}},captureFace() {const canvas = this.$refs.canvas;const video = this.$refs.video;const context = canvas.getContext('2d');canvas.width = video.videoWidth;canvas.height = video.videoHeight;context.drawImage(video, 0, 0);return canvas.toDataURL('image/jpeg');}},mounted() {this.initCamera();// 更新当前时间setInterval(() => {this.currentTime = new Date().toLocaleTimeString();}, 1000);},beforeDestroy() {// 关闭摄像头if (this.stream) {this.stream.getTracks().forEach(track => track.stop());}}
}
</script>

2. 加班申请

2.1 加班申请表
CREATE TABLE overtime_application (id BIGINT PRIMARY KEY,emp_id BIGINT,start_time DATETIME,end_time DATETIME,overtime_type TINYINT COMMENT '加班类型:1-工作日,2-周末,3-节假日',reason VARCHAR(500),status TINYINT COMMENT '状态:0-待审批,1-已通过,2-已拒绝',approver_id BIGINT,approve_time DATETIME,approve_remark VARCHAR(255),create_time DATETIME
);
2.2 加班服务实现
java">@Service
public class OvertimeService {@Autowiredprivate WorkflowService workflowService;public void applyOvertime(OvertimeDTO overtimeDTO) {// 1. 验证加班时长validateOvertimeHours(overtimeDTO);// 2. 创建加班申请OvertimeApplication application = new OvertimeApplication();BeanUtils.copyProperties(overtimeDTO, application);application.setStatus(ApprovalStatus.PENDING.getCode());overtimeMapper.insert(application);// 3. 发起工作流workflowService.startProcess("overtime_process",application.getId(),overtimeDTO.getEmpId());}private void validateOvertimeHours(OvertimeDTO overtime) {// 计算加班时长long hours = ChronoUnit.HOURS.between(overtime.getStartTime(), overtime.getEndTime());// 获取员工当月已加班时长int monthlyHours = overtimeMapper.getMonthlyHours(overtime.getEmpId(),overtime.getStartTime());// 验证是否超过月度限制if (monthlyHours + hours > MAX_MONTHLY_HOURS) {throw new BusinessException("超过月度加班时长限制");}}
}

3. 外出登记

3.1 外出登记表
CREATE TABLE business_trip (id BIGINT PRIMARY KEY,emp_id BIGINT,start_time DATETIME,end_time DATETIME,destination VARCHAR(255),purpose VARCHAR(500),status TINYINT,contact_info VARCHAR(100),create_time DATETIME
);
3.2 外出服务实现
java">@Service
public class BusinessTripService {public void register(BusinessTripDTO tripDTO) {// 1. 检查是否有重叠的外出记录boolean hasOverlap = checkTimeOverlap(tripDTO.getEmpId(),tripDTO.getStartTime(),tripDTO.getEndTime());if (hasOverlap) {throw new BusinessException("当前时间段已有外出记录");}// 2. 保存外出记录BusinessTrip trip = new BusinessTrip();BeanUtils.copyProperties(tripDTO, trip);tripMapper.insert(trip);// 3. 更新考勤规则attendanceRuleService.addException(tripDTO.getEmpId(),tripDTO.getStartTime(),tripDTO.getEndTime(),AttendanceExceptionType.BUSINESS_TRIP);}
}

4. 考勤规则设置

4.1 考勤规则表
CREATE TABLE attendance_rule (id BIGINT PRIMARY KEY,rule_name VARCHAR(50),work_start_time TIME,work_end_time TIME,late_minutes INT COMMENT '迟到判定分钟数',early_leave_minutes INT COMMENT '早退判定分钟数',work_hours DECIMAL(4,1) COMMENT '每日工时',flexible_time INT COMMENT '弹性工作时间(分钟)',dept_id BIGINT COMMENT '适用部门',status TINYINT,create_time DATETIME
);
4.2 规则配置服务
java">@Service
public class AttendanceRuleService {@Cacheable(value = "attendance_rule", key = "#deptId")public AttendanceRule getDeptRule(Long deptId) {return ruleMapper.selectByDeptId(deptId);}@CacheEvict(value = "attendance_rule", key = "#rule.deptId")public void updateRule(AttendanceRule rule) {validateRule(rule);ruleMapper.updateById(rule);}private void validateRule(AttendanceRule rule) {// 验证工作时间设置if (rule.getWorkEndTime().isBefore(rule.getWorkStartTime())) {throw new BusinessException("下班时间不能早于上班时间");}// 验证弹性工作时间if (rule.getFlexibleTime() != null && rule.getFlexibleTime() > MAX_FLEXIBLE_TIME) {throw new BusinessException("弹性工作时间超出限制");}}
}

5. 异常考勤处理

5.1 异常考勤表
CREATE TABLE attendance_exception (id BIGINT PRIMARY KEY,emp_id BIGINT,exception_date DATE,exception_type TINYINT COMMENT '异常类型:1-漏打卡,2-迟到,3-早退',handle_status TINYINT COMMENT '处理状态',handle_result VARCHAR(255),handle_time DATETIME,handler_id BIGINT,create_time DATETIME
);
5.2 异常处理服务
java">@Service
public class ExceptionHandleService {@Asyncpublic void handleException(AttendanceException exception) {// 1. 判断异常类型switch (exception.getExceptionType()) {case MISSING_CHECK:handleMissingCheck(exception);break;case LATE:handleLate(exception);break;case EARLY_LEAVE:handleEarlyLeave(exception);break;}// 2. 发送通知notificationService.sendExceptionNotice(exception);// 3. 更新处理状态exceptionMapper.updateStatus(exception.getId(),ExceptionStatus.HANDLED);}private void handleMissingCheck(AttendanceException exception) {// 检查是否有相关的请假或外出记录List<LeaveRecord> leaveRecords = leaveMapper.findByEmpAndDate(exception.getEmpId(), exception.getExceptionDate());if (!leaveRecords.isEmpty()) {// 有请假记录,标记为已确认exception.setHandleResult("已确认请假");return;}// 发起补卡申请createSupplementaryApplication(exception);}
}

二、请假管理模块

1. 请假申请

1.1 请假记录表
CREATE TABLE leave_record (id BIGINT PRIMARY KEY,emp_id BIGINT,leave_type TINYINT COMMENT '请假类型',start_time DATETIME,end_time DATETIME,duration DECIMAL(5,1) COMMENT '请假时长(天)',reason VARCHAR(500),status TINYINT COMMENT '状态:0-待审批,1-已通过,2-已拒绝',approver_id BIGINT,approve_time DATETIME,approve_remark VARCHAR(255),attachment_url VARCHAR(255) COMMENT '附件URL',create_time DATETIME
);
1.2 请假服务实现
java">@Service
public class LeaveService {@Autowiredprivate LeaveBalanceService balanceService;@Autowiredprivate WorkflowService workflowService;@Transactionalpublic void applyLeave(LeaveApplicationDTO leaveDTO) {// 1. 校验请假时长validateLeaveDuration(leaveDTO);// 2. 检查假期余额checkLeaveBalance(leaveDTO.getEmpId(),leaveDTO.getLeaveType(),leaveDTO.getDuration());// 3. 创建请假记录LeaveRecord record = new LeaveRecord();BeanUtils.copyProperties(leaveDTO, record);record.setStatus(ApprovalStatus.PENDING.getCode());leaveMapper.insert(record);// 4. 发起工作流workflowService.startProcess("leave_process",record.getId(),leaveDTO.getEmpId());}private void checkLeaveBalance(Long empId, LeaveType leaveType, BigDecimal duration) {LeaveBalance balance = balanceService.getBalance(empId, leaveType);if (balance.getRemaining().compareTo(duration) < 0) {throw new BusinessException(leaveType.getName() + "假期余额不足");}}
}

2. 请假审批

2.1 审批流程配置
java">@Configuration
public class LeaveWorkflowConfig {@Autowiredprivate RuntimeService runtimeService;@Beanpublic ProcessEngineConfiguration leaveProcess() {return ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration().setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE).setJdbcUrl("jdbc:mysql://localhost:3306/workflow").setJdbcDriver("com.mysql.cj.jdbc.Driver").setJdbcUsername("root").setJdbcPassword("password").setActivityFontName("宋体").setLabelFontName("宋体").setAnnotationFontName("宋体");}
}
2.2 审批服务实现
java">@Service
public class LeaveApprovalService {@Autowiredprivate TaskService taskService;@Autowiredprivate LeaveBalanceService balanceService;@Transactionalpublic void approve(ApprovalDTO approvalDTO) {// 1. 获取请假记录LeaveRecord record = leaveMapper.selectById(approvalDTO.getRecordId());if (record == null) {throw new BusinessException("请假记录不存在");}// 2. 更新审批状态record.setStatus(approvalDTO.getApproved() ? ApprovalStatus.APPROVED.getCode(): ApprovalStatus.REJECTED.getCode());record.setApproveRemark(approvalDTO.getRemark());record.setApproveTime(LocalDateTime.now());record.setApproverId(approvalDTO.getApproverId());leaveMapper.updateById(record);// 3. 如果审批通过,扣减假期余额if (approvalDTO.getApproved()) {balanceService.deductBalance(record.getEmpId(),record.getLeaveType(),record.getDuration());}// 4. 完成工作流任务taskService.complete(approvalDTO.getTaskId());// 5. 发送通知notificationService.sendApprovalResult(record);}
}

3. 请假类型配置

3.1 请假类型表
CREATE TABLE leave_type (id BIGINT PRIMARY KEY,type_name VARCHAR(50),type_code VARCHAR(50),paid TINYINT COMMENT '是否带薪',max_duration INT COMMENT '最大请假天数',min_unit DECIMAL(2,1) COMMENT '最小请假单位(天)',need_attachment TINYINT COMMENT '是否需要附件',status TINYINT,create_time DATETIME
);
3.2 类型配置服务
java">@Service
public class LeaveTypeService {@Cacheable(value = "leave_type", key = "#typeId")public LeaveType getLeaveType(Long typeId) {return typeMapper.selectById(typeId);}@CacheEvict(value = "leave_type", allEntries = true)public void updateLeaveType(LeaveType leaveType) {validateLeaveType(leaveType);typeMapper.updateById(leaveType);}private void validateLeaveType(LeaveType type) {// 验证最大请假天数if (type.getMaxDuration() <= 0) {throw new BusinessException("最大请假天数必须大于0");}// 验证最小请假单位if (type.getMinUnit().compareTo(BigDecimal.ZERO) <= 0) {throw new BusinessException("最小请假单位必须大于0");}}
}

4. 假期余额查询

4.1 假期余额表
CREATE TABLE leave_balance (id BIGINT PRIMARY KEY,emp_id BIGINT,leave_type TINYINT,year INT,total_days DECIMAL(5,1),used_days DECIMAL(5,1),remaining_days DECIMAL(5,1),update_time DATETIME
);
4.2 余额查询服务
java">@Service
public class LeaveBalanceService {@Cacheable(value = "leave_balance", key = "#empId + ':' + #leaveType")public LeaveBalance getBalance(Long empId, LeaveType leaveType) {return balanceMapper.selectByEmpAndType(empId, leaveType);}@Transactional@CacheEvict(value = "leave_balance", key = "#empId + ':' + #leaveType")public void deductBalance(Long empId, LeaveType leaveType, BigDecimal days) {LeaveBalance balance = getBalance(empId, leaveType);if (balance == null) {throw new BusinessException("假期余额记录不存在");}// 检查余额是否足够if (balance.getRemainingDays().compareTo(days) < 0) {throw new BusinessException("假期余额不足");}// 更新已使用和剩余天数balance.setUsedDays(balance.getUsedDays().add(days));balance.setRemainingDays(balance.getRemainingDays().subtract(days));balanceMapper.updateById(balance);}// 年度假期初始化@Scheduled(cron = "0 0 0 1 1 ?")  // 每年1月1日执行public void initializeYearlyBalance() {int year = LocalDate.now().getYear();// 获取所有在职员工List<Employee> employees = employeeMapper.selectAllActive();for (Employee emp : employees) {// 初始化各类假期余额initializeBalance(emp.getId(), year);}}
}
4.3 余额查询界面
<template><div class="leave-balance"><el-card class="balance-card"><div slot="header"><span>假期余额</span><el-button type="text" @click="refreshBalance"style="float: right;">刷新</el-button></div><el-table :data="balanceList" border><el-table-column prop="typeName" label="假期类型"/><el-table-column prop="totalDays" label="总天数"/><el-table-column prop="usedDays" label="已用天数"/><el-table-column prop="remainingDays" label="剩余天数"><template slot-scope="scope"><span :class="{'warning': scope.row.remainingDays < 5,'danger': scope.row.remainingDays <= 0}">{{ scope.row.remainingDays }}</span></template></el-table-column></el-table></el-card><!-- 假期使用记录 --><el-card class="usage-card"><div slot="header"><span>假期使用记录</span></div><el-table :data="usageRecords" border><el-table-column prop="leaveType" label="假期类型"/><el-table-column prop="startTime" label="开始时间"/><el-table-column prop="endTime" label="结束时间"/><el-table-column prop="duration" label="请假天数"/><el-table-column prop="status" label="状态"><template slot-scope="scope"><el-tag :type="getStatusType(scope.row.status)">{{ getStatusText(scope.row.status) }}</el-tag></template></el-table-column></el-table></el-card></div>
</template><script>
export default {data() {return {balanceList: [],usageRecords: []}},methods: {async refreshBalance() {try {const response = await this.$api.leave.getBalance(this.userId);this.balanceList = response.data;} catch (error) {this.$message.error('获取假期余额失败');}},getStatusType(status) {const typeMap = {0: 'info',1: 'success',2: 'danger'};return typeMap[status] || 'info';},getStatusText(status) {const textMap = {0: '待审批',1: '已通过',2: '已拒绝'};return textMap[status] || '未知';}},created() {this.refreshBalance();}
}
</script><style scoped>
.leave-balance {padding: 20px;
}.balance-card {margin-bottom: 20px;
}.warning {color: #E6A23C;
}.danger {color: #F56C6C;
}
</style>

这些模块的实现涵盖了:

  • 数据库表设计
  • 业务逻辑实现
  • 工作流集成
  • 缓存管理
  • 定时任务
  • 前端界面开发
  • 权限控制
  • 数据验证

通过这些功能的实现,可以为企业提供完整的考勤和请假管理解决方案。

智能考勤系统 - 统计分析与系统管理模块详解

一、统计分析模块

1. 考勤统计报表

1.1 数据维度
-- 考勤统计视图
CREATE VIEW v_attendance_statistics AS
SELECT e.department_id,e.emp_no,e.name,DATE_FORMAT(ar.check_in_time, '%Y-%m') as month,COUNT(DISTINCT DATE(ar.check_in_time)) as work_days,COUNT(CASE WHEN ar.status = 1 THEN 1 END) as normal_days,COUNT(CASE WHEN ar.status = 2 THEN 1 END) as late_days,COUNT(CASE WHEN ar.status = 3 THEN 1 END) as early_leave_days,COUNT(CASE WHEN ar.status = 4 THEN 1 END) as absent_days
FROM sys_employee e
LEFT JOIN attendance_record ar ON e.id = ar.emp_id
GROUP BY e.id, DATE_FORMAT(ar.check_in_time, '%Y-%m');
1.2 报表类型
  • 月度考勤汇总表
  • 个人考勤明细表
  • 部门考勤对比表
  • 异常考勤分析表
1.3 数据展示
java">@Service
public class AttendanceReportService {@Autowiredprivate AttendanceMapper attendanceMapper;public List<AttendanceReportDTO> generateMonthlyReport(String month) {return attendanceMapper.getMonthlyStatistics(month);}// 支持多种导出格式public void exportReport(String format, String month) {List<AttendanceReportDTO> data = generateMonthlyReport(month);switch(format.toLowerCase()) {case "excel":exportToExcel(data);break;case "pdf":exportToPDF(data);break;case "csv":exportToCSV(data);break;}}
}

2. 部门出勤率分析

2.1 核心指标
  • 部门整体出勤率
  • 迟到率
  • 早退率
  • 缺勤率
  • 加班时长
2.2 可视化展示
<template><div class="department-analysis"><!-- 部门出勤率图表 --><div class="chart-container"><v-chart :option="chartOption" /></div><!-- 部门排名列表 --><el-table :data="departmentRanking"><el-table-column prop="deptName" label="部门" /><el-table-column prop="attendanceRate" label="出勤率"><template #default="scope"><el-progress :percentage="scope.row.attendanceRate" :color="getColorByRate(scope.row.attendanceRate)"/></template></el-table-column></el-table></div>
</template><script>
export default {data() {return {chartOption: {title: { text: '部门出勤率分析' },series: [{type: 'pie',data: [{ value: 95, name: '研发部' },{ value: 92, name: '市场部' },{ value: 88, name: '运营部' }]}]}}}
}
</script>

3. 加班统计

3.1 加班类型统计
java">public enum OvertimeType {WORKDAY(1, "工作日加班"),WEEKEND(2, "周末加班"),HOLIDAY(3, "节假日加班");private int code;private String desc;
}@Service
public class OvertimeStatisticsService {public Map<String, Object> calculateOvertimeHours(Long empId, String month) {Map<String, Object> statistics = new HashMap<>();// 计算不同类型加班时长statistics.put("workdayHours", calculateByType(empId, month, OvertimeType.WORKDAY));statistics.put("weekendHours", calculateByType(empId, month, OvertimeType.WEEKEND));statistics.put("holidayHours", calculateByType(empId, month, OvertimeType.HOLIDAY));// 计算加班费statistics.put("overtimePay", calculateOvertimePay(statistics));return statistics;}
}

4. 请假趋势分析

4.1 请假类型分布
SELECT leave_type,COUNT(*) as count,SUM(TIMESTAMPDIFF(HOUR, start_time, end_time)) as total_hours
FROM leave_record
WHERE DATE_FORMAT(start_time, '%Y-%m') = #{month}
GROUP BY leave_type;
4.2 趋势图表配置
javascript">const leaveAnalysisChart = {xAxis: {type: 'category',data: ['1月', '2月', '3月', '4月', '5月', '6月']},yAxis: {type: 'value'},series: [{name: '病假',type: 'line',data: [10, 8, 12, 6, 9, 7]},{name: '事假',type: 'line',data: [5, 7, 4, 8, 6, 9]},{name: '年假',type: 'line',data: [2, 4, 6, 8, 3, 5]}]
}

二、系统管理模块

1. 用户管理

1.1 用户表设计
CREATE TABLE sys_user (id BIGINT PRIMARY KEY,username VARCHAR(50) NOT NULL UNIQUE,password VARCHAR(100) NOT NULL,real_name VARCHAR(50),email VARCHAR(100),mobile VARCHAR(20),status TINYINT DEFAULT 1,create_time DATETIME,update_time DATETIME,last_login_time DATETIME,remark VARCHAR(255)
);
1.2 用户服务实现
java">@Service
public class UserService {@Autowiredprivate PasswordEncoder passwordEncoder;public void createUser(UserDTO userDTO) {// 密码加密String encodedPassword = passwordEncoder.encode(userDTO.getPassword());SysUser user = new SysUser();user.setUsername(userDTO.getUsername());user.setPassword(encodedPassword);// ... 设置其他属性userMapper.insert(user);}public void updateUserStatus(Long userId, Integer status) {userMapper.updateStatus(userId, status);}
}

2. 角色权限

2.1 RBAC权限模型
-- 角色表
CREATE TABLE sys_role (id BIGINT PRIMARY KEY,role_name VARCHAR(50),role_code VARCHAR(50),status TINYINT,create_time DATETIME
);-- 权限表
CREATE TABLE sys_permission (id BIGINT PRIMARY KEY,parent_id BIGINT,name VARCHAR(50),type TINYINT,permission_code VARCHAR(50),path VARCHAR(200),component VARCHAR(100),icon VARCHAR(50),sort INT
);-- 角色权限关联表
CREATE TABLE sys_role_permission (role_id BIGINT,permission_id BIGINT,PRIMARY KEY(role_id, permission_id)
);
2.2 权限控制实现
java">@PreAuthorize("hasRole('ADMIN') or hasPermission(#id, 'attendance:view')")
@GetMapping("/attendance/{id}")
public AttendanceDTO getAttendanceDetail(@PathVariable Long id) {return attendanceService.getById(id);
}@Service
public class CustomPermissionEvaluator implements PermissionEvaluator {@Overridepublic boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {// 权限判断逻辑return checkPermission(authentication, permission.toString());}
}

3. 部门管理

3.1 部门树形结构
java">@Data
public class DepartmentTree {private Long id;private String name;private Long parentId;private List<DepartmentTree> children;private String leader;private Integer employeeCount;
}@Service
public class DepartmentService {public List<DepartmentTree> buildDepartmentTree() {List<Department> allDepts = departmentMapper.selectAll();return buildTree(allDepts, 0L);}private List<DepartmentTree> buildTree(List<Department> depts, Long parentId) {return depts.stream().filter(dept -> dept.getParentId().equals(parentId)).map(dept -> {DepartmentTree node = new DepartmentTree();node.setId(dept.getId());node.setName(dept.getName());node.setChildren(buildTree(depts, dept.getId()));return node;}).collect(Collectors.toList());}
}

4. 系统配置

4.1 配置管理
java">@Configuration
@ConfigurationProperties(prefix = "system")
@Data
public class SystemConfig {private AttendanceConfig attendance;private SecurityConfig security;private NotificationConfig notification;@Datapublic static class AttendanceConfig {private String workStartTime;private String workEndTime;private Integer lateMinutes;private Integer earlyLeaveMinutes;}
}
4.2 动态配置实现
java">@Service
public class ConfigService {@Autowiredprivate StringRedisTemplate redisTemplate;public void updateConfig(String key, String value) {// 更新数据库configMapper.updateValue(key, value);// 更新缓存redisTemplate.opsForValue().set("system:config:" + key, value, 1, TimeUnit.DAYS);}public String getConfig(String key) {// 先从缓存获取String value = redisTemplate.opsForValue().get("system:config:" + key);if (value == null) {// 缓存未命中,从数据库获取value = configMapper.selectByKey(key);if (value != null) {redisTemplate.opsForValue().set("system:config:" + key, value, 1, TimeUnit.DAYS);}}return value;}
}
4.3 配置页面
<template><div class="system-config"><el-form :model="configForm" label-width="120px"><el-tabs v-model="activeTab"><!-- 考勤配置 --><el-tab-pane label="考勤配置" name="attendance"><el-form-item label="上班时间"><el-time-picker v-model="configForm.workStartTime" /></el-form-item><el-form-item label="下班时间"><el-time-picker v-model="configForm.workEndTime" /></el-form-item></el-tab-pane><!-- 系统配置 --><el-tab-pane label="系统配置" name="system"><el-form-item label="系统名称"><el-input v-model="configForm.systemName" /></el-form-item><el-form-item label="Logo"><el-uploadaction="/api/system/upload":show-file-list="false":on-success="handleLogoSuccess"><img v-if="configForm.logo" :src="configForm.logo" class="logo"><el-button v-else>上传Logo</el-button></el-upload></el-form-item></el-tab-pane></el-tabs><el-form-item><el-button type="primary" @click="saveConfig">保存配置</el-button></el-form-item></el-form></div>
</template><script>
export default {data() {return {activeTab: 'attendance',configForm: {workStartTime: '',workEndTime: '',systemName: '',logo: ''}}},methods: {async saveConfig() {try {await this.$api.system.updateConfig(this.configForm)this.$message.success('配置保存成功')} catch (error) {this.$message.error('配置保存失败')}}}
}
</script>

这些模块的实现涉及到了前后端的完整开发流程,包括:

  • 数据库表设计
  • 后端服务实现
  • 权限控制
  • 缓存优化
  • 前端界面开发
  • 数据可视化

通过这些功能的实现,可以为企业提供完整的考勤管理解决方案。


http://www.ppmy.cn/server/153322.html

相关文章

golang实现yaml配置文件的解析

原文地址&#xff1a;golang实现yaml配置文件的解析 – 无敌牛 欢迎参观我的个人博客&#xff1a;无敌牛 – 技术/著作/典籍/分享等 代码 需要建立3个文件&#xff0c;目录结构如下&#xff1a; 配置文件 conf.yaml redis: host: "127.0.0.1"port: 6379db: 11 …

后端接口返回文件流,前端下载(java+vue)

各位小伙伴们大家好&#xff0c;欢迎来到这个小扎扎的专栏 总结 | 提效 | 拓展&#xff0c;在这个系列专栏中记录了博主在学习期间总结的大块知识点&#xff0c;以及日常工作中遇到的各种技术点 ┗|&#xff40;O′|┛ ?? 内容速览 后端获取前端下载 本身前端是可以直接通过文…

鸿蒙UI开发——自定义主题色

1、概述 ArkTs提供了应用内主题切换功能&#xff0c;支持全局主题切换&#xff0c;也支持局部主题切换&#xff0c;效果如下。本文针对主题切换做简单介绍。 2、主题色 ArkTs提供了一套内置主题配色&#xff0c;有Colors对象持有&#xff0c;它包含了默认情况下&#xff0c;关…

IntelliJ IDEA 基本使用教程及Spring Boot项目搭建实战

​ 目录 ​一、简介 二、IntelliJ IDEA 基本使用 三、Spring Boot 项目搭建 一、简介 IntelliJ IDEA 是由 JetBrains 开发的一款强大的 Java 集成开发环境&#xff08;IDE&#xff09;&#xff0c;广泛用于 Java、Kotlin、Groovy、Scala、Spring 和 Android 等项目的开发。…

Docker 安装Mysql

1.打开docker目录 cd /usr/local/mkdir docker2.创建mysql文件夹 cd /usr/local/dockermkdir mysql3.打开mysql文件夹 cd mysql/4.创建配置文件目录 mkdir config5.打开config cd config/6.编写配置文件 vim my.cnf复制如下&#xff1a; [client] # 端口号 port3306[mysq…

「Java EE开发指南」如何用MyEclipse构建一个Web项目?(一)

在本文中您将找到有关Web项目的信息&#xff0c;将了解&#xff1a; Web项目结构和参数Web开发高效率工具JSP代码完成和验证 这些功能在MyEclipse中可用。 MyEclipse v2024.1离线版下载 一、Web项目结构 用最简单的术语来说&#xff0c;MyEclipse Web项目是一个Eclipse Ja…

LabVIEW软件项目设计方案如何制定

制定LabVIEW软件项目设计方案需要综合考虑需求分析、架构设计、功能模块划分和时间预算等多个方面&#xff0c;确保项目开发过程高效、可控且最终满足目标要求。以下是一个详细的制定流程&#xff1a; ​ 1. 需求分析 目标定义&#xff1a;明确项目的目标&#xff0c;例如数据采…

紫光同创-盘古200pro+开发板

本原创文章由深圳市小眼睛科技有限公司创作&#xff0c;版权归本公司所有&#xff0c;如需转载&#xff0c;需授权并注明出处&#xff08;www.meyesemi.com) 一、开发系统介绍 开发系统概述 MES2L676-200HP 开发板采用紫光同创 logos2 系列 FPGA&#xff0c;型号&#xff1a;…