refactor(ems): 重构告警措施步骤的图片存储逻辑,新增告警记录与规则BO/VO

1.  重构告警措施步骤的图片存储:移除子表,改用逗号分隔的OSS ID存储图片,服务层自动解析为URL
2.  新增异常数据记录的BO、VO类
3.  新增告警规则的BO、VO类
4.  调整Mapper XML适配新的字段结构与查询逻辑
main
zch 3 weeks ago
parent fa16c6b352
commit 4e9043670f

@ -41,8 +41,17 @@ public class EmsAlarmActionStep extends BaseEntity
//@ExcelProperty(value = "步骤文字描述")
private String description;
/** 步骤关联的图片列表 */
private List<EmsAlarmActionStepImage> stepImages;
/** 备注 */
private String remark;
/**
* OSSID
* imageUrls
*/
private String ossIds;
/** 查询展示用图片完整URL列表不参与数据库写入。 */
private List<String> imageUrls;
public void setObjId(String objId)
{
@ -81,14 +90,24 @@ public class EmsAlarmActionStep extends BaseEntity
return description;
}
public void setStepImages(List<EmsAlarmActionStepImage> stepImages)
public void setOssIds(String ossIds)
{
this.stepImages = stepImages;
this.ossIds = ossIds;
}
public List<EmsAlarmActionStepImage> getStepImages()
public String getOssIds()
{
return stepImages;
return ossIds;
}
public void setImageUrls(List<String> imageUrls)
{
this.imageUrls = imageUrls;
}
public List<String> getImageUrls()
{
return imageUrls;
}
@Override
@ -98,6 +117,7 @@ public class EmsAlarmActionStep extends BaseEntity
.append("ruleObjId", getRuleObjId())
.append("stepSequence", getStepSequence())
.append("description", getDescription())
.append("ossIds", getOssIds())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())

