Bläddra i källkod

fix: 预警资讯详情

jackzhou 5 månader sedan
förälder
incheckning
3fc420fb01

+ 3 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/alarm/bean/SensorAlarm.java

@@ -127,6 +127,9 @@ public class SensorAlarm extends OrgEntity {
     @Schema(description = "微信请求状态码")
     private String weixinRequestCode;
 
+    @Schema(description = "设备序列号")
+    private String sensorCode;
+
     /**
      * 传感器路数
      */

+ 2 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/alarm/service/SensorAlarmService.java

@@ -18,4 +18,6 @@ public interface SensorAlarmService extends IService<SensorAlarm> {
     Page<Message> getMessages(MessagePageParam messagePageParam);
 
     Page<SensorAlarm> getMessages(MonitorNoticePageParam monitorNoticePageParam);
+
+    long countAlarms(String startDate, String endDate, String sensorCode, String sensorRoute);
 }

+ 24 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/alarm/service/SensorAlarmServiceImpl.java

@@ -35,6 +35,7 @@ public class SensorAlarmServiceImpl extends ServiceImpl<SensorAlarmMapper, Senso
 
     /**
      * app接口
+     *
      * @param messagePageParam
      * @return
      */
@@ -59,6 +60,7 @@ public class SensorAlarmServiceImpl extends ServiceImpl<SensorAlarmMapper, Senso
 
     /**
      * pc接口
+     *
      * @param messagePageParam
      * @return
      */
@@ -67,6 +69,28 @@ public class SensorAlarmServiceImpl extends ServiceImpl<SensorAlarmMapper, Senso
         return getSensorAlarmPage(messagePageParam);
     }
 
