Bläddra i källkod

feate: 延期提醒

jackzhou 3 dagar sedan
förälder
incheckning
a52878cffb
14 ändrade filer med 280 tillägg och 15 borttagningar
  1. 12 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/alarm/service/delay/DelayInfo.java
  2. 74 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/alarm/service/delay/DeviceAlertDelayController.java
  3. 117 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/alarm/service/delay/DeviceAlertDelayService.java
  4. 10 1
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/alarm/service/messagepush/LocalSensorAlarmMessagePushService.java
  5. 13 1
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/alarm/service/messagepush/RedisSensorAlarmMessagePushService.java
  6. 6 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/param/AppDevice.java
  7. 8 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/param/AppDeviceData.java
  8. 8 12
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/service/AppDeviceService.java
  9. 6 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortarget/entity/MonitorTarget.java
  10. 6 1
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortarget/param/MonitorTargetAddParam.java
  11. 6 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortarget/param/MonitorTargetAddWithRoomParam.java
  12. 6 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortarget/param/MonitorTargetEditParam.java
  13. 6 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortarget/param/MonitorTargetEditWithRoomParam.java
  14. 2 0
      snowy-web-app/src/main/java/vip/xiaonuo/Application.java

+ 12 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/alarm/service/delay/DelayInfo.java

@@ -0,0 +1,12 @@
+package vip.xiaonuo.coldchain.core.alarm.service.delay;
+
+import lombok.Data;
+
+/**
+ * 设备延期提醒的信息
+ */
+@Data
+public class DelayInfo {
+    private Boolean delay;
+    private Integer hours;
+}

+ 74 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/alarm/service/delay/DeviceAlertDelayController.java

@@ -0,0 +1,74 @@
+package vip.xiaonuo.coldchain.core.alarm.service.delay;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+import vip.xiaonuo.common.pojo.CommonResult;
+
+/**
+ * 设备预警延期控制接口
+ *
+ * @author jackzhou 2025 11-03 23:05
+ */
+@RestController
+@RequestMapping("/coldchain/monitordevice/alert-delay")
+@RequiredArgsConstructor
+public class DeviceAlertDelayController {
+
+    private final DeviceAlertDelayService delayService;
+
+    /**
+     * 【POST】禁用设备预警(设备级)
+     * <p>
+     * 示例:POST /coldchain/monitordevice/alert-delay/0001?hours=4
+     */
+    @PostMapping("/{deviceId}")
+    public CommonResult<String> disableDeviceAlert(@PathVariable String deviceId, @RequestParam(defaultValue = "1") long hours) {
+        delayService.disableDeviceAlert(deviceId, hours);
+        return CommonResult.data(String.format("设备[%s] 预警已禁用 %d 小时", deviceId, hours));
+    }
+
+    /**
+     * 【POST】禁用设备某路预警(路级)
+     * <p>
+     * 示例:POST /coldchain/monitordevice/alert-delay/0001/channel/2?hours=8
+     */
+    @PostMapping("/{deviceId}/channel/{channelNo}")
+    public CommonResult<String> disableChannelAlert(@PathVariable String deviceId, @PathVariable int channelNo, @RequestParam(defaultValue = "1") long hours) {
+        delayService.disableChannelAlert(deviceId, channelNo, hours);
+        return CommonResult.data(String.format("设备[%s] 第[%d]路预警已禁用 %d 小时", deviceId, channelNo, hours));
+    }
+
+    /**
+     * 【GET】查询设备或通道是否在延期中
+     * <p>
+     * 示例:
+     * GET /coldchain/monitordevice/alert-delay/0001   -> 查询设备级
+     * GET /coldchain/monitordevice/alert-delay/0001/channel/2 -> 查询第2路
+     */
+    @GetMapping({"/{deviceId}", "/{deviceId}/channel/{channelNo}"})
+    public CommonResult<DelayInfo> isAlertDelayed(@PathVariable String deviceId, @PathVariable(required = false) Integer channelNo) {
+        return CommonResult.data(delayService.isAlertDelayed(deviceId, channelNo));
+    }
+
+    /**
+     * 【POST】清除设备级禁用
+     * <p>
+     * 示例:POST /coldchain/monitordevice/alert-delay/0001/clear
+     */
+    @PostMapping("/{deviceId}/clear")
+    public CommonResult<String> clearDeviceDelay(@PathVariable String deviceId) {
+        delayService.clearDeviceDelay(deviceId);
+        return CommonResult.data(String.format("设备[%s] 的延期预警已清除", deviceId));
+    }
+
+    /**
+     * 【POST】清除路级禁用
+     * <p>
+     * 示例:POST /coldchain/monitordevice/alert-delay/0001/channel/2/clear
+     */
+    @PostMapping("/{deviceId}/channel/{channelNo}/clear")
+    public CommonResult<String> clearChannelDelay(@PathVariable String deviceId, @PathVariable int channelNo) {
+        delayService.clearChannelDelay(deviceId, channelNo);
+        return CommonResult.data(String.format("设备[%s] 第[%d]路延期预警已清除", deviceId, channelNo));
+    }
+}

