From 571ccc18671ef45c6403496e8d99efec82168083 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期五, 26 六月 2026 10:21:02 +0800
Subject: [PATCH] 1.人员排班同步请假信息 2.人员排班同步调休信息

---
 src/main/java/com/ruoyi/staff/service/impl/PersonalShiftServiceImpl.java |  201 ++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 163 insertions(+), 38 deletions(-)

diff --git a/src/main/java/com/ruoyi/staff/service/impl/PersonalShiftServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/PersonalShiftServiceImpl.java
index dd4cf4b..3da6ffb 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/PersonalShiftServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/PersonalShiftServiceImpl.java
@@ -1,25 +1,23 @@
 package com.ruoyi.staff.service.impl;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.project.system.domain.SysDictData;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.staff.dto.PerformanceShiftAddDto;
 import com.ruoyi.staff.dto.PerformanceShiftMapDto;
 import com.ruoyi.staff.mapper.PersonalAttendanceLocationConfigMapper;
+import com.ruoyi.staff.mapper.PersonalShiftMapper;
 import com.ruoyi.staff.pojo.PersonalAttendanceLocationConfig;
 import com.ruoyi.staff.pojo.PersonalShift;
-import com.ruoyi.staff.mapper.PersonalShiftMapper;
-import com.ruoyi.staff.service.PersonalAttendanceLocationConfigService;
 import com.ruoyi.staff.service.PersonalShiftService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.staff.utils.JackSonUtil;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
-import cn.hutool.core.date.DateUtil;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.ObjectUtils;
 
@@ -27,11 +25,11 @@
 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
-import java.time.YearMonth;
 import java.time.ZoneId;
 import java.time.format.DateTimeFormatter;
 import java.time.temporal.TemporalAdjusters;
 import java.util.*;
+import java.util.stream.Collectors;
 
 
 /**
@@ -44,10 +42,10 @@
  */
 @Service
 @Transactional(rollbackFor = Exception.class)
+@RequiredArgsConstructor
 public class PersonalShiftServiceImpl extends ServiceImpl<PersonalShiftMapper, PersonalShift> implements PersonalShiftService {
 
-    @Autowired
-    private PersonalAttendanceLocationConfigMapper personalAttendanceLocationConfigMapper;
+    private final PersonalAttendanceLocationConfigMapper personalAttendanceLocationConfigMapper;
 
     @Override
     public int performanceShiftAdd(PerformanceShiftAddDto performanceShiftAddDto) {
@@ -119,47 +117,146 @@
         IPage<PerformanceShiftMapDto> mapIPage = baseMapper.performanceShiftPage(page, time, userName, sysDeptId);
         //鏌ヨ鎵�鏈夌彮娆�(鎵撳崱瑙勫垯)
         List<PersonalAttendanceLocationConfig> personalAttendanceLocationConfigs = personalAttendanceLocationConfigMapper.selectList(null);
-        mapIPage.getRecords().forEach(i -> {
-            String[] shiftTimes = i.getShiftTime().split(";");
+
+        // 鑾峰彇褰撴湀鏃堕棿鑼冨洿
+        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());
+
+        // 鏀堕泦鎵�鏈夊憳宸D
+        List<Long> staffIds = mapIPage.getRecords().stream()
+                .filter(dto -> dto.getUserId() != null)
+                .map(dto -> Long.valueOf(dto.getUserId()))
+                .distinct()
+                .collect(Collectors.toList());
+
+        // 鏌ヨ褰撴湀瀹℃牳閫氳繃鐨勮鍋囪褰曪紙浠巃pproval_instance鐨刦orm_config瑙f瀽锛�
+        Map<Long, List<String>> staffHolidayMap = new HashMap<>();
+        if (!staffIds.isEmpty()) {
+            // 閫氳繃鍏宠仈鏌ヨ鑾峰彇鍛樺伐璇峰亣淇℃伅
+            List<Map<String, Object>> holidayRecords = baseMapper.selectStaffHolidayDates(staffIds);
+
+            // 鏋勫缓鍛樺伐-璇峰亣鏃ユ湡鏄犲皠锛堜粠form_config JSON瑙f瀽锛�
+            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 {
+                        // 瑙f瀽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);
+
+                                    // 瑙f瀽鏃ユ湡锛堟牸寮忥細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瑙f瀽澶辫触锛岃烦杩囨璁板綍
+                    }
+                }
+            }
+        }
+
+        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);
                 Map<String, Object> hashMap = new HashMap<>();
-                String[] shiftTimeAndShift = shiftTime.split("锛�");
+                List<String> shiftTimeAndShift = StrUtil.split(shiftTime, "锛�");
+                if(CollUtil.isEmpty(shiftTimeAndShift) || shiftTimeAndShift.size() != 3){
+                    continue;
+                }
                 //鎺掔彮璇︾粏鏁版嵁
