Explorar o código

优化排班表

xuzhancheng hai 1 mes
pai
achega
e0a4b64ae3
Modificáronse 16 ficheiros con 656 adicións e 246 borrados
  1. 2 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/EquipPipeSchedulingController.java
  2. 3 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/vo/PipeShiftScheduleReqVO.java
  3. 50 52
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/vo/PipeShiftScheduleRespVO.java
  4. 8 4
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/vo/PipeShiftScheduleSaveRespVO.java
  5. 2 2
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/vo/PipeShiftScheduleTeamRespVO.java
  6. 4 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/dataobject/equipboilerscheduling/EquipBoilerSchedulingDO.java
  7. 5 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/dataobject/equippipescheduling/EquipPipeSchedulingDO.java
  8. 1 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/mysql/equipboiler/EquipBoilerMapper.java
  9. 1 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/mysql/equippipe/EquipPipeMapper.java
  10. 3 1
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/mysql/equippipescheduling/EquipPipeSchedulingMapper.java
  11. 1 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/equippipescheduling/EquipPipeSchedulingService.java
  12. 531 186
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/equippipescheduling/EquipPipeSchedulingServiceImpl.java
  13. 13 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/synchronization/SynchronizationServiceImpl.java
  14. 3 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/synchronization/dto/BoilerDto.java
  15. 5 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/synchronization/dto/PipeDto.java
  16. 24 1
      tz-module-pressure2/tz-module-pressure2-biz/src/main/resources/mapper/equippipescheduling/EquipPipeSchedulingMapper.xml

+ 2 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/EquipPipeSchedulingController.java

@@ -13,6 +13,8 @@ import io.swagger.v3.oas.annotations.Operation;
 import jakarta.validation.constraints.*;
 import jakarta.validation.*;
 import jakarta.servlet.http.*;
+
+import java.time.LocalDate;
 import java.util.*;
 import java.io.IOException;
 

+ 3 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/vo/PipeShiftScheduleReqVO.java

@@ -34,4 +34,7 @@ public class PipeShiftScheduleReqVO {
 
     @Schema(description = "排序方式")
     private String orderType;
+
+    @Schema(description = "confirmOrderId")
+    private String confirmOrderId;
 }

+ 50 - 52
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/vo/PipeShiftScheduleRespVO.java