@ -5,20 +5,38 @@ import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.ems.base.domain.EmsAlarmActionStep;
import org.dromara.ems.base.domain.EmsAlarmActionStepImage;
import org.dromara.ems.base.mapper.EmsAlarmActionStepImageMapper;
import org.dromara.ems.base.mapper.EmsAlarmActionStepMapper;
import org.dromara.ems.base.service.IEmsAlarmActionStepService;
import org.springframework.beans.factory.annotation.Value;
import org.dromara.system.domain.vo.SysOssVo;
import org.dromara.system.service.ISysOssService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.File;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Service
* Service
*
* <h3>v2</h3>
* <p>
* {@code POST /resource/oss/upload} {@code ossId}
* {@code ems_alarm_action_step.oss_ids}
* Service {@link ISysOssService#listByIds(List)}
* ossId HTTP URL {@code imageUrls}
* {@link ISysOssService#deleteWithValidByIds(List, boolean)}
* OSS
*
* <h4></h4>
* <ul>
* <li> {@code ems_alarm_action_step_image} </li>
* <li> {@code java.io.File.delete()} OSS </li>
* <li>ossId image_sequence </li>
* </ul>
*
* @author zch
* @date 2025-05-29
@ -30,45 +48,48 @@ public class EmsAlarmActionStepServiceImpl implements IEmsAlarmActionStepService
private final EmsAlarmActionStepMapper emsAlarmActionStepMapper;
private final EmsAlarmActionStepImageMapper emsAlarmActionStepImageMapper;
/**
*
* OSS
* <p>RuoYi-Vue-Plus 5.6.0 OSS {@code OssClient}
* AWS S3 Async MinIO/S3
* {@code java.io.File} 访 {@link ISysOssService}
* API URL
* <p>EMS System
* OSS
*/
@Value("${ruoyi.compat.upload-path:${user.dir}/uploadPath}")
private String uploadPath;
private final ISysOssService sysOssService;
/**
*
*
* @param objId
* @return
* ossIds URL
* <p> Mapper {@code ossIds}
* URL {@link #fillImageUrls(EmsAlarmActionStep)}
* ossId URL ossId
*/
@Override
public EmsAlarmActionStep selectEmsAlarmActionStepByObjId(String objId)
{
return emsAlarmActionStepMapper.selectEmsAlarmActionStepByObjId(objId);
EmsAlarmActionStep step = emsAlarmActionStepMapper.selectEmsAlarmActionStepByObjId(objId);
fillImageUrls(step);
return step;
}
/**
*
*
* @param emsAlarmActionStep
* @return
* URL
* <p> DB ossIds OSS
* OSS
*/
@Override
public List<EmsAlarmActionStep> selectEmsAlarmActionStepList(EmsAlarmActionStep emsAlarmActionStep)
{
return emsAlarmActionStepMapper.selectEmsAlarmActionStepList(emsAlarmActionStep);
List<EmsAlarmActionStep> list = emsAlarmActionStepMapper.selectEmsAlarmActionStepList(emsAlarmActionStep);
fillImageUrls(list);
return list;
}
/**
*
*
* @param emsAlarmActionStep
* @return
*
* <p>{@code ossIds}
*/
@Override
public int insertEmsAlarmActionStep(EmsAlarmActionStep emsAlarmActionStep)
@ -78,10 +99,9 @@ public class EmsAlarmActionStepServiceImpl implements IEmsAlarmActionStepService
}
/**
*
*
* @param emsAlarmActionStep
* @return
* ossIds
* <p>MyBatis XML {@code <if test="ossIds != null">} SQL
*
*/
@Override
public int updateEmsAlarmActionStep(EmsAlarmActionStep emsAlarmActionStep)
@ -90,12 +110,6 @@ public class EmsAlarmActionStepServiceImpl implements IEmsAlarmActionStepService
return emsAlarmActionStepMapper.updateEmsAlarmActionStep(emsAlarmActionStep);
}
/**
*
*
* @param objIds
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int deleteEmsAlarmActionStepByObjIds(String[] objIds)
@ -112,10 +126,14 @@ public class EmsAlarmActionStepServiceImpl implements IEmsAlarmActionStepService
}
/**
*
* OSS
*
* @param objId
* @return
* <p><b>Why OSS </b>
* OSS API DB OSS
* DB OSS
* OSS DBOSS DB
* OSS + DB DB OSS
* OssClient
*/
@Override
@Transactional(rollbackFor = Exception.class)
@ -128,24 +146,8 @@ public class EmsAlarmActionStepServiceImpl implements IEmsAlarmActionStepService
throw new RuntimeException("措施步骤不存在 ");
}
// 2. 删除该步骤关联的所有图片文件
EmsAlarmActionStepImage imageQuery = new EmsAlarmActionStepImage();
imageQuery.setActionStepObjId(objId);
List<EmsAlarmActionStepImage> images = emsAlarmActionStepImageMapper.selectEmsAlarmActionStepImageList(imageQuery);
if (images != null && !images.isEmpty()) {
for (EmsAlarmActionStepImage image : images) {
try {
// 删除物理文件
deleteImageFile(image.getImageUrl());
// 删除数据库记录
emsAlarmActionStepImageMapper.deleteEmsAlarmActionStepImageByObjId(image.getObjId());
} catch (Exception e) {
throw new RuntimeException("删除措施步骤图片失败,导致事务回滚: " + e.getMessage(), e);
}
}
System.out.println("删除措施步骤 " + actionStep.getDescription() + " 关联的 " + images.size() + " 张图片");
}
// 2. 删除该步骤关联的 OSS 文件(先于 DB 删除,理由见方法注释)
deleteOssFiles(actionStep.getOssIds());
// 3. 最后删除措施步骤本身
int result = emsAlarmActionStepMapper.deleteEmsAlarmActionStepByObjId(objId);
@ -161,89 +163,87 @@ public class EmsAlarmActionStepServiceImpl implements IEmsAlarmActionStepService
}
/**
* ID
*
* @param ruleObjId ID
* @return
* ID URL
* <p>使 {@code imageUrls}
* OSS
*/
@Override
public List<EmsAlarmActionStep> selectEmsAlarmActionStepByRuleObjId(String ruleObjId)
{
return emsAlarmActionStepMapper.selectEmsAlarmActionStepByRuleObjId(ruleObjId);
List<EmsAlarmActionStep> list = emsAlarmActionStepMapper.selectEmsAlarmActionStepByRuleObjId(ruleObjId);
fillImageUrls(list);
return list;
}
/**
*
*
* @param monitorId
* @param cause
* @return
* +
* <p> SOP
* URL
*/
@Override
public List<EmsAlarmActionStep> selectActionStepsByAlarmInfo(String monitorId, String cause)
{
return emsAlarmActionStepMapper.selectActionStepsByAlarmInfo(monitorId, cause);
List<EmsAlarmActionStep> list = emsAlarmActionStepMapper.selectActionStepsByAlarmInfo(monitorId, cause);
fillImageUrls(list);
return list;
}
/**
*
*
*
* <h4>Why </h4>
* <p>"当前全量期望数据""先删旧、再插新"
* OSS
*
* OSS "保留复用"
* {@link #collectOssIds(List)} ossId
* <em></em> OSS
*
* <h4></h4>
* <p>{@code @Transactional} OSS
* OSS
*
* @param ruleObjId ID
* @param stepList
* @return
* @param stepList
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int batchSaveActionSteps(String ruleObjId, List<EmsAlarmActionStep> stepList)
{
if (ObjectUtil.isEmpty(ruleObjId) || stepList == null || stepList.isEmpty()) {
if (ObjectUtil.isEmpty(ruleObjId)) {
return 0;
}
try {
// 1. 先删除该规则下的所有现有步骤和图片(包括物理文件)
// 1. 先收集本次提交中所有引用的 ossId用于差异化删除
Set<Long> retainedOssIds = collectOssIds(stepList);
// 2. 删除该规则下的所有现有步骤。OSS 只删除本次提交不再引用的旧文件。
List<EmsAlarmActionStep> existingSteps = emsAlarmActionStepMapper.selectEmsAlarmActionStepByRuleObjId(ruleObjId);
int deletedCount = 0;
for (EmsAlarmActionStep existingStep : existingSteps) {
// 删除步骤关联的图片
EmsAlarmActionStepImage imageQuery = new EmsAlarmActionStepImage();
imageQuery.setActionStepObjId(existingStep.getObjId());
List<EmsAlarmActionStepImage> existingImages = emsAlarmActionStepImageMapper.selectEmsAlarmActionStepImageList(imageQuery);
for (EmsAlarmActionStepImage image : existingImages) {
try {
deleteImageFile(image.getImageUrl());
emsAlarmActionStepImageMapper.deleteEmsAlarmActionStepImageByObjId(image.getObjId());
} catch (Exception e) {
throw new RuntimeException("文件删除失败,导致事务回滚: " + e.getMessage(), e);
}
}
// 删除步骤
emsAlarmActionStepMapper.deleteEmsAlarmActionStepByObjId(existingStep.getObjId());
// retainedOssIds 中的 ossId 不会被删除(它们在新提交中仍然被引用)
deleteOssFiles(existingStep.getOssIds(), retainedOssIds);
deletedCount += emsAlarmActionStepMapper.deleteEmsAlarmActionStepByObjId(existingStep.getObjId());
}
// 2. 保存新的步骤和图片
// 3. 如果前端提交了空步骤列表(清空操作),直接返回删除计数
if (stepList == null || stepList.isEmpty()) {
return deletedCount > 0 ? deletedCount : 1;
}
// 4. 保存新的步骤。图片只保存 OSS ID 列表,不再写子表。
int result = 0;
for (EmsAlarmActionStep step : stepList) {
// 生成步骤ID
if (ObjectUtil.isEmpty(step.getObjId())) {
step.setObjId(IdUtil.fastSimpleUUID());
// 使用雪花算法生成时间有序的主键,对于按序插入的表索引更友好
step.setObjId(IdUtil.getSnowflakeNextIdStr());
}
step.setRuleObjId(ruleObjId);
step.setCreateTime(DateUtils.getNowDate());
// 保存步骤
result += emsAlarmActionStepMapper.insertEmsAlarmActionStep(step);
// 保存步骤关联的图片
if (step.getStepImages() != null && !step.getStepImages().isEmpty()) {
for (EmsAlarmActionStepImage image : step.getStepImages()) {
if (ObjectUtil.isEmpty(image.getObjId())) {
image.setObjId(IdUtil.fastSimpleUUID());
}
image.setActionStepObjId(step.getObjId());
image.setCreateTime(DateUtils.getNowDate());
emsAlarmActionStepImageMapper.insertEmsAlarmActionStepImage(image);
}
}
}
return result;
@ -252,48 +252,181 @@ public class EmsAlarmActionStepServiceImpl implements IEmsAlarmActionStepService
}
}
// ======================== 图片 URL 解析 ========================
/**
*
*
* @param imageUrl URL
* {@code imageUrls}
* <p> Service Mapper
* ossId URL {@link ISysOssService}
* MyBatis Mapper System
* Service DB + OSS
*/
private void deleteImageFile(String imageUrl) {
if (ObjectUtil.isEmpty(imageUrl) || ObjectUtil.isEmpty(uploadPath)) {
private void fillImageUrls(List<EmsAlarmActionStep> steps)
{
if (steps == null || steps.isEmpty()) {
return;
}
for (EmsAlarmActionStep step : steps) {
fillImageUrls(step);
}
}
private void fillImageUrls(EmsAlarmActionStep step)
{
if (step == null) {
return;
}
step.setImageUrls(resolveOssUrls(step.getOssIds()));
}
/**
* ossId URL
*
* <p><b> Map Why Map-based ordering</b>
* {@link ISysOssService#listByIds(List)} 使
* {@code WHERE oss_id IN (...)} IN
* listByIds URL
* Map(ossIdurl) ossId
* {@code imageUrls[0]} {@code ossIds} ossId
*
* @param ossIds OSS ID "1765432109876543210,1765432109876543211"
* @return URL ossIds
*/
private List<String> resolveOssUrls(String ossIds)
{
List<Long> idList = parseOssIds(ossIds);
if (idList.isEmpty()) {
return List.of();
}
// 批量查询 OSS 记录,一次性获取所有 URL避免 N+1 查询
List<SysOssVo> ossList = sysOssService.listByIds(idList);
// 构建 ossId → url 映射表,用于按原始顺序取值
Map<Long, String> urlMap = new HashMap<>();
for (SysOssVo oss : ossList) {
if (oss.getOssId() != null && ObjectUtil.isNotEmpty(oss.getUrl())) {
urlMap.put(oss.getOssId(), oss.getUrl());
}
}
// 严格按 ossIds 的原始顺序构建 URL 列表
List<String> urls = new ArrayList<>();
for (Long ossId : idList) {
String url = urlMap.get(ossId);
if (ObjectUtil.isNotEmpty(url)) {
urls.add(url);
}
// ossId 在 sys_oss 表中不存在时静默跳过。
// 这可能发生在 OSS 记录被管理员手动删除但步骤数据未同步的场景,
// 相比抛异常让整个查询失败,静默跳过对前端展示的影响更小。
}
return urls;
}
// ======================== OSS 文件删除 ========================
/**
* ossIds OSS
* <p>"彻底删除步骤"
*
*/
private void deleteOssFiles(String ossIds)
{
deleteOssFiles(ossIds, Set.of());
}
/**
* OSS ossId
*
* <p><b> {@link ISysOssService#deleteWithValidByIds(List, boolean)}</b>
* {@code validation=true}
* <ol>
* <li> ossId {@code sys_oss} </li>
* <li> {@code sys_oss} </li>
* <li> OSS </li>
* </ol>
* {@code java.io.File.delete()}
*
* <p><b></b>
* {@code catch} {@code System.err.println}
* OSS
* {@link RuntimeException} {@code @Transactional}
* DB OSS
*
* @param ossIds OSS ID
* @param retainedOssIds ossId
*/
private void deleteOssFiles(String ossIds, Set<Long> retainedOssIds)
{
List<Long> idList = parseOssIds(ossIds);
if (idList.isEmpty()) {
return;
}
try {
// 解析图片URL获取相对路径
// 例如:/profile/upload/2024/05/29/xxx.jpg -> upload/2024/05/29/xxx.jpg
String relativePath = null;
if (imageUrl.startsWith("/profile/")) {
relativePath = imageUrl.substring("/profile/".length());
} else if (imageUrl.contains("/upload/")) {
int uploadIndex = imageUrl.indexOf("/upload/");
relativePath = imageUrl.substring(uploadIndex + 1); // 去掉前面的"/"
}
// 过滤掉本次提交仍然引用的 ossId它们在新的步骤列表中继续使用
idList.removeIf(retainedOssIds::contains);
if (idList.isEmpty()) {
return;
}
if (ObjectUtil.isNotEmpty(relativePath)) {
// URL解码处理中文文件名
relativePath = URLDecoder.decode(relativePath, "UTF-8");
// 构建完整的文件路径
String fullPath = uploadPath + File.separator + relativePath.replace("/", File.separator);
File file = new File(fullPath);
if (file.exists() && file.isFile()) {
boolean deleted = file.delete();
if (deleted) {
System.out.println("成功删除图片文件: " + fullPath);
} else {
System.err.println("删除图片文件失败: " + fullPath);
}
} else {
System.out.println("图片文件不存在,无需删除: " + fullPath);
}
}
} catch (Exception e) {
System.err.println("删除图片文件时发生异常: " + imageUrl + ", 错误信息: " + e.getMessage());
Boolean deleted = sysOssService.deleteWithValidByIds(idList, true);
if (!Boolean.TRUE.equals(deleted)) {
throw new RuntimeException("删除措施步骤 OSS 文件失败ossIds=" + ossIds);
}
}
/**
* ossId
* <p>使 {@link Set} {@link List}
*
* Set ossId
*/
private Set<Long> collectOssIds(List<EmsAlarmActionStep> stepList)
{
Set<Long> idSet = new HashSet<>();
if (stepList == null || stepList.isEmpty()) {
return idSet;
}
for (EmsAlarmActionStep step : stepList) {
idSet.addAll(parseOssIds(step.getOssIds()));
}
return idSet;
}
/**
* ossId Long
*
* <p><b> NumberFormatException </b>
* ossIds
*
*
* {@code throw IllegalArgumentException}Fail Fast
*
*
* @param ossIds OSS ID null
* @return Long
* @throws IllegalArgumentException
*/
private List<Long> parseOssIds(String ossIds)
{
List<Long> idList = new ArrayList<>();
if (ObjectUtil.isEmpty(ossIds)) {
return idList;
}
String[] ids = ossIds.split(",");
for (String id : ids) {
String trimmedId = id == null ? "" : id.trim();
if (ObjectUtil.isEmpty(trimmedId)) {
continue; // 跳过连续逗号产生的空段(如 "123,,456" → 取 123 和 456
}
try {
idList.add(Long.valueOf(trimmedId));
} catch (NumberFormatException e) {
throw new IllegalArgumentException("措施步骤图片 OSS ID 非法: " + trimmedId, e);
}
}
return idList;
}
}

@ -0,0 +1,82 @@
package org.dromara.ems.record.domain.bo;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.ems.record.domain.EmsRecordAlarmData;
import java.math.BigDecimal;
import java.util.Date;
/**
* ems_record_alarm_data
*
* @author Yinq
* @date 2024-05-15
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = EmsRecordAlarmData.class, reverseConvertGenerate = false)
public class EmsRecordAlarmDataBo extends BaseEntity {
/** 自增标识 */
@NotNull(message = "主键不能为空", groups = { EditGroup.class })
private Long objId;
/** 计量设备编号 */
private String monitorId;
/** 采集设备编号 */
private String collectDeviceId;
/** 记录时间 */
private Date collectTime;
/** 异常类型0超过阈值 1小于阈值 */
private Long alarmType;
/** 异常状态0已处理 1未处理 */
private Long alarmStatus;
/** 异常数据 */
private String alarmData;
/** 操作人员 */
private String operationName;
/** 操作时间 */
private Date operationTime;
/** 原因 */
private String cause;
/** 通知用户 */
private String notifyUser;
private String tenantId;
private String metricCode;
private String alarmLevel;
private BigDecimal thresholdValue;
private BigDecimal actualValue;
private String alarmTitle;
private String alarmContent;
private Date recoverTime;
private String pushStatus;
private Integer pushCount;
private Long confirmUserId;
private String confirmRemark;
}

@ -0,0 +1,89 @@
package org.dromara.ems.record.domain.bo;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.ems.record.domain.EmsRecordAlarmRule;
import java.math.BigDecimal;
import java.util.Date;
/**
* ems_record_alarm_rule
*
* @author Yinq
* @date 2024-05-15
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = EmsRecordAlarmRule.class, reverseConvertGenerate = false)
public class EmsRecordAlarmRuleBo extends BaseEntity {
/** 自增标识 */
@NotNull(message = "主键不能为空", groups = { EditGroup.class })
private Long objId;
/** 规则编号 */
private String ruleId;
/** 规则名称 */
@NotBlank(message = "规则名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String ruleName;
/** 计量设备编号 */
@NotBlank(message = "计量设备编号不能为空", groups = { AddGroup.class, EditGroup.class })
private String monitorId;
/** 记录时间 */
private Date collectTime;
/** 能源类型 */
private Long energyType;
/** 触发规则0大于 1小于 */
private Long triggerRule;
/** 监测字段 */
private Long monitorField;
/** 时间范围(分) */
private Long timeRange;
/** 触发阈值量 */
private BigDecimal triggerValue;
/** 通知用户 */
private String notifyUser;
/** 备注 */
private String cause;
private String tenantId;
private String metricCode;
private BigDecimal alarmUpper;
private BigDecimal alarmLower;
private BigDecimal recoverUpper;
private BigDecimal recoverLower;
/** 回差 */
private BigDecimal hysteresis;
/** 持续触发秒数 */
private Integer durationSec;
private String alarmLevel;
private Long notifyGroupId;
private String isEnable;
}

@ -0,0 +1,132 @@
package org.dromara.ems.record.domain.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.ems.record.domain.EmsRecordAlarmData;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* ems_record_alarm_data
*
* @author Yinq
* @date 2024-05-15
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = EmsRecordAlarmData.class)
public class EmsRecordAlarmDataVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/** 自增标识 */
@ExcelProperty(value = "自增标识")
private Long objId;
/** 计量设备编号 */
@ExcelProperty(value = "计量设备编号")
private String monitorId;
/** 计量设备名称 */
@ExcelProperty(value = "计量设备名称")
private String monitorName;
private String monitorCode;
/** 采集设备编号 */
@ExcelProperty(value = "采集设备编号")
private String collectDeviceId;
/** 采集设备名称 */
@ExcelProperty(value = "采集设备名称")
private String collectDeviceName;
/** 记录时间 */
@ExcelProperty(value = "记录时间")
private Date collectTime;
/** 异常类型0超过阈值 1小于阈值 */
private Long alarmType;
/** 异常状态0已处理 1未处理 */
@ExcelProperty(value = "异常状态")
private Long alarmStatus;
/** 异常数据 */
@ExcelProperty(value = "异常数据")
private String alarmData;
/** 操作人员 */
@ExcelProperty(value = "操作人员")
private String operationName;
/** 操作时间 */
@ExcelProperty(value = "操作时间")
private Date operationTime;
private String beginOperationTime;
private String endOperationTime;
private String beginCollectTime;
private String endCollectTime;
private String[] monitorIds;
/** 原因 */
@ExcelProperty(value = "原因")
private String cause;
/** 通知用户 */
private String notifyUser;
private String tenantId;
private String metricCode;
/** 告警级别 */
@ExcelProperty(value = "告警级别")
private String alarmLevel;
/** 触发阈值 */
@ExcelProperty(value = "触发阈值")
private BigDecimal thresholdValue;
/** 实际值 */
@ExcelProperty(value = "实际值")
private BigDecimal actualValue;
/** 告警标题 */
@ExcelProperty(value = "告警标题")
private String alarmTitle;
/** 告警内容 */
@ExcelProperty(value = "告警内容")
private String alarmContent;
/** 恢复时间 */
@ExcelProperty(value = "恢复时间")
private Date recoverTime;
/** 推送状态 */
@ExcelProperty(value = "推送状态")
private String pushStatus;
/** 推送次数 */
@ExcelProperty(value = "推送次数")
private Integer pushCount;
private Long confirmUserId;
/** 确认备注 */
@ExcelProperty(value = "确认备注")
private String confirmRemark;
/** 统一设备名称 */
private String deviceName;
}