-                hashMap.put("id", shiftTimeAndShift[2]);
-                hashMap.put("shift", shiftTimeAndShift[1]);
-                hashMap.put("time", shiftTimeAndShift[0]);
+                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涓簍rue锛屽苟灏嗙彮娆¤涓轰紤鎭�
+                if (holidayDateSet.contains(workDate)) {
+                    hashMap.put("isHoliday", true);
+                    hashMap.put("shift", "浼戞伅");
+                } else {
+                    hashMap.put("isHoliday", false);
+                }
+
                 map.add(hashMap);
                 i.setList(map);
-                //姹囨�荤殑鍚勭彮娆$粺璁℃暟鎹�
-                for (PersonalAttendanceLocationConfig personalAttendanceLocationConfig : personalAttendanceLocationConfigs) {
-                    if (!i.getMonthlyAttendance().containsKey(personalAttendanceLocationConfig.getShift())){
-                        i.getMonthlyAttendance().put(personalAttendanceLocationConfig.getShift(), 0);
+
+                // 缁熻鐝鏁版嵁
+                if (holidayDateSet.contains(workDate)) {
+                    // 濡傛灉鏄鍋囨棩鏈燂紝缁熻涓轰紤鎭紙鍙粺璁′竴娆★級
+                    if (!i.getMonthlyAttendance().containsKey("浼戞伅")){
+                        i.getMonthlyAttendance().put("浼戞伅", 0);
                     }
-                    if (personalAttendanceLocationConfig.getShift().equals(shiftTimeAndShift[1])) {
-                        BigDecimal bigDecimal = new BigDecimal(i.getMonthlyAttendance().get(personalAttendanceLocationConfig.getShift()).toString());
-                        i.getMonthlyAttendance().put(personalAttendanceLocationConfig.getShift(), bigDecimal.add(new BigDecimal("1")));
+                    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);
+                        }
+                        if (personalAttendanceLocationConfig.getShift().equals(shiftTimeAndShift.get(1))) {
+                            BigDecimal bigDecimal = new BigDecimal(i.getMonthlyAttendance().get(personalAttendanceLocationConfig.getShift()).toString());
+                            i.getMonthlyAttendance().put(personalAttendanceLocationConfig.getShift(), bigDecimal.add(new BigDecimal("1")));
+                        }
                     }
-                }
-                //缁熻鎬诲嚭鍕ゅぉ鏁�(鏃�/涓�/鏅�/澶�)閮界畻鍑哄嫟,鍏朵綑閮芥槸浼戞伅
-                if (shiftTimeAndShift[1].contains("鏃�") ||
-                        shiftTimeAndShift[1].contains("涓�") ||
-                        shiftTimeAndShift[1].contains("鏅�") ||
-                        shiftTimeAndShift[1].contains("澶�")) {
-                    i.getMonthlyAttendance().put("totalAttendance", totalAttendance += 1);
+                    // 缁熻鎬诲嚭鍕ゅぉ鏁�(鏃�/涓�/鏅�/澶�)閮界畻鍑哄嫟
+                    if (shiftTimeAndShift.get(1).contains("鏃�") ||
+                        shiftTimeAndShift.get(1).contains("涓�") ||
+                        shiftTimeAndShift.get(1).contains("鏅�") ||
+                        shiftTimeAndShift.get(1).contains("澶�")) {
+                        i.getMonthlyAttendance().put("totalAttendance", totalAttendance += 1);
+                    }
                 }
             }
-        });
+        }
         // 鑾峰彇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) {
@@ -173,6 +270,21 @@
         resultMap.put("page", mapIPage);
         resultMap.put("headerList", list1);
         return resultMap;
+    }
+
+    /**
+     * 鑾峰彇涓や釜鏃ユ湡涔嬮棿鐨勬墍鏈夋棩鏈燂紙鏍煎紡锛歽yyy-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
@@ -220,6 +332,9 @@
             for (String shiftTime : shiftTimes) {
                 Map<String, Object> hashMap = new HashMap<>();
                 String[] shiftTimeAndShift = shiftTime.split("锛�");
+                if(shiftTimeAndShift.length != 3){
+                    continue;
+                }
                 for (PersonalAttendanceLocationConfig personalAttendanceLocationConfig : personalAttendanceLocationConfigs) {
                     if (!i.getMonthlyAttendance().containsKey(personalAttendanceLocationConfig.getShift())) {
                         i.getMonthlyAttendance().put(personalAttendanceLocationConfig.getShift(), 0);
@@ -250,6 +365,16 @@
         LocalDateTime localDateTime = LocalDateTime.parse(time, formatters);
         map.put("header", getMonthHeader(localDateTime));
         List<List<Object>> lists = dataRequiredForProcessingIntoExcelMonth(mapIPage, personalAttendanceLocationConfigs);
+        int maxSize = lists.stream()
+                .mapToInt(List::size)
+                .max()
+                .orElse(0);
+
+        for (List<Object> row : lists) {
+            while (row.size() < maxSize) {
+                row.add("-");
+            }
+        }
         map.put("data", lists);
         return map;
     }

--
Gitblit v1.9.3