+ 117 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/alarm/service/delay/DeviceAlertDelayService.java

@@ -0,0 +1,117 @@
+package vip.xiaonuo.coldchain.core.alarm.service.delay;
+
+import cn.hutool.core.util.StrUtil;
+import lombok.RequiredArgsConstructor;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.time.Duration;
+
+/**
+ * @author jackzhou 2025 11-03 23:05
+ */
+@Service
+@RequiredArgsConstructor
+public class DeviceAlertDelayService {
+    /**
+     * 设备预警禁用 Key 前缀
+     */
+    String DEVICE_ALERT_DISABLE_PREFIX = "device:alert:disable:";
+
+    private final StringRedisTemplate redisTemplate;
+
+    /**
+     * 禁用设备预警(设备级)
+     *
+     * @param deviceCode 设备编码
+     * @param hours      禁用时长(小时)
+     */
+    public void disableDeviceAlert(String deviceCode, long hours) {
+        String key = buildDeviceKey(deviceCode);
+        redisTemplate.opsForValue().set(key, String.valueOf(hours), Duration.ofHours(hours));
+    }
+
+    /**
+     * 禁用某路预警(路级)
+     *
+     * @param deviceCode 设备编码
+     * @param channelNo  路号
+     * @param hours      禁用时长(小时)
+     */
+    public void disableChannelAlert(String deviceCode, int channelNo, long hours) {
+        String key = buildChannelKey(deviceCode, channelNo);
+        redisTemplate.opsForValue().set(key, String.valueOf(hours), Duration.ofHours(hours));
+    }
+
+    /**
+     * 判断设备是否处于预警延期中(含路级优先)
+     *
+     * @param deviceCode 设备编码
+     * @param channelNo  路号(可为 null)
+     * @return true 表示当前处于延期中
+     */
+    /**
+     * 判断设备或通道是否处于预警延迟状态
+     * <p>
+     * 优先级:通道级 > 设备级
+     *
+     * @author jackzhou
+     * @since 2019-12
+     */
+    public DelayInfo isAlertDelayed(String deviceId, Integer channelNo) {
+        DelayInfo delayInfo = new DelayInfo();
+        delayInfo.setDelay(false);
+        delayInfo.setHours(0);
+        // 1️⃣ 通道级优先判断
+        if (channelNo != null) {
+            String channelKey = buildChannelKey(deviceId, channelNo);
+            String channelValue = redisTemplate.opsForValue().get(channelKey);
+            if (StrUtil.isNotBlank(channelValue)) {
+                delayInfo.setDelay(true);
+                delayInfo.setHours(Integer.parseInt(channelValue));
+                return delayInfo; // 通道级存在直接返回
+            }
+        }
+
+        // 2️⃣ 再判断设备级
+        String deviceKey = buildDeviceKey(deviceId);
+        String deviceValue = redisTemplate.opsForValue().get(deviceKey);
+        if (StrUtil.isNotBlank(deviceValue)) {
+            delayInfo.setDelay(true);
+            delayInfo.setHours(Integer.parseInt(deviceValue));
+        } else {
+            delayInfo.setDelay(false);
+            delayInfo.setHours(0);
+        }
+        return delayInfo;
+    }
+
+
+    /**
+     * 清除设备延期状态
+     */
+    public void clearDeviceDelay(String deviceId) {
+        redisTemplate.delete(buildDeviceKey(deviceId));
+    }
+
+    /**
+     * 清除路级延期状态
+     */
+    public void clearChannelDelay(String deviceId, int channelNo) {
+        redisTemplate.delete(buildChannelKey(deviceId, channelNo));
+    }
+
+    /**
+     * 拼接设备级Key
+     */
+    private String buildDeviceKey(String deviceId) {
+        return DEVICE_ALERT_DISABLE_PREFIX + deviceId;
+    }
+
+    /**
+     * 拼接路级Key
+     */
+    private String buildChannelKey(String deviceId, int channelNo) {
+        return DEVICE_ALERT_DISABLE_PREFIX + deviceId + ":" + channelNo;
+    }
+}

