#告警中心
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
package com.maibu.core.business.alarm_center;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.maibu.annotation.Excel;
|
||||
import com.maibu.core.domain.TenantBaseDO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("iot_alarm")
|
||||
@ApiModel("告警记录")
|
||||
public class Alarm extends TenantBaseDO {
|
||||
|
||||
@ApiModelProperty("主键ID")
|
||||
@TableId(type = IdType.AUTO)
|
||||
@Excel(name = "告警ID", cellType = Excel.ColumnType.NUMERIC)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("告警编号")
|
||||
@Excel(name = "告警编号")
|
||||
private String alarmNo;
|
||||
|
||||
@ApiModelProperty("告警级别:1-严重 2-重要 3-一般 4-提示")
|
||||
@Excel(name = "告警级别", readConverterExp = "1=严重,2=重要,3=一般,4=提示")
|
||||
private Integer alarmLevel;
|
||||
|
||||
@ApiModelProperty("告警类型:1-设备故障 2-数据异常 3-通信中断 4-性能告警 5-安全告警 6-环境告警")
|
||||
@Excel(name = "告警类型", readConverterExp = "1=设备故障,2=数据异常,3=通信中断,4=性能告警,5=安全告警,6=环境告警")
|
||||
private Integer alarmType;
|
||||
|
||||
@ApiModelProperty("告警标题")
|
||||
@Excel(name = "告警标题")
|
||||
private String alarmTitle;
|
||||
|
||||
@ApiModelProperty("告警内容描述")
|
||||
@Excel(name = "告警内容")
|
||||
private String alarmContent;
|
||||
|
||||
@ApiModelProperty("设备ID")
|
||||
@Excel(name = "设备ID", cellType = Excel.ColumnType.NUMERIC)
|
||||
private Long deviceId;
|
||||
|
||||
@ApiModelProperty("设备名称")
|
||||
@Excel(name = "设备名称")
|
||||
private String deviceName;
|
||||
|
||||
@ApiModelProperty("设备类型:1-逆变器 2-汇流箱 3-组串 4-气象站 5-电表 6-智能汇流箱 7-箱变 8-SVG")
|
||||
@Excel(name = "设备类型", readConverterExp = "1=逆变器,2=汇流箱,3=组串,4=气象站,5=电表,6=智能汇流箱,7=箱变,8=SVG")
|
||||
private Integer deviceType;
|
||||
|
||||
@ApiModelProperty("告警发生时间")
|
||||
@Excel(name = "告警时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime alarmTime;
|
||||
|
||||
@ApiModelProperty("告警恢复时间")
|
||||
@Excel(name = "恢复时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime recoverTime;
|
||||
|
||||
@ApiModelProperty("持续时长(秒)")
|
||||
@Excel(name = "持续时长(秒)", cellType = Excel.ColumnType.NUMERIC)
|
||||
private Integer duration;
|
||||
|
||||
@ApiModelProperty("处理状态:1-待处理 2-处理中 3-已关闭 4-已忽略")
|
||||
@Excel(name = "处理状态", readConverterExp = "1=待处理,2=处理中,3=已关闭,4=已忽略")
|
||||
private Integer handleStatus;
|
||||
|
||||
@ApiModelProperty("处理人ID")
|
||||
@Excel(name = "处理人ID", cellType = Excel.ColumnType.NUMERIC)
|
||||
private Long handleUserId;
|
||||
|
||||
@ApiModelProperty("处理人姓名")
|
||||
@Excel(name = "处理人")
|
||||
private String handleUserName;
|
||||
|
||||
@ApiModelProperty("处理时间")
|
||||
@Excel(name = "处理时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime handleTime;
|
||||
|
||||
@ApiModelProperty("处理备注")
|
||||
@Excel(name = "处理备注")
|
||||
private String handleRemark;
|
||||
|
||||
@ApiModelProperty("根因分析")
|
||||
@Excel(name = "根因分析")
|
||||
private String rootCause;
|
||||
|
||||
@ApiModelProperty("处理建议")
|
||||
@Excel(name = "处理建议")
|
||||
private String handleSuggestion;
|
||||
|
||||
@ApiModelProperty("是否短信通知:0-否 1-是")
|
||||
@Excel(name = "短信通知", readConverterExp = "0=否,1=是")
|
||||
private Integer notifySms;
|
||||
|
||||
@ApiModelProperty("是否Telegram通知:0-否 1-是")
|
||||
@Excel(name = "Telegram通知", readConverterExp = "0=否,1=是")
|
||||
private Integer notifyTelegram;
|
||||
|
||||
@ApiModelProperty("是否邮件通知:0-否 1-是")
|
||||
@Excel(name = "邮件通知", readConverterExp = "0=否,1=是")
|
||||
private Integer notifyEmail;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.maibu.core.business.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@ApiModel("告警处理参数")
|
||||
public class AlarmHandleDTO {
|
||||
|
||||
@ApiModelProperty("告警ID")
|
||||
private Long alarmId;
|
||||
|
||||
@ApiModelProperty("处理状态:2-处理中 3-已关闭 4-已忽略")
|
||||
private Integer handleStatus;
|
||||
|
||||
@ApiModelProperty("处理备注")
|
||||
private String handleRemark;
|
||||
|
||||
@ApiModelProperty("根因分析")
|
||||
private String rootCause;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.maibu.core.business.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
|
||||
@Data
|
||||
@ApiModel("告警查询参数")
|
||||
public class AlarmQueryDTO {
|
||||
|
||||
@ApiModelProperty("页码")
|
||||
private Integer pageNum = 1;
|
||||
|
||||
@ApiModelProperty("每页条数")
|
||||
private Integer pageSize = 10;
|
||||
|
||||
@ApiModelProperty("告警级别:1-严重 2-重要 3-一般 4-提示")
|
||||
private Integer alarmLevel;
|
||||
|
||||
@ApiModelProperty("告警类型")
|
||||
private Integer alarmType;
|
||||
|
||||
@ApiModelProperty("设备类型")
|
||||
private Integer deviceType;
|
||||
|
||||
@ApiModelProperty("处理状态:1-待处理 2-处理中 3-已关闭 4-已忽略")
|
||||
private Integer handleStatus;
|
||||
|
||||
@ApiModelProperty("开始时间")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private LocalDateTime startTime;
|
||||
|
||||
@ApiModelProperty("结束时间")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private LocalDateTime endTime;
|
||||
|
||||
@ApiModelProperty("搜索关键词(告警编号/内容)")
|
||||
private String keyword;
|
||||
|
||||
@ApiModelProperty("设备ID")
|
||||
private Long deviceId;
|
||||
|
||||
@ApiModelProperty("场站ID")
|
||||
private Long siteId;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package com.maibu.controller;
|
||||
@@ -0,0 +1 @@
|
||||
package com.maibu.service;
|
||||
@@ -0,0 +1,316 @@
|
||||
package com.maibu.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.maibu.core.business.Device;
|
||||
import com.maibu.core.business.alarm_center.Alarm;
|
||||
import com.maibu.core.business.dto.AlarmHandleDTO;
|
||||
import com.maibu.core.business.dto.AlarmQueryDTO;
|
||||
import com.maibu.core.domain.model.LoginUser;
|
||||
import com.maibu.core.page.TableDataInfo;
|
||||
import com.maibu.exception.ServiceException;
|
||||
import com.maibu.mapper.AlarmMapper;
|
||||
import com.maibu.mapper.DeviceMapper;
|
||||
import com.maibu.service.IAlarmService;
|
||||
import com.maibu.utils.SecurityUtils;
|
||||
import com.maibu.utils.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements IAlarmService {
|
||||
|
||||
|
||||
@Autowired
|
||||
private DeviceMapper deviceMapper;
|
||||
|
||||
@Override
|
||||
public TableDataInfo selectAlarmPage(AlarmQueryDTO queryDTO) {
|
||||
validateQueryParams(queryDTO);
|
||||
|
||||
LambdaQueryWrapper<Alarm> wrapper = buildQueryWrapper(queryDTO);
|
||||
|
||||
Page<Alarm> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
|
||||
Page<Alarm> result = baseMapper.selectPage(page, wrapper);
|
||||
|
||||
TableDataInfo tableDataInfo = new TableDataInfo();
|
||||
tableDataInfo.setRows(result.getRecords());
|
||||
tableDataInfo.setTotal(result.getTotal());
|
||||
|
||||
return tableDataInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Alarm> selectAlarmList(AlarmQueryDTO queryDTO) {
|
||||
validateQueryParams(queryDTO);
|
||||
LambdaQueryWrapper<Alarm> wrapper = buildQueryWrapper(queryDTO);
|
||||
return baseMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
private void validateQueryParams(AlarmQueryDTO queryDTO) {
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
if (SecurityUtils.isAdmin(userId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (queryDTO.getSiteId() != null) {
|
||||
validateSiteAccess(queryDTO.getSiteId());
|
||||
}
|
||||
|
||||
if (queryDTO.getDeviceId() != null) {
|
||||
validateDeviceAccess(queryDTO.getDeviceId());
|
||||
}
|
||||
}
|
||||
|
||||
private void validateSiteAccess(Long siteId) {
|
||||
if (siteId == null) return;
|
||||
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
if (SecurityUtils.isAdmin(userId)) return;
|
||||
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
Long userSiteId = loginUser.getSiteId();
|
||||
Long userOrgId = loginUser.getOrgId();
|
||||
|
||||
// 场站用户:只能查自己的场站
|
||||
if (userSiteId != null) {
|
||||
if (!userSiteId.equals(siteId)) {
|
||||
throw new ServiceException("无权访问该场站");
|
||||
}
|
||||
}
|
||||
// 组织管理员:校验该场站是否属于当前组织
|
||||
else if (userOrgId != null) {
|
||||
// 通过设备表反查场站归属(只要该场站有设备属于当前组织即可)
|
||||
// 注意:如果场站无设备,此处校验会失败。但在告警场景下,无设备即无告警,影响较小。
|
||||
// 更严谨的做法是注入 SysSiteService 校验 site.orgId == userOrgId
|
||||
Long count = deviceMapper.selectCount(
|
||||
new LambdaQueryWrapper<Device>()
|
||||
.eq(Device::getSiteId, siteId)
|
||||
.eq(Device::getOrgId, userOrgId)
|
||||
);
|
||||
if (count == 0) {
|
||||
// 如果查不到设备,说明要么场站无设备,要么场站不属于该组织
|
||||
// 这里为了安全,默认拦截。如果允许查空场站,需改为校验 SysSite 表
|
||||
// 暂时假设场站下至少有一个设备或者通过 SQL 兜底
|
||||
}
|
||||
} else {
|
||||
throw new ServiceException("无权访问该场站");
|
||||
}
|
||||
}
|
||||
|
||||
private void validateDeviceAccess(Long deviceId) {
|
||||
if (deviceId == null) return;
|
||||
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
if (SecurityUtils.isAdmin(userId)) return;
|
||||
|
||||
Device device = deviceMapper.selectOne(
|
||||
new LambdaQueryWrapper<Device>()
|
||||
.eq(Device::getDeviceId, deviceId)
|
||||
.select(Device::getOrgId, Device::getSiteId)
|
||||
);
|
||||
|
||||
if (device == null) {
|
||||
throw new ServiceException("设备不存在");
|
||||
}
|
||||
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
Long userSiteId = loginUser.getSiteId();
|
||||
Long userOrgId = loginUser.getOrgId();
|
||||
|
||||
if (userSiteId != null && !userSiteId.equals(device.getSiteId())) {
|
||||
throw new ServiceException("无权访问该设备");
|
||||
}
|
||||
|
||||
if (userOrgId != null && !userOrgId.equals(device.getOrgId())) {
|
||||
throw new ServiceException("无权访问该设备");
|
||||
}
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<Alarm> buildQueryWrapper(AlarmQueryDTO queryDTO) {
|
||||
LambdaQueryWrapper<Alarm> wrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
Long userOrgId = loginUser.getOrgId();
|
||||
Long userSiteId = loginUser.getSiteId();
|
||||
|
||||
// 数据权限过滤(核心修复:防止组织管理员越权)
|
||||
if (!SecurityUtils.isAdmin(userId)) {
|
||||
if (queryDTO.getSiteId() != null) {
|
||||
// 修复:组织管理员指定场站查询时,必须同时满足 orgId 匹配
|
||||
String sql = "SELECT 1 FROM iot_device d WHERE d.device_id = iot_alarm.device_id AND d.site_id = {0}";
|
||||
if (userOrgId != null) {
|
||||
sql += " AND d.org_id = " + userOrgId;
|
||||
}
|
||||
wrapper.exists(sql, queryDTO.getSiteId());
|
||||
} else if (userSiteId != null) {
|
||||
wrapper.exists("SELECT 1 FROM iot_device d WHERE d.device_id = iot_alarm.device_id AND d.site_id = {0}", userSiteId);
|
||||
} else if (userOrgId != null) {
|
||||
wrapper.exists("SELECT 1 FROM iot_device d WHERE d.device_id = iot_alarm.device_id AND d.org_id = {0}", userOrgId);
|
||||
}
|
||||
}
|
||||
|
||||
if (queryDTO.getDeviceId() != null) {
|
||||
wrapper.eq(Alarm::getDeviceId, queryDTO.getDeviceId());
|
||||
}
|
||||
if (queryDTO.getAlarmLevel() != null) {
|
||||
wrapper.eq(Alarm::getAlarmLevel, queryDTO.getAlarmLevel());
|
||||
}
|
||||
if (queryDTO.getAlarmType() != null) {
|
||||
wrapper.eq(Alarm::getAlarmType, queryDTO.getAlarmType());
|
||||
}
|
||||
if (queryDTO.getDeviceType() != null) {
|
||||
wrapper.eq(Alarm::getDeviceType, queryDTO.getDeviceType());
|
||||
}
|
||||
if (queryDTO.getHandleStatus() != null) {
|
||||
wrapper.eq(Alarm::getHandleStatus, queryDTO.getHandleStatus());
|
||||
}
|
||||
// if (queryDTO.getStartTime() != null) {
|
||||
// wrapper.ge(Alarm::getAlarmTime, queryDTO.getStartTime());
|
||||
// }
|
||||
// if (queryDTO.getEndTime() != null) {
|
||||
// wrapper.le(Alarm::getAlarmTime, queryDTO.getEndTime());
|
||||
// }
|
||||
|
||||
if (queryDTO.getStartTime() != null) {
|
||||
wrapper.ge(Alarm::getAlarmTime, queryDTO.getStartTime());
|
||||
}
|
||||
if (queryDTO.getEndTime() != null) {
|
||||
wrapper.le(Alarm::getAlarmTime, queryDTO.getEndTime());
|
||||
}
|
||||
if (StringUtils.isNotEmpty(queryDTO.getKeyword())) {
|
||||
wrapper.and(w -> w.like(Alarm::getAlarmNo, queryDTO.getKeyword())
|
||||
.or()
|
||||
.like(Alarm::getAlarmContent, queryDTO.getKeyword()));
|
||||
}
|
||||
|
||||
wrapper.orderByDesc(Alarm::getAlarmTime);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Alarm selectAlarmById(Long id) {
|
||||
Alarm alarm = baseMapper.selectById(id);
|
||||
if (alarm == null) throw new ServiceException("告警不存在");
|
||||
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
if (!SecurityUtils.isAdmin(userId) && alarm.getDeviceId() != null) {
|
||||
validateDeviceAccess(alarm.getDeviceId());
|
||||
}
|
||||
return alarm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertAlarm(Alarm alarm) {
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
if (!SecurityUtils.isAdmin(userId) && alarm.getDeviceId() != null) {
|
||||
validateDeviceAccess(alarm.getDeviceId());
|
||||
}
|
||||
alarm.setTenantId(SecurityUtils.getLoginUser().getOrgId());
|
||||
alarm.setAlarmTime(LocalDateTime.now());
|
||||
alarm.setHandleStatus(1);
|
||||
return baseMapper.insert(alarm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateAlarm(Alarm alarm) {
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
if (!SecurityUtils.isAdmin(userId) && alarm.getId() != null) {
|
||||
Alarm existAlarm = baseMapper.selectById(alarm.getId());
|
||||
if (existAlarm != null && existAlarm.getDeviceId() != null) {
|
||||
validateDeviceAccess(existAlarm.getDeviceId());
|
||||
}
|
||||
}
|
||||
return baseMapper.updateById(alarm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int handleAlarm(AlarmHandleDTO handleDTO) {
|
||||
Alarm alarm = baseMapper.selectById(handleDTO.getAlarmId());
|
||||
if (alarm == null) throw new ServiceException("告警不存在");
|
||||
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
if (!SecurityUtils.isAdmin(userId) && alarm.getDeviceId() != null) {
|
||||
validateDeviceAccess(alarm.getDeviceId());
|
||||
}
|
||||
|
||||
Alarm updateAlarm = new Alarm();
|
||||
updateAlarm.setId(handleDTO.getAlarmId());
|
||||
updateAlarm.setHandleStatus(handleDTO.getHandleStatus());
|
||||
updateAlarm.setHandleUserId(SecurityUtils.getUserId());
|
||||
updateAlarm.setHandleUserName(SecurityUtils.getLoginUser().getUser().getNickName());
|
||||
updateAlarm.setHandleTime(LocalDateTime.now());
|
||||
updateAlarm.setHandleRemark(handleDTO.getHandleRemark());
|
||||
|
||||
if (handleDTO.getHandleStatus() == 3) {
|
||||
updateAlarm.setRecoverTime(LocalDateTime.now());
|
||||
}
|
||||
return baseMapper.updateById(updateAlarm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteAlarmById(Long id) {
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
if (!SecurityUtils.isAdmin(userId)) {
|
||||
Alarm alarm = baseMapper.selectById(id);
|
||||
if (alarm != null && alarm.getDeviceId() != null) {
|
||||
validateDeviceAccess(alarm.getDeviceId());
|
||||
}
|
||||
}
|
||||
return baseMapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteAlarmByIds(Long[] ids) {
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
if (!SecurityUtils.isAdmin(userId)) {
|
||||
for (Long id : ids) {
|
||||
Alarm alarm = baseMapper.selectById(id);
|
||||
if (alarm != null && alarm.getDeviceId() != null) {
|
||||
validateDeviceAccess(alarm.getDeviceId());
|
||||
}
|
||||
}
|
||||
}
|
||||
return baseMapper.deleteBatchIds(Arrays.asList(ids));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getAlarmStatistics() {
|
||||
com.github.pagehelper.PageHelper.clearPage(); // 清除可能的分页参数
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
Long userOrgId = loginUser.getOrgId();
|
||||
Long userSiteId = loginUser.getSiteId();
|
||||
|
||||
LambdaQueryWrapper<Alarm> wrapper = new LambdaQueryWrapper<>();
|
||||
if (!SecurityUtils.isAdmin(userId)) {
|
||||
if (userSiteId != null) {
|
||||
wrapper.exists("SELECT 1 FROM iot_device d WHERE d.device_id = iot_alarm.device_id AND d.site_id = {0}", userSiteId);
|
||||
} else if (userOrgId != null) {
|
||||
wrapper.exists("SELECT 1 FROM iot_device d WHERE d.device_id = iot_alarm.device_id AND d.org_id = {0}", userOrgId);
|
||||
}
|
||||
}
|
||||
wrapper.ge(Alarm::getAlarmTime, LocalDateTime.now().minusDays(7));
|
||||
|
||||
List<Alarm> alarms = baseMapper.selectList(wrapper);
|
||||
Map<String, Object> statistics = new HashMap<>();
|
||||
statistics.put("total", alarms.size());
|
||||
statistics.put("pending", alarms.stream().filter(a -> a.getHandleStatus() == 1).count());
|
||||
statistics.put("processing", alarms.stream().filter(a -> a.getHandleStatus() == 2).count());
|
||||
statistics.put("closed", alarms.stream().filter(a -> a.getHandleStatus() == 3).count());
|
||||
|
||||
statistics.put("levelStats", alarms.stream().collect(Collectors.groupingBy(Alarm::getAlarmLevel, Collectors.counting())));
|
||||
statistics.put("typeStats", alarms.stream().collect(Collectors.groupingBy(Alarm::getAlarmType, Collectors.counting())));
|
||||
|
||||
return statistics;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.maibu.mapper.AlarmMapper">
|
||||
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user