Browse Source

优化巡检记录定时任务调度器可多线程;巡检子计划为向前预生成today+7+补最近7天缺口

zhaojinyu 4 ngày trước cách đây
mục cha
commit
d38d229e17

+ 32 - 0
service-fire/service-fire-biz/src/main/java/com/usky/fire/service/config/SchedulerConfig.java

@@ -0,0 +1,32 @@
+package com.usky.fire.service.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.SchedulingConfigurer;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
+import org.springframework.scheduling.config.ScheduledTaskRegistrar;
+
+/**
+ * 定时任务调度器配置
+ * 默认 Spring 调度器线程池为 1,多个 @Scheduled 任务会互相阻塞,
+ * 当某个任务(如每 5 分钟的 task())发生网络阻塞时会拖垮其它任务(如巡检计划补生成 task5)。
+ * 这里改为多线程调度器,避免任务间相互饿死。
+ *
+ * @author JCB
+ * @since 2026-07-13
+ */
+@Configuration
+@EnableScheduling
+public class SchedulerConfig implements SchedulingConfigurer {
+
+    @Override
+    public void configureTasks(ScheduledTaskRegistrar registrar) {
+        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
+        scheduler.setPoolSize(5);
+        scheduler.setThreadNamePrefix("sched-pool-");
+        scheduler.setWaitForTasksToCompleteOnShutdown(true);
+        scheduler.setAwaitTerminationSeconds(60);
+        scheduler.initialize();
+        registrar.setTaskScheduler(scheduler);
+    }
+}

+ 98 - 82
service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/PatrolInspectionPlanServiceImpl.java

@@ -25,6 +25,7 @@ import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -481,94 +482,109 @@ public class PatrolInspectionPlanServiceImpl extends AbstractCrudService<PatrolI
 
     @Override
     @Transactional