+ 10 - 1
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/alarm/service/messagepush/LocalSensorAlarmMessagePushService.java

@@ -8,6 +8,7 @@ import vip.xiaonuo.coldchain.core.alarm.bean.NotificationChannel;
 import vip.xiaonuo.coldchain.core.alarm.bean.SensorAlarm;
 import vip.xiaonuo.coldchain.core.alarm.bean.SensorAlarmUser;
 import vip.xiaonuo.coldchain.core.alarm.mapper.SensorAlarmMapper;
+import vip.xiaonuo.coldchain.core.alarm.service.delay.DeviceAlertDelayService;
 import vip.xiaonuo.coldchain.core.config.JfcloudColdChainConstants;
 
 import java.util.*;
@@ -21,7 +22,7 @@ public class LocalSensorAlarmMessagePushService {
     private final SensorAlarmMapper sensorAlarmMapper;
     // 用来记录每个用户对某设备和告警类型的推送历史,key 为 (openid, deviceID, alarmType),value 为推送时间列表
     private final Map<String, List<Long>> userDeviceAlarmPushHistory = new ConcurrentHashMap<>();
-
+    private final DeviceAlertDelayService deviceAlertDelayService;
 
     /**
      * 根据通知渠道推送消息,并更新通知状态
@@ -41,6 +42,14 @@ public class LocalSensorAlarmMessagePushService {
                 .toList();
 
         for (String openid : openids) {
+            // ✅ 1️⃣ 首先判断该设备或该路是否处于预警延期(禁用)状态
+            if (deviceAlertDelayService.isAlertDelayed(deviceID, alarm.getSensorRoute()).getDelay()) {
+                log.info("设备 {} 第 {} 路处于延期预警状态(单路禁用),跳过推送", deviceID, alarm.getSensorRoute());
+                continue;
+            } else if (deviceAlertDelayService.isAlertDelayed(deviceID,null).getDelay()) {
+                log.info("设备 {} 处于延期预警状态(整机禁用),跳过推送", deviceID);
+                continue;
+            }
             // 判断该用户对该设备和告警类型的推送是否超过限制
             if (hasExceededPushLimit(openid, deviceID, alarm.getSensorRoute(), alarmType)) {
                 log.info("用户 {} 对设备 {} 的告警类型 {} \n在过去{}分钟内推送次数超过限制,跳过推送", openid, deviceID, alarmType, JfcloudColdChainConstants.MESS_PUSH_TIME_WINDOW / 60 / 1000);

+ 13 - 1
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/alarm/service/messagepush/RedisSensorAlarmMessagePushService.java

@@ -11,6 +11,7 @@ import vip.xiaonuo.coldchain.core.alarm.bean.NotificationChannel;
 import vip.xiaonuo.coldchain.core.alarm.bean.SensorAlarm;
 import vip.xiaonuo.coldchain.core.alarm.bean.SensorAlarmUser;
 import vip.xiaonuo.coldchain.core.alarm.mapper.SensorAlarmMapper;
+import vip.xiaonuo.coldchain.core.alarm.service.delay.DeviceAlertDelayService;
 import vip.xiaonuo.coldchain.core.config.JfcloudColdChainConstants;
 
 import java.util.*;
@@ -31,6 +32,7 @@ public class RedisSensorAlarmMessagePushService {
     private final Map<String, MessagePushService> pushServices;
     private final SensorAlarmMapper sensorAlarmMapper;
     private final RedisTemplate<String, Object> redisTemplate;
+    private final DeviceAlertDelayService deviceAlertDelayService;
 
     @Async("coldChainAsyncTask")
     public void pushAlarmMessage(SensorAlarm alarm) {
@@ -53,8 +55,18 @@ public class RedisSensorAlarmMessagePushService {
         List<SensorAlarmUser> alarmUsers = users.values().stream().toList();
         for (String openid : users.keySet()) {
             SensorAlarmUser user = users.get(openid);
+            // ✅ 1️⃣ 首先判断该设备或该路是否处于预警延期(禁用)状态
+            if (deviceAlertDelayService.isAlertDelayed(deviceID, alarm.getSensorRoute()).getDelay()) {
+                log.info("设备 {} 第 {} 路处于延期预警状态(单路禁用),跳过推送", deviceID, alarm.getSensorRoute());
+                continue;
+            } else if (deviceAlertDelayService.isAlertDelayed(deviceID,null).getDelay()) {
+                log.info("设备 {} 处于延期预警状态(整机禁用),跳过推送", deviceID);
+                continue;
+            }
+            // ✅ 2️⃣ 再判断该用户是否超出推送频率限制
             if (hasExceededPushLimit(openid, deviceID, alarm.getSensorRoute(), alarmType)) {
-                log.info("用户 {} 对设备 {} 的告警类型 {} \n在过去{}分钟内推送次数超过限制,跳过推送", openid, deviceID, alarmType, JfcloudColdChainConstants.MESS_PUSH_TIME_WINDOW / 60 / 1000);
+                log.info("用户 {} 对设备 {} 的告警类型 {} 在过去 {} 分钟内推送次数超过限制,跳过推送",
+                        openid, deviceID, alarmType, JfcloudColdChainConstants.MESS_PUSH_TIME_WINDOW / 60 / 1000);
                 delAlarmTime(deviceID, alarm.getSensorRoute(), alarmType);
                 continue;
             }

+ 6 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/param/AppDevice.java

@@ -14,6 +14,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import vip.xiaonuo.coldchain.core.alarm.service.delay.DelayInfo;
 import vip.xiaonuo.coldchain.core.service.dataprocess.model.PowerEnum;
 import vip.xiaonuo.coldchain.modular.monitortarget.entity.MonitorTarget;
 
@@ -48,4 +49,9 @@ public class AppDevice extends MonitorTarget {
     @Schema(description = "关键的设备探头集合")
     private List<AppDeviceData> children = new ArrayList<AppDeviceData>();
 
+    /**
+     * 延迟信息
+     */
+    @Schema(description = "延迟信息")
+    private DelayInfo delayInfo;
 }

