From c7673b8c8f1d20c58c7265fa00c6fbf69caf994d Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期三, 04 十一月 2026 13:55:39 +0800
Subject: [PATCH] fix(shift): 修复排班与考勤的时间范围查询条件

---
 src/main/java/com/ruoyi/staff/service/impl/PersonalShiftServiceImpl.java |  111 ++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 80 insertions(+), 31 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 420bb71..9880ed5 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/PersonalShiftServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/PersonalShiftServiceImpl.java
@@ -2,26 +2,22 @@
 
 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;
 
@@ -29,7 +25,6 @@
 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;
@@ -46,10 +41,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) {
@@ -58,19 +53,21 @@
         LocalDateTime endWeek = performanceShiftAddDto.getEndWeek();//缁撴潫鏃ユ湡
 
 
-        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-        String formattedDateTime = performanceShiftAddDto.getStartWeek().format(formatter);
         String[] splitUserId = performanceShiftAddDto.getStaffOnJobId().split(",");
         for (String userId : splitUserId) {
             //鍒ゆ柇鏄惁璺ㄦ湀
             boolean isMonth = startWeek.getMonthValue() != endWeek.getMonthValue();
             if (isMonth){
                 //濡傛灉璺ㄦ湀,鍒欎袱涓湀閮藉垽鏂竴涓嬬湅鏁版嵁搴撴槸鍝釜鏈堜唤鐨勬暟鎹病鏈�
+                LocalDateTime startMonthBegin = startWeek.toLocalDate().withDayOfMonth(1).atStartOfDay();
+                LocalDateTime endMonthBegin = endWeek.toLocalDate().withDayOfMonth(1).atStartOfDay();
                 boolean exists1 = baseMapper.exists(Wrappers.<PersonalShift>lambdaQuery()
-                        .eq(PersonalShift::getWorkTime, startWeek)
+                        .ge(PersonalShift::getWorkTime, startMonthBegin)
+                        .lt(PersonalShift::getWorkTime, startMonthBegin.plusMonths(1))
                         .eq(PersonalShift::getStaffOnJobId, userId));
                 boolean exists2 = baseMapper.exists(Wrappers.<PersonalShift>lambdaQuery()
-                        .eq(PersonalShift::getWorkTime, endWeek)
+                        .ge(PersonalShift::getWorkTime, endMonthBegin)
+                        .lt(PersonalShift::getWorkTime, endMonthBegin.plusMonths(1))
                         .eq(PersonalShift::getStaffOnJobId, userId));
                 if (!exists1 && !exists2){
                     //涓や釜鏈堥兘涓嶅瓨鍦ㄦ暟鎹�
@@ -85,8 +82,10 @@
                 }
             }else {
                 //涓嶈法鏈�
+                LocalDateTime monthBegin = startWeek.toLocalDate().withDayOfMonth(1).atStartOfDay();
                 boolean exists = baseMapper.exists(Wrappers.<PersonalShift>lambdaQuery()
-                        .in(PersonalShift::getWorkTime, formattedDateTime)
+                        .ge(PersonalShift::getWorkTime, monthBegin)
+                        .lt(PersonalShift::getWorkTime, monthBegin.plusMonths(1))
                         .eq(PersonalShift::getStaffOnJobId, userId));
                 // 濡傛灉涓嶅瓨鍦ㄦ坊鍔犳暟鎹�
                 if (!exists) {
@@ -101,16 +100,17 @@
         // 鍐嶆鏇存柊
         List<LocalDateTime> datesBetween = getLocalDateTimesBetween(performanceShiftAddDto.getStartWeek(), performanceShiftAddDto.getEndWeek());
         for (LocalDateTime date : datesBetween) {
+            LocalDateTime dayBegin = date.toLocalDate().atStartOfDay();
             for (String s : splitUserId) {
                 PersonalShift personalShift = new PersonalShift();
                 personalShift.setPersonalAttendanceLocationConfigId(performanceShiftAddDto.getPersonalAttendanceLocationConfigId());
                 personalShift.setStaffOnJobId(Long.valueOf(s));
                 personalShift.setWorkTime(date);
-                String formatterDateTime = date.format(formatter);
                 baseMapper.update(new PersonalShift(), Wrappers.<PersonalShift>lambdaUpdate()
                         .set(PersonalShift::getPersonalAttendanceLocationConfigId, performanceShiftAddDto.getPersonalAttendanceLocationConfigId())
                         .eq(PersonalShift::getStaffOnJobId, s)
-                        .eq(PersonalShift::getWorkTime, formatterDateTime));
+                        .ge(PersonalShift::getWorkTime, dayBegin)
+                        .lt(PersonalShift::getWorkTime, dayBegin.plusDays(1)));
             }
         }
         return 0;
@@ -161,6 +161,12 @@
                 }
             }
         }
