yuan
8 天以前 4bcba729142ded6cd008f324e6a3bae364b6233b
Merge remote-tracking branch 'origin/dev_pro_河南鹤壁' into dev_pro_河南鹤壁
已修改4个文件
234 ■■■■ 文件已修改
src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java 50 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/quality/QualityInspectMapper.xml 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
@@ -62,8 +62,8 @@
    @Schema(description = "最后执行时间")
    private LocalDateTime lastExecutionTime;
    @Schema(description = "是否激活")
    private boolean isActive;
    @Schema(description = "是否激活, 1=启用, 0=停用")
    private Integer isActive;
    @Schema(description = "备注")
    @Excel(name = "备注")
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java
@@ -25,13 +25,25 @@
    private final Scheduler scheduler;
    /**
     * 添加新任务到调度器
     * 添加或更新任务到调度器
     */
    public void scheduleMaintenanceTask(MaintenanceTask task){
        try {
            JobDetail jobDetail = buildJobDetail(task);
            Trigger trigger = buildJobTrigger(task, jobDetail);
            scheduler.scheduleJob(jobDetail, trigger);
            // 检查触发器是否已存在
            TriggerKey triggerKey = trigger.getKey();
            Trigger existingTrigger = scheduler.getTrigger(triggerKey);
            if (existingTrigger != null) {
                // 触发器已存在,更新它
                scheduler.rescheduleJob(triggerKey, trigger);
            } else {
                // 触发器不存在,先确保 Job 存在,然后调度触发器
                scheduler.addJob(jobDetail, true);
                scheduler.scheduleJob(trigger);
            }
        }catch (SchedulerException e){
            log.error("SchedulerException scheduleMaintenanceTask ERROR",e);
            throw new RuntimeException(e);
@@ -45,26 +57,41 @@
       try{
           TriggerKey triggerKey = new TriggerKey("triggerMaintenanceTask_" + task.getId());
           // 获取现有触发器并转换为 CronTrigger
           // 获取现有触发器
           Trigger oldTrigger = scheduler.getTrigger(triggerKey);
           // 构建新的 JobDetail 和 Trigger
           JobDetail jobDetail = buildJobDetail(task);
           Trigger newTrigger = buildJobTrigger(task, jobDetail);
           if (oldTrigger == null) {
               // 触发器不存在,说明任务之前被删除过
               // 先确保 Job 存在,然后调度触发器
               scheduler.addJob(jobDetail, true);
               scheduler.scheduleJob(newTrigger);
               return;
           }
           // 触发器存在,直接更新
           if (!(oldTrigger instanceof CronTrigger)) {
               throw new SchedulerException("Existing trigger is not a CronTrigger");
           }
           // 3. 构建CronTrigger,确保持久化配置
           CronTrigger newTrigger = TriggerBuilder.newTrigger()
                   .withIdentity(triggerKey)                // 唯一标识,用于持久化存储
                   .withDescription(task.getTaskName() + "_TRIGGER") // 触发器描述
                   .forJob(oldTrigger.getJobKey())                       // 关联对应的Job
           // 构建新的 CronTrigger
           CronTrigger cronTrigger = TriggerBuilder.newTrigger()
                   .withIdentity(triggerKey)
                   .withDescription(task.getTaskName() + "_TRIGGER")
                   .forJob(oldTrigger.getJobKey())
                   .withSchedule(CronScheduleBuilder
                           .cronSchedule(convertToCronExpression(task)) // 错过执行时的策略(根据业务调整)
                           .cronSchedule(convertToCronExpression(task))
                           .withMisfireHandlingInstructionDoNothing()
                   )
                   // 4. 设置开始时间(若为null则立即生效)
                   .startAt(task.getNextExecutionTime() != null
                           ? Date.from(task.getNextExecutionTime().atZone(ZoneId.systemDefault()).toInstant())
                           : new Date())
                   .build();
           scheduler.rescheduleJob(triggerKey, newTrigger);
           scheduler.rescheduleJob(triggerKey, cronTrigger);
       }catch (SchedulerException e){
           log.error("SchedulerException rescheduleMaintenanceTask ERROR",e);
           throw new RuntimeException(e);
@@ -93,6 +120,7 @@
    public void unscheduleMaintenanceTask(Long taskId){
        try {
            JobKey jobKey = new JobKey("MaintenanceTask_" + taskId);
            // 删除 Job 会自动删除关联的 Trigger
            scheduler.deleteJob(jobKey);
        }catch (SchedulerException e){
            log.error("SchedulerException unscheduleMaintenanceTask ERROR",e);
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java
@@ -67,7 +67,6 @@
    @Override
    public AjaxResult add(MaintenanceTask maintenanceTask) {
        maintenanceTask.setActive(true);
        // 计算首次执行时间
        TimingTask task = new TimingTask();
        task.setFrequencyType(maintenanceTask.getFrequencyType());
@@ -76,7 +75,10 @@
        maintenanceTask.setNextExecutionTime(firstExecutionTime);
        int insert = maintenanceTaskMapper.insert(maintenanceTask);
        if (insert > 0) {
            // 只有当 isActive 为 1 时才添加到定时任务调度器
            if (maintenanceTask.getIsActive() != null && maintenanceTask.getIsActive() == 1) {
            maintenanceTaskScheduler.scheduleMaintenanceTask(maintenanceTask);
            }
        }
        return AjaxResult.success("添加成功");
    }
@@ -87,22 +89,50 @@
        if (maintenanceTask1 == null) {
            return AjaxResult.warn("没有此数据");
        }
        // 保存旧的 isActive 状态
        Integer oldIsActive = maintenanceTask1.getIsActive();
        Integer newIsActive = maintenanceTask.getIsActive();
        BeanUtils.copyProperties(maintenanceTask, maintenanceTask1);
        int update = maintenanceTaskMapper.updateById(maintenanceTask1);
        if (update > 0) {
            // 处理 isActive 状态变化
            if (newIsActive != null && newIsActive == 1) {
                // 新状态为启用:添加到定时任务调度器
                if (oldIsActive == null || oldIsActive != 1) {
                    // 从未启用变为启用,添加到调度器
                    maintenanceTaskScheduler.scheduleMaintenanceTask(maintenanceTask1);
                } else {
                    // 已经启用,更新调度器中的任务
            maintenanceTaskScheduler.rescheduleMaintenanceTask(maintenanceTask1);
                }
            } else {
                // 新状态为停用:从定时任务调度器中移除
                if (oldIsActive != null && oldIsActive == 1) {
                    maintenanceTaskScheduler.unscheduleMaintenanceTask(maintenanceTask1.getId());
                }
            }
        }
        return AjaxResult.success("更新成功");
    }
    @Override
    public AjaxResult delete(List<Long> ids) {
        // 先从定时任务调度器中移除所有待删除的任务
        ids.forEach(id -> {
            try {
                maintenanceTaskScheduler.unscheduleMaintenanceTask(id);
            } catch (Exception e) {
                log.error("删除定时任务调度失败, id: {}", id, e);
            }
        });
        // 再从数据库中删除记录
        int delete = maintenanceTaskMapper.deleteBatchIds(ids);
        if (delete > 0) {
            ids.forEach(id -> {
                maintenanceTaskScheduler.unscheduleMaintenanceTask(id);
            });
        }
        return AjaxResult.success("删除成功");
    }
        return AjaxResult.error("删除失败");
    }
}
src/main/resources/mapper/quality/QualityInspectMapper.xml
@@ -94,11 +94,7 @@
    </delete>
    <select id="getInspectStatistics" resultType="com.ruoyi.quality.dto.QualityInspectStatDto">
        SELECT CASE pp.product_name
                   WHEN '原材料' THEN 0
                   WHEN '半成品' THEN 1
                   WHEN '成品' THEN 2
                   END                     AS modelType,
        SELECT qi.inspect_type AS modelType,
               IFNULL(SUM(qi.quantity), 0) AS totalCount,
@@ -107,22 +103,14 @@
                              ELSE 0
                   END), 0)                AS completedCount
        FROM product p
                 INNER JOIN product pp
                            ON p.parent_id = pp.id
                 LEFT JOIN product_model pm
                           ON pm.product_id = p.id
                 LEFT JOIN quality_inspect qi
                           ON qi.product_model_id = pm.id
        FROM quality_inspect qi
        WHERE pp.product_name IN ('原材料', '半成品', '成品')
        GROUP BY pp.product_name
        GROUP BY qi.inspect_type
    </select>
    <select id="getPassRateStatistics" resultType="com.ruoyi.quality.dto.QualityPassRateDto">
        SELECT t.modelType,
        SELECT qi.inspect_type AS modelType,
               COALESCE(SUM(qi.quantity), 0) AS totalCount,