+ 8 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/param/AppDeviceData.java

@@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import vip.xiaonuo.coldchain.core.alarm.service.delay.DelayInfo;
 import vip.xiaonuo.coldchain.core.service.dataprocess.model.PowerEnum;
 import vip.xiaonuo.coldchain.modular.monitortargetregion.entity.MonitorTargetRegion;
 
@@ -54,5 +55,12 @@ public class AppDeviceData extends MonitorTargetRegion {
     @Schema(description = "CO2状态 (0正常1临界2异常)")
     private String co2Status;
 
+
+    /**
+     * 延迟信息
+     */
+    @Schema(description = "延迟信息")
+    private DelayInfo delayInfo;
+
     // 默认构造函数不再需要显式定义,Lombok 会自动生成
 }

+ 8 - 12
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/service/AppDeviceService.java

@@ -10,7 +10,6 @@ package vip.xiaonuo.coldchain.modular.app.service;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.date.StopWatch;
 import cn.hutool.core.lang.Assert;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
@@ -20,15 +19,12 @@ import com.github.jfcloud.influxdb.flux.AggregationWindow;
 import com.google.common.collect.Lists;
 import com.itextpdf.io.image.ImageData;
 import com.itextpdf.io.image.ImageDataFactory;
-import com.itextpdf.kernel.pdf.PdfObject;
-import com.itextpdf.kernel.pdf.WriterProperties;
-import com.itextpdf.layout.element.Image;
-import com.itextpdf.kernel.colors.ColorConstants;
 import com.itextpdf.kernel.font.PdfFont;
 import com.itextpdf.kernel.font.PdfFontFactory;
 import com.itextpdf.kernel.geom.PageSize;
 import com.itextpdf.kernel.pdf.PdfDocument;
 import com.itextpdf.kernel.pdf.PdfWriter;