+        // 鍚堣鍑哄嫟澶╂暟浠ュ疄闄呮墦鍗¤褰曚负鍑嗭紙鎺掔彮鍙唬琛ㄨ鍒掞級
+        Map<String, Integer> attendanceDays = loadMonthAttendanceDays(time, userName, sysDeptId);
+        for (PerformanceShiftMapDto i : mapIPage.getRecords()) {
+            i.getMonthlyAttendance().put("totalAttendance",
+                    attendanceDays.getOrDefault(i.getUserId(), 0));
+        }
         // 鑾峰彇header鏃堕棿
         DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
         DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@@ -195,7 +201,8 @@
         IPage<Map<String, Object>> mapYearIPage = baseMapper.performanceShiftYear(page, time, userName, sysDeptId);
         //鏌ヨ鎵�鏈夌彮娆�(鎵撳崱瑙勫垯)
         List<PersonalAttendanceLocationConfig> personalAttendanceLocationConfigs = personalAttendanceLocationConfigMapper.selectList(null);
-        mapYearIPage.setRecords(annualAttendanceProcessing(mapYearIPage.getRecords(), personalAttendanceLocationConfigs));
+        Map<String, Map<Integer, Integer>> attendanceCounts = loadYearAttendanceDays(time, userName, sysDeptId);
+        mapYearIPage.setRecords(annualAttendanceProcessing(mapYearIPage.getRecords(), personalAttendanceLocationConfigs, attendanceCounts));
         return mapYearIPage;
     }
 
@@ -209,7 +216,8 @@
         LocalDateTime localDateTime = LocalDateTime.parse(time, formatters);
         map.put("header", getYearHeader(localDateTime.getYear() + " 骞�", personalAttendanceLocationConfigs));
         List<Map<String, Object>> mapYearList = baseMapper.performanceShiftYearList(time, userName, sysDeptId);
-        annualAttendanceProcessing(mapYearList, personalAttendanceLocationConfigs);
+        Map<String, Map<Integer, Integer>> attendanceCounts = loadYearAttendanceDays(time, userName, sysDeptId);
+        annualAttendanceProcessing(mapYearList, personalAttendanceLocationConfigs, attendanceCounts);
         List<List<Object>> lists = dataRequiredForProcessingIntoExcel(mapYearList, personalAttendanceLocationConfigs);
         map.put("data", lists);
         return map;
@@ -220,6 +228,8 @@
         //鏌ヨ鎵�鏈夌彮娆�(鎵撳崱瑙勫垯)
         List<PersonalAttendanceLocationConfig> personalAttendanceLocationConfigs = personalAttendanceLocationConfigMapper.selectList(null);
         List<PerformanceShiftMapDto> mapIPage = baseMapper.performanceShiftList(time, userName, sysDeptId);
+        // 鍚堣鍑哄嫟澶╂暟浠ュ疄闄呮墦鍗¤褰曚负鍑嗭紙鎺掔彮鍙唬琛ㄨ鍒掞級
+        Map<String, Integer> attendanceDays = loadMonthAttendanceDays(time, userName, sysDeptId);
         mapIPage.forEach(i -> {
             String[] shiftTimes = i.getShiftTime().split(";");
             double totalAttendance = 0;
@@ -228,6 +238,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);
@@ -251,6 +264,8 @@
             }
             i.setList(map);
             i.setShiftTime(null);
+            i.getMonthlyAttendance().put("totalAttendance",
+                    attendanceDays.getOrDefault(i.getUserId(), 0));
         });
         Map<Object, Object> map = new HashMap<>();
         DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@@ -258,20 +273,60 @@
         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;
     }
 