+    @Override
+    public long countAlarms(String startDate, String endDate, String sensorCode, String sensorRoute) {
+        QueryWrapper<SensorAlarm> queryWrapper = new QueryWrapper<>();
+        // 获取当前登录用户ID
+        String orgId = StpLoginUserUtil.getLoginUser().getOrgId();
+        // 查询创建用户为当前用户的记录
+        queryWrapper.lambda().eq(SensorAlarm::getCreateOrg, orgId);  // 创建组织ID条件
+        // 根据传入的 sensorCode 和 sensorRoute 条件查询
+        if (sensorCode != null) {
+            queryWrapper.lambda().eq(SensorAlarm::getSensorCode, sensorCode);
+        }
+        if (sensorRoute != null) {
+            queryWrapper.lambda().eq(SensorAlarm::getSensorRoute, sensorRoute);
+        }
+        // 时间范围查询,确保传入的日期格式正确
+        if (startDate != null && endDate != null) {
+            queryWrapper.lambda().between(SensorAlarm::getCreateTime, startDate, endDate);
+        }
+        // 返回符合条件的记录数量
+        return this.count(queryWrapper);
+    }
+
     public Page<SensorAlarm> getSensorAlarmPage(MessagePageParam messagePageParam) {
         // 创建查询条件
         QueryWrapper<SensorAlarm> queryWrapper = new QueryWrapper<SensorAlarm>().checkSqlInjection();

+ 2 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/alarm/service/check/DefaultSensorAlarmChecker.java

@@ -91,6 +91,7 @@ public class DefaultSensorAlarmChecker implements SensorAlarmChecker {
     private void publishAlarm(String alarmType, Float value, String unit, String time, float threshold, MonitorTargetRegion monitorTargetRegion) {
         String monitorTargetId = monitorTargetRegion.getMonitorTargetId();
         Integer sensorRoute = monitorTargetRegion.getSensorRoute();
+        String  sensorCode = monitorTargetRegion.getSensorCode();
         String deviceName = monitorTargetRegion.getName();
         String deviceId = monitorTargetRegion.getId();
         String alarmMessage = getAlarmMessage(alarmType, value, unit, deviceName, time, threshold);
@@ -108,6 +109,7 @@ public class DefaultSensorAlarmChecker implements SensorAlarmChecker {
         sensorAlarm.setThreshold(threshold);  // 设置预警值
         sensorAlarm.setMonitorTargetId(monitorTargetId);
         sensorAlarm.setSensorRoute(sensorRoute);
+        sensorAlarm.setSensorCode(sensorCode);
         sensorAlarm.setCreateUser(monitorTargetRegion.getCreateUser());
         List<SensorAlarmUser> alarmUsers = monitorTargetRegion.getAlarmUsers();
         sensorAlarm.setAlarmUsers(alarmUsers);

+ 127 - 2
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/core/service/JfcloudSensorDataService.java

@@ -9,8 +9,12 @@ import com.influxdb.client.QueryApi;
 import com.influxdb.query.FluxTable;
 import org.springframework.stereotype.Service;
 import org.springframework.util.Assert;
+import vip.xiaonuo.coldchain.core.alarm.service.SensorAlarmService;
 import vip.xiaonuo.coldchain.core.bean.influxdb.SensorData;
+import vip.xiaonuo.coldchain.core.config.JfcloudColdChainConstants;
 
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -24,8 +28,11 @@ import java.util.stream.Collectors;
  */
 @Service
 public class JfcloudSensorDataService extends JfcloudFluxDataService<SensorData> {
-    public JfcloudSensorDataService(JfcloudInfluxDBService jfcloudInfluxDBService, JfcloudInfluxDB2Properties jfcloudInfluxDB2Properties) {
+    private SensorAlarmService sensorAlarmService;
+
+    public JfcloudSensorDataService(JfcloudInfluxDBService jfcloudInfluxDBService, JfcloudInfluxDB2Properties jfcloudInfluxDB2Properties, SensorAlarmService sensorAlarmService) {
         super(jfcloudInfluxDBService, jfcloudInfluxDB2Properties);
+        this.sensorAlarmService = sensorAlarmService;
     }
 
 
@@ -75,7 +82,7 @@ public class JfcloudSensorDataService extends JfcloudFluxDataService<SensorData>
         // 获取聚合窗口的代码
         String aggregationWindowCode = aggregationWindow != null ? aggregationWindow.getCode() : "default";
         // 构建查询语句
-        String measurement = "sensor_data"; // 数据表名称
+        String measurement = JfcloudColdChainConstants.INFLUXDB_DEFAULT_MEASUREMENT_NAME; // 数据表名称
         Map<String, String> filters = Map.of(
                 "device_id", deviceId,
                 "roads", roads.toString()
@@ -130,4 +137,122 @@ public class JfcloudSensorDataService extends JfcloudFluxDataService<SensorData>
 //        return outputFormatter.format(instant.atZone(ZoneOffset.UTC));
     }
 
+    /**
+     * 获取当前月的数据总数
+     *
+     * @param deviceId 设备ID
+     * @param roads    道路字段
+     * @return 当前月数据总数
+     */
+    public long getCurrentMonthDataCount(String deviceId, String roads) {
+        // 获取当前月份的起始时间和结束时间
+        String startDate = getFirstDayOfCurrentMonth();
+        String endDate = getLastDayOfCurrentMonth();
+        return getSensorDataCount(startDate, endDate, deviceId, roads);
+    }
+
+    /**
+     * 获取上月的数据总数
+     *
+     * @param deviceId 设备ID
+     * @param roads    道路字段
+     * @return 上月数据总数
+     */
+    public long getLastMonthDataCount(String deviceId, String roads) {
+        // 获取上个月的起始时间和结束时间
+        String startDate = getFirstDayOfLastMonth();
+        String endDate = getLastDayOfLastMonth();
+        return getSensorDataCount(startDate, endDate, deviceId, roads);
+    }
+
+    /**
+     * 获取数据总数,传入查询时间范围和参数
+     *
+     * @param startDate 查询开始日期
+     * @param endDate   查询结束日期
+     * @param deviceId  设备ID
+     * @param roads     道路字段
+     * @return 数据总数
+     */
+    private long getSensorDataCount(String startDate, String endDate, String deviceId, String roads) {
+        long count = 0;
+        try {
+            // 构建Flux查询,简化了不必要的group操作
+            String query = String.format("""
+                    from(bucket: "%s")
+                      |> range(start: %s, stop: %s)
+                      |> filter(fn: (r) => r["_measurement"] == "%s")
+                      |> filter(fn: (r) => r["device_id"] == "%s" and r["roads"] == "%s")
+                      |> count()
+                    """, getBucketName(), startDate, endDate, JfcloudColdChainConstants.INFLUXDB_DEFAULT_MEASUREMENT_NAME, deviceId, roads);
+
+            // 获取QueryApi并执行查询
+            QueryApi queryApi = jfcloudInfluxDBService.getInfluxDBClient().getQueryApi();
+            List<FluxTable> result = queryApi.query(query);
+
+            // 处理查询结果
+            if (result != null && !result.isEmpty()) {
+                FluxTable fluxTable = result.get(0);
+                if (fluxTable.getRecords() != null && !fluxTable.getRecords().isEmpty()) {
+                    // 获取结果值
+                    Object countValue = fluxTable.getRecords().get(0).getValues().get("_value");
+                    if (countValue != null) {
+                        // 确保转换为正确的数字类型
+                        if (countValue instanceof Number) {
+                            count = ((Number) countValue).longValue();  // 类型安全转换
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace(); // 打印异常信息
+        }
+        return count; // 返回统计结果
+    }
+
+
+    /**
+     * 获取当前月的起始日期
+     */
+    private String getFirstDayOfCurrentMonth() {
+        LocalDate firstDayOfCurrentMonth = LocalDate.now().withDayOfMonth(1);
+        return firstDayOfCurrentMonth.format(DateTimeFormatter.ISO_DATE) + "T00:00:00Z";
+    }
+
+    /**
+     * 获取当前月的结束日期
+     */
+    private String getLastDayOfCurrentMonth() {
+        LocalDate lastDayOfCurrentMonth = LocalDate.now().withDayOfMonth(1).plusMonths(1).minusDays(1);
+        return lastDayOfCurrentMonth.format(DateTimeFormatter.ISO_DATE) + "T23:59:59Z";
+    }
+
+    /**
+     * 获取上月的起始日期
+     */
+    private String getFirstDayOfLastMonth() {
+        LocalDate firstDayOfLastMonth = LocalDate.now().minusMonths(1).withDayOfMonth(1);
+        return firstDayOfLastMonth.format(DateTimeFormatter.ISO_DATE) + "T00:00:00Z";
+    }
+
+    /**
+     * 获取上月的结束日期
+     */
+    private String getLastDayOfLastMonth() {
+        LocalDate lastDayOfLastMonth = LocalDate.now().minusMonths(1).withDayOfMonth(1).plusMonths(1).minusDays(1);
+        return lastDayOfLastMonth.format(DateTimeFormatter.ISO_DATE) + "T23:59:59Z";
+    }
+
+    public long getLastMonthAlarmCount(String sensorCode, String sensorRoute) {
+        // 获取上个月的起始时间和结束时间
+        String startDate = getFirstDayOfLastMonth();
+        String endDate = getLastDayOfLastMonth();
+        return sensorAlarmService.countAlarms(startDate, endDate, sensorCode, sensorRoute);
+    }
+
+    public long getCurrentMonthAlarmCount(String sensorCode, String sensorRoute) {
+        String startDate = getFirstDayOfCurrentMonth();
+        String endDate = getLastDayOfCurrentMonth();
+        return sensorAlarmService.countAlarms(startDate, endDate, sensorCode, sensorRoute);
+    }
 }

+ 1 - 1
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/param/AppIndicatorQueryParams.java

@@ -16,7 +16,7 @@ public class AppIndicatorQueryParams {
     @Schema(description = "设备序列号")
     private String sensorCode;
     @Schema(description = "设备路数")
-    private Integer sensorRoute;
+    private String sensorRoute;
     @Schema(description = "查询月度2024-12")
     private String month;
 

+ 2 - 2
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/app/param/SensorIndicator.java

@@ -15,9 +15,9 @@ public class SensorIndicator {
     @Schema(description = "采集数据总数")
     private long totalCollected;
     @Schema(description = "预警总数")
-    private int totalWarnings;
+    private long totalWarnings;
     @Schema(description = "异常总数")
-    private int totalAbnormal;
+    private long totalAbnormal;
     @Schema(description = "采集数据总数同比变化")
     private String collectedChange;
     @Schema(description = "预警同比变化")

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

@@ -13,11 +13,11 @@ import cn.hutool.core.lang.Assert;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.github.jfcloud.influxdb.flux.AggregationWindow;
-import com.github.jfcloud.influxdb.service.JfcloudInfluxDBService;
 import com.google.common.collect.Lists;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 import vip.xiaonuo.coldchain.core.bean.influxdb.SensorData;
+import vip.xiaonuo.coldchain.core.service.JfcloudSensorDataService;
 import vip.xiaonuo.coldchain.modular.app.param.*;
 import vip.xiaonuo.coldchain.modular.monitordevice.service.MonitorDeviceService;
 import vip.xiaonuo.coldchain.modular.monitortarget.entity.MonitorTarget;
@@ -36,7 +36,7 @@ import java.util.function.Supplier;
 public class AppDeviceService {
     private final MonitorTargetService monitorTargetService;
     private final MonitorTargetRegionService monitorTargetRegionService;
-    private final JfcloudInfluxDBService jfcloudInfluxDBService;
+    private final JfcloudSensorDataService jfcloudSensorDataService;
     private final MonitorDeviceService monitorDeviceService;
 
     // 模拟设备保存操作,实际应用中可能会是数据库操作
@@ -235,23 +235,42 @@ public class AppDeviceService {
 
     public SensorIndicator indicators(AppIndicatorQueryParams appDeviceQueryParams) {
         // 假设上月数据
-        int lastMonthCollected = 30000;  // 上月采集数据总数
-        int lastMonthWarnings = 100;   // 上月预警总数
-        int lastMonthAbnormal = 150;   // 上月异常总数
+        long lastMonthCollected = jfcloudSensorDataService.getLastMonthDataCount(appDeviceQueryParams.getSensorCode(),appDeviceQueryParams.getSensorRoute());
+        long lastMonthWarnings = jfcloudSensorDataService.getLastMonthAlarmCount(appDeviceQueryParams.getSensorCode(),appDeviceQueryParams.getSensorRoute());   // 上月预警总数
+        long lastMonthAbnormal = 0;   // 上月异常总数
         // 计算本月数据
-        int totalCollected = (int) (lastMonthCollected * 1.30); // 同比增长30%
-        int totalWarnings = (int) (lastMonthWarnings * 0.95);   // 同比减少5%
-        int totalAbnormal = (int) (lastMonthAbnormal * 1.10);   // 同比增长10%
+        long totalCollected = jfcloudSensorDataService.getCurrentMonthDataCount(appDeviceQueryParams.getSensorCode(),appDeviceQueryParams.getSensorRoute());
+        long totalWarnings = jfcloudSensorDataService.getCurrentMonthAlarmCount(appDeviceQueryParams.getSensorCode(),appDeviceQueryParams.getSensorRoute());   // 同比减少5%
+        long totalAbnormal = 0;   // 同比增长10%
         // 创建响应对象
         SensorIndicator response = new SensorIndicator();
         response.setTotalCollected(totalCollected);
         response.setTotalWarnings(totalWarnings);
         response.setTotalAbnormal(totalAbnormal);
-        response.setCollectedChange("+30%");
-        response.setWarningsChange("-5%");
-        response.setAbnormalChange("+10%");
+        //计算相对上个月的半分比
+        response.setCollectedChange(formatChange(calculateChange(lastMonthCollected, totalCollected)));
+        response.setWarningsChange(formatChange(calculateChange(lastMonthWarnings, totalWarnings)));
+        response.setAbnormalChange(formatChange(totalAbnormal));
         return response;
     }
+    // 计算百分比变化的辅助方法
+    private double calculateChange(long lastMonthValue, long currentMonthValue) {
+        if (lastMonthValue == 0) {
+            return currentMonthValue > 0 ? 100.0 : 0.0;  // 如果上月数据为0,本月有数据则变化为100%,否则为0%
+        }
+        return ((double) (currentMonthValue - lastMonthValue) / lastMonthValue) * 100;
+    }
+
+    // 格式化百分比变化(添加正负符号并限制小数位数)
+    private String formatChange(double change) {
+        if (change > 0) {
+            return String.format("+%.2f%%", change);
+        } else if (change < 0) {
+            return String.format("%.2f%%", change);
+        } else {
+            return "0.00%";
+        }
+    }
 
     public Boolean updateDeviceInfo(AppDeviceUpdateParam appDeviceAlarmParam) {
         MonitorTargetRegion monitorTargetRegion = monitorTargetRegionService.getById(appDeviceAlarmParam.getMonitorTargetRegionId());

+ 2 - 2
snowy-web-app/src/main/resources/application.properties

@@ -135,8 +135,8 @@ spring.data.redis.lettuce.pool.min-idle=0
 #########################################
 # mybatis-plus configuration
 #########################################
-#mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
-mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.slf4j.Slf4jImpl
+mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
+#mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.slf4j.Slf4jImpl
 mybatis-plus.configuration.jdbc-type-for-null=null
 mybatis-plus.global-config.banner=false
 mybatis-plus.global-config.enable-sql-runner=true