+import com.itextpdf.kernel.pdf.WriterProperties;
 import com.itextpdf.layout.Document;
 import com.itextpdf.layout.element.*;
 import com.itextpdf.layout.properties.HorizontalAlignment;
@@ -38,10 +34,10 @@ import jakarta.annotation.Resource;
 import jakarta.servlet.http.HttpServletResponse;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.checkerframework.checker.units.qual.C;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 import vip.xiaonuo.auth.core.util.StpLoginUserUtil;
+import vip.xiaonuo.coldchain.core.alarm.service.delay.DeviceAlertDelayService;
 import vip.xiaonuo.coldchain.core.bean.influxdb.SensorData;
 import vip.xiaonuo.coldchain.core.service.JfcloudSensorDataService;
 import vip.xiaonuo.coldchain.modular.app.dto.AppInfo;
@@ -60,25 +56,22 @@ import vip.xiaonuo.common.exception.CommonException;
 import vip.xiaonuo.dev.modular.config.entity.DevConfig;
 import vip.xiaonuo.dev.modular.config.service.DevConfigService;
 
-import java.io.*;
+import java.io.IOException;
+import java.io.OutputStream;
 import java.math.RoundingMode;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.text.DecimalFormat;
-import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.util.*;
 import java.util.List;
+import java.util.*;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
-import java.util.stream.IntStream;
 
 @Slf4j
 @Service
