7 小时以前 571ccc18671ef45c6403496e8d99efec82168083
src/main/java/com/ruoyi/staff/service/impl/PersonalShiftServiceImpl.java
@@ -29,6 +29,7 @@
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;
/**
@@ -116,13 +117,89 @@
        IPage<PerformanceShiftMapDto> mapIPage = baseMapper.performanceShiftPage(page, time, userName, sysDeptId);
        //查询所有班次(打卡规则)
        List<PersonalAttendanceLocationConfig> personalAttendanceLocationConfigs = personalAttendanceLocationConfigMapper.selectList(null);
        // 获取当月时间范围
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime localDateTime = LocalDateTime.parse(time, formatters);
        LocalDate firstDayOfMonth = localDateTime.toLocalDate().withDayOfMonth(1);
        LocalDate lastDayOfMonth = localDateTime.toLocalDate().with(TemporalAdjusters.lastDayOfMonth());
        // 收集所有员工ID
        List<Long> staffIds = mapIPage.getRecords().stream()
                .filter(dto -> dto.getUserId() != null)
                .map(dto -> Long.valueOf(dto.getUserId()))
                .distinct()
                .collect(Collectors.toList());
        // 查询当月审核通过的请假记录(从approval_instance的form_config解析)
        Map<Long, List<String>> staffHolidayMap = new HashMap<>();
        if (!staffIds.isEmpty()) {
            // 通过关联查询获取员工请假信息
            List<Map<String, Object>> holidayRecords = baseMapper.selectStaffHolidayDates(staffIds);
            // 构建员工-请假日期映射(从form_config JSON解析)
            for (Map<String, Object> record : holidayRecords) {
                Long staffId = ((Number) record.get("staff_id")).longValue();
                String formConfig = (String) record.get("form_config");
                if (formConfig != null && !formConfig.isEmpty()) {
                    try {
                        // 解析form_config JSON
                        Map<String, Object> formMap = JackSonUtil.unmarshal(formConfig, Map.class);
                        Object formPayloadObj = formMap.get("formPayload");
                        if (formPayloadObj instanceof Map) {
                            Map<String, Object> formPayload = (Map<String, Object>) formPayloadObj;
                            Object dateRangeObj = formPayload.get("00"); // 请假日期字段key为"00"
                            if (dateRangeObj instanceof List) {
                                List<String> dateRange = (List<String>) dateRangeObj;
                                if (dateRange.size() >= 2) {
                                    String startDateTime = dateRange.get(0);
                                    String endDateTime = dateRange.get(1);
                                    // 解析日期(格式:yyyy-MM-dd HH:mm:ss)
                                    LocalDate startDate = LocalDate.parse(startDateTime.substring(0, 10));
                                    LocalDate endDate = LocalDate.parse(endDateTime.substring(0, 10));
                                    // 过滤当月范围内的请假日期
                                    List<String> dates = getDatesBetween(startDate, endDate).stream()
                                            .filter(date -> {
                                                LocalDate d = LocalDate.parse(date);
                                                return !d.isBefore(firstDayOfMonth) && !d.isAfter(lastDayOfMonth);
                                            })
                                            .collect(Collectors.toList());
                                    if (!dates.isEmpty()) {
                                        staffHolidayMap.computeIfAbsent(staffId, k -> new ArrayList<>()).addAll(dates);
                                    }
                                }
                            }
                        }
                    } catch (Exception e) {
                        // JSON解析失败,跳过此记录
                    }
                }
            }
        }
        for (PerformanceShiftMapDto i : mapIPage.getRecords()) {
            // 设置请假日期列表
            if (i.getUserId() != null) {
                Long staffId = Long.valueOf(i.getUserId());
                List<String> holidayDates = staffHolidayMap.getOrDefault(staffId, new ArrayList<>());
                i.setHolidayDates(holidayDates);
            }
            List<String> shiftTimes = StrUtil.split(i.getShiftTime(), ";");
            if(CollUtil.isEmpty(shiftTimes)){
                continue;
            }
            double totalAttendance = 0;//总出勤天数
            List<Map<String, Object>> map = new ArrayList<>();
            // 获取该员工的请假日期集合
            Set<String> holidayDateSet = new HashSet<>(i.getHolidayDates());
            // 分割日期
            for (String shiftTime : shiftTimes) {
                i.setShiftTime(null);
@@ -135,9 +212,31 @@
                hashMap.put("id", shiftTimeAndShift.get(2));
                hashMap.put("shift", shiftTimeAndShift.get(1));
                hashMap.put("time", shiftTimeAndShift.get(0));
                // 提取日期部分(格式:yyyy-MM-dd HH:mm:ss -> yyyy-MM-dd)
                String workTimeStr = shiftTimeAndShift.get(0);
                String workDate = workTimeStr.length() >= 10 ? workTimeStr.substring(0, 10) : workTimeStr;
                // 如果该日期有审核通过的请假记录,设置isHoliday为true,并将班次设为休息
                if (holidayDateSet.contains(workDate)) {
                    hashMap.put("isHoliday", true);
                    hashMap.put("shift", "休息");
                } else {
                    hashMap.put("isHoliday", false);
                }
                map.add(hashMap);
                i.setList(map);
                //汇总的各班次统计数据
                // 统计班次数据
                if (holidayDateSet.contains(workDate)) {
                    // 如果是请假日期,统计为休息(只统计一次)
                    if (!i.getMonthlyAttendance().containsKey("休息")){
                        i.getMonthlyAttendance().put("休息", 0);
                    }
                    i.getMonthlyAttendance().put("休息", new BigDecimal(i.getMonthlyAttendance().get("休息").toString()).add(new BigDecimal("1")));
                } else {
                    // 不是请假日期,统计原班次
                for (PersonalAttendanceLocationConfig personalAttendanceLocationConfig : personalAttendanceLocationConfigs) {
                    if (!i.getMonthlyAttendance().containsKey(personalAttendanceLocationConfig.getShift())){
                        i.getMonthlyAttendance().put(personalAttendanceLocationConfig.getShift(), 0);
@@ -147,7 +246,7 @@
                        i.getMonthlyAttendance().put(personalAttendanceLocationConfig.getShift(), bigDecimal.add(new BigDecimal("1")));
                    }
                }
                //统计总出勤天数(早/中/晚/夜)都算出勤,其余都是休息
                    // 统计总出勤天数(早/中/晚/夜)都算出勤
                if (shiftTimeAndShift.get(1).contains("早") ||
                        shiftTimeAndShift.get(1).contains("中") ||
                        shiftTimeAndShift.get(1).contains("晚") ||
@@ -156,13 +255,8 @@
                }
            }
        }
        }
        // 获取header时间
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 将字符串时间转换为 LocalDateTime 类型时间
        LocalDateTime localDateTime = LocalDateTime.parse(time, formatters);
        LocalDate firstDayOfMonth = localDateTime.toLocalDate().withDayOfMonth(1);
        LocalDate lastDayOfMonth = localDateTime.toLocalDate().with(TemporalAdjusters.lastDayOfMonth());
        List<LocalDateTime> localDateTimesBetween = getLocalDateTimesBetween(firstDayOfMonth.atStartOfDay(), lastDayOfMonth.atStartOfDay());
        List<Object> list1 = new ArrayList<>();
        for (LocalDateTime dateTime : localDateTimesBetween) {
@@ -178,6 +272,21 @@
        return resultMap;
    }
    /**
     * 获取两个日期之间的所有日期(格式:yyyy-MM-dd)
     * 注意:结束日期不包含在内(请假日期范围是开始日期到结束日期,不含结束日期)
     */
    private List<String> getDatesBetween(LocalDate startDate, LocalDate endDate) {
        List<String> dates = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate current = startDate;
        while (current.isBefore(endDate)) {
            dates.add(current.format(formatter));
            current = current.plusDays(1);
        }
        return dates;
    }
    @Override
    public void performanceShiftUpdate(PersonalShift personalShift) {
        baseMapper.update(new PersonalShift(), Wrappers.<PersonalShift>lambdaUpdate()