@@ -185,27 +173,10 @@
                                   ), 0) * 100, 2)
               )                             AS passRate
        FROM (SELECT 0 AS modelType
              UNION ALL
              SELECT 1
              UNION ALL
              SELECT 2) t
                 LEFT JOIN product p
                           ON 1 = 1
                 LEFT JOIN product pp
                           ON p.parent_id = pp.id
                 LEFT JOIN product_model pm
                           ON pm.product_id = p.id
                 LEFT JOIN quality_inspect qi
                           ON qi.product_model_id = pm.id
                               AND (
                                  (pp.product_name = '原材料' AND t.modelType = 0) OR
                                  (pp.product_name = '半成品' AND t.modelType = 1) OR
                                  (pp.product_name = '成品' AND t.modelType = 2)
                                  )
        FROM quality_inspect qi
        GROUP BY t.modelType
        ORDER BY t.modelType;
        GROUP BY qi.inspect_type
        ORDER BY qi.inspect_type;
    </select>
@@ -297,18 +268,10 @@
               )                             AS passRate
        FROM base b
                 LEFT JOIN product p ON 1 = 1
                 LEFT JOIN product pp ON p.parent_id = pp.id
                 LEFT JOIN product_model pm ON pm.product_id = p.id
                 LEFT JOIN quality_inspect qi
                           ON qi.product_model_id = pm.id
                           ON qi.inspect_type = b.modelType
                               AND YEAR(qi.check_time) = #{year}
                               AND MONTH(qi.check_time) = b.month_num
                               AND (
                                  (pp.product_name = '原材料' AND b.modelType = 0)
                                      OR (pp.product_name = '半成品' AND b.modelType = 1)
                                      OR (pp.product_name = '成品' AND b.modelType = 2)
                                  )
        GROUP BY b.month_num, b.modelType
        ORDER BY b.month_num, b.modelType;