-    public void addPatrolInspectionPlanSon(){
-        LambdaQueryWrapper<PatrolInspectionPlan> queryWrapper = Wrappers.lambdaQuery();
-        queryWrapper.le(PatrolInspectionPlan::getStartDate,LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))
-                .ge(PatrolInspectionPlan::getEndDate,OnlineMethod.getDate(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), "yyyy-MM-dd", true, 7))
-                .eq(PatrolInspectionPlan::getEnable,1);
-        List<PatrolInspectionPlan> list = this.list(queryWrapper);
-        if(CollectionUtils.isNotEmpty(list)){
-            List<Integer> planIdList = new ArrayList<>();
-            for (int i = 0; i < list.size(); i++) {
-                planIdList.add(list.get(i).getId());
-            }
-
-            //巡检日程关联信息
-            LambdaQueryWrapper<PatrolInspectionPlanSchedule> queryWrapper1 = Wrappers.lambdaQuery();
-            queryWrapper1.in(PatrolInspectionPlanSchedule::getPlanId,planIdList);
-            List<PatrolInspectionPlanSchedule> scheduleList = planScheduleService.list(queryWrapper1);
-            if(CollectionUtils.isEmpty(scheduleList)){
-                throw new BusinessException("无巡检日程关联信息");
-            }
+    public void addPatrolInspectionPlanSon() {
+        LocalDate today = LocalDate.now();
+        // 1) 补最近 7 天缺口:today-6 ~ today(含当天,共 7 天)
+        LocalDate backfillStart = today.minusDays(6);
+        // 2) 维持向前预生成:today + 7(保持未来 7 天视野)
+        LocalDate forwardDate = today.plusDays(7);
 
-            //主计划地点关联
-            LambdaQueryWrapper<PatrolInspectionPlanSite> queryWrapper2 = Wrappers.lambdaQuery();
-            queryWrapper2.in(PatrolInspectionPlanSite::getPlanId,planIdList);
-            List<PatrolInspectionPlanSite> siteList = planSiteService.list(queryWrapper2);
-            if(CollectionUtils.isEmpty(siteList)){
-                throw new BusinessException("无主计划地点关联信息");
-            }
+        // 候选日期集合 = 最近 7 天 + 向前第 7 天(不做全量历史回填)
+        List<LocalDate> candidateDates = new ArrayList<>();
+        for (int i = 0; i <= 6; i++) {
+            candidateDates.add(backfillStart.plusDays(i));
+        }
+        candidateDates.add(forwardDate);
 
-            //分配创建巡检计划之前先判断数据库中是否已经存在这条计划记录
-            LocalDate inspectionDate = OnlineMethod.getDate(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), "yyyy-MM-dd", true, 7);
-            LambdaQueryWrapper<PatrolInspectionPlanSon> queryWrapper3 = Wrappers.lambdaQuery();
-            queryWrapper3.select(PatrolInspectionPlanSon::getPlanId)
-                    .eq(PatrolInspectionPlanSon::getInspectionDate,inspectionDate);
-            List<PatrolInspectionPlanSon> planSonList = patrolInspectionPlanSonService.list(queryWrapper3);
-            List<Integer> planSonPlanIdList = new ArrayList<>();
-            if(CollectionUtils.isNotEmpty(planSonList)){
-                for (int i = 0; i < planSonList.size(); i++) {
-                    planSonPlanIdList.add(planSonList.get(i).getPlanId());
+        // 查询在候选日期窗口内仍生效、且覆盖该窗口的普通计划
+        LambdaQueryWrapper<PatrolInspectionPlan> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.le(PatrolInspectionPlan::getStartDate, forwardDate)
+                .ge(PatrolInspectionPlan::getEndDate, backfillStart)
+                .eq(PatrolInspectionPlan::getEnable, 1)
+                .eq(PatrolInspectionPlan::getPlanType, 1);
+        List<PatrolInspectionPlan> list = this.list(queryWrapper);
+        if (CollectionUtils.isEmpty(list)) {
+            return;
+        }
+
+        List<Integer> planIdList = list.stream().map(PatrolInspectionPlan::getId).collect(Collectors.toList());
+
+        //巡检日程关联信息
+        LambdaQueryWrapper<PatrolInspectionPlanSchedule> queryWrapper1 = Wrappers.lambdaQuery();
+        queryWrapper1.in(PatrolInspectionPlanSchedule::getPlanId, planIdList);
+        List<PatrolInspectionPlanSchedule> scheduleList = planScheduleService.list(queryWrapper1);
+        if (CollectionUtils.isEmpty(scheduleList)) {
+            throw new BusinessException("无巡检日程关联信息");
+        }
+
+        //主计划地点关联
+        LambdaQueryWrapper<PatrolInspectionPlanSite> queryWrapper2 = Wrappers.lambdaQuery();
+        queryWrapper2.in(PatrolInspectionPlanSite::getPlanId, planIdList);
+        List<PatrolInspectionPlanSite> siteList = planSiteService.list(queryWrapper2);
+        if (CollectionUtils.isEmpty(siteList)) {
+            throw new BusinessException("无主计划地点关联信息");
+        }
+
+        // 已生成过子计划的 (planId, inspectionDate) 组合,避免重复插入
+        LambdaQueryWrapper<PatrolInspectionPlanSon> queryWrapper3 = Wrappers.lambdaQuery();
+        queryWrapper3.in(PatrolInspectionPlanSon::getPlanId, planIdList)
+                .in(PatrolInspectionPlanSon::getInspectionDate, candidateDates)
+                .select(PatrolInspectionPlanSon::getPlanId, PatrolInspectionPlanSon::getInspectionDate);
+        Set<String> existsKeys = patrolInspectionPlanSonService.list(queryWrapper3).stream()
+                .map(e -> e.getPlanId() + "_" + e.getInspectionDate().toString())
+                .collect(Collectors.toSet());
+
+        for (PatrolInspectionPlan plan : list) {
+            for (LocalDate targetDate : candidateDates) {
+                // 仅处理落在计划有效期内的日期
+                if (targetDate.isBefore(plan.getStartDate()) || targetDate.isAfter(plan.getEndDate())) {
+                    continue;
                 }
-            }
-
-            for (int m = 0; m < list.size(); m++) {
-                //子表数据添加
-                if (list.get(m).getPlanType() == 1) {//普通计划 当前日期+7天在巡检计划时间范围内,就创建一条当前日期+7天日期对应的巡检记录
-                    for (int j = 0; j < scheduleList.size(); j++) {
-                        if((list.get(m).getId().equals(scheduleList.get(j).getPlanId())) && (!planSonPlanIdList.contains(list.get(m).getId()))){
-                            LocalDate s = OnlineMethod.getDate(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), "yyyy-MM-dd", true, 7);
-                            Date date = Date.from(s.atStartOfDay(ZoneOffset.ofHours(8)).toInstant());
-                            String week = OnlineMethod.getWeekOfDate(date);
-                            if (!list.get(m).getRestDay().contains(week)) {
-                                PatrolInspectionPlanSon patrolInspectionPlanSon = new PatrolInspectionPlanSon();
-                                patrolInspectionPlanSon.setPlanId(list.get(m).getId());
-                                patrolInspectionPlanSon.setInspectionDate(s);
-                                patrolInspectionPlanSon.setStartTime(scheduleList.get(j).getStartTime());
-                                patrolInspectionPlanSon.setEndTime(scheduleList.get(j).getEndTime());
-                                patrolInspectionPlanSon.setPersonnelId(scheduleList.get(j).getPersonnelId());
-                                patrolInspectionPlanSon.setAreaId(list.get(m).getAreaId());
-                                patrolInspectionPlanSon.setPlanType(list.get(m).getPlanType());
-                                patrolInspectionPlanSon.setPlanCycle(list.get(m).getPlanCycle());
-                                patrolInspectionPlanSon.setPlanFrequency(list.get(m).getPlanFrequency());
-                                patrolInspectionPlanSon.setLapTime(list.get(m).getLapTime());
-                                patrolInspectionPlanSon.setIntervalTime(list.get(m).getIntervalTime());
-                                patrolInspectionPlanSon.setPlanDescribe(list.get(m).getPlanDescribe());
-                                patrolInspectionPlanSon.setCompletion(0);
-                                patrolInspectionPlanSon.setCreateTime(LocalDateTime.now());
-                                patrolInspectionPlanSon.setCreator(list.get(m).getCreator());
-                                patrolInspectionPlanSon.setAlternateField("0");
-                                patrolInspectionPlanSon.setTenantId(list.get(m).getTenantId());
-                                patrolInspectionPlanSon.setCompanyId(list.get(m).getCompanyId());
-                                patrolInspectionPlanSonService.save(patrolInspectionPlanSon);
-                                Integer zfid = patrolInspectionPlanSon.getId();
-                                for (int k = 0; k < siteList.size(); k++) {
-                                    if(list.get(m).getId().equals(siteList.get(k).getPlanId())){
-                                        PatrolInspectionPlanSiteSon planSiteSon = new PatrolInspectionPlanSiteSon();
-                                        planSiteSon.setPlanId(zfid);
-                                        planSiteSon.setSiteId(siteList.get(k).getSiteId());
-                                        planSiteSon.setInspectionStatus(1);
-                                        planSiteSonService.save(planSiteSon);
-                                    }
-
-                                }
-                            }
+                // 已生成过则跳过(防重复)
+                if (existsKeys.contains(plan.getId() + "_" + targetDate.toString())) {
+                    continue;
+                }
+                Date date = Date.from(targetDate.atStartOfDay(ZoneOffset.ofHours(8)).toInstant());
+                String week = OnlineMethod.getWeekOfDate(date);
+                if (plan.getRestDay() != null && plan.getRestDay().contains(week)) {
+                    continue;
+                }
+                for (PatrolInspectionPlanSchedule schedule : scheduleList) {
+                    if (!plan.getId().equals(schedule.getPlanId())) {
+                        continue;
+                    }
+                    PatrolInspectionPlanSon son = new PatrolInspectionPlanSon();
+                    son.setPlanId(plan.getId());
+                    son.setInspectionDate(targetDate);
+                    son.setStartTime(schedule.getStartTime());
+                    son.setEndTime(schedule.getEndTime());
+                    son.setPersonnelId(schedule.getPersonnelId());
+                    son.setAreaId(plan.getAreaId());
+                    son.setPlanType(plan.getPlanType());
+                    son.setPlanCycle(plan.getPlanCycle());
+                    son.setPlanFrequency(plan.getPlanFrequency());
+                    son.setLapTime(plan.getLapTime());
+                    son.setIntervalTime(plan.getIntervalTime());
+                    son.setPlanDescribe(plan.getPlanDescribe());
+                    son.setCompletion(0);
+                    son.setCreateTime(LocalDateTime.now());
+                    son.setCreator(plan.getCreator());
+                    son.setAlternateField("0");
+                    son.setTenantId(plan.getTenantId());
+                    son.setCompanyId(plan.getCompanyId());
+                    patrolInspectionPlanSonService.save(son);
+                    Integer zfid = son.getId();
+                    for (PatrolInspectionPlanSite site : siteList) {
+                        if (plan.getId().equals(site.getPlanId())) {
+                            PatrolInspectionPlanSiteSon planSiteSon = new PatrolInspectionPlanSiteSon();
+                            planSiteSon.setPlanId(zfid);
+                            planSiteSon.setSiteId(site.getSiteId());
+                            planSiteSon.setInspectionStatus(1);
+                            planSiteSonService.save(planSiteSon);
                         }
-
                     }
                 }
             }
-
         }
     }
 
@@ -773,4 +789,4 @@ public class PatrolInspectionPlanServiceImpl extends AbstractCrudService<PatrolI
         }
         return list;
     }
-}
+}

