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

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

@ -41,8 +41,17 @@ public class EmsAlarmActionStep extends BaseEntity
//@ExcelProperty(value = "步骤文字描述") //@ExcelProperty(value = "步骤文字描述")
private String description; 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) public void setObjId(String objId)
{ {
@ -81,14 +90,24 @@ public class EmsAlarmActionStep extends BaseEntity
return description; 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 @Override
@ -98,6 +117,7 @@ public class EmsAlarmActionStep extends BaseEntity
.append("ruleObjId", getRuleObjId()) .append("ruleObjId", getRuleObjId())
.append("stepSequence", getStepSequence()) .append("stepSequence", getStepSequence())
.append("description", getDescription()) .append("description", getDescription())
.append("ossIds", getOssIds())
.append("createBy", getCreateBy()) .append("createBy", getCreateBy())
.append("createTime", getCreateTime()) .append("createTime", getCreateTime())
.append("updateBy", getUpdateBy()) .append("updateBy", getUpdateBy())

@ -5,20 +5,38 @@ import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.DateUtils; import org.dromara.common.core.utils.DateUtils;
import org.dromara.ems.base.domain.EmsAlarmActionStep; 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.mapper.EmsAlarmActionStepMapper;
import org.dromara.ems.base.service.IEmsAlarmActionStepService; 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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.io.File; import java.util.ArrayList;
import java.net.URLDecoder; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; 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 * @author zch
* @date 2025-05-29 * @date 2025-05-29
@ -30,45 +48,48 @@ public class EmsAlarmActionStepServiceImpl implements IEmsAlarmActionStepService
private final EmsAlarmActionStepMapper emsAlarmActionStepMapper; 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 final ISysOssService sysOssService;
private String uploadPath;
/** /**
* * ossIds URL
* * <p> Mapper {@code ossIds}
* @param objId * URL {@link #fillImageUrls(EmsAlarmActionStep)}
* @return * ossId URL ossId
*/ */
@Override @Override
public EmsAlarmActionStep selectEmsAlarmActionStepByObjId(String objId) public EmsAlarmActionStep selectEmsAlarmActionStepByObjId(String objId)
{ {
return emsAlarmActionStepMapper.selectEmsAlarmActionStepByObjId(objId); EmsAlarmActionStep step = emsAlarmActionStepMapper.selectEmsAlarmActionStepByObjId(objId);
fillImageUrls(step);
return step;
} }
/** /**
* * URL
* * <p> DB ossIds OSS
* @param emsAlarmActionStep * OSS
* @return
*/ */
@Override @Override
public List<EmsAlarmActionStep> selectEmsAlarmActionStepList(EmsAlarmActionStep emsAlarmActionStep) public List<EmsAlarmActionStep> selectEmsAlarmActionStepList(EmsAlarmActionStep emsAlarmActionStep)
{ {
return emsAlarmActionStepMapper.selectEmsAlarmActionStepList(emsAlarmActionStep); List<EmsAlarmActionStep> list = emsAlarmActionStepMapper.selectEmsAlarmActionStepList(emsAlarmActionStep);
fillImageUrls(list);
return list;
} }
/** /**
* *
* * <p>{@code ossIds}
* @param emsAlarmActionStep
* @return
*/ */
@Override @Override
public int insertEmsAlarmActionStep(EmsAlarmActionStep emsAlarmActionStep) public int insertEmsAlarmActionStep(EmsAlarmActionStep emsAlarmActionStep)
@ -78,10 +99,9 @@ public class EmsAlarmActionStepServiceImpl implements IEmsAlarmActionStepService
} }
/** /**
* * ossIds
* * <p>MyBatis XML {@code <if test="ossIds != null">} SQL
* @param emsAlarmActionStep *
* @return
*/ */
@Override @Override
public int updateEmsAlarmActionStep(EmsAlarmActionStep emsAlarmActionStep) public int updateEmsAlarmActionStep(EmsAlarmActionStep emsAlarmActionStep)
@ -90,12 +110,6 @@ public class EmsAlarmActionStepServiceImpl implements IEmsAlarmActionStepService
return emsAlarmActionStepMapper.updateEmsAlarmActionStep(emsAlarmActionStep); return emsAlarmActionStepMapper.updateEmsAlarmActionStep(emsAlarmActionStep);
} }
/**
*
*
* @param objIds
* @return
*/
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public int deleteEmsAlarmActionStepByObjIds(String[] objIds) public int deleteEmsAlarmActionStepByObjIds(String[] objIds)
@ -112,10 +126,14 @@ public class EmsAlarmActionStepServiceImpl implements IEmsAlarmActionStepService
} }
/** /**
* * OSS
* *
* @param objId * <p><b>Why OSS </b>
* @return * OSS API DB OSS
* DB OSS
* OSS DBOSS DB
* OSS + DB DB OSS
* OssClient
*/ */
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@ -128,24 +146,8 @@ public class EmsAlarmActionStepServiceImpl implements IEmsAlarmActionStepService
throw new RuntimeException("措施步骤不存在 "); throw new RuntimeException("措施步骤不存在 ");
} }
// 2. 删除该步骤关联的所有图片文件 // 2. 删除该步骤关联的 OSS 文件(先于 DB 删除,理由见方法注释)
EmsAlarmActionStepImage imageQuery = new EmsAlarmActionStepImage(); deleteOssFiles(actionStep.getOssIds());
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() + " 张图片");
}
// 3. 最后删除措施步骤本身 // 3. 最后删除措施步骤本身
int result = emsAlarmActionStepMapper.deleteEmsAlarmActionStepByObjId(objId); int result = emsAlarmActionStepMapper.deleteEmsAlarmActionStepByObjId(objId);
@ -161,89 +163,87 @@ public class EmsAlarmActionStepServiceImpl implements IEmsAlarmActionStepService
} }
/** /**
* ID * ID URL
* * <p>使 {@code imageUrls}
* @param ruleObjId ID * OSS
* @return
*/ */
@Override @Override
public List<EmsAlarmActionStep> selectEmsAlarmActionStepByRuleObjId(String ruleObjId) public List<EmsAlarmActionStep> selectEmsAlarmActionStepByRuleObjId(String ruleObjId)
{ {
return emsAlarmActionStepMapper.selectEmsAlarmActionStepByRuleObjId(ruleObjId); List<EmsAlarmActionStep> list = emsAlarmActionStepMapper.selectEmsAlarmActionStepByRuleObjId(ruleObjId);
fillImageUrls(list);
return list;
} }
/** /**
* * +
* * <p> SOP
* @param monitorId * URL
* @param cause
* @return
*/ */
@Override @Override
public List<EmsAlarmActionStep> selectActionStepsByAlarmInfo(String monitorId, String cause) 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 ruleObjId ID
* @param stepList * @param stepList
* @return * @return
*/ */
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public int batchSaveActionSteps(String ruleObjId, List<EmsAlarmActionStep> stepList) public int batchSaveActionSteps(String ruleObjId, List<EmsAlarmActionStep> stepList)
{ {
if (ObjectUtil.isEmpty(ruleObjId) || stepList == null || stepList.isEmpty()) { if (ObjectUtil.isEmpty(ruleObjId)) {
return 0; return 0;
} }
try { try {
// 1. 先删除该规则下的所有现有步骤和图片(包括物理文件) // 1. 先收集本次提交中所有引用的 ossId用于差异化删除
Set<Long> retainedOssIds = collectOssIds(stepList);
// 2. 删除该规则下的所有现有步骤。OSS 只删除本次提交不再引用的旧文件。
List<EmsAlarmActionStep> existingSteps = emsAlarmActionStepMapper.selectEmsAlarmActionStepByRuleObjId(ruleObjId); List<EmsAlarmActionStep> existingSteps = emsAlarmActionStepMapper.selectEmsAlarmActionStepByRuleObjId(ruleObjId);
int deletedCount = 0;
for (EmsAlarmActionStep existingStep : existingSteps) { for (EmsAlarmActionStep existingStep : existingSteps) {
// 删除步骤关联的图片 // retainedOssIds 中的 ossId 不会被删除(它们在新提交中仍然被引用)
EmsAlarmActionStepImage imageQuery = new EmsAlarmActionStepImage(); deleteOssFiles(existingStep.getOssIds(), retainedOssIds);
imageQuery.setActionStepObjId(existingStep.getObjId()); deletedCount += emsAlarmActionStepMapper.deleteEmsAlarmActionStepByObjId(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());
} }
// 2. 保存新的步骤和图片 // 3. 如果前端提交了空步骤列表(清空操作),直接返回删除计数
if (stepList == null || stepList.isEmpty()) {
return deletedCount > 0 ? deletedCount : 1;
}
// 4. 保存新的步骤。图片只保存 OSS ID 列表,不再写子表。
int result = 0; int result = 0;
for (EmsAlarmActionStep step : stepList) { for (EmsAlarmActionStep step : stepList) {
// 生成步骤ID
if (ObjectUtil.isEmpty(step.getObjId())) { if (ObjectUtil.isEmpty(step.getObjId())) {
step.setObjId(IdUtil.fastSimpleUUID()); // 使用雪花算法生成时间有序的主键,对于按序插入的表索引更友好
step.setObjId(IdUtil.getSnowflakeNextIdStr());
} }
step.setRuleObjId(ruleObjId); step.setRuleObjId(ruleObjId);
step.setCreateTime(DateUtils.getNowDate()); step.setCreateTime(DateUtils.getNowDate());
// 保存步骤
result += emsAlarmActionStepMapper.insertEmsAlarmActionStep(step); 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; return result;
@ -252,48 +252,181 @@ public class EmsAlarmActionStepServiceImpl implements IEmsAlarmActionStepService
} }
} }
// ======================== 图片 URL 解析 ========================
/** /**
* * {@code imageUrls}
* * <p> Service Mapper
* @param imageUrl URL * ossId URL {@link ISysOssService}
* MyBatis Mapper System
* Service DB + OSS
*/ */
private void deleteImageFile(String imageUrl) { private void fillImageUrls(List<EmsAlarmActionStep> steps)
if (ObjectUtil.isEmpty(imageUrl) || ObjectUtil.isEmpty(uploadPath)) { {
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; return;
} }
try { // 过滤掉本次提交仍然引用的 ossId它们在新的步骤列表中继续使用
// 解析图片URL获取相对路径 idList.removeIf(retainedOssIds::contains);
// 例如:/profile/upload/2024/05/29/xxx.jpg -> upload/2024/05/29/xxx.jpg if (idList.isEmpty()) {
String relativePath = null; return;
if (imageUrl.startsWith("/profile/")) { }
relativePath = imageUrl.substring("/profile/".length());
} else if (imageUrl.contains("/upload/")) {
int uploadIndex = imageUrl.indexOf("/upload/");
relativePath = imageUrl.substring(uploadIndex + 1); // 去掉前面的"/"
}
if (ObjectUtil.isNotEmpty(relativePath)) { Boolean deleted = sysOssService.deleteWithValidByIds(idList, true);
// URL解码处理中文文件名 if (!Boolean.TRUE.equals(deleted)) {
relativePath = URLDecoder.decode(relativePath, "UTF-8"); throw new RuntimeException("删除措施步骤 OSS 文件失败ossIds=" + ossIds);
// 构建完整的文件路径
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());
} }
} }
/**
* 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="updateBy" column="update_by" />
<result property="updateTime" column="update_time" /> <result property="updateTime" column="update_time" />
<result property="remark" column="remark" /> <result property="remark" column="remark" />
</resultMap> <result property="ossIds" column="oss_ids" />
<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>
</resultMap> </resultMap>
<sql id="selectEmsAlarmActionStepVo"> <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> </sql>
<select id="selectEmsAlarmActionStepList" parameterType="EmsAlarmActionStep" resultMap="EmsAlarmActionStepResult"> <select id="selectEmsAlarmActionStepList" parameterType="EmsAlarmActionStep" resultMap="EmsAlarmActionStepResult">
@ -54,30 +35,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where obj_id = #{objId} where obj_id = #{objId}
</select> </select>
<select id="selectEmsAlarmActionStepByRuleObjId" parameterType="String" resultMap="EmsAlarmActionStepWithImagesResult"> <select id="selectEmsAlarmActionStepByRuleObjId" parameterType="String" resultMap="EmsAlarmActionStepResult">
SELECT <include refid="selectEmsAlarmActionStepVo"/>
step.obj_id, WHERE rule_obj_id = #{ruleObjId}
step.rule_obj_id, ORDER BY step_sequence ASC
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> </select>
<select id="selectActionStepsByAlarmInfo" resultMap="EmsAlarmActionStepWithImagesResult"> <select id="selectActionStepsByAlarmInfo" resultMap="EmsAlarmActionStepResult">
SELECT SELECT
step.obj_id, step.obj_id,
step.rule_obj_id, step.rule_obj_id,
@ -88,14 +52,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
step.update_by, step.update_by,
step.update_time, step.update_time,
step.remark, step.remark,
img.obj_id as img_obj_id, step.oss_ids
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 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 INNER JOIN ems_record_alarm_rule rule ON step.rule_obj_id = rule.obj_id
WHERE rule.monitor_id = #{monitorId} WHERE rule.monitor_id = #{monitorId}
AND ( AND (
@ -118,7 +76,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-- 历史版本规则monitor_field为空匹配所有字段类型 -- 历史版本规则monitor_field为空匹配所有字段类型
(rule.monitor_field IS NULL) (rule.monitor_field IS NULL)
) )
ORDER BY step.step_sequence ASC, img.image_sequence ASC ORDER BY step.step_sequence ASC
</select> </select>
<insert id="insertEmsAlarmActionStep" parameterType="EmsAlarmActionStep" useGeneratedKeys="true" keyProperty="objId"> <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="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if> <if test="updateTime != null">update_time,</if>
<if test="remark != null">remark,</if> <if test="remark != null">remark,</if>
<if test="ossIds != null and ossIds != ''">oss_ids,</if>
</trim> </trim>
<trim prefix="values (" suffix=")" suffixOverrides=","> <trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="ruleObjId != null and ruleObjId != ''">#{ruleObjId},</if> <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="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if> <if test="updateTime != null">#{updateTime},</if>
<if test="remark != null">#{remark},</if> <if test="remark != null">#{remark},</if>
<if test="ossIds != null and ossIds != ''">#{ossIds},</if>
</trim> </trim>
</insert> </insert>
@ -156,6 +116,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="updateBy != null">update_by = #{updateBy},</if> <if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if> <if test="updateTime != null">update_time = #{updateTime},</if>
<if test="remark != null">remark = #{remark},</if> <if test="remark != null">remark = #{remark},</if>
<if test="ossIds != null">oss_ids = #{ossIds},</if>
</trim> </trim>
where obj_id = #{objId} where obj_id = #{objId}
</update> </update>

Loading…
Cancel
Save