@@ -316,45 +279,58 @@
    </select>
    <select id="getYearlyPassRateStatistics" resultType="com.ruoyi.quality.dto.QualityPassRateDto">
        SELECT t.modelType,
        SELECT qi.inspect_type AS modelType,
               COALESCE(SUM(qi.quantity), 0) AS totalCount,
               COALESCE(SUM(
                                CASE
                                    WHEN pp.product_name = '原材料' AND t.modelType = 0 THEN qi.quantity
                                    WHEN pp.product_name = '半成品' AND t.modelType = 1 THEN qi.quantity
                                    WHEN pp.product_name = '成品' AND t.modelType = 2 THEN qi.quantity
                                    WHEN qi.inspect_state = 1 THEN qi.quantity
                                    ELSE 0
                                    END
                        ), 0) AS totalCount,
                        ), 0)                AS completedCount,
               COALESCE(SUM(
                                CASE
                                    WHEN pp.product_name = '原材料' AND t.modelType = 0 THEN qi.qualified_quantity
                                    WHEN pp.product_name = '半成品' AND t.modelType = 1 THEN qi.qualified_quantity
                                    WHEN pp.product_name = '成品' AND t.modelType = 2 THEN qi.qualified_quantity
                                    WHEN qi.inspect_state = 1 THEN qi.qualified_quantity
                                    ELSE 0
                                    END
                        ), 0) AS qualifiedCount,
               COALESCE(SUM(
                                CASE
                                    WHEN pp.product_name = '原材料' AND t.modelType = 0 THEN qi.unqualified_quantity
                                    WHEN pp.product_name = '半成品' AND t.modelType = 1 THEN qi.unqualified_quantity
                                    WHEN pp.product_name = '成品' AND t.modelType = 2 THEN qi.unqualified_quantity
                                    WHEN qi.inspect_state = 1 THEN qi.unqualified_quantity
                                    ELSE 0
                                    END
                        ), 0) AS unqualifiedCount
        FROM (SELECT 0 AS modelType
              UNION ALL
              SELECT 1
              UNION ALL
              SELECT 2) t
                 LEFT JOIN product p ON 1 = 1
                 LEFT JOIN product pp ON p.parent_id = pp.id
                 LEFT JOIN product_model pm ON pm.product_id = p.id
                 LEFT JOIN quality_inspect qi
                           ON qi.product_model_id = pm.id
                               AND YEAR(qi.check_time) = #{year}
                               AND qi.inspect_state = 1
        GROUP BY t.modelType
        ORDER BY t.modelType;
                        ), 0)                AS unqualifiedCount,
            /* 完成率 */
               IF(COALESCE(SUM(qi.quantity), 0) = 0, 0,
                  ROUND(
                          COALESCE(SUM(
                                           CASE WHEN qi.inspect_state = 1 THEN qi.quantity ELSE 0 END
                                   ), 0)
                              / SUM(qi.quantity) * 100, 2)
               )                             AS completionRate,
            /* 合格率 */
               IF(COALESCE(SUM(
                                   CASE WHEN qi.inspect_state = 1 THEN qi.quantity ELSE 0 END
                           ), 0) = 0, 0,
                  ROUND(
                          COALESCE(SUM(
                                           CASE WHEN qi.inspect_state = 1 THEN qi.qualified_quantity ELSE 0 END
                                   ), 0)
                              /
                          COALESCE(SUM(
                                           CASE WHEN qi.inspect_state = 1 THEN qi.quantity ELSE 0 END
                                   ), 0) * 100, 2)
               )                             AS passRate
        FROM quality_inspect qi
        WHERE YEAR(qi.check_time) = #{year}
        GROUP BY qi.inspect_type
        ORDER BY qi.inspect_type;
    </select>