@@ -13,9 +13,6 @@ import java.util.List;
 @Data
 public class PipeShiftScheduleRespVO {
 
-    @Schema(description = "任务")
-    private List<PipeShiftScheduleItemRespVO> taskItems;
-
     @Schema(description = "检验员")
     private List<String> checkers;
 
@@ -34,76 +31,77 @@ public class PipeShiftScheduleRespVO {
     @Schema(description = "管道介质")
     private List<String> pipeMedium;
 
-    @Data
-    public static class PipeShiftScheduleItemRespVO {
+    @Schema(description = "单位名称")
+    private String unitName;
+
+    @Schema(description = "单位地址")
+    private String unitAddress;
 
-        @Schema(description = "单位名称")
-        private String unitName;
+    private String pipeAddress;
 
-        @Schema(description = "单位地址")
-        private String unitAddress;
+    private Integer equipDistrict;
 
-        private String pipeAddress;
+    @Schema(description = "设备所在区域名称")
+    private String equipDistrictName;
 
-        private Integer equipDistrict;
+    private Integer equipStreet;
 
-        @Schema(description = "设备所在区域名称")
-        private String equipDistrictName;
+    @Schema(description = "设备所在街道名称")
+    private String equipStreetName;
 
-        private Integer equipStreet;
+    @Schema(description = "任务id")
+    private String taskId;
 
-        @Schema(description = "设备所在街道名称")
-        private String equipStreetName;
+    @Schema(description = "检验类型")
+    private String checkType;
 
-        @Schema(description = "任务id")
-        private String taskId;
+    @Schema(description = "设备数量")
+    private String equipCount;
 
-        @Schema(description = "检验类型")
-        private String checkType;
+    @Schema(description = "日期")
+    private LocalDate planDate;
 
-        @Schema(description = "设备数量")
-        private String equipCount;
+    @Schema(description = "周")
+    private String week;
 
-        @Schema(description = "日期")
-        private LocalDate planDate;
+    @Schema(description = "来源")
+    private Integer source;
 
-        @Schema(description = "来源")
-        private Integer source;
+    @Schema(description = "纬度")
+    private Double lat;
 
-        @Schema(description = "纬度")
-        private Double lat;
+    @Schema(description = "经度")
+    private Double lng;
 
-        @Schema(description = "经度")
-        private Double lng;
 
-        private Integer status;
+    private Integer taskStatus;
 
-        private Integer taskStatus;
+    private Integer acceptStatus;
 
-        private Integer acceptStatus;
+    private String appointmentId;
 
-        private String appointmentId;
+    // 联系人
+    @Schema(description = "联系人")
+    private String contact;
 
-        // 联系人
-        @Schema(description = "联系人")
-        private String contact;
+    // 电话
+    @Schema(description = "联系人电话")
+    private String contactPhone;
 
-        // 电话
-        @Schema(description = "联系人电话")
-        private String contactPhone;
+    // 管线长度 (m)
+    @Schema(description = "管道长度")
+    private String pipeLengthTotal;
 
-        // 管线长度 (m)
-        @Schema(description = "管道长度")
-        private String pipeLengthTotal;
+    // 上次报告编号
+    @Schema(description = "上次定检报告编号")
+    private String lastLegalPeriodicalInspectionReportNo;
 
-        // 上次报告编号
-        @Schema(description = "上次定检报告编号")
-        private String lastLegalPeriodicalInspectionReportNo;
+    @Schema(description = "上次年检报告编号")
+    private String lastYearReportNo;
+    // 监督报告编号
+    @Schema(description = "监督检验报告编号")
+    private String lastMaintenanceReportNo;
 
-        @Schema(description = "上次年检报告编号")
-        private String lastYearReportNo;
-        // 监督报告编号
-        @Schema(description = "监督检验报告编号")
-        private String lastMaintenanceReportNo;
-    }
+    @Schema(description = "约检确认单ID(排期表的confirm_order_id)")
+    private String confirmOrderId;
 }

+ 8 - 4
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/vo/PipeShiftScheduleSaveRespVO.java

@@ -11,21 +11,25 @@ import lombok.Data;
 import java.time.LocalDate;
 import java.util.List;
 
-@Schema(description = "管理后台 - 计划排期日历 Response VO")
+@Schema(description = "管理后台 - 排班表保存 Request VO")
 @Data
 public class PipeShiftScheduleSaveRespVO {
 
 
     @Schema(description = "小组信息")
-    @Size(min = 1, message = "小组信息不能为空")
     private List<BoilerPlanSchedulingAssignTeamItemVO> teamList;
 
-
-    @NotNull
+    @Schema(description = "排期ID(修改时必传)")
     private String id;
 
     @Schema(description = "日期")
     @NotNull
     private LocalDate date;
 
+    @Schema(description = "是否为复制操作,true=复制,false/null=修改")
+    private Boolean isCopy;
+
+    @Schema(description = "源排期ID(复制时必传,用于查找原行数据)")
+    private String sourceId;
+
 }

+ 2 - 2
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/equippipescheduling/vo/PipeShiftScheduleTeamRespVO.java

@@ -12,8 +12,8 @@ public class PipeShiftScheduleTeamRespVO {
     private String groupTeamId;
 
     @Schema(description = "组长")
-    private List<PipeShiftScheduleUserRespVO> leaders;
+    private List<AdminUserRespDTO> leaders;
 
     @Schema(description = "成员")
-    private List<PipeShiftScheduleUserRespVO> members;
+    private List<AdminUserRespDTO> members;
 }

+ 4 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/dataobject/equipboilerscheduling/EquipBoilerSchedulingDO.java

@@ -94,4 +94,8 @@ public class EquipBoilerSchedulingDO extends BaseDO {
 
     private String factoryCode;
 
+    /**
+     * 约检确认id
+     */
+    private String confirmOrderId;
 }

+ 5 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/dataobject/equippipescheduling/EquipPipeSchedulingDO.java

@@ -54,4 +54,9 @@ public class EquipPipeSchedulingDO extends BaseDO {
      * 是否需要前台约检确认
      */
     private Boolean hasOrderConfirm;
+
+    /**
+     * 约检确认id
+     */
+    private String confirmOrderId;
 }

+ 1 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/mysql/equipboiler/EquipBoilerMapper.java

@@ -189,6 +189,7 @@ public interface EquipBoilerMapper extends BaseMapperX<EquipBoilerDO> {
                 .set(EquipBoilerDO::getUsepressure, equipBoilerDO.getUsepressure())
                 .set(EquipBoilerDO::getWaterlastresult, equipBoilerDO.getWaterlastresult())
                 .set(EquipBoilerDO::getWorkpressure, equipBoilerDO.getWorkpressure())
+                .set(EquipBoilerDO::getEquipStreet, equipBoilerDO.getEquipStreet())
                 .set(EquipBoilerDO::getUpdateTime, LocalDateTime.now())
                 .set(EquipBoilerDO::getUpdater, equipBoilerDO.getUpdater())
                 .set(EquipBoilerDO::getCreateTime, equipBoilerDO.getCreateTime())

+ 1 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/mysql/equippipe/EquipPipeMapper.java

@@ -157,6 +157,7 @@ public interface EquipPipeMapper extends BaseMapperX<EquipPipeDO> {
                 .set(EquipPipeDO::getRecord, updateObj.getRecord())
                 .set(EquipPipeDO::getSevereCyclic, updateObj.getSevereCyclic())
                 .set(EquipPipeDO::getStandard, updateObj.getStandard())
+                .set(EquipPipeDO::getEquipStreet, updateObj.getEquipStreet())
                 .set(EquipPipeDO::getUpdateTime, LocalDateTime.now())
                 .set(EquipPipeDO::getUpdater, updateObj.getUpdater())
                 .eq(EquipPipeDO::getId, updateObj.getId())

+ 3 - 1
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/mysql/equippipescheduling/EquipPipeSchedulingMapper.java

@@ -65,7 +65,9 @@ public interface EquipPipeSchedulingMapper extends BaseMapperX<EquipPipeScheduli
 
     List<BoilerCalendarItemRespVO> selectPlanCalendar(BoilerCalendarReqVO reqVO);
 
-    List<PipeShiftScheduleRespVO.PipeShiftScheduleItemRespVO> selectShiftSchedule(PipeShiftScheduleReqVO reqVO);
+    List<PipeShiftScheduleRespVO> selectShiftSchedule(PipeShiftScheduleReqVO reqVO);
+
+    PipeShiftScheduleRespVO getShiftScheduleById(PipeShiftScheduleReqVO reqVO);
 
     List<EquipPipeSchedulingPipesRespVO> selectPlanPipesPage(EquipPipeSchedulingPageReqVO reqVO);
 

+ 1 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/equippipescheduling/EquipPipeSchedulingService.java

@@ -1,5 +1,6 @@
 package cn.start.tz.module.pressure2.service.equippipescheduling;
 
+import java.time.LocalDate;
 import java.util.*;
 
 import cn.start.tz.module.pressure2.controller.admin.equipboilerscheduling.vo.*;

+ 531 - 186
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/equippipescheduling/EquipPipeSchedulingServiceImpl.java

@@ -2,10 +2,14 @@ package cn.start.tz.module.pressure2.service.equippipescheduling;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.ListUtil;
+import cn.start.tz.framework.common.exception.ServiceException;
 import cn.start.tz.framework.common.pojo.CommonResult;
 import cn.start.tz.framework.ip.core.Area;
 import cn.start.tz.framework.ip.core.utils.AreaUtils;
 import cn.start.tz.framework.mybatis.core.query.LambdaQueryWrapperX;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.stream.Collectors;
 import cn.start.tz.module.pressure2.controller.admin.appointmentconfirmorder.vo.AppointmentSubmitVO;
 import cn.start.tz.module.pressure2.controller.admin.appointmentconfirmorder.vo.PipeAppointmentSubmitVO;
 import cn.start.tz.module.pressure2.controller.admin.appointmentconfirmorder.vo.SubmitTeamItemVO;
@@ -615,6 +619,11 @@ public class EquipPipeSchedulingServiceImpl extends ServiceImpl<EquipPipeSchedul
 
         for (EquipPipeSchedulingDO schedulingDO : equipPipeSchedulingDOS) {
             String id = schedulingDO.getId();
+
+            //
+            if (schedulingDO.getConfirmOrderId() != null){
+                continue;
+            }
             List<EquipPipeSchedulingItemDO> equipPipeSchedulingItemDOS = equipPipeSchedulingItemMapper.selectList(EquipPipeSchedulingItemDO::getSchedulingId, id);
 
             //获取管道排期设备信息
@@ -744,7 +753,8 @@ public class EquipPipeSchedulingServiceImpl extends ServiceImpl<EquipPipeSchedul
             appointmentConfirmOrderDO.setEquipNumBoiler(equipPipeSchedulingItemDOS.size());
             // 创建约检确认单
             String confirmOrderId = appointmentConfirmOrderService.create(appointmentConfirmOrderDO);
-
+            schedulingDO.setConfirmOrderId(confirmOrderId);
+            equipPipeSchedulingMapper.updateById(schedulingDO);
             // 创建任务单项目
             equipPipeSchedulingItemDOS.forEach(item->{
                 PipeAppointmentConfirmOrderItemDO orderItem = new PipeAppointmentConfirmOrderItemDO();
@@ -1191,161 +1201,504 @@ public class EquipPipeSchedulingServiceImpl extends ServiceImpl<EquipPipeSchedul
 
     @Override
     public List<PipeShiftScheduleRespVO> shiftSchedule(PipeShiftScheduleReqVO pageReqVO) {
-        List<PipeShiftScheduleRespVO.PipeShiftScheduleItemRespVO>  pipeShiftScheduleItemRespVOS = equipPipeSchedulingMapper.selectShiftSchedule(pageReqVO);
+        List<PipeShiftScheduleRespVO>  pipeShiftScheduleItemRespVOS = equipPipeSchedulingMapper.selectShiftSchedule(pageReqVO);
 
-        List<PipeShiftScheduleRespVO>  list = new ArrayList<>();
         if(pipeShiftScheduleItemRespVOS == null || pipeShiftScheduleItemRespVOS.isEmpty()){
-            return list;
+            return pipeShiftScheduleItemRespVOS;
+        }
+
+        // 获取所有任务ID
+        List<String> taskIds = pipeShiftScheduleItemRespVOS.stream()
+                .map(PipeShiftScheduleRespVO::getTaskId)
+                .filter(Objects::nonNull)
+                .toList();
+
+        // 查询检验员和团队信息
+        Map<String, List<EquipPipeSchedulingUserDO>> taskIdToUsersMap = new HashMap<>();
+        if (!taskIds.isEmpty()) {
+            List<EquipPipeSchedulingUserDO> schedulingUsers = equipPipeSchedulingUserMapper.selectList(
+                    new LambdaQueryWrapperX<EquipPipeSchedulingUserDO>()
+                            .in(EquipPipeSchedulingUserDO::getSchedulingId, taskIds)
+                            .eq(EquipPipeSchedulingUserDO::getDeleted, 0)
+            );
+
+            // 按任务ID分组
+            taskIdToUsersMap = schedulingUsers.stream()
+                    .filter(user -> user.getSchedulingId() != null) // 过滤掉 schedulingId 为 null 的记录
+                    .collect(Collectors.groupingBy(EquipPipeSchedulingUserDO::getSchedulingId));
+        }
+
+        // 查询任务ID对应的设备ID列表
+        Map<String, List<String>> taskIdToEquipIdsMap = new HashMap<>();
+        if (!taskIds.isEmpty()) {
+            List<EquipPipeSchedulingItemDO> schedulingItems = equipPipeSchedulingItemMapper.selectList(
+                    new LambdaQueryWrapperX<EquipPipeSchedulingItemDO>()
+                            .in(EquipPipeSchedulingItemDO::getSchedulingId, taskIds)
+                            .eq(EquipPipeSchedulingItemDO::getDeleted, 0)
+            );
+
+            // 按任务ID分组
+            taskIdToEquipIdsMap = schedulingItems.stream()
+                    .filter(item -> item.getSchedulingId() != null) // 过滤掉 schedulingId 为 null 的记录
+                    .filter(item -> item.getEquipId() != null) // 过滤掉 equipId 为 null 的记录
+                    .collect(Collectors.groupingBy(
+                            EquipPipeSchedulingItemDO::getSchedulingId,
+                            Collectors.mapping(EquipPipeSchedulingItemDO::getEquipId, Collectors.toList())
+                    ));
+        }
+
+        // 收集所有设备ID
+        List<String> allEquipIds = taskIdToEquipIdsMap.values().stream()
+                .flatMap(List::stream)
+                .distinct()
+                .toList();
+
+        // 查询管道介质信息(通过明细表 PRESSURE2_EQUIP_PIPE_DETAIL)
+        Map<String, List<String>> equipIdToMediumsMap;
+        if (!allEquipIds.isEmpty()) {
+            List<EquipPipeDetailDO> pipeDetails = equipPipeDetailMapper.selectList(
+                    new LambdaQueryWrapperX<EquipPipeDetailDO>()
+                            .in(EquipPipeDetailDO::getEquipPipeId, allEquipIds)
+                            .eq(EquipPipeDetailDO::getDeleted, 0)
+            );
+
+            // 按设备ID分组并收集管道介质
+            equipIdToMediumsMap = pipeDetails.stream()
+                    .filter(detail -> detail.getPipeMedium() != null && !detail.getPipeMedium().isEmpty())
+                    .filter(detail -> detail.getEquipPipeId() != null) // 过滤掉 equipPipeId 为 null 的记录
+                    .collect(Collectors.groupingBy(
+                            EquipPipeDetailDO::getEquipPipeId,
+                            Collectors.mapping(EquipPipeDetailDO::getPipeMedium, Collectors.toList())
+                    ));
+        } else {
+            equipIdToMediumsMap = new HashMap<>();
+        }
+
+        // 构建任务ID到管道介质列表的映射
+        Map<String, List<String>> taskIdToMediumsMap = new HashMap<>();
+        for (Map.Entry<String, List<String>> entry : taskIdToEquipIdsMap.entrySet()) {
+            String taskId = entry.getKey();
+            List<String> equipIdsForTask = entry.getValue();
+            if (taskId != null && equipIdsForTask != null) {
+                List<String> mediums = equipIdsForTask.stream()
+                        .filter(equipId -> equipId != null && equipIdToMediumsMap.containsKey(equipId))
+                        .map(equipIdToMediumsMap::get)
+                        .filter(Objects::nonNull)
+                        .flatMap(List::stream)
+                        .distinct()
+                        .toList();
+                taskIdToMediumsMap.put(taskId, mediums);
+            }
+        }
+
+        // 查询所有检验员的用户信息
+        Set<String> allCheckerIds = new HashSet<>();
+        taskIdToUsersMap.values().stream()
+                .flatMap(List::stream)
+                .filter(user -> user.getUserId() != null)
+                .forEach(user -> allCheckerIds.add(user.getUserId()));
+
+        // 批量获取用户信息
+        Map<String, AdminUserRespDTO> userIdToUserMap = new HashMap<>();
+        if (!allCheckerIds.isEmpty()) {
+            List<AdminUserRespDTO> users = adminUserApi.getUserList(new ArrayList<>(allCheckerIds)).getCheckedData();
+            for (AdminUserRespDTO user : users) {
+                if (user != null && user.getId() != null) {
+                    userIdToUserMap.put(user.getId(), user);
+                }
+            }
         }
 
-        // 根据taskId 分组
-        Map<String, List<PipeShiftScheduleRespVO.PipeShiftScheduleItemRespVO>> taskIdToPipeShiftScheduleItemRespVOS = pipeShiftScheduleItemRespVOS.stream().collect(Collectors.groupingBy(PipeShiftScheduleRespVO.PipeShiftScheduleItemRespVO::getTaskId));
-        taskIdToPipeShiftScheduleItemRespVOS.forEach((taskId, scheduleItemRespVOS)->{
-            PipeShiftScheduleRespVO pipeShiftScheduleRespVO = new PipeShiftScheduleRespVO();
-            pipeShiftScheduleRespVO.setId(taskId);
-            pipeShiftScheduleRespVO.setStatus(100);
-            PipeShiftScheduleRespVO.PipeShiftScheduleItemRespVO pipeShiftScheduleItemRespVO = scheduleItemRespVOS.get(0);
-            pipeShiftScheduleRespVO.setDate(pipeShiftScheduleItemRespVO.getPlanDate());
-            if (pipeShiftScheduleItemRespVO.getAppointmentId() != null){
-                pipeShiftScheduleRespVO.setStatus(200);
-                if (pipeShiftScheduleItemRespVO.getAcceptStatus() != null){
-                    pipeShiftScheduleRespVO.setStatus(300);
-                    if (pipeShiftScheduleItemRespVO.getTaskStatus() != null){
-                        pipeShiftScheduleRespVO.setStatus(400);
+        // 处理数据,确保所有字段都有值
+        for (PipeShiftScheduleRespVO item : pipeShiftScheduleItemRespVOS) {
+            // 设置状态
+            item.setId(item.getTaskId());
+            int status = 100; // 默认已排期
+            if (item.getAppointmentId() != null) {
+                status = 200; // 待约检
+            }
+            if (item.getAcceptStatus() != null && item.getAcceptStatus() == 200){
+                status = 300;
+            }
+            if (item.getTaskStatus() != null) {
+                status = 400; // 检测中
+            }
+            item.setStatus(status);
+
+            // 复制出来的行没有约检确认单,通过 confirmOrderId 找源排期,用源排期的关联状态
+            if (status == 100 && StringUtils.isNotBlank(item.getConfirmOrderId())) {
+                PipeShiftScheduleReqVO r = new PipeShiftScheduleReqVO();
+                r.setConfirmOrderId(item.getConfirmOrderId());
+                PipeShiftScheduleRespVO sourceItem = equipPipeSchedulingMapper.getShiftScheduleById(r);
+                if (sourceItem != null) {
+                    if (sourceItem.getAppointmentId() != null) {
+                        status = 200; // 待约检
+                    }
+                    if (sourceItem.getAcceptStatus() != null && sourceItem.getAcceptStatus() == 200) {
+                        status = 300; // 已受理
+                    }
+                    if (sourceItem.getTaskStatus() != null) {
+                        status = 400; // 检测中
                     }
                 }
             }
+            item.setStatus(status);
+
+            // 处理日期和星期
+            if (item.getPlanDate() != null) {
+                item.setDate(item.getPlanDate());
+                // 计算星期
+                int dayOfWeek = item.getPlanDate().getDayOfWeek().getValue();
+                String[] weekDays = {"日", "一", "二", "三", "四", "五", "六"};
+                item.setWeek(weekDays[dayOfWeek - 1]);
+            }
+
+            // 设置管道介质
+            String taskId = item.getTaskId();
+            if (taskId != null && taskIdToMediumsMap.containsKey(taskId)) {
+                item.setPipeMedium(taskIdToMediumsMap.get(taskId));
+            } else {
+                item.setPipeMedium(new ArrayList<>());
+            }
 
-            List<EquipPipeSchedulingUserDO> equipPipeSchedulingUserDOS = equipPipeSchedulingUserMapper.selectList(EquipPipeSchedulingUserDO::getSchedulingId, taskId);
-            pipeShiftScheduleRespVO.setCheckers(equipPipeSchedulingUserDOS.stream().map(EquipPipeSchedulingUserDO::getUserId).toList());
-
-            //List<EquipPipeSchedulingUserDO> equipPipeSchedulingUserDOS = equipPipeSchedulingUserMapper.selectList(EquipPipeSchedulingUserDO::getSchedulingId, taskId);
-            List<String> userIds = equipPipeSchedulingUserDOS.stream().map(item -> item.getUserId()).toList();
-            Map<String, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
-
-            Set<String> set = equipPipeSchedulingUserDOS.stream().map(item -> item.getGroupTeamId()).collect(Collectors.toSet());
-            set.stream().sorted();
-
-            List<PipeShiftScheduleTeamRespVO> userList = set.stream().map(groupTeamId ->
-                    {
-                        PipeShiftScheduleTeamRespVO taskDetailsItemVO = new PipeShiftScheduleTeamRespVO();
-                        List<PipeShiftScheduleUserRespVO> leaderList = new ArrayList<>();
-                        List<PipeShiftScheduleUserRespVO> membetList = new ArrayList<>();
-
-                        equipPipeSchedulingUserDOS.forEach(item2->{
-                            if(groupTeamId != null && groupTeamId.equals(item2.getGroupTeamId())){
-                                PipeShiftScheduleUserRespVO userRespVO = new PipeShiftScheduleUserRespVO();
-                                AdminUserRespDTO userRespDTO = userMap.get(item2.getUserId());
-                                userRespVO.setDate(item2.getDate());
-                                userRespVO.setEquipPipeScheduleUserId(item2.getId());
-                                userRespVO.setAdminUserRespDTO(userRespDTO);
-                                if(item2.getType() == 100){
-                                    leaderList.add(userRespVO);
-                                } else if (item2.getType() == 200) {
-                                    membetList.add(userRespVO);
-                                }
+            // 处理区域和街道名称
+            if (item.getEquipDistrict() != null) {
+                item.setEquipDistrictName(AreaUtils.getAreaName(item.getEquipDistrict()));
+            }
+            if (item.getEquipStreet() != null) {
+                item.setEquipStreetName(AreaUtils.getAreaName(item.getEquipStreet()));
+            }
+
+            // 处理检验员和团队信息
+            if (taskId != null && taskIdToUsersMap.containsKey(taskId)) {
+                List<EquipPipeSchedulingUserDO> users = taskIdToUsersMap.get(taskId);
+                if (users != null && !users.isEmpty()) {
+                        // 按团队分组
+                        Map<String, List<EquipPipeSchedulingUserDO>> teamMap = users.stream()
+                                .filter(user -> user.getGroupTeamId() != null) // 过滤掉 groupTeamId 为 null 的记录
+                                .collect(Collectors.groupingBy(EquipPipeSchedulingUserDO::getGroupTeamId));
+
+                    // 构建团队列表
+                    List<PipeShiftScheduleTeamRespVO> teamList = new ArrayList<>();
+                    List<String> checkers = new ArrayList<>();
+
+                    for (Map.Entry<String, List<EquipPipeSchedulingUserDO>> entry : teamMap.entrySet()) {
+                        String groupTeamId = entry.getKey();
+                        List<EquipPipeSchedulingUserDO> teamUsers = entry.getValue();
+
+                        PipeShiftScheduleTeamRespVO team = new PipeShiftScheduleTeamRespVO();
+                        team.setGroupTeamId(groupTeamId);
+
+                        List<AdminUserRespDTO> leaders = new ArrayList<>();
+                        List<AdminUserRespDTO> members = new ArrayList<>();
+
+                        for (EquipPipeSchedulingUserDO user : teamUsers) {
+                            AdminUserRespDTO userResp = new AdminUserRespDTO();
+                            
+                            // 设置用户信息
+                            AdminUserRespDTO adminUser = userIdToUserMap.get(user.getUserId());
+                            if (adminUser != null) {
+                                userResp = adminUser;
                             }
-                        });
-                        taskDetailsItemVO.setGroupTeamId(groupTeamId);
-                        taskDetailsItemVO.setLeaders(leaderList);
-                        taskDetailsItemVO.setMembers(membetList);
-                        return taskDetailsItemVO;
+                            
+                            if (user.getType() == 100) { // 100 表示组长
+                                leaders.add(userResp);
+                            } else if (user.getType() == 200) { // 200 表示成员
+                                members.add(userResp);
+                            }
+                            // 添加到检验员列表
+                            checkers.add(user.getUserId());
+                        }
+
+                        team.setLeaders(leaders);
+                        team.setMembers(members);
+                        teamList.add(team);
                     }
-            ).toList();
-            pipeShiftScheduleRespVO.setTeamList(userList);
 
-            scheduleItemRespVOS.forEach((item)-> {
-                Area area = AreaUtils.getArea(item.getEquipStreet());
-                if (area != null) {
-                    item.setEquipStreetName(area.getName());
+                    item.setTeamList(teamList);
+                    item.setCheckers(checkers);
                 }
+            }
 
-                area = AreaUtils.getArea(item.getEquipDistrict());
-                if (area != null) {
-                    item.setEquipDistrictName(area.getName());
-                }
-            });
-            pipeShiftScheduleRespVO.setTaskItems(scheduleItemRespVOS);
-
-            List<EquipPipeSchedulingItemDetailDO> equipPipeSchedulingItemDetailDOS = equipPipeSchedulingItemDetailMapper.selectList(EquipPipeSchedulingItemDetailDO::getSchedulingId, taskId);
-            List<String> equipDetailIds = equipPipeSchedulingItemDetailDOS.stream().map(EquipPipeSchedulingItemDetailDO::getEquipDetailId).toList();
-            List<EquipPipeDetailDO> equipPipeDetailDOS = equipPipeDetailMapper.selectByIds(equipDetailIds);
-            List<String> pipeMediums = equipPipeDetailDOS.stream().map(EquipPipeDetailDO::getPipeMedium).toList();
-            pipeShiftScheduleRespVO.setPipeMedium(pipeMediums);
-            list.add(pipeShiftScheduleRespVO);
-        });
+            // 确保团队列表和检验员列表不为 null
+            if (item.getTeamList() == null) {
+                item.setTeamList(new ArrayList<>());
+            }
+            if (item.getCheckers() == null) {
+                item.setCheckers(new ArrayList<>());
+            }
+
+
+        }
 
         if (pageReqVO.getStatus() != null){
-            return list.stream().filter(item -> Objects.equals(item.getStatus(), pageReqVO.getStatus())).toList();
+            return pipeShiftScheduleItemRespVOS.stream().filter(item -> Objects.equals(item.getStatus(), pageReqVO.getStatus())).toList();
         }
-        return list;
+        return pipeShiftScheduleItemRespVOS;
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void setShiftSchedule(List<PipeShiftScheduleSaveRespVO> pipeShiftScheduleRespVOS) {
-        //检查员
-        List<EquipPipeSchedulingUserDO> schedulingMemberList = new ArrayList<>();
-        List<PipeAppointmentConfirmOrderUserDO> appointmentConfirmOrderUserDOS = new ArrayList<>();
-        for (PipeShiftScheduleSaveRespVO pipeShiftScheduleRespVO : pipeShiftScheduleRespVOS) {
-            String id = pipeShiftScheduleRespVO.getId();
-            pipeShiftScheduleRespVO.getTeamList().forEach(team -> {
-                EquipPipeSchedulingUserDO leader = new EquipPipeSchedulingUserDO();
-                leader.setSchedulingId(id);
-                leader.setType(100);
-                leader.setGroupTeamId(team.getGroupTeamId());
-                leader.setUserId(team.getLeaderId());
-                leader.setDate(pipeShiftScheduleRespVO.getDate());
-
-                List<EquipPipeSchedulingUserDO> memberList = team.getMemberIdList().stream().map(memberId -> {
-                    EquipPipeSchedulingUserDO member = new EquipPipeSchedulingUserDO();
-                    member.setSchedulingId(id);
-                    member.setType(200);
-                    member.setUserId(memberId);
-                    member.setGroupTeamId(team.getGroupTeamId());
-                    member.setDate(pipeShiftScheduleRespVO.getDate());
-                    return member;
-                }).toList();
+        for (PipeShiftScheduleSaveRespVO vo : pipeShiftScheduleRespVOS) {
+            if (Boolean.TRUE.equals(vo.getIsCopy())) {
+                // 复制操作
+                doCopyShiftSchedule(vo);
+            } else {
+                // 修改操作
+                doModifyShiftSchedule(vo);
+            }
+        }
+    }
 
+    /**
+     * 修改排班:更新主表日期 + 替换子表检验员数据
+     */
+    private void doModifyShiftSchedule(PipeShiftScheduleSaveRespVO vo) {
+        String id = vo.getId();
+        if (id == null || id.isEmpty()) {
+            throw new RuntimeException("修改操作缺少排期ID");
+        }
+        // 更新主表排期日期
+        EquipPipeSchedulingDO schedulingDO = equipPipeSchedulingMapper.selectById(id);
+        if (schedulingDO == null) {
+            throw new RuntimeException("排期记录不存在: " + id);
+        }
+        schedulingDO.setPlanDate(vo.getDate());
+        equipPipeSchedulingMapper.updateById(schedulingDO);
+
+        // 删除旧的检验员数据
+        equipPipeSchedulingUserMapper.delete(new LambdaQueryWrapperX<EquipPipeSchedulingUserDO>()
+                .eq(EquipPipeSchedulingUserDO::getSchedulingId, id));
+
+        // 插入新检验员数据
+        List<EquipPipeSchedulingUserDO> newUsers = new ArrayList<>();
+        List<BoilerPlanSchedulingAssignTeamItemVO> teamList = vo.getTeamList();
+        if (teamList != null) {
+            for (BoilerPlanSchedulingAssignTeamItemVO team : teamList) {
                 if (StringUtils.isNotBlank(team.getLeaderId())) {
-                    schedulingMemberList.add(leader);
+                    EquipPipeSchedulingUserDO leader = new EquipPipeSchedulingUserDO();
+                    leader.setSchedulingId(id);
+                    leader.setType(100);
+                    leader.setGroupTeamId(team.getGroupTeamId());
+                    leader.setUserId(team.getLeaderId());
+                    leader.setDate(vo.getDate());
+                    newUsers.add(leader);
                 }
+                if (team.getMemberIdList() != null && !team.getMemberIdList().isEmpty()) {
+                    for (String memberId : team.getMemberIdList()) {
+                        EquipPipeSchedulingUserDO member = new EquipPipeSchedulingUserDO();
+                        member.setSchedulingId(id);
+                        member.setType(200);
+                        member.setGroupTeamId(team.getGroupTeamId());
+                        member.setUserId(memberId);
+                        member.setDate(vo.getDate());
+                        newUsers.add(member);
+                    }
+                }
+            }
+        }
+        if (!newUsers.isEmpty()) {
+            equipPipeSchedulingUserMapper.insert(newUsers);
+        }
 
-                schedulingMemberList.addAll(memberList);
-            });
-            List<AppointmentConfirmOrderDO> appointmentConfirmOrderDOS = appointmentConfirmOrderMapper.selectList(AppointmentConfirmOrderDO::getSchedulingId, id);
-            if (appointmentConfirmOrderDOS != null && !appointmentConfirmOrderDOS.isEmpty()) {
-                AppointmentConfirmOrderDO appointmentConfirmOrderDO = appointmentConfirmOrderDOS.get(0);
-                List<PipeAppointmentConfirmOrderUserDO> pipeAppointmentConfirmOrderUserDOS = pipeAppointmentConfirmOrderUserMapper.selectList(PipeAppointmentConfirmOrderUserDO::getOrderId, id);
-                Set<String> ids = pipeAppointmentConfirmOrderUserDOS.stream().map(PipeAppointmentConfirmOrderUserDO::getUserId).collect(Collectors.toSet());
-                pipeShiftScheduleRespVO.getTeamList().forEach(team -> {
-                    PipeAppointmentConfirmOrderUserDO leader = new PipeAppointmentConfirmOrderUserDO();
-                    leader.setOrderId(appointmentConfirmOrderDO.getId());
+        // 同步更新约检确认单的检验员
+        addAppointmentConfirmOrderUsers(schedulingDO.getConfirmOrderId(), teamList);
+    }
+
+    /**
+     * 复制排班:根据源排期创建新排期,复制除日期和检验员外的所有数据
+     */
+    private void doCopyShiftSchedule(PipeShiftScheduleSaveRespVO vo) {
+        String sourceId = vo.getSourceId();
+        if (sourceId == null || sourceId.isEmpty()) {
+            throw new ServiceException(500,"复制操作缺少源排期ID");
+        }
+
+        // 1. 获取源排期信息
+        EquipPipeSchedulingDO sourceScheduling = equipPipeSchedulingMapper.selectById(sourceId);
+        if (sourceScheduling == null) {
+            throw new ServiceException(500,"源排期不存在: " + sourceId);
+        }
+
+        // 2. 校验:原行必须有 confirmOrderId 才能复制
+        if (StringUtils.isBlank(sourceScheduling.getConfirmOrderId())) {
+            throw new ServiceException(500,"原行没有约检确认单,无法复制");
+        }
+
+        // 3. 校验:同一个 confirmOrderId 的日期不能重复
+        List<EquipPipeSchedulingDO> sameConfirmList = equipPipeSchedulingMapper.selectList(
+                new LambdaQueryWrapperX<EquipPipeSchedulingDO>()
+                        .eq(EquipPipeSchedulingDO::getConfirmOrderId, sourceScheduling.getConfirmOrderId()));
+        boolean dateDuplicate = sameConfirmList.stream()
+                .anyMatch(item -> vo.getDate().equals(item.getPlanDate()));
+        if (dateDuplicate) {
+            throw new ServiceException(500,"同一个约检确认单下日期不能重复: " + vo.getDate());
+        }
+
+        // 4. 创建新排期主表(复制所有字段,使用原行的 confirmOrderId)
+        EquipPipeSchedulingDO newScheduling = new EquipPipeSchedulingDO();
+        cn.hutool.core.bean.BeanUtil.copyProperties(sourceScheduling, newScheduling, "id", "createTime", "updateTime", "deleted", "planDate");
+        newScheduling.setPlanDate(vo.getDate());
+        equipPipeSchedulingMapper.insert(newScheduling);
+        String newSchedulingId = newScheduling.getId();
+
+        // 5. 复制子表 EquipPipeSchedulingItemDO(设备排期项)
+        List<EquipPipeSchedulingItemDO> sourceItems = equipPipeSchedulingItemMapper.selectList(
+                EquipPipeSchedulingItemDO::getSchedulingId, sourceId);
+        if (sourceItems != null && !sourceItems.isEmpty()) {
+            List<EquipPipeSchedulingItemDO> newItems = new ArrayList<>();
+            for (EquipPipeSchedulingItemDO sourceItem : sourceItems) {
+                EquipPipeSchedulingItemDO newItem = new EquipPipeSchedulingItemDO();
+                cn.hutool.core.bean.BeanUtil.copyProperties(sourceItem, newItem, "id", "schedulingId", "createTime", "updateTime", "deleted");
+                newItem.setSchedulingId(newSchedulingId);
+                newItems.add(newItem);
+            }
+            equipPipeSchedulingItemMapper.insert(newItems);
+
+            // 6. 复制子表 EquipPipeSchedulingItemDetailDO(管线明细)
+            for (EquipPipeSchedulingItemDO sourceItem : sourceItems) {
+                List<EquipPipeSchedulingItemDetailDO> sourceDetails = equipPipeSchedulingItemDetailMapper.selectList(
+                        EquipPipeSchedulingItemDetailDO::getSchedulingItemId, sourceItem.getId());
+                if (sourceDetails != null && !sourceDetails.isEmpty()) {
+                    EquipPipeSchedulingItemDO newItem = newItems.stream()
+                            .filter(item -> Objects.equals(item.getEquipId(), sourceItem.getEquipId()))
+                            .findFirst().orElse(null);
+                    if (newItem != null) {
+                        List<EquipPipeSchedulingItemDetailDO> newDetails = new ArrayList<>();
+                        for (EquipPipeSchedulingItemDetailDO sourceDetail : sourceDetails) {
+                            EquipPipeSchedulingItemDetailDO newDetail = new EquipPipeSchedulingItemDetailDO();
+                            cn.hutool.core.bean.BeanUtil.copyProperties(sourceDetail, newDetail, "id", "schedulingItemId", "createTime", "updateTime", "deleted");
+                            newDetail.setSchedulingItemId(newItem.getId());
+                            newDetails.add(newDetail);
+                        }
+                        if (!newDetails.isEmpty()) {
+                            equipPipeSchedulingItemDetailMapper.insert(newDetails);
+                        }
+                    }
+                }
+            }
+        }
+
+        // 7. 复制检验项目 EquipPipeSchedulingCheckDO
+        List<EquipPipeSchedulingCheckDO> sourceChecks = equipPipeSchedulingCheckMapper.selectList(
+                EquipPipeSchedulingCheckDO::getSchedulingId, sourceId);
+        if (sourceChecks != null && !sourceChecks.isEmpty()) {
+            List<EquipPipeSchedulingCheckDO> newChecks = new ArrayList<>();
+            for (EquipPipeSchedulingCheckDO sourceCheck : sourceChecks) {
+                EquipPipeSchedulingCheckDO newCheck = new EquipPipeSchedulingCheckDO();
+                cn.hutool.core.bean.BeanUtil.copyProperties(sourceCheck, newCheck, "id", "schedulingId", "createTime", "updateTime", "deleted", "taskOrderId", "acceptOrderId");
+                newCheck.setSchedulingId(newSchedulingId);
+                newChecks.add(newCheck);
+            }
+            equipPipeSchedulingCheckMapper.insert(newChecks);
+        }
+
+        // 8. 复制费用 EquipPipeSchedulingFeeDO
+        List<EquipPipeSchedulingFeeDO> sourceFees = equipPipeSchedulingFeeMapper.selectList(
+                EquipPipeSchedulingFeeDO::getSchedulingId, sourceId);
+        if (sourceFees != null && !sourceFees.isEmpty()) {
+            List<EquipPipeSchedulingFeeDO> newFees = new ArrayList<>();
+            for (EquipPipeSchedulingFeeDO sourceFee : sourceFees) {
+                EquipPipeSchedulingFeeDO newFee = new EquipPipeSchedulingFeeDO();
+                cn.hutool.core.bean.BeanUtil.copyProperties(sourceFee, newFee, "id", "schedulingId", "createTime", "updateTime", "deleted");
+                newFee.setSchedulingId(newSchedulingId);
+                newFees.add(newFee);
+            }
+            equipPipeSchedulingFeeMapper.insert(newFees);
+        }
+
+        // 9. 创建新检验员数据
+        List<EquipPipeSchedulingUserDO> newUsers = new ArrayList<>();
+        List<BoilerPlanSchedulingAssignTeamItemVO> teamList = vo.getTeamList();
+        if (teamList != null) {
+            for (BoilerPlanSchedulingAssignTeamItemVO team : teamList) {
+                if (StringUtils.isNotBlank(team.getLeaderId())) {
+                    EquipPipeSchedulingUserDO leader = new EquipPipeSchedulingUserDO();
+                    leader.setSchedulingId(newSchedulingId);
                     leader.setType(100);
                     leader.setGroupTeamId(team.getGroupTeamId());
                     leader.setUserId(team.getLeaderId());
+                    leader.setDate(vo.getDate());
+                    newUsers.add(leader);
+                }
+                if (team.getMemberIdList() != null && !team.getMemberIdList().isEmpty()) {
+                    for (String memberId : team.getMemberIdList()) {
+                        EquipPipeSchedulingUserDO member = new EquipPipeSchedulingUserDO();
+                        member.setSchedulingId(newSchedulingId);
+                        member.setType(200);
+                        member.setGroupTeamId(team.getGroupTeamId());
+                        member.setUserId(memberId);
+                        member.setDate(vo.getDate());
+                        newUsers.add(member);
+                    }
+                }
+            }
+        }
+        if (!newUsers.isEmpty()) {
+            equipPipeSchedulingUserMapper.insert(newUsers);
+        }
+
+        // 增量添加约检确认单的检验员(源排期的 confirmOrderId)
+        addAppointmentConfirmOrderUsers(sourceScheduling.getConfirmOrderId(), teamList);
+    }
 
-                    List<PipeAppointmentConfirmOrderUserDO> memberList = team.getMemberIdList().stream().map(memberId -> {
+    /**
+     * 增量添加约检确认单子表 PipeAppointmentConfirmOrderUserDO 的检验员
+     * 按 groupTeamId + userId 去重,不可重复添加
+     *
+     * @param confirmOrderId AppointmentConfirmOrderDO 的 id
+     * @param teamList 团队列表
+     */
+    private void addAppointmentConfirmOrderUsers(String confirmOrderId, List<BoilerPlanSchedulingAssignTeamItemVO> teamList) {
+        if (confirmOrderId == null || confirmOrderId.isEmpty() || teamList == null || teamList.isEmpty()) {
+            return;
+        }
+        AppointmentConfirmOrderDO order = appointmentConfirmOrderMapper.selectById(confirmOrderId);
+        if (order == null) {
+            return;
+        }
+        // 查询已有的检验员,构建 (groupTeamId + ":" + userId) 去重集合
+        List<PipeAppointmentConfirmOrderUserDO> existingUsers = appointmentConfirmOrderUserMapper.selectList(
+                PipeAppointmentConfirmOrderUserDO::getOrderId, order.getId());
+        Set<String> existingKeys = existingUsers.stream()
+                .map(u -> u.getGroupTeamId() + ":" + u.getUserId())
+                .collect(Collectors.toSet());
+
+        List<PipeAppointmentConfirmOrderUserDO> newAppointmentUsers = new ArrayList<>();
+        for (BoilerPlanSchedulingAssignTeamItemVO team : teamList) {
+            String groupTeamId = team.getGroupTeamId();
+            // 添加组长
+            if (StringUtils.isNotBlank(team.getLeaderId())) {
+                String key = groupTeamId + ":" + team.getLeaderId();
+                if (!existingKeys.contains(key)) {
+                    PipeAppointmentConfirmOrderUserDO leader = new PipeAppointmentConfirmOrderUserDO();
+                    leader.setOrderId(order.getId());
+                    leader.setType(100);
+                    leader.setGroupTeamId(groupTeamId);
+                    leader.setUserId(team.getLeaderId());
+                    newAppointmentUsers.add(leader);
+                    existingKeys.add(key); // 本次批量内也去重
+                }
+            }
+            // 添加组员
+            if (team.getMemberIdList() != null) {
+                for (String memberId : team.getMemberIdList()) {
+                    String key = groupTeamId + ":" + memberId;
+                    if (!existingKeys.contains(key)) {
                         PipeAppointmentConfirmOrderUserDO member = new PipeAppointmentConfirmOrderUserDO();
-                        member.setOrderId(appointmentConfirmOrderDO.getId());
+                        member.setOrderId(order.getId());
                         member.setType(200);
+                        member.setGroupTeamId(groupTeamId);
                         member.setUserId(memberId);
-                        member.setGroupTeamId(team.getGroupTeamId());
-                        return member;
-                    }).toList();
-                    // 去重
-                    if (StringUtils.isNotBlank(team.getLeaderId()) && !ids.contains(team.getLeaderId())) {
-                        appointmentConfirmOrderUserDOS.add(leader);
+                        newAppointmentUsers.add(member);
+                        existingKeys.add(key); // 本次批量内也去重
                     }
-                    memberList.stream().filter(member -> !ids.contains(member.getUserId())).forEach(appointmentConfirmOrderUserDOS::add);
-//                    appointmentConfirmOrderUserDOS.addAll(memberList);
-                });
+                }
             }
         }
-        if (!schedulingMemberList.isEmpty()) {
-            equipPipeSchedulingUserMapper.insert(schedulingMemberList);
-        }
-        if (!appointmentConfirmOrderUserDOS.isEmpty()) {
-            pipeAppointmentConfirmOrderUserMapper.insert(appointmentConfirmOrderUserDOS);
+        if (!newAppointmentUsers.isEmpty()) {
+            appointmentConfirmOrderUserMapper.insert(newAppointmentUsers);
         }
     }
 
@@ -1404,90 +1757,82 @@ public class EquipPipeSchedulingServiceImpl extends ServiceImpl<EquipPipeSchedul
         if (list == null || list.isEmpty()) {
             return List.of();
         }
+        // 批量查询检验员昵称
+        Set<String> allCheckerIds = list.stream()
+                .filter(source -> source.getCheckers() != null)
+                .flatMap(source -> source.getCheckers().stream())
+                .collect(Collectors.toSet());
+        Map<String, String> userIdToNickname = new HashMap<>();
+        if (!allCheckerIds.isEmpty()) {
+            List<AdminUserRespDTO> users = adminUserApi.getUserList(new ArrayList<>(allCheckerIds)).getCheckedData();
+            if (users != null) {
+                for (AdminUserRespDTO user : users) {
+                    if (user != null && user.getId() != null) {
+                        userIdToNickname.put(user.getId(), user.getNickname() != null ? user.getNickname() : user.getId());
+                    }
+                }
+            }
+        }
+
         return list.stream().map(source -> {
             PipeShiftScheduleExportRespVO target = new PipeShiftScheduleExportRespVO();
 
             // 日期
             target.setDate(source.getDate());
-
             // 星期
-            target.setWeek(calculateWeek(source.getDate()));
+            target.setWeek(source.getWeek());
 
-            // 检验员(将检验员ID列表转换为字符串)
+            // 检验员
             if (source.getCheckers() != null && !source.getCheckers().isEmpty()) {
-                List<AdminUserRespDTO> checkedData = adminUserApi.getUserList(source.getCheckers()).getCheckedData();
-                target.setCheckers(String.join(",", checkedData.stream().map(AdminUserRespDTO::getNickname).toList()));
+                String checkerNames = source.getCheckers().stream()
+                        .map(id -> userIdToNickname.getOrDefault(id, id))
+                        .collect(Collectors.joining("、"));
+                target.setCheckers(checkerNames);
             }
 
-            // 获取第一个任务项
-            PipeShiftScheduleRespVO.PipeShiftScheduleItemRespVO taskItem =
-                    source.getTaskItems() != null && !source.getTaskItems().isEmpty()
-                            ? source.getTaskItems().get(0)
-                            : null;
+            // 检验类型
+            target.setCheckType("100".equals(source.getCheckType()) ? "定期检验" : "200".equals(source.getCheckType()) ? "年度检查" : source.getCheckType());
 
-            if (taskItem != null) {
-                // 检验类型
-                target.setCheckType("100".equals(taskItem.getCheckType()) ? "定期检验" : "年度检查");
+            // 使用单位
+            target.setUnitName(source.getUnitName());
 
-                // 使用单位
-                target.setUnitName(taskItem.getUnitName());
+            // 管道使用地址
+            target.setPipeAddress(source.getPipeAddress());
 
-                // 管道使用地址
-                target.setPipeAddress(taskItem.getPipeAddress());
+            // 联系人
+            target.setContact(source.getContact());
 
-                // 联系人(去重后用/拼接)
-                List<String> contacts = source.getTaskItems().stream()
-                        .map(PipeShiftScheduleRespVO.PipeShiftScheduleItemRespVO::getContact)
-                        .filter(contact -> contact != null && !contact.isEmpty())
-                        .distinct()
-                        .collect(Collectors.toList());
-                target.setContact(String.join("/", contacts));
+            // 电话
+            target.setContactPhone(source.getContactPhone());
 
-                // 电话(去重后用/拼接)
-                List<String> contactPhones = source.getTaskItems().stream()
-                        .map(PipeShiftScheduleRespVO.PipeShiftScheduleItemRespVO::getContactPhone)
-                        .filter(phone -> phone != null && !phone.isEmpty())
-                        .distinct()
-                        .collect(Collectors.toList());
-                target.setContactPhone(String.join("/", contactPhones));
-
-                // 管线长度(累加)
-                double totalLength = source.getTaskItems().stream()
-                        .mapToDouble(item -> {
-                            try {
-                                return item.getPipeLengthTotal() != null
-                                        ? Double.parseDouble(item.getPipeLengthTotal())
-                                        : 0;
-                            } catch (NumberFormatException e) {
-                                return 0;
-                            }
-                        })
-                        .sum();
-                target.setPipeLengthTotal(totalLength);
-
-                // 上次报告编号(根据检验类型选择)
-                if ("100".equals(taskItem.getCheckType())) {
-                    target.setLastReportNo(taskItem.getLastLegalPeriodicalInspectionReportNo());
-                } else {
-                    target.setLastReportNo(taskItem.getLastYearReportNo());
+            // 管道介质
+            if (source.getPipeMedium() != null && !source.getPipeMedium().isEmpty()) {
+                target.setMedium(String.join("、", source.getPipeMedium().stream().distinct().toList()));
+            }
+
+            // 管线长度
+            if (source.getPipeLengthTotal() != null) {
+                try {
+                    target.setPipeLengthTotal(Double.parseDouble(source.getPipeLengthTotal()));
+                } catch (NumberFormatException e) {
+                    target.setPipeLengthTotal(0.0);
                 }
+            }
 
-                // 监督报告编号
-                target.setLastMaintenanceReportNo(taskItem.getLastMaintenanceReportNo());
+            // 区域街道
+            String district = source.getEquipDistrictName() != null ? source.getEquipDistrictName() : "";
+            String street = source.getEquipStreetName() != null ? source.getEquipStreetName() : "";
+            target.setStreet(district + street);
 
-                // 区域街道
-                String district = taskItem.getEquipDistrictName() != null ? taskItem.getEquipDistrictName() : "";
-                String street = taskItem.getEquipStreetName() != null ? taskItem.getEquipStreetName() : "";
-                target.setStreet(district + street);
+            // 上次报告编号(根据检验类型)
+            if ("100".equals(source.getCheckType())) {
+                target.setLastReportNo(source.getLastLegalPeriodicalInspectionReportNo());
+            } else {
+                target.setLastReportNo(source.getLastYearReportNo());
             }
 
-            // 管道介质(去重后用、拼接)
-            if (source.getPipeMedium() != null && !source.getPipeMedium().isEmpty()) {
-                List<String> distinctMediums = source.getPipeMedium().stream()
-                        .distinct()
-                        .collect(Collectors.toList());
-                target.setMedium(String.join("、", distinctMediums));
-            }
+            // 监督报告编号
+            target.setLastMaintenanceReportNo(source.getLastMaintenanceReportNo());
 
             // 状态
             target.setStatus(getStatusText(source.getStatus()));

+ 13 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/synchronization/SynchronizationServiceImpl.java

@@ -7,6 +7,8 @@ import cn.hutool.http.HttpResponse;
 import cn.hutool.http.HttpUtil;
 
 import cn.start.tz.framework.common.pojo.CommonResult;
+import cn.start.tz.framework.ip.core.Area;
+import cn.start.tz.framework.ip.core.utils.AreaUtils;
 import cn.start.tz.module.pressure2.controller.admin.equippipe.vo.EquipPipeSaveReqVO;
 import cn.start.tz.module.pressure2.controller.admin.equippipedetail.vo.EquipPipeDetailSaveReqVO;
 import cn.start.tz.module.pressure2.dal.dataobject.equipboiler.EquipBoilerDO;
@@ -369,6 +371,11 @@ public class SynchronizationServiceImpl implements SynchronizationService {
         // 设置区域代码
         equipBoilerDO.setEquipDistrict(parseInteger(boilerDto.AREACODE));
 
+        if (boilerDto.STREET != null){
+            Area area = AreaUtils.parseArea(boilerDto.STREET);
+            equipBoilerDO.setEquipStreet(area != null ? area.getId() : null);
+        }
+
         // 设置设备基本信息
         equipBoilerDO.setEquipCode(boilerDto.REGISTERNO);
         equipBoilerDO.setUseRegisterNo(boilerDto.USENO);
@@ -550,6 +557,12 @@ public class SynchronizationServiceImpl implements SynchronizationService {
             equipPipeDO.setPipeCategory(pipeCategory);
         }
 
+        if (pipeDto.STREET != null){
+            Area area = AreaUtils.parseArea(pipeDto.STREET);
+            equipPipeDO.setEquipStreet(area != null ? area.getId() : null);
+        }
+
+
         // 设置基本信息
         equipPipeDO.setSecurityMan(pipeDto.SECURITYMAN);
         equipPipeDO.setContact(pipeDto.UNIT_OPERATOR);

+ 3 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/synchronization/dto/BoilerDto.java

@@ -668,5 +668,8 @@ public class BoilerDto {
 
     public String DEPARTMENT;
 
+    /**
+     * 街道
+     */
     public String STREET;
 }

+ 5 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/synchronization/dto/PipeDto.java

@@ -338,4 +338,9 @@ public class PipeDto {
      * 管道类别
      */
     public  String PIPE_CATEGORY;
+
+    /**
+     * 街道
+     */
+    public String STREET;
 }

+ 24 - 1
tz-module-pressure2/tz-module-pressure2-biz/src/main/resources/mapper/equippipescheduling/EquipPipeSchedulingMapper.xml

@@ -557,7 +557,7 @@
         select a.ID task_id,a.TYPE check_type,b.unit_code,b.unit_name,b.unit_address,a.plan_date,count(distinct c.ID) equip_count,
         b.equip_district,b.equip_street,a.source,FIRST_VALUE(b.lng) lng,FIRST_VALUE(b.lat) lat,
         b.CONTACT,b.CONTACT_PHONE,b.PIPE_LENGTH_TOTAL,b.LAST_LEGAL_PERIODICAL_INSPECTION_REPORT_NO,b.LAST_YEAR_REPORT_NO,b.LAST_MAINTENANCE_REPORT_NO,
-        e.id APPOINTMENT_ID,f.id ACCEPT_ORDER_ID,f.STATUS accept_status, g.TASK_STATUS ,b.PIPE_ADDRESS
+        e.id APPOINTMENT_ID,f.id ACCEPT_ORDER_ID,f.STATUS accept_status, g.TASK_STATUS ,b.PIPE_ADDRESS,a.confirm_order_id
         from PRESSURE2_EQUIP_PIPE_SCHEDULING a
         inner join PRESSURE2_EQUIP_PIPE_SCHEDULING_ITEM c on c.SCHEDULING_ID = a.ID and c.DELETED = 0
         inner join PRESSURE2_EQUIP_PIPE b on b.ID = c.equip_id and b.DELETED = 0
@@ -769,4 +769,27 @@
         ) a
     </select>
 
+    <select id="getShiftScheduleById"
+            resultType="cn.start.tz.module.pressure2.controller.admin.equippipescheduling.vo.PipeShiftScheduleRespVO">
+        select a.ID task_id,a.TYPE check_type,b.unit_code,b.unit_name,b.unit_address,a.plan_date,count(distinct c.ID) equip_count,
+        b.equip_district,b.equip_street,a.source,FIRST_VALUE(b.lng) lng,FIRST_VALUE(b.lat) lat,
+        b.CONTACT,b.CONTACT_PHONE,b.PIPE_LENGTH_TOTAL,b.LAST_LEGAL_PERIODICAL_INSPECTION_REPORT_NO,b.LAST_YEAR_REPORT_NO,b.LAST_MAINTENANCE_REPORT_NO,
+        e.id APPOINTMENT_ID,f.id ACCEPT_ORDER_ID,f.STATUS accept_status, g.TASK_STATUS ,b.PIPE_ADDRESS,a.confirm_order_id
+        from PRESSURE2_EQUIP_PIPE_SCHEDULING a
+        inner join PRESSURE2_EQUIP_PIPE_SCHEDULING_ITEM c on c.SCHEDULING_ID = a.ID and c.DELETED = 0
+        inner join PRESSURE2_EQUIP_PIPE b on b.ID = c.equip_id and b.DELETED = 0
+        --inner join PRESSURE2_EQUIP_PIPE_SCHEDULING_USER d on d.SCHEDULING_ID = a.ID and d.DELETED = 0
+        left join PRESSURE_APPOINTMENT_CONFIRM_ORDER e on e.SCHEDULING_ID = a.ID
+        left join PRESSURE_ACCEPT_ORDER f on f.APPOINTMENT_ID = e.ID
+        left join PRESSURE_Task_ORDER g on g.ACCEPT_ORDER_ID = f.ID
+
+        <where>
+            a.DELETED = 0
+            <if test="confirmOrderId != null and confirmOrderId != ''">
+                and a.confirm_order_id = #{confirmOrderId}
+                and e.id is not null
+            </if>
+        </where>
+        limit 1
+    </select>
 </mapper>