+    // 瀹為檯鎵撳崱鍑哄嫟澶╂暟锛堟寜鏈堬級
+    private Map<String, Integer> loadMonthAttendanceDays(String time, String userName, Integer sysDeptId) {
+        Map<String, Integer> result = new HashMap<>();
+        for (Map<String, Object> row : baseMapper.attendanceDayCountByMonth(time, userName, sysDeptId)) {
+            Object userId = row.get("user_id");
+            Object days = row.get("days");
+            if (userId != null && days != null) {
+                result.put(String.valueOf(userId), new BigDecimal(days.toString()).intValue());
+            }
+        }
+        return result;
+    }
+
+    // 瀹為檯鎵撳崱鍑哄嫟澶╂暟锛堟寜骞达紝姣忎汉姣忔湀锛�
+    private Map<String, Map<Integer, Integer>> loadYearAttendanceDays(String time, String userName, Integer sysDeptId) {
+        Map<String, Map<Integer, Integer>> result = new HashMap<>();
+        for (Map<String, Object> row : baseMapper.attendanceMonthCountByYear(time, userName, sysDeptId)) {
+            Object userId = row.get("user_id");
+            Object month = row.get("month");
+            Object days = row.get("days");
+            if (userId == null || month == null || days == null) {
+                continue;
+            }
+            result.computeIfAbsent(String.valueOf(userId), k -> new HashMap<>())
+                    .put(Integer.parseInt(month.toString()), new BigDecimal(days.toString()).intValue());
+        }
+        return result;
+    }
+
     // 骞村垎椤典笌瀵煎嚭鍏卞悓浣跨敤
-    public List<Map<String, Object>> annualAttendanceProcessing(List<Map<String, Object>> mapYearList,List<PersonalAttendanceLocationConfig> personalAttendanceLocationConfigs) {
+    public List<Map<String, Object>> annualAttendanceProcessing(List<Map<String, Object>> mapYearList, List<PersonalAttendanceLocationConfig> personalAttendanceLocationConfigs, Map<String, Map<Integer, Integer>> attendanceCounts) {
         for (Map<String, Object> map : mapYearList) {
             Map<String, Object> resultMap = new LinkedHashMap<>();
             Map<String, Object> hashMapYear = new LinkedHashMap<>();
             double totalYearAttendance = 0;
+            // 姣忎釜鏈堢殑鍚堣鍑哄嫟澶╂暟浠ュ疄闄呮墦鍗¤褰曚负鍑�
+            Map<Integer, Integer> staffMonthAttendance = attendanceCounts.getOrDefault(String.valueOf(map.get("user_id")), Collections.emptyMap());
             // 涓�骞�12涓湀
             for (int i = 1; i < 13; i++) {
                 Map<String, Object> hashMapMonth = new LinkedHashMap<>();
-                double totalMonthAttendance = 0;
                 for (PersonalAttendanceLocationConfig personalAttendanceLocationConfig : personalAttendanceLocationConfigs) {
                     // 鍒濆鍖栬祴鍊�
                     if (!hashMapYear.containsKey(personalAttendanceLocationConfig.getShift())){
@@ -283,14 +338,6 @@
                         int count = countOccurrences(charArray, i + "锛�" + personalAttendanceLocationConfig.getShift());
                         hashMapMonth.put(personalAttendanceLocationConfig.getShift(), count);
                         hashMapYear.put(personalAttendanceLocationConfig.getShift(), new BigDecimal(hashMapYear.get(personalAttendanceLocationConfig.getShift()).toString()).add(new BigDecimal(count)));
-                        // 鏃╋紝涓紝澶滐紝宸�
-                        if (personalAttendanceLocationConfig.getShift().contains("鏃�") ||
-                                personalAttendanceLocationConfig.getShift().contains("涓�") ||
-                                personalAttendanceLocationConfig.getShift().contains("鏅�") ||
-                                personalAttendanceLocationConfig.getShift().contains("澶�")) {
-                            totalMonthAttendance += count;
-                            totalYearAttendance += count;
-                        }
                     }
                     // 绌烘暟鎹�
                     else {
@@ -298,7 +345,9 @@
                         hashMapMonth.put(personalAttendanceLocationConfig.getShift(), 0);
                     }
                 }
-                hashMapMonth.put("totalMonthAttendance", totalMonthAttendance);
+                int monthAttendance = staffMonthAttendance.getOrDefault(i, 0);
+                totalYearAttendance += monthAttendance;
+                hashMapMonth.put("totalMonthAttendance", monthAttendance);
                 hashMapYear.put("totalYearAttendance", totalYearAttendance);
                 resultMap.put(i + "", hashMapMonth);
             }

--
Gitblit v1.9.3