@@ -383,7 +359,7 @@
            /* 原材料 */
               COALESCE(SUM(
                                CASE
                                    WHEN pp.product_name = '原材料'
                                    WHEN qi.inspect_type = 0
                                        THEN qi.quantity
                                    ELSE 0
                                    END
@@ -392,7 +368,7 @@
            /* 半成品 */
               COALESCE(SUM(
                                CASE
                                    WHEN pp.product_name = '半成品'
                                    WHEN qi.inspect_type = 1
                                        THEN qi.quantity
                                    ELSE 0
                                    END
@@ -401,19 +377,15 @@
            /* 成品 */
               COALESCE(SUM(
                                CASE
                                    WHEN pp.product_name = '成品'
                                    WHEN qi.inspect_type = 2
                                        THEN qi.quantity
                                    ELSE 0
                                    END
                        ), 0) AS outgoingCount
        FROM months m
                 LEFT JOIN product p ON 1 = 1
                 LEFT JOIN product pp ON p.parent_id = pp.id
                 LEFT JOIN product_model pm ON pm.product_id = p.id
                 LEFT JOIN quality_inspect qi
                           ON qi.product_model_id = pm.id
                               AND qi.inspect_state = 1
                           ON qi.inspect_state = 1
                               AND YEAR(qi.check_time) = #{year}
                               AND MONTH(qi.check_time) = m.month_num
@@ -428,16 +400,8 @@
                                  FROM quality_inspect_param qip
                                           JOIN quality_inspect qi
                                                ON qip.inspect_id = qi.id
                                           JOIN product p
                                                ON qi.product_id = p.id
                                           JOIN product pp
                                                ON p.parent_id = pp.id
                                  WHERE qi.inspect_state = 1
                                    AND (
                                      (#{modelType} = 1 AND pp.product_name = '原材料')
                                          OR (#{modelType} = 2 AND pp.product_name = '半成品')
                                          OR (#{modelType} = 3 AND pp.product_name = '成品')
                                      )
                                    AND qi.inspect_type = #{modelType} - 1
                                  GROUP BY qip.parameter_item),
             ranked AS (SELECT name,
                               count,