@@ -88,6 +81,7 @@ public class AppDeviceService {
     private final MonitorTargetRegionService monitorTargetRegionService;
     private final JfcloudSensorDataService jfcloudSensorDataService;
     private final MonitorDeviceService monitorDeviceService;
+    private final DeviceAlertDelayService delayService;
     @Resource
     DevConfigService devConfigService;
 
@@ -127,6 +121,7 @@ public class AppDeviceService {
             appDevice.setMonitorTargetRegionList(null);
             // 获取当前监控目标的 ID,用于查询子设备数据
             String monitorTargetId = monitorTarget.getId();
+            appDevice.setDelayInfo(delayService.isAlertDelayed(monitorTargetId,null));
             // 获取当前监控目标下的所有监控区域(子设备数据)
             List<MonitorTargetRegion> monitorTargetRegions = monitorTargetRegionService.getRegionListByTargetId(monitorTargetId);
             // 如果监控目标下存在区域(即有子设备)
@@ -148,6 +143,7 @@ public class AppDeviceService {
                     // 传感器路数
                     Integer sensorRoute = appDeviceData.getSensorRoute();
                     if (!Objects.isNull(sensorRoute) && StrUtil.isNotBlank(deviceCode)) {
+                        appDeviceData.setDelayInfo(delayService.isAlertDelayed(monitorTargetId, sensorRoute));
                         SensorData sensorData = monitorDeviceService.queryLatestDataByDeviceIdAndRoads(deviceCode, sensorRoute);
                         if (!Objects.isNull(sensorData)) {
                             appDeviceData.setBatteryPercentage(sensorData.getBattery());

+ 6 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortarget/entity/MonitorTarget.java

@@ -115,4 +115,10 @@ public class MonitorTarget extends OrgEntity {
     @Schema(description = "用户的通知渠道设置,支持选择接收告警的多个渠道,如短信、邮件、APP通知等")
     @TableField(value = "notification_channel", typeHandler = NotificationChannelListTypeHandler.class)
     private List<NotificationChannel> notificationChannel = List.of(NotificationChannel.WECHAT);
+
+    /**
+     * 是否启用预警通知,0=启用,1=禁用
+     */
+    @Schema(description = "是否启用预警通知,0=启用,1=禁用")
+    private Integer enabled;
 }

+ 6 - 1
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortarget/param/MonitorTargetAddParam.java

@@ -15,7 +15,6 @@ package vip.xiaonuo.coldchain.modular.monitortarget.param;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.google.common.collect.Lists;
 import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotNull;
 import lombok.Getter;
 import lombok.Setter;
 import org.hibernate.validator.constraints.Length;
@@ -67,4 +66,10 @@ public class MonitorTargetAddParam {
     @Schema(description = "告警接收人,存储告警通知的接收用户信息")
     private List<SensorAlarmUser> alarmUsers = Lists.newArrayList();
 
+    /**
+     * 是否启用预警通知,0=启用,1=禁用
+     */
+    @Schema(description = "是否启用预警通知,0=启用,1=禁用")
+    private Integer enabled;
+
 }

+ 6 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortarget/param/MonitorTargetAddWithRoomParam.java

@@ -73,4 +73,10 @@ public class MonitorTargetAddWithRoomParam {
     @NotNull(message = "房间不能为空")
     private String roomId;
 
+    /**
+     * 是否启用预警通知,0=启用,1=禁用
+     */
+    @Schema(description = "是否启用预警通知,0=启用,1=禁用")
+    private Integer enabled;
+
 }

+ 6 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortarget/param/MonitorTargetEditParam.java

@@ -86,4 +86,10 @@ public class MonitorTargetEditParam {
     @TableField(value = "alarm_users", typeHandler = SensorAlarmUserTypeHandler.class)
     @Schema(description = "告警接收人,存储告警通知的接收用户信息")
     private List<SensorAlarmUser> alarmUsers = Lists.newArrayList();
+
+    /**
+     * 是否启用预警通知,0=启用,1=禁用
+     */
+    @Schema(description = "是否启用预警通知,0=启用,1=禁用")
+    private Integer enabled;
 }

+ 6 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortarget/param/MonitorTargetEditWithRoomParam.java

@@ -93,4 +93,10 @@ public class MonitorTargetEditWithRoomParam {
      */
     @NotNull(message = "房间不能为空")
     private String roomId;
+
+    /**
+     * 是否启用预警通知,0=启用,1=禁用
+     */
+    @Schema(description = "是否启用预警通知,0=启用,1=禁用")
+    private Integer enabled;
 }

+ 2 - 0
snowy-web-app/src/main/java/vip/xiaonuo/Application.java

@@ -31,6 +31,8 @@ import vip.xiaonuo.core.config.JfcloudApplication;
  */
 @Slf4j
 @JfcloudApplication
+@EnableScheduling
+@EnableAsync
 public class Application {
     /* 解决druid 日志报错:discard long time none received connection:xxx */
     static {