@ -0,0 +1,121 @@
package org.dromara.ems.record.domain.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.ems.record.domain.EmsRecordAlarmRule;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* ems_record_alarm_rule
*
* @author Yinq
* @date 2024-05-15
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = EmsRecordAlarmRule.class)
public class EmsRecordAlarmRuleVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/** 自增标识 */
@ExcelProperty(value = "自增标识")
private Long objId;
/** 规则编号 */
@ExcelProperty(value = "规则编号")
private String ruleId;
/** 规则名称 */
@ExcelProperty(value = "规则名称")
private String ruleName;
/** 计量设备编号 */
@ExcelProperty(value = "计量设备编号")
private String monitorId;
private String monitorCode;
/** 计量设备名称 */
@ExcelProperty(value = "计量设备名称")
private String monitorName;
/** 记录时间 */
@ExcelProperty(value = "记录时间")
private Date collectTime;
/** 能源类型 */
@ExcelProperty(value = "能源类型")
private Long energyType;
/** 触发规则0大于 1小于 */
@ExcelProperty(value = "触发规则")
private Long triggerRule;
/** 监测字段 */
@ExcelProperty(value = "监测字段")
private Long monitorField;
/** 时间范围(分) */
@ExcelProperty(value = "时间范围(分)")
private Long timeRange;
/** 触发阈值量 */
@ExcelProperty(value = "触发阈值量")
private BigDecimal triggerValue;
/** 通知用户 */
@ExcelProperty(value = "通知用户")
private String notifyUser;
/** 备注 */
@ExcelProperty(value = "备注")
private String cause;
private String tenantId;
private String metricCode;
/** 告警上限 */
@ExcelProperty(value = "告警上限")
private BigDecimal alarmUpper;
/** 告警下限 */
@ExcelProperty(value = "告警下限")
private BigDecimal alarmLower;
/** 恢复上限 */
@ExcelProperty(value = "恢复上限")
private BigDecimal recoverUpper;
/** 恢复下限 */
@ExcelProperty(value = "恢复下限")
private BigDecimal recoverLower;
/** 回差 */
@ExcelProperty(value = "回差")
private BigDecimal hysteresis;
/** 持续触发秒数 */
@ExcelProperty(value = "持续触发秒数")
private Integer durationSec;
/** 告警级别 */
@ExcelProperty(value = "告警级别")
private String alarmLevel;
private Long notifyGroupId;
/** 启用状态 */
@ExcelProperty(value = "启用状态")
private String isEnable;
private String nickName;
}

