From 7188f28998d47c286e34cbd525986603cfc19ba9 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期五, 31 七月 2026 17:58:25 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_business' into dev_business

---
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImpl.java |   52 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImpl.java
index 8dbb2dc..9192b5b 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImpl.java
@@ -1,13 +1,16 @@
 package cn.iocoder.yudao.module.mes.service.cal.team;
 
 import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.shift.MesCalTeamShiftListReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.cal.holiday.MesCalHolidayDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanShiftDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanTeamDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamShiftDO;
 import cn.iocoder.yudao.module.mes.dal.mysql.cal.team.MesCalTeamShiftMapper;
+import cn.iocoder.yudao.module.mes.enums.cal.MesCalHolidayTypeEnum;
 import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftMethodEnum;
 import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftTypeEnum;
+import cn.iocoder.yudao.module.mes.service.cal.holiday.MesCalHolidayService;
 import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanService;
 import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanShiftService;
 import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanTeamService;
@@ -18,11 +21,14 @@
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
+import java.time.DayOfWeek;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_TEAM_SHIFT_GENERATE_SHIFT_NOT_ENOUGH;
@@ -49,6 +55,9 @@
     @Resource
     @Lazy
     private MesCalPlanTeamService planTeamService;
+    @Resource
+    @Lazy
+    private MesCalHolidayService holidayService;
 
     @Transactional(rollbackFor = Exception.class)
     @Override
@@ -69,23 +78,56 @@
             throw exception(CAL_TEAM_SHIFT_GENERATE_SHIFT_NOT_ENOUGH);
         }
 
-        // 2. 璁$畻鏃ユ湡璺ㄥ害锛岄亶鍘嗘瘡澶╃敓鎴愭帓鐝褰曪紝鏈�鍚庣粺涓�鍐欏叆鏁版嵁搴�
+        // 1.5 鍔犺浇鏃ユ湡鍖洪棿鍐呯殑鍋囨棩鏁版嵁锛屾瀯寤� Map<鏃ユ湡, 绫诲瀷>
+        Map<LocalDate, Integer> holidayMap = holidayService.getHolidayList(plan.getStartDate(), plan.getEndDate())
+                .stream().collect(Collectors.toMap(h -> h.getDay().toLocalDate(), MesCalHolidayDO::getType));
+
+        // 2. 璁$畻鏃ユ湡璺ㄥ害锛岄�愬ぉ鍒ゆ柇宸ヤ綔鏃ワ紝鐢熸垚鎺掔彮璁板綍
         LocalDate startDate = plan.getStartDate().toLocalDate();
         LocalDate endDate = plan.getEndDate().toLocalDate();
         long days = ChronoUnit.DAYS.between(startDate, endDate) + 1;
+        boolean excludeWeekend = plan.getExcludeWeekend() != null && plan.getExcludeWeekend();
         List<MesCalTeamShiftDO> allRecords = new ArrayList<>();
         int shiftIndex = 0;
+        int workdayOffset = 0; // 浠呭伐浣滄棩閫掑锛岀敤浜庡�掔彮杞崲璁℃暟
         for (int i = 0; i < days; i++) {
             LocalDate currentDate = startDate.plusDays(i);
+            // 2.1 璺宠繃闈炲伐浣滄棩
+            if (!isWorkday(currentDate, holidayMap, excludeWeekend)) {
+                continue;
+            }
             LocalDateTime currentDay = currentDate.atStartOfDay();
-            // 2.2.1 鏍规嵁鍊掔彮鏂瑰紡璁$畻 shiftIndex
-            shiftIndex = calculateShiftIndex(shiftIndex, i, currentDate, startDate, plan);
+            // 2.2.1 鏍规嵁鍊掔彮鏂瑰紡璁$畻 shiftIndex锛堜互宸ヤ綔鏃ュ亸绉讳负鍑嗭級
+            shiftIndex = calculateShiftIndex(shiftIndex, workdayOffset, currentDate, startDate, plan);
             // 2.2.2 鏍规嵁杞彮鏂瑰紡鐢熸垚鎺掔彮璁板綍锛屾敹闆嗗埌鍒楄〃
             buildRecordsForDay(allRecords, planId, currentDay, shiftIndex, plan.getShiftType(), teams, shifts);
+            workdayOffset++;
         }
 
         // 3. 鎵归噺鎻掑叆鎺掔彮璁板綍
         teamShiftMapper.insertBatch(allRecords);
+    }
+
+    /**
+     * 鍒ゆ柇鎸囧畾鏃ユ湡鏄惁涓哄伐浣滄棩
+     *
+     * 浼樺厛绾э細holiday 琛� > 鍛ㄦ湯鎺掗櫎寮�鍏� > 榛樿宸ヤ綔鏃�
+     */
+    private boolean isWorkday(LocalDate date, Map<LocalDate, Integer> holidayMap, boolean excludeWeekend) {
+        // 1. holiday 琛ㄤ紭鍏堬細鏄惧紡鏍囪鐨勬棩鏈熶互鏍囪涓哄噯
+        Integer holidayType = holidayMap.get(date);
+        if (holidayType != null) {
+            return MesCalHolidayTypeEnum.WORKDAY.getType().equals(holidayType);
+        }
+        // 2. 鑻ュ紑鍚簡鎺掗櫎鍛ㄦ湯锛屽懆鍏棩榛樿涓轰紤鎭棩
+        if (excludeWeekend) {
+            DayOfWeek dow = date.getDayOfWeek();
+            if (dow == DayOfWeek.SATURDAY || dow == DayOfWeek.SUNDAY) {
+                return false;
+            }
+        }
+        // 3. 榛樿宸ヤ綔鏃�
+        return true;
     }
 
     /**
@@ -96,6 +138,10 @@
         if (dayOffset == 0) {
             return shiftIndex; // 绗竴澶╀笉閫掑
         }
+        // 鍗曠櫧鐝笉闇�瑕佸�掔彮锛宻hiftMethod 涓� null锛岀洿鎺ヨ繑鍥�
+        if (plan.getShiftMethod() == null) {
+            return shiftIndex;
+        }
         if (MesCalShiftMethodEnum.QUARTER.getMethod().equals(plan.getShiftMethod())) {
             // 鎸夊搴﹁疆鐝細鍒颁簡鏂板搴︾殑绗竴澶�
             LocalDate quarterStart = LocalDateTimeUtils.getQuarterStart(currentDate);

--
Gitblit v1.9.3