|
|
@@ -0,0 +1,537 @@
|
|
|
+package com.zksy.WaterSupply.MonitorAlarm.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
+import com.zksy.WaterSupply.MonitorAlarm.domain.AlarmAudit;
|
|
|
+import com.zksy.WaterSupply.MonitorAlarm.dto.in.AlarmAuditInDTO;
|
|
|
+import com.zksy.WaterSupply.MonitorAlarm.dto.in.AlarmDispatchInDTO;
|
|
|
+import com.zksy.WaterSupply.MonitorAlarm.dto.out.AlarmAuditOutDTO;
|
|
|
+import com.zksy.WaterSupply.MonitorAlarm.dto.out.AlarmFlowOutDTO;
|
|
|
+import com.zksy.WaterSupply.MonitorAlarm.dto.out.AlarmMapPointOutDTO;
|
|
|
+import com.zksy.WaterSupply.MonitorAlarm.dto.out.AlarmStatsOutDTO;
|
|
|
+import com.zksy.WaterSupply.MonitorAlarm.dto.out.WaterAlarmOutDTO;
|
|
|
+import com.zksy.WaterSupply.MonitorAlarm.mapper.AlarmAuditMapper;
|
|
|
+import com.zksy.WaterSupply.MonitorAlarm.service.IWaterSupplyAlarmService;
|
|
|
+import com.zksy.base.alarm.domain.AlarmData;
|
|
|
+import com.zksy.base.alarm.service.AlarmDataService;
|
|
|
+import com.zksy.base.domain.EquipmentBase;
|
|
|
+import com.zksy.base.domain.WorkOrder;
|
|
|
+import com.zksy.base.domain.WorkOrderLog;
|
|
|
+import com.zksy.base.mapper.EquipmentBaseMapper;
|
|
|
+import com.zksy.base.mapper.WorkOrderLogMapper;
|
|
|
+import com.zksy.base.mapper.WorkOrderMapper;
|
|
|
+import com.zksy.base.service.EquipmentBaseService;
|
|
|
+import com.zksy.common.core.domain.model.LoginUser;
|
|
|
+import com.zksy.common.exception.ServiceException;
|
|
|
+import com.zksy.common.utils.SecurityUtils;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.time.LocalDate;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.Comparator;
|
|
|
+import java.util.LinkedHashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Objects;
|
|
|
+import java.util.Random;
|
|
|
+import java.util.Set;
|
|
|
+import java.util.function.Function;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 供水监测报警业务实现
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+public class WaterSupplyAlarmServiceImpl implements IWaterSupplyAlarmService {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 供水设备顶级类型名称(equipment_type 中 parent_type_id='0' 的顶级类型)
|
|
|
+ */
|
|
|
+ @Value("${waterSupply.alarm.top-level-type:供水}")
|
|
|
+ private String waterTopLevelTypeName;
|
|
|
+
|
|
|
+ private static final DateTimeFormatter ORDER_NO_FMT = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private AlarmDataService alarmDataService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private EquipmentBaseService equipmentBaseService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private EquipmentBaseMapper equipmentBaseMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private WorkOrderMapper workOrderMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private WorkOrderLogMapper workOrderLogMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private AlarmAuditMapper alarmAuditMapper;
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------
|
|
|
+ // 供水设备范围解析
|
|
|
+ // ------------------------------------------------------------------
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析全部供水设备编码(按设备类别顶级类型"供水"动态查询)
|
|
|
+ */
|
|
|
+ private Set<String> resolveWaterDeviceCodes() {
|
|
|
+ return equipmentBaseService.findByTopLevelType(waterTopLevelTypeName).stream()
|
|
|
+ .map(EquipmentBase::getEquipmentCode)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .collect(Collectors.toSet());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设备编码 -> 设备信息映射
|
|
|
+ */
|
|
|
+ private Map<String, EquipmentBase> loadEquipmentCodeMap() {
|
|
|
+ return equipmentBaseMapper.selectList(null).stream()
|
|
|
+ .collect(Collectors.toMap(EquipmentBase::getEquipmentCode, Function.identity(), (a, b) -> a));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设备编码 -> 工单映射(同一报警派发多个工单时取最新)
|
|
|
+ */
|
|
|
+ private Map<String, WorkOrder> loadWorkOrderMapByAlarmIds(List<String> alarmIds) {
|
|
|
+ if (CollUtil.isEmpty(alarmIds)) {
|
|
|
+ return Collections.emptyMap();
|
|
|
+ }
|
|
|
+ List<WorkOrder> orders = workOrderMapper.selectList(new LambdaQueryWrapper<WorkOrder>()
|
|
|
+ .in(WorkOrder::getAlarmId, alarmIds)
|
|
|
+ .orderByDesc(WorkOrder::getOrderId));
|
|
|
+ return orders.stream()
|
|
|
+ .collect(Collectors.toMap(WorkOrder::getAlarmId, Function.identity(), (a, b) -> a));
|
|
|
+ }
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------
|
|
|
+ // 统计
|
|
|
+ // ------------------------------------------------------------------
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public AlarmStatsOutDTO getAlarmStats() {
|
|
|
+ AlarmStatsOutDTO stats = new AlarmStatsOutDTO();
|
|
|
+ Set<String> waterCodes = resolveWaterDeviceCodes();
|
|
|
+ stats.setTotalDeviceCount(waterCodes.size());
|
|
|
+ if (waterCodes.isEmpty()) {
|
|
|
+ stats.setDeviceAbnormalRate("0.00");
|
|
|
+ stats.setAvgResponseMinutes("0.00");
|
|
|
+ return stats;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 未处理报警(实时报警)
|
|
|
+ List<AlarmData> pendingAlarms = alarmDataService.list(new LambdaQueryWrapper<AlarmData>()
|
|
|
+ .in(AlarmData::getDeviceCode, waterCodes)
|
|
|
+ .eq(AlarmData::getAlarmStatus, 0));
|
|
|
+ Set<String> abnormalDevices = pendingAlarms.stream()
|
|
|
+ .map(AlarmData::getDeviceCode)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .collect(Collectors.toSet());
|
|
|
+ stats.setRealtimeAlarmCount(abnormalDevices.size());
|
|
|
+ stats.setAbnormalDeviceCount(abnormalDevices.size());
|
|
|
+ stats.setDeviceAbnormalRate(waterCodes.isEmpty() ? "0.00"
|
|
|
+ : String.format("%.2f", abnormalDevices.size() * 100.0d / waterCodes.size()));
|
|
|
+
|
|
|
+ // 今日报警总数
|
|
|
+ LocalDateTime todayStart = LocalDate.now().atStartOfDay();
|
|
|
+ long todayCount = alarmDataService.count(new LambdaQueryWrapper<AlarmData>()
|
|
|
+ .in(AlarmData::getDeviceCode, waterCodes)
|
|
|
+ .ge(AlarmData::getAlarmTime, todayStart));
|
|
|
+ stats.setTodayAlarmCount(todayCount);
|
|
|
+
|
|
|
+ // 平均响应时间:今日已处理报警(处理时间-报警时间)均值,单位分钟
|
|
|
+ List<AlarmData> handledToday = alarmDataService.list(new LambdaQueryWrapper<AlarmData>()
|
|
|
+ .in(AlarmData::getDeviceCode, waterCodes)
|
|
|
+ .eq(AlarmData::getAlarmStatus, 1)
|
|
|
+ .ge(AlarmData::getHandleTime, todayStart));
|
|
|
+ double totalSeconds = 0;
|
|
|
+ int count = 0;
|
|
|
+ for (AlarmData alarm : handledToday) {
|
|
|
+ if (alarm.getAlarmTime() == null || alarm.getHandleTime() == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ totalSeconds += alarm.getHandleTime().toEpochSecond(java.time.ZoneOffset.ofHours(8))
|
|
|
+ - alarm.getAlarmTime().toEpochSecond(java.time.ZoneOffset.ofHours(8));
|
|
|
+ count++;
|
|
|
+ }
|
|
|
+ stats.setAvgResponseMinutes(count == 0 ? "0.00" : String.format("%.2f", totalSeconds / 60.0d / count));
|
|
|
+ return stats;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------
|
|
|
+ // 实时 / 历史 / 详情
|
|
|
+ // ------------------------------------------------------------------
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<WaterAlarmOutDTO> getRealtimeAlarmList() {
|
|
|
+ Set<String> waterCodes = resolveWaterDeviceCodes();
|
|
|
+ if (waterCodes.isEmpty()) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+ List<AlarmData> alarms = alarmDataService.list(new LambdaQueryWrapper<AlarmData>()
|
|
|
+ .in(AlarmData::getDeviceCode, waterCodes)
|
|
|
+ .eq(AlarmData::getAlarmStatus, 0)
|
|
|
+ .orderByDesc(AlarmData::getAlarmTime));
|
|
|
+ return convertToVoList(alarms);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Page<WaterAlarmOutDTO> getHistoryAlarmPage(long pageNum, long pageSize,
|
|
|
+ String deviceCode, String warningType,
|
|
|
+ Integer alarmLevel, Integer alarmStatus,
|
|
|
+ LocalDateTime startTime, LocalDateTime endTime,
|
|
|
+ String keyword) {
|
|
|
+ Page<AlarmData> page = new Page<>(pageNum, pageSize);
|
|
|
+ Set<String> waterCodes = resolveWaterDeviceCodes();
|
|
|
+ LambdaQueryWrapper<AlarmData> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ if (!waterCodes.isEmpty()) {
|
|
|
+ wrapper.in(AlarmData::getDeviceCode, waterCodes);
|
|
|
+ } else {
|
|
|
+ wrapper.eq(AlarmData::getId, "-1");
|
|
|
+ }
|
|
|
+ wrapper.eq(StrUtil.isNotBlank(deviceCode), AlarmData::getDeviceCode, deviceCode)
|
|
|
+ .like(StrUtil.isNotBlank(warningType), AlarmData::getWarningType, warningType)
|
|
|
+ .eq(alarmLevel != null, AlarmData::getAlarmLevel, alarmLevel)
|
|
|
+ .eq(alarmStatus != null, AlarmData::getAlarmStatus, alarmStatus)
|
|
|
+ .ge(startTime != null, AlarmData::getAlarmTime, startTime)
|
|
|
+ .le(endTime != null, AlarmData::getAlarmTime, endTime)
|
|
|
+ .and(StrUtil.isNotBlank(keyword), w -> w.like(AlarmData::getDeviceCode, keyword)
|
|
|
+ .or().like(AlarmData::getWarningType, keyword)
|
|
|
+ .or().like(AlarmData::getWarningCode, keyword))
|
|
|
+ .orderByDesc(AlarmData::getAlarmTime);
|
|
|
+ Page<AlarmData> result = alarmDataService.page(page, wrapper);
|
|
|
+ Page<WaterAlarmOutDTO> outPage = new Page<>(pageNum, pageSize, result.getTotal());
|
|
|
+ outPage.setRecords(convertToVoList(result.getRecords()));
|
|
|
+ return outPage;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public WaterAlarmOutDTO getAlarmDetail(String alarmId) {
|
|
|
+ AlarmData alarm = alarmDataService.getById(alarmId);
|
|
|
+ if (alarm == null) {
|
|
|
+ throw new ServiceException("报警信息不存在");
|
|
|
+ }
|
|
|
+ List<WaterAlarmOutDTO> vos = convertToVoList(Collections.singletonList(alarm));
|
|
|
+ return vos.isEmpty() ? null : vos.get(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 报警记录 -> 出参(填充设备名称/位置/经纬度及关联工单)
|
|
|
+ */
|
|
|
+ private List<WaterAlarmOutDTO> convertToVoList(List<AlarmData> alarms) {
|
|
|
+ if (CollUtil.isEmpty(alarms)) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+ Map<String, EquipmentBase> eqMap = loadEquipmentCodeMap();
|
|
|
+ List<String> alarmIds = alarms.stream().map(AlarmData::getId).collect(Collectors.toList());
|
|
|
+ Map<String, WorkOrder> orderMap = loadWorkOrderMapByAlarmIds(alarmIds);
|
|
|
+ List<WaterAlarmOutDTO> vos = new ArrayList<>();
|
|
|
+ for (AlarmData alarm : alarms) {
|
|
|
+ WaterAlarmOutDTO vo = BeanUtil.copyProperties(alarm, WaterAlarmOutDTO.class);
|
|
|
+ EquipmentBase eq = alarm.getDeviceCode() == null ? null : eqMap.get(alarm.getDeviceCode());
|
|
|
+ if (eq != null) {
|
|
|
+ vo.setEquipmentId(eq.getEquipmentId());
|
|
|
+ if (StrUtil.isBlank(vo.getDeviceName())) {
|
|
|
+ vo.setDeviceName(eq.getEquipmentName());
|
|
|
+ }
|
|
|
+ vo.setEquipmentLocation(eq.getEquipmentLocation());
|
|
|
+ if (eq.getLongitude() != null) {
|
|
|
+ vo.setLongitude(eq.getLongitude().toPlainString());
|
|
|
+ }
|
|
|
+ if (eq.getLatitude() != null) {
|
|
|
+ vo.setLatitude(eq.getLatitude().toPlainString());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ vo.setAlarmLevelText(formatAlarmLevel(alarm.getAlarmLevel()));
|
|
|
+ vo.setAlarmStatusText(alarm.getAlarmStatus() != null && alarm.getAlarmStatus() == 0 ? "待处理" : "已处理");
|
|
|
+ WorkOrder order = alarm.getId() == null ? null : orderMap.get(alarm.getId());
|
|
|
+ if (order != null) {
|
|
|
+ vo.setOrderNo(order.getOrderNo());
|
|
|
+ vo.setOrderStatus(order.getOrderStatus());
|
|
|
+ }
|
|
|
+ vos.add(vo);
|
|
|
+ }
|
|
|
+ return vos;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String formatAlarmLevel(Integer alarmLevel) {
|
|
|
+ if (alarmLevel == null) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ switch (alarmLevel) {
|
|
|
+ case 1:
|
|
|
+ return "一级报警";
|
|
|
+ case 2:
|
|
|
+ return "二级报警";
|
|
|
+ case 3:
|
|
|
+ return "三级报警";
|
|
|
+ case 4:
|
|
|
+ return "四级报警";
|
|
|
+ default:
|
|
|
+ return "报警";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------
|
|
|
+ // 处理 / 派发工单
|
|
|
+ // ------------------------------------------------------------------
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean resolveAlarm(String alarmId, String handleRemark) {
|
|
|
+ AlarmData alarm = alarmDataService.getById(alarmId);
|
|
|
+ if (alarm == null) {
|
|
|
+ throw new ServiceException("报警信息不存在");
|
|
|
+ }
|
|
|
+ alarm.setAlarmStatus(1);
|
|
|
+ alarm.setHandleTime(LocalDateTime.now());
|
|
|
+ alarm.setHandleUser(currentUserName());
|
|
|
+ alarm.setHandleRemark(StrUtil.blankToDefault(handleRemark, "标记已处理"));
|
|
|
+ alarm.setUpdateTime(LocalDateTime.now());
|
|
|
+ return alarmDataService.updateById(alarm);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public boolean dispatchToWorkOrder(AlarmDispatchInDTO inDTO) {
|
|
|
+ if (inDTO == null || StrUtil.isBlank(inDTO.getAlarmId())) {
|
|
|
+ throw new ServiceException("报警ID不能为空");
|
|
|
+ }
|
|
|
+ AlarmData alarm = alarmDataService.getById(inDTO.getAlarmId());
|
|
|
+ if (alarm == null) {
|
|
|
+ throw new ServiceException("报警信息不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设备信息(用于回填 deviceId/deviceCode)
|
|
|
+ EquipmentBase equipment = alarm.getDeviceCode() == null ? null
|
|
|
+ : equipmentBaseMapper.selectOne(new LambdaQueryWrapper<EquipmentBase>()
|
|
|
+ .eq(EquipmentBase::getEquipmentCode, alarm.getDeviceCode())
|
|
|
+ .last("LIMIT 1"));
|
|
|
+
|
|
|
+ WorkOrder workOrder = new WorkOrder();
|
|
|
+ workOrder.setOrderNo(generateOrderNo());
|
|
|
+ workOrder.setAlarmId(alarm.getId());
|
|
|
+ workOrder.setDeviceId(equipment != null ? equipment.getEquipmentId() : alarm.getDeviceCode());
|
|
|
+ workOrder.setDeviceCode(alarm.getDeviceCode());
|
|
|
+ workOrder.setOrderType(inDTO.getOrderType() == null ? 1 : inDTO.getOrderType());
|
|
|
+ workOrder.setOrderLevel(inDTO.getOrderLevel() == null
|
|
|
+ ? mapAlarmLevelToOrderLevel(alarm.getAlarmLevel()) : inDTO.getOrderLevel());
|
|
|
+ workOrder.setOrderDesc(StrUtil.isNotBlank(inDTO.getOrderDesc()) ? inDTO.getOrderDesc()
|
|
|
+ : buildDefaultOrderDesc(alarm));
|
|
|
+ workOrder.setDeptId(inDTO.getDeptId());
|
|
|
+ workOrder.setPlanFinishTime(inDTO.getPlanFinishTime());
|
|
|
+ workOrder.setOrderStatus(1); // 1-待派单
|
|
|
+ workOrder.setCreateTime(new java.util.Date());
|
|
|
+ workOrder.setUpdateTime(new java.util.Date());
|
|
|
+ workOrderMapper.insert(workOrder);
|
|
|
+
|
|
|
+ // 写工单操作日志(1-创建工单)
|
|
|
+ WorkOrderLog workOrderLog = new WorkOrderLog();
|
|
|
+ workOrderLog.setOrderId(workOrder.getOrderId());
|
|
|
+ workOrderLog.setOperType(1);
|
|
|
+ workOrderLog.setOperDesc("由供水监测报警[" + alarm.getWarningType() + "]派发工单:" + workOrder.getOrderNo());
|
|
|
+ workOrderLog.setOperUserId(currentUserId());
|
|
|
+ workOrderLog.setOperUserName(currentUserName());
|
|
|
+ workOrderLog.setOperTime(new java.util.Date());
|
|
|
+ workOrderLogMapper.insert(workOrderLog);
|
|
|
+
|
|
|
+ // 回写报警处理信息
|
|
|
+ alarm.setAlarmStatus(1);
|
|
|
+ alarm.setHandleTime(LocalDateTime.now());
|
|
|
+ alarm.setHandleUser(currentUserName());
|
|
|
+ alarm.setHandleRemark("已派发工单:" + workOrder.getOrderNo());
|
|
|
+ alarm.setUpdateTime(LocalDateTime.now());
|
|
|
+ alarmDataService.updateById(alarm);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 报警等级 -> 工单优先级:1级→紧急,2/3级→一般,4级→低
|
|
|
+ */
|
|
|
+ private Integer mapAlarmLevelToOrderLevel(Integer alarmLevel) {
|
|
|
+ if (alarmLevel == null || alarmLevel == 1) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ if (alarmLevel == 4) {
|
|
|
+ return 3;
|
|
|
+ }
|
|
|
+ return 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String buildDefaultOrderDesc(AlarmData alarm) {
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ sb.append(StrUtil.blankToDefault(alarm.getWarningType(), "监测报警"));
|
|
|
+ sb.append(",当前值:").append(alarm.getActualValue() == null ? "-" : alarm.getActualValue().toPlainString());
|
|
|
+ if (alarm.getMinValue() != null || alarm.getMaxValue() != null) {
|
|
|
+ sb.append(",阈值范围:").append(alarm.getMinValue() == null ? "-" : alarm.getMinValue().toPlainString())
|
|
|
+ .append("~").append(alarm.getMaxValue() == null ? "-" : alarm.getMaxValue().toPlainString());
|
|
|
+ }
|
|
|
+ sb.append(",请及时现场核实处理");
|
|
|
+ return sb.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成工单编号:WO + yyyyMMddHHmmss + 4位随机数
|
|
|
+ */
|
|
|
+ private String generateOrderNo() {
|
|
|
+ return "WO" + LocalDateTime.now().format(ORDER_NO_FMT)
|
|
|
+ + String.format("%04d", new Random().nextInt(10000));
|
|
|
+ }
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------
|
|
|
+ // 报警审核 / 全流程跟踪
|
|
|
+ // ------------------------------------------------------------------
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public AlarmAuditOutDTO auditAlarm(AlarmAuditInDTO inDTO) {
|
|
|
+ if (inDTO == null || StrUtil.isBlank(inDTO.getAlarmId())) {
|
|
|
+ throw new ServiceException("报警ID不能为空");
|
|
|
+ }
|
|
|
+ if (inDTO.getAuditAction() == null) {
|
|
|
+ throw new ServiceException("审核动作不能为空");
|
|
|
+ }
|
|
|
+ if (inDTO.getAuditResult() == null) {
|
|
|
+ throw new ServiceException("审核结果不能为空");
|
|
|
+ }
|
|
|
+ AlarmData alarm = alarmDataService.getById(inDTO.getAlarmId());
|
|
|
+ if (alarm == null) {
|
|
|
+ throw new ServiceException("报警信息不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ AlarmAudit audit = new AlarmAudit();
|
|
|
+ audit.setAlarmId(inDTO.getAlarmId());
|
|
|
+ audit.setAuditAction(inDTO.getAuditAction());
|
|
|
+ audit.setAuditResult(inDTO.getAuditResult());
|
|
|
+ audit.setAuditOpinion(inDTO.getAuditOpinion());
|
|
|
+ audit.setAttachUrl(inDTO.getAttachUrl());
|
|
|
+ audit.setAuditUserId(currentUserId());
|
|
|
+ audit.setAuditUserName(currentUserName());
|
|
|
+ audit.setAuditTime(LocalDateTime.now());
|
|
|
+ audit.setCreateTime(LocalDateTime.now());
|
|
|
+ audit.setUpdateTime(LocalDateTime.now());
|
|
|
+ alarmAuditMapper.insert(audit);
|
|
|
+
|
|
|
+ // 审核结果=误报 或 动作=解除 时,直接关闭报警
|
|
|
+ boolean releaseAlarm = inDTO.getAuditResult() == 2 || inDTO.getAuditAction() == 2;
|
|
|
+ if (releaseAlarm) {
|
|
|
+ alarm.setAlarmStatus(1);
|
|
|
+ alarm.setHandleTime(LocalDateTime.now());
|
|
|
+ alarm.setHandleUser(audit.getAuditUserName());
|
|
|
+ alarm.setHandleRemark("误报解除:" + StrUtil.blankToDefault(inDTO.getAuditOpinion(), "经审核确认为误报"));
|
|
|
+ alarm.setUpdateTime(LocalDateTime.now());
|
|
|
+ alarmDataService.updateById(alarm);
|
|
|
+ }
|
|
|
+ return toAuditOutDTO(audit);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<AlarmAuditOutDTO> getAuditList(String alarmId) {
|
|
|
+ List<AlarmAudit> audits = alarmAuditMapper.selectList(new LambdaQueryWrapper<AlarmAudit>()
|
|
|
+ .eq(AlarmAudit::getAlarmId, alarmId)
|
|
|
+ .orderByDesc(AlarmAudit::getAuditTime));
|
|
|
+ return audits.stream().map(this::toAuditOutDTO).collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public AlarmFlowOutDTO getAlarmFlow(String alarmId) {
|
|
|
+ AlarmFlowOutDTO flow = new AlarmFlowOutDTO();
|
|
|
+ flow.setAlarm(getAlarmDetail(alarmId));
|
|
|
+ flow.setAuditList(getAuditList(alarmId));
|
|
|
+ WorkOrder order = workOrderMapper.selectOne(new LambdaQueryWrapper<WorkOrder>()
|
|
|
+ .eq(WorkOrder::getAlarmId, alarmId)
|
|
|
+ .orderByDesc(WorkOrder::getOrderId)
|
|
|
+ .last("LIMIT 1"));
|
|
|
+ flow.setWorkOrder(order);
|
|
|
+ if (order != null) {
|
|
|
+ flow.setWorkOrderLogList(workOrderLogMapper.selectList(new LambdaQueryWrapper<WorkOrderLog>()
|
|
|
+ .eq(WorkOrderLog::getOrderId, order.getOrderId())
|
|
|
+ .orderByAsc(WorkOrderLog::getOperTime)));
|
|
|
+ }
|
|
|
+ return flow;
|
|
|
+ }
|
|
|
+
|
|
|
+ private AlarmAuditOutDTO toAuditOutDTO(AlarmAudit audit) {
|
|
|
+ AlarmAuditOutDTO vo = BeanUtil.copyProperties(audit, AlarmAuditOutDTO.class);
|
|
|
+ vo.setAuditActionText(audit.getAuditAction() != null && audit.getAuditAction() == 2 ? "解除" : "审核");
|
|
|
+ vo.setAuditResultText(audit.getAuditResult() != null && audit.getAuditResult() == 2 ? "误报" : "属实");
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------
|
|
|
+ // 监测报警一张图
|
|
|
+ // ------------------------------------------------------------------
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<AlarmMapPointOutDTO> getAlarmMapPoints() {
|
|
|
+ Set<String> waterCodes = resolveWaterDeviceCodes();
|
|
|
+ if (waterCodes.isEmpty()) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+ List<AlarmData> pendingAlarms = alarmDataService.list(new LambdaQueryWrapper<AlarmData>()
|
|
|
+ .in(AlarmData::getDeviceCode, waterCodes)
|
|
|
+ .eq(AlarmData::getAlarmStatus, 0)
|
|
|
+ .orderByDesc(AlarmData::getAlarmTime));
|
|
|
+ Map<String, EquipmentBase> eqMap = loadEquipmentCodeMap();
|
|
|
+ // 同一设备只展示最新一条未处理报警
|
|
|
+ Map<String, AlarmData> latestPerDevice = new LinkedHashMap<>();
|
|
|
+ for (AlarmData alarm : pendingAlarms) {
|
|
|
+ latestPerDevice.putIfAbsent(alarm.getDeviceCode(), alarm);
|
|
|
+ }
|
|
|
+ List<AlarmMapPointOutDTO> points = new ArrayList<>();
|
|
|
+ for (AlarmData alarm : latestPerDevice.values()) {
|
|
|
+ EquipmentBase eq = alarm.getDeviceCode() == null ? null : eqMap.get(alarm.getDeviceCode());
|
|
|
+ if (eq == null || eq.getLongitude() == null || eq.getLatitude() == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ AlarmMapPointOutDTO point = new AlarmMapPointOutDTO();
|
|
|
+ point.setAlarmId(alarm.getId());
|
|
|
+ point.setDeviceCode(alarm.getDeviceCode());
|
|
|
+ point.setDeviceName(eq.getEquipmentName());
|
|
|
+ point.setEquipmentLocation(eq.getEquipmentLocation());
|
|
|
+ point.setLongitude(eq.getLongitude().toPlainString());
|
|
|
+ point.setLatitude(eq.getLatitude().toPlainString());
|
|
|
+ point.setWarningType(alarm.getWarningType());
|
|
|
+ point.setActualValue(alarm.getActualValue());
|
|
|
+ point.setAlarmLevel(alarm.getAlarmLevel());
|
|
|
+ point.setAlarmLevelText(formatAlarmLevel(alarm.getAlarmLevel()));
|
|
|
+ point.setAlarmTime(alarm.getAlarmTime());
|
|
|
+ points.add(point);
|
|
|
+ }
|
|
|
+ points.sort(Comparator.comparing(AlarmMapPointOutDTO::getAlarmLevel, Comparator.nullsLast(Comparator.naturalOrder())));
|
|
|
+ return points;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------
|
|
|
+ // 当前用户
|
|
|
+ // ------------------------------------------------------------------
|
|
|
+
|
|
|
+ private Long currentUserId() {
|
|
|
+ LoginUser loginUser = SecurityUtils.getLoginUser();
|
|
|
+ return loginUser != null ? loginUser.getUserId() : null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String currentUserName() {
|
|
|
+ LoginUser loginUser = SecurityUtils.getLoginUser();
|
|
|
+ if (loginUser == null) {
|
|
|
+ return "系统";
|
|
|
+ }
|
|
|
+ if (loginUser.getUser() != null && StrUtil.isNotBlank(loginUser.getUser().getNickName())) {
|
|
|
+ return loginUser.getUser().getNickName();
|
|
|
+ }
|
|
|
+ return loginUser.getUsername();
|
|
|
+ }
|
|
|
+}
|