@ -14,30 +14,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
</resultMap>
<resultMap type="EmsAlarmActionStep" id="EmsAlarmActionStepWithImagesResult">
<result property="objId" column="obj_id" />
<result property="ruleObjId" column="rule_obj_id" />
<result property="stepSequence" column="step_sequence" />
<result property="description" column="description" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
<collection property="stepImages" ofType="EmsAlarmActionStepImage">
<result property="objId" column="img_obj_id" />
<result property="actionStepObjId" column="img_action_step_obj_id" />
<result property="imageUrl" column="img_image_url" />
<result property="imageSequence" column="img_image_sequence" />
<result property="description" column="img_description" />
<result property="remark" column="img_remark" />
</collection>
<result property="ossIds" column="oss_ids" />
</resultMap>
<sql id="selectEmsAlarmActionStepVo">
select obj_id, rule_obj_id, step_sequence, description, create_by, create_time, update_by, update_time, remark from ems_alarm_action_step
select obj_id, rule_obj_id, step_sequence, description, create_by, create_time, update_by, update_time, remark, oss_ids from ems_alarm_action_step
</sql>
<select id="selectEmsAlarmActionStepList" parameterType="EmsAlarmActionStep" resultMap="EmsAlarmActionStepResult">
@ -54,30 +35,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where obj_id = #{objId}
</select>
<select id="selectEmsAlarmActionStepByRuleObjId" parameterType="String" resultMap="EmsAlarmActionStepWithImagesResult">
SELECT
step.obj_id,
step.rule_obj_id,
step.step_sequence,
step.description,
step.create_by,
step.create_time,
step.update_by,
step.update_time,
step.remark,
img.obj_id as img_obj_id,
img.action_step_obj_id as img_action_step_obj_id,
img.image_url as img_image_url,
img.image_sequence as img_image_sequence,
img.description as img_description,
img.remark as img_remark
FROM ems_alarm_action_step step
LEFT JOIN ems_alarm_action_step_image img ON step.obj_id = img.action_step_obj_id
WHERE step.rule_obj_id = #{ruleObjId}
ORDER BY step.step_sequence ASC, img.image_sequence ASC
<select id="selectEmsAlarmActionStepByRuleObjId" parameterType="String" resultMap="EmsAlarmActionStepResult">
<include refid="selectEmsAlarmActionStepVo"/>
WHERE rule_obj_id = #{ruleObjId}
ORDER BY step_sequence ASC
</select>
<select id="selectActionStepsByAlarmInfo" resultMap="EmsAlarmActionStepWithImagesResult">
<select id="selectActionStepsByAlarmInfo" resultMap="EmsAlarmActionStepResult">
SELECT
step.obj_id,
step.rule_obj_id,
@ -88,14 +52,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
step.update_by,
step.update_time,
step.remark,
img.obj_id as img_obj_id,
img.action_step_obj_id as img_action_step_obj_id,
img.image_url as img_image_url,
img.image_sequence as img_image_sequence,
img.description as img_description,
img.remark as img_remark
step.oss_ids
FROM ems_alarm_action_step step
LEFT JOIN ems_alarm_action_step_image img ON step.obj_id = img.action_step_obj_id
INNER JOIN ems_record_alarm_rule rule ON step.rule_obj_id = rule.obj_id
WHERE rule.monitor_id = #{monitorId}
AND (
@ -118,7 +76,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-- 历史版本规则monitor_field为空匹配所有字段类型
(rule.monitor_field IS NULL)
)
ORDER BY step.step_sequence ASC, img.image_sequence ASC
ORDER BY step.step_sequence ASC
</select>
<insert id="insertEmsAlarmActionStep" parameterType="EmsAlarmActionStep" useGeneratedKeys="true" keyProperty="objId">
@ -132,6 +90,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="remark != null">remark,</if>
<if test="ossIds != null and ossIds != ''">oss_ids,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="ruleObjId != null and ruleObjId != ''">#{ruleObjId},</if>
@ -142,6 +101,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="remark != null">#{remark},</if>
<if test="ossIds != null and ossIds != ''">#{ossIds},</if>
</trim>
</insert>
@ -156,6 +116,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="ossIds != null">oss_ids = #{ossIds},</if>
</trim>
where obj_id = #{objId}
</update>

Loading…
Cancel
Save