+ 22 - 4
service-sas/service-sas-biz/src/main/java/com/usky/sas/service/impl/SasSystemServiceImpl.java

@@ -26,6 +26,7 @@ import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.UUID;
 import java.util.stream.Collectors;
 
 /**
@@ -58,14 +59,31 @@ public class SasSystemServiceImpl implements SasSystemService {
         wrapper.orderByDesc(SasSystemActivation::getUpdateTime).last("limit 1");
         List<SasSystemActivation> activationList = sasSystemActivationMapper.selectList(wrapper);
 
-        SasSystemActivation activation = null;
+        SasSystemActivation activation;
         if (activationList != null && !activationList.isEmpty()) {
             activation = activationList.get(0);
         } else {
-            return response;
+            // 表中无记录,创建一条新记录
+            activation = new SasSystemActivation();
+            activation.setClientId(UUID.randomUUID().toString());
+            activation.setCreateTime(LocalDateTime.now());
+            activation.setUpdateTime(LocalDateTime.now());
+            sasSystemActivationMapper.insert(activation);
+            log.info("系统激活表无记录,已创建新记录,clientId:{}", activation.getClientId());
+        }
+
+        // 检查 clientId 是否需要重新生成:为空或等于默认占位值时重新生成
+        String clientId = activation.getClientId();
+        if (StringUtils.isEmpty(clientId) || "66331ef6-b55b-4828-a2a8-2cb0d24edee7".equals(clientId)) {
+            String newClientId = UUID.randomUUID().toString();
+            activation.setClientId(newClientId);
+            activation.setUpdateTime(LocalDateTime.now());
+            sasSystemActivationMapper.updateById(activation);
+            log.info("clientId需重新生成,旧值:{},新值:{}", clientId, newClientId);
+            clientId = newClientId;
         }
 
-        response.setClientId(activation.getClientId());
+        response.setClientId(clientId);
         response.setIsPerpetual(activation.getIsPerpetual());
         response.setValidityTime(activation.getValidityTime());
         response.setCreateTime(activation.getCreateTime());
@@ -262,4 +280,4 @@ public class SasSystemServiceImpl implements SasSystemService {
             return seconds + "秒";
         }
     }
-}
+}