mirror of
https://codeup.aliyun.com/64f7d6b8ce01efaafef1e678/coal/coal.git
synced 2026-07-25 23:27:07 +08:00
feat(WeightDeviceDataAlert): implement alert management functionality with CRUD operations and notification checks
This commit is contained in:
@@ -12,6 +12,7 @@ import cn.lihongjie.coal.weightDevice.entity.WeightDeviceEntity;
|
||||
import cn.lihongjie.coal.weightDevice.service.WeightDeviceService;
|
||||
import cn.lihongjie.coal.weightDeviceData.entity.WeightDeviceDataEntity;
|
||||
import cn.lihongjie.coal.weightDeviceData.service.WeightDeviceDataService;
|
||||
import cn.lihongjie.coal.weightDeviceDataAlert.service.WeightDeviceDataAlertService;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@@ -69,6 +70,8 @@ public class WeightListener {
|
||||
|
||||
@Autowired WeightDeviceService weightDeviceService;
|
||||
|
||||
@Autowired WeightDeviceDataAlertService weightDeviceDataAlertService;
|
||||
|
||||
@Autowired
|
||||
ConversionService conversionService;
|
||||
|
||||
@@ -598,6 +601,13 @@ public class WeightListener {
|
||||
|
||||
weightDeviceDataService.save(deviceData);
|
||||
});
|
||||
|
||||
// 触发告警规则检查
|
||||
try {
|
||||
weightDeviceDataAlertService.checkAllAlertsAndNotify(device.getOrganizationId());
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to check alerts for device {}: {}", device.getId(), e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private Integer toBoolean(JsonNode node) {
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package cn.lihongjie.coal.weightDeviceDataAlert.controller;
|
||||
|
||||
import cn.lihongjie.coal.annotation.OrgScope;
|
||||
import cn.lihongjie.coal.annotation.SysLog;
|
||||
import cn.lihongjie.coal.base.dto.CommonQuery;
|
||||
import cn.lihongjie.coal.base.dto.IdRequest;
|
||||
import cn.lihongjie.coal.weightDeviceDataAlert.dto.CreateWeightDeviceDataAlertDto;
|
||||
import cn.lihongjie.coal.weightDeviceDataAlert.dto.UpdateWeightDeviceDataAlertDto;
|
||||
import cn.lihongjie.coal.weightDeviceDataAlert.dto.WeightDeviceDataAlertDto;
|
||||
import cn.lihongjie.coal.weightDeviceDataAlert.service.WeightDeviceDataAlertService;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/weightDeviceDataAlert")
|
||||
@SysLog(module = "")
|
||||
@Slf4j
|
||||
@OrgScope
|
||||
public class WeightDeviceDataAlertController {
|
||||
@Autowired private WeightDeviceDataAlertService service;
|
||||
|
||||
@PostMapping("/create")
|
||||
public WeightDeviceDataAlertDto create(@RequestBody CreateWeightDeviceDataAlertDto request) {
|
||||
return this.service.create(request);
|
||||
}
|
||||
|
||||
@PostMapping("/update")
|
||||
public WeightDeviceDataAlertDto update(@RequestBody UpdateWeightDeviceDataAlertDto request) {
|
||||
return this.service.update(request);
|
||||
}
|
||||
|
||||
@PostMapping("/delete")
|
||||
public Object delete(@RequestBody IdRequest request) {
|
||||
this.service.delete(request);
|
||||
return true;
|
||||
}
|
||||
|
||||
@PostMapping("/getById")
|
||||
public WeightDeviceDataAlertDto getById(@RequestBody IdRequest request) {
|
||||
return this.service.getById(request.getId());
|
||||
}
|
||||
|
||||
@PostMapping("/list")
|
||||
public Page<WeightDeviceDataAlertDto> list(@RequestBody CommonQuery request) {
|
||||
return this.service.list(request);
|
||||
}
|
||||
|
||||
@PostMapping("/checkAndNotify")
|
||||
@SysLog(action = "检查告警规则并发送通知")
|
||||
public Object checkAndNotify() {
|
||||
this.service.checkAllAlertsAndNotify();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package cn.lihongjie.coal.weightDeviceDataAlert.dto;
|
||||
|
||||
import cn.lihongjie.coal.base.dto.OrgCommonDto;
|
||||
|
||||
import jakarta.persistence.ManyToOne;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import org.hibernate.annotations.Comment;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class CreateWeightDeviceDataAlertDto extends OrgCommonDto {
|
||||
|
||||
@Comment("查询条件JSON")
|
||||
private String queryJson;
|
||||
|
||||
@Comment("预期吨数-jz")
|
||||
private Double expectedTonnage;
|
||||
|
||||
|
||||
@Comment("推送阈值 吨数")
|
||||
private Double alertTonnageThreshold;
|
||||
|
||||
@Comment("截止日期")
|
||||
private LocalDateTime endDate;
|
||||
|
||||
/**
|
||||
* 关联的场景 用于推送消息
|
||||
*/
|
||||
@ManyToOne
|
||||
private String scene;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package cn.lihongjie.coal.weightDeviceDataAlert.dto;
|
||||
|
||||
import cn.lihongjie.coal.base.dto.OrgCommonDto;
|
||||
|
||||
import jakarta.persistence.ManyToOne;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import org.hibernate.annotations.Comment;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class UpdateWeightDeviceDataAlertDto extends OrgCommonDto {
|
||||
|
||||
@Comment("查询条件JSON")
|
||||
private String queryJson;
|
||||
|
||||
@Comment("预期吨数-jz")
|
||||
private Double expectedTonnage;
|
||||
|
||||
@Comment("推送阈值 吨数")
|
||||
private Double alertTonnageThreshold;
|
||||
|
||||
@Comment("截止日期")
|
||||
private LocalDateTime endDate;
|
||||
|
||||
/**
|
||||
* 关联的场景 用于推送消息
|
||||
*/
|
||||
@ManyToOne
|
||||
private String scene;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package cn.lihongjie.coal.weightDeviceDataAlert.dto;
|
||||
|
||||
import cn.lihongjie.coal.base.dto.OrgCommonDto;
|
||||
import cn.lihongjie.coal.dingtalkBotScene.entity.DingtalkBotSceneEntity;
|
||||
|
||||
import jakarta.persistence.ManyToOne;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import org.hibernate.annotations.Comment;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class WeightDeviceDataAlertDto extends OrgCommonDto {
|
||||
|
||||
@Comment("查询条件JSON")
|
||||
private String queryJson;
|
||||
|
||||
@Comment("预期吨数-jz")
|
||||
private Double expectedTonnage;
|
||||
|
||||
@Comment("实际吨数-jz")
|
||||
private Double actualTonnage;
|
||||
|
||||
@Comment("进度 %")
|
||||
private Double progressPercent;
|
||||
|
||||
@Comment("推送阈值 吨数")
|
||||
private Double alertTonnageThreshold;
|
||||
|
||||
@Comment("上次提醒时间")
|
||||
private LocalDateTime lastAlertTime;
|
||||
|
||||
@Comment("上次提醒进度")
|
||||
private Double lastAlertProgressPercent;
|
||||
|
||||
@Comment("上次提醒吨数")
|
||||
private Double lastAlertTonnage;
|
||||
|
||||
@Comment("截止日期")
|
||||
private LocalDateTime endDate;
|
||||
|
||||
/**
|
||||
* 关联的场景 用于推送消息
|
||||
*/
|
||||
@ManyToOne
|
||||
private DingtalkBotSceneEntity scene;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package cn.lihongjie.coal.weightDeviceDataAlert.entity;
|
||||
|
||||
import cn.lihongjie.coal.base.entity.OrgCommonEntity;
|
||||
import cn.lihongjie.coal.dingtalkBotScene.entity.DingtalkBotSceneEntity;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import org.hibernate.annotations.Comment;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Table(
|
||||
indexes =
|
||||
@jakarta.persistence.Index(
|
||||
name = "idx_weightDeviceDataAlert_org_id",
|
||||
columnList = "organization_id"))
|
||||
public class WeightDeviceDataAlertEntity extends OrgCommonEntity {
|
||||
|
||||
|
||||
@Comment("查询条件JSON")
|
||||
private String queryJson;
|
||||
|
||||
|
||||
@Comment("预期吨数-jz")
|
||||
private Double expectedTonnage;
|
||||
|
||||
|
||||
|
||||
@Comment("实际吨数-jz")
|
||||
private Double actualTonnage;
|
||||
|
||||
|
||||
@Comment("进度 %")
|
||||
private Double progressPercent;
|
||||
|
||||
|
||||
@Comment("推送阈值 吨数")
|
||||
private Double alertTonnageThreshold;
|
||||
|
||||
|
||||
@Comment("上次提醒时间")
|
||||
private LocalDateTime lastAlertTime;
|
||||
|
||||
@Comment("上次提醒进度")
|
||||
private Double lastAlertProgressPercent;
|
||||
|
||||
@Comment("上次提醒吨数")
|
||||
private Double lastAlertTonnage;
|
||||
|
||||
@Comment("截止日期")
|
||||
private LocalDateTime endDate;
|
||||
|
||||
/**
|
||||
* 关联的场景 用于推送消息
|
||||
*/
|
||||
@ManyToOne
|
||||
private DingtalkBotSceneEntity scene;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.lihongjie.coal.weightDeviceDataAlert.mapper;
|
||||
|
||||
import cn.lihongjie.coal.base.mapper.BaseMapper;
|
||||
import cn.lihongjie.coal.base.mapper.CommonEntityMapper;
|
||||
import cn.lihongjie.coal.base.mapper.CommonMapper;
|
||||
import cn.lihongjie.coal.weightDeviceDataAlert.dto.CreateWeightDeviceDataAlertDto;
|
||||
import cn.lihongjie.coal.weightDeviceDataAlert.dto.UpdateWeightDeviceDataAlertDto;
|
||||
import cn.lihongjie.coal.weightDeviceDataAlert.dto.WeightDeviceDataAlertDto;
|
||||
import cn.lihongjie.coal.weightDeviceDataAlert.entity.WeightDeviceDataAlertEntity;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.control.DeepClone;
|
||||
|
||||
@Mapper(
|
||||
componentModel = org.mapstruct.MappingConstants.ComponentModel.SPRING,
|
||||
uses = {CommonMapper.class, CommonEntityMapper.class},
|
||||
mappingControl = DeepClone.class)
|
||||
public interface WeightDeviceDataAlertMapper
|
||||
extends BaseMapper<
|
||||
WeightDeviceDataAlertEntity,
|
||||
WeightDeviceDataAlertDto,
|
||||
CreateWeightDeviceDataAlertDto,
|
||||
UpdateWeightDeviceDataAlertDto> {}
|
||||
@@ -0,0 +1,16 @@
|
||||
package cn.lihongjie.coal.weightDeviceDataAlert.repository;
|
||||
|
||||
import cn.lihongjie.coal.base.dao.BaseRepository;
|
||||
import cn.lihongjie.coal.weightDeviceDataAlert.entity.WeightDeviceDataAlertEntity;
|
||||
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface WeightDeviceDataAlertRepository
|
||||
extends BaseRepository<WeightDeviceDataAlertEntity> {
|
||||
@Query("select false")
|
||||
boolean isLinked(List<String> ids);
|
||||
}
|
||||
@@ -0,0 +1,348 @@
|
||||
package cn.lihongjie.coal.weightDeviceDataAlert.service;
|
||||
|
||||
import cn.lihongjie.coal.base.dto.CommonQuery;
|
||||
import cn.lihongjie.coal.base.dto.IdRequest;
|
||||
import cn.lihongjie.coal.base.service.BaseService;
|
||||
import cn.lihongjie.coal.dbFunctions.DbFunctionService;
|
||||
import cn.lihongjie.coal.dingtalkBot.entity.DingtalkBotEntity;
|
||||
import cn.lihongjie.coal.dingtalkBot.service.DingtalkBotService;
|
||||
import cn.lihongjie.coal.exception.BizException;
|
||||
import cn.lihongjie.coal.weightDeviceData.entity.WeightDeviceDataEntity;
|
||||
import cn.lihongjie.coal.weightDeviceData.repository.WeightDeviceDataRepository;
|
||||
import cn.lihongjie.coal.weightDeviceDataAlert.dto.CreateWeightDeviceDataAlertDto;
|
||||
import cn.lihongjie.coal.weightDeviceDataAlert.dto.UpdateWeightDeviceDataAlertDto;
|
||||
import cn.lihongjie.coal.weightDeviceDataAlert.dto.WeightDeviceDataAlertDto;
|
||||
import cn.lihongjie.coal.weightDeviceDataAlert.entity.WeightDeviceDataAlertEntity;
|
||||
import cn.lihongjie.coal.weightDeviceDataAlert.mapper.WeightDeviceDataAlertMapper;
|
||||
import cn.lihongjie.coal.weightDeviceDataAlert.repository.WeightDeviceDataAlertRepository;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
@Transactional
|
||||
public class WeightDeviceDataAlertService
|
||||
extends BaseService<WeightDeviceDataAlertEntity, WeightDeviceDataAlertRepository> {
|
||||
@Autowired private WeightDeviceDataAlertRepository repository;
|
||||
|
||||
@Autowired private WeightDeviceDataAlertMapper mapper;
|
||||
|
||||
@Autowired private ConversionService conversionService;
|
||||
|
||||
@Autowired private DbFunctionService dbFunctionService;
|
||||
|
||||
@Autowired private WeightDeviceDataRepository weightDeviceDataRepository;
|
||||
|
||||
@Autowired private DingtalkBotService dingtalkBotService;
|
||||
|
||||
@Autowired private ObjectMapper objectMapper;
|
||||
|
||||
public WeightDeviceDataAlertDto create(CreateWeightDeviceDataAlertDto request) {
|
||||
WeightDeviceDataAlertEntity entity = mapper.toEntity(request);
|
||||
|
||||
this.repository.save(entity);
|
||||
return getById(entity.getId());
|
||||
}
|
||||
|
||||
public WeightDeviceDataAlertDto update(UpdateWeightDeviceDataAlertDto request) {
|
||||
WeightDeviceDataAlertEntity entity = this.repository.get(request.getId());
|
||||
this.mapper.updateEntity(entity, request);
|
||||
|
||||
this.repository.save(entity);
|
||||
|
||||
return getById(entity.getId());
|
||||
}
|
||||
|
||||
public void delete(IdRequest request) {
|
||||
boolean linked = this.repository.isLinked(request.getIds());
|
||||
|
||||
if (linked) {
|
||||
throw new BizException("数据已被关联,无法删除");
|
||||
}
|
||||
|
||||
this.repository.deleteAllById(request.getIds());
|
||||
}
|
||||
|
||||
public WeightDeviceDataAlertDto getById(String id) {
|
||||
WeightDeviceDataAlertEntity entity = repository.get(id);
|
||||
|
||||
return mapper.toDto(entity);
|
||||
}
|
||||
|
||||
public Page<WeightDeviceDataAlertDto> list(CommonQuery query) {
|
||||
Page<WeightDeviceDataAlertEntity> page =
|
||||
repository.findAll(
|
||||
query.specification(conversionService),
|
||||
PageRequest.of(
|
||||
query.getPageNo(),
|
||||
query.getPageSize(),
|
||||
Sort.by(query.getOrders())));
|
||||
|
||||
return page.map(this.mapper::toDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查所有告警规则并发送通知
|
||||
*/
|
||||
public void checkAllAlertsAndNotify() {
|
||||
checkAllAlertsAndNotify(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查指定机构的告警规则并发送通知
|
||||
* @param organizationId 机构ID,如果为null则检查所有机构
|
||||
*/
|
||||
public void checkAllAlertsAndNotify(String organizationId) {
|
||||
if (organizationId != null) {
|
||||
log.info("开始检查机构 {} 的称重数据告警规则", organizationId);
|
||||
} else {
|
||||
log.info("开始检查所有称重数据告警规则");
|
||||
}
|
||||
|
||||
// 获取所有启用的告警规则,过滤掉已截止的规则
|
||||
Specification<WeightDeviceDataAlertEntity> spec = (root, query, criteriaBuilder) -> {
|
||||
List<Predicate> predicates = new ArrayList<>();
|
||||
|
||||
// 过滤机构
|
||||
if (organizationId != null) {
|
||||
predicates.add(criteriaBuilder.equal(root.get("organizationId"), organizationId));
|
||||
}
|
||||
|
||||
// 过滤截止日期:只查询未截止的规则(endDate为null或endDate在当前时间之后)
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
predicates.add(
|
||||
criteriaBuilder.or(
|
||||
criteriaBuilder.isNull(root.get("endDate")),
|
||||
criteriaBuilder.greaterThan(root.get("endDate"), now)
|
||||
)
|
||||
);
|
||||
|
||||
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
|
||||
};
|
||||
|
||||
List<WeightDeviceDataAlertEntity> alerts = repository.findAll(spec);
|
||||
|
||||
if (alerts.isEmpty()) {
|
||||
log.info("没有找到任何有效的告警规则");
|
||||
return;
|
||||
}
|
||||
|
||||
int checkedCount = 0;
|
||||
int notifiedCount = 0;
|
||||
|
||||
for (WeightDeviceDataAlertEntity alert : alerts) {
|
||||
try {
|
||||
checkedCount++;
|
||||
boolean notified = checkAndNotify(alert);
|
||||
if (notified) {
|
||||
notifiedCount++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("检查告警规则失败, 规则ID: {}, 错误: {}", alert.getId(), e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("告警规则检查完成, 共检查 {} 条规则, 发送 {} 条通知", checkedCount, notifiedCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查单个告警规则并发送通知
|
||||
* @param alert 告警规则
|
||||
* @return 是否发送了通知
|
||||
*/
|
||||
private boolean checkAndNotify(WeightDeviceDataAlertEntity alert) {
|
||||
log.debug("检查告警规则: {}", alert.getName());
|
||||
|
||||
// 构建查询条件
|
||||
Specification<WeightDeviceDataEntity> spec = buildSpecification(alert);
|
||||
|
||||
// 查询符合条件的称重数据
|
||||
List<WeightDeviceDataEntity> dataList = weightDeviceDataRepository.findAll(spec);
|
||||
|
||||
if (dataList.isEmpty()) {
|
||||
log.debug("规则 {} 没有找到匹配的数据", alert.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 计算总吨数(净重)
|
||||
double totalTonnage = dataList.stream()
|
||||
.mapToDouble(data -> data.getJz() != null ? data.getJz() : 0.0)
|
||||
.sum();
|
||||
|
||||
// 计算进度百分比
|
||||
Double expectedTonnage = alert.getExpectedTonnage();
|
||||
double progressPercent = 0.0;
|
||||
if (expectedTonnage != null && expectedTonnage > 0) {
|
||||
progressPercent = (totalTonnage / expectedTonnage) * 100.0;
|
||||
}
|
||||
|
||||
log.debug("规则 {}: 实际吨数={}, 预期吨数={}, 进度={}%",
|
||||
alert.getName(), totalTonnage, expectedTonnage, String.format("%.2f", progressPercent));
|
||||
|
||||
// 更新实际吨数和进度
|
||||
alert.setActualTonnage(totalTonnage);
|
||||
alert.setProgressPercent(progressPercent);
|
||||
|
||||
// 判断是否需要发送通知
|
||||
boolean shouldNotify = shouldSendNotification(alert, totalTonnage, progressPercent);
|
||||
|
||||
if (shouldNotify) {
|
||||
sendNotification(alert, totalTonnage, progressPercent, dataList.size());
|
||||
|
||||
// 更新最后通知时间和吨数
|
||||
alert.setLastAlertTime(LocalDateTime.now());
|
||||
alert.setLastAlertTonnage(totalTonnage);
|
||||
alert.setLastAlertProgressPercent(progressPercent);
|
||||
}
|
||||
|
||||
// 保存更新
|
||||
repository.save(alert);
|
||||
|
||||
return shouldNotify;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建查询规格
|
||||
*/
|
||||
private Specification<WeightDeviceDataEntity> buildSpecification(WeightDeviceDataAlertEntity alert) {
|
||||
return (root, query, cb) -> {
|
||||
List<Predicate> predicates = new ArrayList<>();
|
||||
|
||||
// 机构过滤 - 必须使用规则的机构ID
|
||||
if (alert.getOrganizationId() != null) {
|
||||
predicates.add(cb.equal(root.get("organizationId"), alert.getOrganizationId()));
|
||||
}
|
||||
|
||||
// 使用 queryJson 构建额外的查询条件
|
||||
if (alert.getQueryJson() != null && !alert.getQueryJson().isEmpty()) {
|
||||
try {
|
||||
List<CommonQuery.QueryItem> queryItems = objectMapper.readValue(
|
||||
alert.getQueryJson(),
|
||||
new TypeReference<List<CommonQuery.QueryItem>>() {});
|
||||
|
||||
CommonQuery commonQuery = new CommonQuery();
|
||||
commonQuery.setItems(new ArrayList<>(queryItems));
|
||||
|
||||
Specification<WeightDeviceDataEntity> spec =
|
||||
(Specification<WeightDeviceDataEntity>) commonQuery.specification(conversionService);
|
||||
|
||||
if (spec != null) {
|
||||
Predicate specPredicate = spec.toPredicate(root, query, cb);
|
||||
if (specPredicate != null) {
|
||||
predicates.add(specPredicate);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("解析查询条件JSON失败: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
return cb.and(predicates.toArray(new Predicate[0]));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否应该发送通知
|
||||
*
|
||||
* 通知逻辑:
|
||||
* 1. 当实际吨数达到或超过 alertTonnageThreshold 时开始发送通知
|
||||
* 2. 只要超过阈值后,每次吨数有变化就发送通知
|
||||
* 3. 如果吨数与上次通知相同,不重复发送
|
||||
*
|
||||
* 例如:预期1000吨,阈值800吨
|
||||
* - 实际吨数达到800吨时 → 发送通知
|
||||
* - 实际吨数达到850吨时 → 发送通知
|
||||
* - 实际吨数达到900吨时 → 发送通知
|
||||
* - 实际吨数仍是900吨时 → 不发送(避免重复)
|
||||
*/
|
||||
private boolean shouldSendNotification(WeightDeviceDataAlertEntity alert, double currentTonnage, double currentProgress) {
|
||||
// 如果没有配置阈值,不发送通知
|
||||
Double threshold = alert.getAlertTonnageThreshold();
|
||||
if (threshold == null || threshold <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 当前吨数未达到阈值,不发送通知
|
||||
if (currentTonnage < threshold) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 如果从未发送过通知,且达到阈值,发送首次通知
|
||||
if (alert.getLastAlertTonnage() == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 如果吨数与上次通知相同,不重复发送
|
||||
return !(Math.abs(currentTonnage - alert.getLastAlertTonnage()) < 0.01);
|
||||
|
||||
// 吨数有变化且超过阈值,发送通知
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送通知
|
||||
*/
|
||||
private void sendNotification(WeightDeviceDataAlertEntity alert, double tonnage, double progress, int recordCount) {
|
||||
try {
|
||||
// 构建通知数据
|
||||
Map<String, Object> notificationData = new HashMap<>();
|
||||
notificationData.put("alertId", alert.getId());
|
||||
notificationData.put("alertName", alert.getName());
|
||||
notificationData.put("actualTonnage", tonnage);
|
||||
notificationData.put("expectedTonnage", alert.getExpectedTonnage());
|
||||
notificationData.put("progressPercent", progress);
|
||||
notificationData.put("recordCount", recordCount);
|
||||
notificationData.put("lastAlertTonnage", alert.getLastAlertTonnage());
|
||||
notificationData.put("lastAlertTime", alert.getLastAlertTime());
|
||||
notificationData.put("organizationId", alert.getOrganizationId());
|
||||
notificationData.put("sceneId", alert.getScene() != null ? alert.getScene().getId() : null);
|
||||
notificationData.put("timestamp", LocalDateTime.now());
|
||||
|
||||
// 如果配置了钉钉场景,发送钉钉通知
|
||||
if (alert.getScene() != null) {
|
||||
List<DingtalkBotEntity> bots = alert.getScene().getDingtalkBots();
|
||||
|
||||
if (bots != null && !bots.isEmpty()) {
|
||||
for (DingtalkBotEntity bot : bots) {
|
||||
try {
|
||||
dingtalkBotService.doSend(
|
||||
bot,
|
||||
alert.getScene().getDingtalkBotTemplate(),
|
||||
notificationData);
|
||||
|
||||
log.info("钉钉通知发送成功: 规则={}, Bot={}", alert.getName(), bot.getName());
|
||||
} catch (Exception e) {
|
||||
log.error("发送钉钉通知失败: Bot={}, 错误={}", bot.getName(), e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.warn("规则 {} 配置了场景但没有可用的钉钉机器人", alert.getName());
|
||||
}
|
||||
}
|
||||
|
||||
log.info("发送告警通知: 规则={}, 实际吨数={}, 进度={}%, 记录数={}",
|
||||
alert.getName(), String.format("%.2f", tonnage), String.format("%.2f", progress), recordCount);
|
||||
} catch (Exception e) {
|
||||
log.error("发送告警通知失败: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
|
||||
package scripts.dict
|
||||
|
||||
import cn.lihongjie.coal.base.dto.CommonQuery
|
||||
import cn.lihongjie.coal.weightDeviceDataAlert.controller.WeightDeviceDataAlertController
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import org.springframework.context.ApplicationContext
|
||||
|
||||
ApplicationContext ioc = ioc
|
||||
|
||||
def controller = ioc.getBean(WeightDeviceDataAlertController.class)
|
||||
def objectMapper = ioc.getBean(ObjectMapper.class) as ObjectMapper
|
||||
|
||||
|
||||
|
||||
|
||||
return controller.list(params!=null ? objectMapper.convertValue(params, CommonQuery.class ) : new CommonQuery())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user