mirror of
https://gitee.com/yudaocode/yudao-boot-mini.git
synced 2026-10-06 14:13:14 +08:00
fix: 优化IoT告警配置支持动态选择邮件、短信、站内信的模板,不再依赖templateCode。
This commit is contained in:
+9
@@ -37,6 +37,15 @@ public class IotAlertConfigRespVO {
|
||||
@Schema(description = "接收的类型数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1,2,3")
|
||||
private List<Integer> receiveTypes;
|
||||
|
||||
@Schema(description = "短信模板编号", example = "iot_alert_sms")
|
||||
private String smsTemplateCode;
|
||||
|
||||
@Schema(description = "邮件模板编号", example = "iot_alert_mail")
|
||||
private String mailTemplateCode;
|
||||
|
||||
@Schema(description = "站内信模板编号", example = "iot_alert_notify")
|
||||
private String notifyTemplateCode;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
|
||||
+8
@@ -44,4 +44,12 @@ public class IotAlertConfigSaveReqVO {
|
||||
@NotEmpty(message = "接收的类型数组不能为空")
|
||||
private List<Integer> receiveTypes;
|
||||
|
||||
@Schema(description = "短信模板编号", example = "iot_alert_sms")
|
||||
private String smsTemplateCode;
|
||||
|
||||
@Schema(description = "邮件模板编号", example = "iot_alert_mail")
|
||||
private String mailTemplateCode;
|
||||
|
||||
@Schema(description = "站内信模板编号", example = "iot_alert_notify")
|
||||
private String notifyTemplateCode;
|
||||
}
|
||||
+18
@@ -81,4 +81,22 @@ public class IotAlertConfigDO extends BaseDO {
|
||||
@TableField(typeHandler = IntegerListTypeHandler.class)
|
||||
private List<Integer> receiveTypes;
|
||||
|
||||
/**
|
||||
* 短信模板编号
|
||||
*
|
||||
* 关联 SmsTemplateDO 的 code 属性
|
||||
*/
|
||||
private String smsTemplateCode;
|
||||
/**
|
||||
* 邮件模板编号
|
||||
*
|
||||
* 关联 MailTemplateDO 的 code 属性
|
||||
*/
|
||||
private String mailTemplateCode;
|
||||
/**
|
||||
* 站内信模板编号
|
||||
*
|
||||
* 关联 NotifyTemplateDO 的 code 属性
|
||||
*/
|
||||
private String notifyTemplateCode;
|
||||
}
|
||||
|
||||
+3
@@ -98,6 +98,9 @@ public interface ErrorCodeConstants {
|
||||
|
||||
// ========== IoT 告警配置 1-050-013-000 ==========
|
||||
ErrorCode ALERT_CONFIG_NOT_EXISTS = new ErrorCode(1_050_013_000, "IoT 告警配置不存在");
|
||||
ErrorCode ALERT_CONFIG_SMS_TEMPLATE_REQUIRED = new ErrorCode(1_050_013_001, "已选择短信接收方式,短信模板不能为空");
|
||||
ErrorCode ALERT_CONFIG_MAIL_TEMPLATE_REQUIRED = new ErrorCode(1_050_013_002, "已选择邮件接收方式,邮件模板不能为空");
|
||||
ErrorCode ALERT_CONFIG_NOTIFY_TEMPLATE_REQUIRED = new ErrorCode(1_050_013_003, "已选择站内信接收方式,站内信模板不能为空");
|
||||
|
||||
// ========== IoT 告警记录 1-050-014-000 ==========
|
||||
ErrorCode ALERT_RECORD_NOT_EXISTS = new ErrorCode(1_050_014_000, "IoT 告警记录不存在");
|
||||
|
||||
+26
@@ -1,11 +1,14 @@
|
||||
package cn.iocoder.yudao.module.iot.service.alert;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.alert.vo.config.IotAlertConfigPageReqVO;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.alert.vo.config.IotAlertConfigSaveReqVO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertConfigDO;
|
||||
import cn.iocoder.yudao.module.iot.dal.mysql.alert.IotAlertConfigMapper;
|
||||
import cn.iocoder.yudao.module.iot.enums.alert.IotAlertReceiveTypeEnum;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.IotSceneRuleService;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import jakarta.annotation.Resource;
|
||||
@@ -16,7 +19,10 @@ import org.springframework.validation.annotation.Validated;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.ALERT_CONFIG_MAIL_TEMPLATE_REQUIRED;
|
||||
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.ALERT_CONFIG_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.ALERT_CONFIG_NOTIFY_TEMPLATE_REQUIRED;
|
||||
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.ALERT_CONFIG_SMS_TEMPLATE_REQUIRED;
|
||||
|
||||
/**
|
||||
* IoT 告警配置 Service 实现类
|
||||
@@ -42,6 +48,7 @@ public class IotAlertConfigServiceImpl implements IotAlertConfigService {
|
||||
// 校验关联数据是否存在
|
||||
sceneRuleService.validateSceneRuleList(createReqVO.getSceneRuleIds());
|
||||
adminUserApi.validateUserList(createReqVO.getReceiveUserIds());
|
||||
validateReceiveTemplates(createReqVO);
|
||||
|
||||
// 插入
|
||||
IotAlertConfigDO alertConfig = BeanUtils.toBean(createReqVO, IotAlertConfigDO.class);
|
||||
@@ -56,6 +63,7 @@ public class IotAlertConfigServiceImpl implements IotAlertConfigService {
|
||||
// 校验关联数据是否存在
|
||||
sceneRuleService.validateSceneRuleList(updateReqVO.getSceneRuleIds());
|
||||
adminUserApi.validateUserList(updateReqVO.getReceiveUserIds());
|
||||
validateReceiveTemplates(updateReqVO);
|
||||
|
||||
// 更新
|
||||
IotAlertConfigDO updateObj = BeanUtils.toBean(updateReqVO, IotAlertConfigDO.class);
|
||||
@@ -76,6 +84,24 @@ public class IotAlertConfigServiceImpl implements IotAlertConfigService {
|
||||
}
|
||||
}
|
||||
|
||||
private void validateReceiveTemplates(IotAlertConfigSaveReqVO reqVO) {
|
||||
if (CollUtil.isEmpty(reqVO.getReceiveTypes())) {
|
||||
return;
|
||||
}
|
||||
if (reqVO.getReceiveTypes().contains(IotAlertReceiveTypeEnum.SMS.getType())
|
||||
&& StrUtil.isBlank(reqVO.getSmsTemplateCode())) {
|
||||
throw exception(ALERT_CONFIG_SMS_TEMPLATE_REQUIRED);
|
||||
}
|
||||
if (reqVO.getReceiveTypes().contains(IotAlertReceiveTypeEnum.MAIL.getType())
|
||||
&& StrUtil.isBlank(reqVO.getMailTemplateCode())) {
|
||||
throw exception(ALERT_CONFIG_MAIL_TEMPLATE_REQUIRED);
|
||||
}
|
||||
if (reqVO.getReceiveTypes().contains(IotAlertReceiveTypeEnum.NOTIFY.getType())
|
||||
&& StrUtil.isBlank(reqVO.getNotifyTemplateCode())) {
|
||||
throw exception(ALERT_CONFIG_NOTIFY_TEMPLATE_REQUIRED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IotAlertConfigDO getAlertConfig(Long id) {
|
||||
return alertConfigMapper.selectById(id);
|
||||
|
||||
+23
-5
@@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.iot.service.rule.scene.action;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
@@ -79,30 +80,38 @@ public class IotAlertTriggerSceneRuleAction implements IotSceneRuleAction {
|
||||
}
|
||||
Map<String, Object> templateParams = buildTemplateParams(config, deviceMessage, device);
|
||||
config.getReceiveUserIds().forEach(userId ->
|
||||
config.getReceiveTypes().forEach(receiveType -> sendAlertMessageToUser(userId, receiveType, templateParams)));
|
||||
config.getReceiveTypes().forEach(receiveType ->
|
||||
sendAlertMessageToUser(userId, receiveType, config, templateParams)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 按指定接收方式,给单个用户发送告警消息
|
||||
*/
|
||||
private void sendAlertMessageToUser(Long userId, Integer receiveType, Map<String, Object> templateParams) {
|
||||
private void sendAlertMessageToUser(Long userId, Integer receiveType, IotAlertConfigDO config,
|
||||
Map<String, Object> templateParams) {
|
||||
IotAlertReceiveTypeEnum typeEnum = IotAlertReceiveTypeEnum.of(receiveType);
|
||||
if (typeEnum == null) {
|
||||
return;
|
||||
}
|
||||
String templateCode = resolveTemplateCode(config, typeEnum);
|
||||
if (StrUtil.isBlank(templateCode)) {//为了兼容老的结构
|
||||
templateCode=typeEnum.getTemplateCode();
|
||||
log.warn("[sendAlertMessageToUser][配置({}) 用户({}) 接收方式({}) 未配置模板,使用默认模板({})]",
|
||||
config.getId(), userId, typeEnum,templateCode);
|
||||
}
|
||||
try {
|
||||
switch (typeEnum) {
|
||||
case SMS:
|
||||
smsSendApi.sendSingleSmsToAdmin(new SmsSendSingleToUserReqDTO().setUserId(userId)
|
||||
.setTemplateCode(typeEnum.getTemplateCode()).setTemplateParams(templateParams));
|
||||
.setTemplateCode(templateCode).setTemplateParams(templateParams));
|
||||
break;
|
||||
case MAIL:
|
||||
mailSendApi.sendSingleMailToAdmin(new MailSendSingleToUserReqDTO().setUserId(userId)
|
||||
.setTemplateCode(typeEnum.getTemplateCode()).setTemplateParams(templateParams));
|
||||
.setTemplateCode(templateCode).setTemplateParams(templateParams));
|
||||
break;
|
||||
case NOTIFY:
|
||||
notifyMessageSendApi.sendSingleMessageToAdmin(new NotifySendSingleToUserReqDTO().setUserId(userId)
|
||||
.setTemplateCode(typeEnum.getTemplateCode()).setTemplateParams(templateParams));
|
||||
.setTemplateCode(templateCode).setTemplateParams(templateParams));
|
||||
break;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
@@ -111,6 +120,15 @@ public class IotAlertTriggerSceneRuleAction implements IotSceneRuleAction {
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveTemplateCode(IotAlertConfigDO config, IotAlertReceiveTypeEnum typeEnum) {
|
||||
String templateCode = switch (typeEnum) {
|
||||
case SMS -> config.getSmsTemplateCode();
|
||||
case MAIL -> config.getMailTemplateCode();
|
||||
case NOTIFY -> config.getNotifyTemplateCode();
|
||||
};
|
||||
return StrUtil.blankToDefault(templateCode, typeEnum.getTemplateCode());
|
||||
}
|
||||
|
||||
private Map<String, Object> buildTemplateParams(IotAlertConfigDO config,
|
||||
@Nullable IotDeviceMessage deviceMessage,
|
||||
@Nullable IotDeviceDO device) {
|
||||
|
||||
+6
-3
@@ -106,6 +106,9 @@ public class IotAlertTriggerSceneRuleActionTest extends BaseMockitoUnitTest {
|
||||
IotAlertReceiveTypeEnum.SMS.getType(),
|
||||
IotAlertReceiveTypeEnum.MAIL.getType(),
|
||||
IotAlertReceiveTypeEnum.NOTIFY.getType()));
|
||||
c.setSmsTemplateCode("custom_sms");
|
||||
c.setMailTemplateCode("custom_mail");
|
||||
c.setNotifyTemplateCode("custom_notify");
|
||||
});
|
||||
IotDeviceDO device = randomPojo(IotDeviceDO.class);
|
||||
|
||||
@@ -130,13 +133,13 @@ public class IotAlertTriggerSceneRuleActionTest extends BaseMockitoUnitTest {
|
||||
ArgumentCaptor<SmsSendSingleToUserReqDTO> smsCaptor = ArgumentCaptor.forClass(SmsSendSingleToUserReqDTO.class);
|
||||
verify(smsSendApi, times(1)).sendSingleSmsToAdmin(smsCaptor.capture());
|
||||
assertEquals(userId, smsCaptor.getValue().getUserId());
|
||||
assertEquals(IotAlertReceiveTypeEnum.SMS.getTemplateCode(), smsCaptor.getValue().getTemplateCode());
|
||||
assertEquals("custom_sms", smsCaptor.getValue().getTemplateCode());
|
||||
ArgumentCaptor<MailSendSingleToUserReqDTO> mailCaptor = ArgumentCaptor.forClass(MailSendSingleToUserReqDTO.class);
|
||||
verify(mailSendApi, times(1)).sendSingleMailToAdmin(mailCaptor.capture());
|
||||
assertEquals(IotAlertReceiveTypeEnum.MAIL.getTemplateCode(), mailCaptor.getValue().getTemplateCode());
|
||||
assertEquals("custom_mail", mailCaptor.getValue().getTemplateCode());
|
||||
ArgumentCaptor<NotifySendSingleToUserReqDTO> notifyCaptor = ArgumentCaptor.forClass(NotifySendSingleToUserReqDTO.class);
|
||||
verify(notifyMessageSendApi, times(1)).sendSingleMessageToAdmin(notifyCaptor.capture());
|
||||
assertEquals(IotAlertReceiveTypeEnum.NOTIFY.getTemplateCode(), notifyCaptor.getValue().getTemplateCode());
|
||||
assertEquals("custom_notify", notifyCaptor.getValue().getTemplateCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+3
@@ -13,4 +13,7 @@ public class MailTemplateSimpleRespVO {
|
||||
@Schema(description = "模版名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "哒哒哒")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "模版编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "mail_001")
|
||||
private String code;
|
||||
|
||||
}
|
||||
|
||||
+8
@@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.Notify
|
||||
import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateSendReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateSimpleRespVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO;
|
||||
import cn.iocoder.yudao.module.system.service.notify.NotifySendService;
|
||||
import cn.iocoder.yudao.module.system.service.notify.NotifyTemplateService;
|
||||
@@ -86,6 +87,13 @@ public class NotifyTemplateController {
|
||||
return success(BeanUtils.toBean(pageResult, NotifyTemplateRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping({"/list-all-simple", "/simple-list"})
|
||||
@Operation(summary = "获得站内信模版精简列表")
|
||||
public CommonResult<List<NotifyTemplateSimpleRespVO>> getSimpleTemplateList() {
|
||||
List<NotifyTemplateDO> list = notifyTemplateService.getNotifyTemplateList();
|
||||
return success(BeanUtils.toBean(list, NotifyTemplateSimpleRespVO.class));
|
||||
}
|
||||
|
||||
@PostMapping("/send-notify")
|
||||
@Operation(summary = "发送站内信")
|
||||
@PreAuthorize("@ss.hasPermission('system:notify-template:send-notify')")
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.notify.vo.template;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - 站内信模版的精简 Response VO")
|
||||
@Data
|
||||
public class NotifyTemplateSimpleRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "模版名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "系统通知")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "模版编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "notify_001")
|
||||
private String code;
|
||||
|
||||
}
|
||||
+8
@@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTempla
|
||||
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSendReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSimpleRespVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO;
|
||||
import cn.iocoder.yudao.module.system.service.sms.SmsSendService;
|
||||
import cn.iocoder.yudao.module.system.service.sms.SmsTemplateService;
|
||||
@@ -88,6 +89,13 @@ public class SmsTemplateController {
|
||||
return success(BeanUtils.toBean(pageResult, SmsTemplateRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping({"/list-all-simple", "/simple-list"})
|
||||
@Operation(summary = "获得短信模板精简列表")
|
||||
public CommonResult<List<SmsTemplateSimpleRespVO>> getSimpleTemplateList() {
|
||||
List<SmsTemplateDO> list = smsTemplateService.getSmsTemplateList();
|
||||
return success(BeanUtils.toBean(list, SmsTemplateSimpleRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出短信模板 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('system:sms-template:export')")
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.sms.vo.template;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - 短信模板的精简 Response VO")
|
||||
@Data
|
||||
public class SmsTemplateSimpleRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "验证码")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "sms_001")
|
||||
private String code;
|
||||
|
||||
}
|
||||
+7
@@ -69,6 +69,13 @@ public interface NotifyTemplateService {
|
||||
*/
|
||||
PageResult<NotifyTemplateDO> getNotifyTemplatePage(NotifyTemplatePageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 获得启用状态的站内信模版列表
|
||||
*
|
||||
* @return 站内信模版列表
|
||||
*/
|
||||
List<NotifyTemplateDO> getNotifyTemplateList();
|
||||
|
||||
/**
|
||||
* 格式化站内信内容
|
||||
*
|
||||
|
||||
+6
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.service.notify;
|
||||
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplatePageReqVO;
|
||||
@@ -115,6 +116,11 @@ public class NotifyTemplateServiceImpl implements NotifyTemplateService {
|
||||
return notifyTemplateMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NotifyTemplateDO> getNotifyTemplateList() {
|
||||
return notifyTemplateMapper.selectList(NotifyTemplateDO::getStatus, CommonStatusEnum.ENABLE.getStatus());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void validateNotifyTemplateCodeDuplicate(Long id, String code) {
|
||||
NotifyTemplateDO template = notifyTemplateMapper.selectByCode(code);
|
||||
|
||||
+7
@@ -70,6 +70,13 @@ public interface SmsTemplateService {
|
||||
*/
|
||||
PageResult<SmsTemplateDO> getSmsTemplatePage(SmsTemplatePageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 获得启用状态的短信模板列表
|
||||
*
|
||||
* @return 短信模板列表
|
||||
*/
|
||||
List<SmsTemplateDO> getSmsTemplateList();
|
||||
|
||||
/**
|
||||
* 获得指定短信渠道下的短信模板数量
|
||||
*
|
||||
|
||||
+5
@@ -130,6 +130,11 @@ public class SmsTemplateServiceImpl implements SmsTemplateService {
|
||||
return smsTemplateMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SmsTemplateDO> getSmsTemplateList() {
|
||||
return smsTemplateMapper.selectList(SmsTemplateDO::getStatus, CommonStatusEnum.ENABLE.getStatus());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getSmsTemplateCountByChannelId(Long channelId) {
|
||||
return smsTemplateMapper.selectCountByChannelId(channelId);
|
||||
|
||||
Reference in New Issue
Block a user