feat:【IoT 物联网】完成告警配置的管理

This commit is contained in:
YunaiV 2025-06-27 23:46:53 +08:00
parent 9d6b37c476
commit 1beb5c039c
9 changed files with 111 additions and 32 deletions

View File

@ -1,33 +1,30 @@
package cn.iocoder.yudao.module.iot.controller.admin.alert; package cn.iocoder.yudao.module.iot.controller.admin.alert;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.constraints.*;
import jakarta.validation.*;
import jakarta.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import cn.iocoder.yudao.module.iot.controller.admin.alert.vo.IotAlertConfigPageReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.alert.vo.IotAlertConfigRespVO;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.module.iot.controller.admin.alert.vo.IotAlertConfigSaveReqVO;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
import cn.iocoder.yudao.module.iot.controller.admin.alert.vo.*;
import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertConfigDO; import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertConfigDO;
import cn.iocoder.yudao.module.iot.service.alert.IotAlertConfigService; import cn.iocoder.yudao.module.iot.service.alert.IotAlertConfigService;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
@Tag(name = "管理后台 - IoT 告警配置") @Tag(name = "管理后台 - IoT 告警配置")
@RestController @RestController
@ -38,6 +35,9 @@ public class IotAlertConfigController {
@Resource @Resource
private IotAlertConfigService alertConfigService; private IotAlertConfigService alertConfigService;
@Resource
private AdminUserApi adminUserApi;
@PostMapping("/create") @PostMapping("/create")
@Operation(summary = "创建告警配置") @Operation(summary = "创建告警配置")
@PreAuthorize("@ss.hasPermission('iot:alert-config:create')") @PreAuthorize("@ss.hasPermission('iot:alert-config:create')")
@ -76,7 +76,12 @@ public class IotAlertConfigController {
@PreAuthorize("@ss.hasPermission('iot:alert-config:query')") @PreAuthorize("@ss.hasPermission('iot:alert-config:query')")
public CommonResult<PageResult<IotAlertConfigRespVO>> getAlertConfigPage(@Valid IotAlertConfigPageReqVO pageReqVO) { public CommonResult<PageResult<IotAlertConfigRespVO>> getAlertConfigPage(@Valid IotAlertConfigPageReqVO pageReqVO) {
PageResult<IotAlertConfigDO> pageResult = alertConfigService.getAlertConfigPage(pageReqVO); PageResult<IotAlertConfigDO> pageResult = alertConfigService.getAlertConfigPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, IotAlertConfigRespVO.class)); // 转换返回
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
convertSetByFlatMap(pageResult.getList(), config -> config.getReceiveUserIds().stream()));
return success(BeanUtils.toBean(pageResult, IotAlertConfigRespVO.class, vo ->
vo.setReceiveUserNames(vo.getReceiveUserIds().stream().map(userMap::get)
.filter(Objects::nonNull).map(AdminUserRespDTO::getNickname).collect(Collectors.toList()))));
} }
} }

View File

@ -31,6 +31,9 @@ public class IotAlertConfigRespVO {
@Schema(description = "接收的用户编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "100,200") @Schema(description = "接收的用户编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "100,200")
private List<Long> receiveUserIds; private List<Long> receiveUserIds;
@Schema(description = "接收的用户名称数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三,李四")
private List<String> receiveUserNames;
@Schema(description = "接收的类型数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1,2,3") @Schema(description = "接收的类型数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1,2,3")
private List<Integer> receiveTypes; private List<Integer> receiveTypes;

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.iot.controller.admin.rule; package cn.iocoder.yudao.module.iot.controller.admin.rule;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
@ -18,7 +19,10 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
@Tag(name = "管理后台 - IoT 场景联动") @Tag(name = "管理后台 - IoT 场景联动")
@RestController @RestController
@ -70,6 +74,14 @@ public class IotRuleSceneController {
return success(BeanUtils.toBean(pageResult, IotRuleSceneRespVO.class)); return success(BeanUtils.toBean(pageResult, IotRuleSceneRespVO.class));
} }
@GetMapping("/simple-list")
@Operation(summary = "获取场景联动的精简信息列表", description = "主要用于前端的下拉选项")
public CommonResult<List<IotRuleSceneRespVO>> getRuleSceneSimpleList() {
List<IotRuleSceneDO> list = ruleSceneService.getRuleSceneListByStatus(CommonStatusEnum.ENABLE.getStatus());
return success(convertList(list, scene -> // 只返回 idname 字段
new IotRuleSceneRespVO().setId(scene.getId()).setName(scene.getName())));
}
@GetMapping("/test") @GetMapping("/test")
@PermitAll @PermitAll
public void test() { public void test() {

View File

@ -6,7 +6,7 @@ import cn.iocoder.yudao.framework.mybatis.core.type.IntegerListTypeHandler;
import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
import cn.iocoder.yudao.module.iot.enums.DictTypeConstants; import cn.iocoder.yudao.module.iot.enums.DictTypeConstants;
import cn.iocoder.yudao.module.iot.enums.alert.IotAlertConfigReceiveTypeEnum; import cn.iocoder.yudao.module.iot.enums.alert.IotAlertReceiveTypeEnum;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
@ -24,7 +24,7 @@ import java.util.List;
* *
* @author 芋道源码 * @author 芋道源码
*/ */
@TableName("iot_alert_config") @TableName(value = "iot_alert_config", autoResultMap = true)
@KeySequence("iot_alert_config_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写 @KeySequence("iot_alert_config_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data @Data
@Builder @Builder
@ -76,7 +76,7 @@ public class IotAlertConfigDO extends BaseDO {
/** /**
* 接收的类型数组 * 接收的类型数组
* *
* 枚举 {@link IotAlertConfigReceiveTypeEnum} * 枚举 {@link IotAlertReceiveTypeEnum}
*/ */
@TableField(typeHandler = IntegerListTypeHandler.class) @TableField(typeHandler = IntegerListTypeHandler.class)
private List<Integer> receiveTypes; private List<Integer> receiveTypes;

View File

@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePa
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/** /**
* IoT 场景联动 Mapper * IoT 场景联动 Mapper
* *
@ -24,4 +26,8 @@ public interface IotRuleSceneMapper extends BaseMapperX<IotRuleSceneDO> {
.orderByDesc(IotRuleSceneDO::getId)); .orderByDesc(IotRuleSceneDO::getId));
} }
default List<IotRuleSceneDO> selectListByStatus(Integer status) {
return selectList(IotRuleSceneDO::getStatus, status);
}
} }

View File

@ -7,21 +7,22 @@ import lombok.RequiredArgsConstructor;
import java.util.Arrays; import java.util.Arrays;
/** /**
* IoT 告警配置的接收方式枚举 * IoT 告警的接收方式枚举
* *
* @author 芋道源码 * @author 芋道源码
*/ */
@RequiredArgsConstructor @RequiredArgsConstructor
@Getter @Getter
public enum IotAlertConfigReceiveTypeEnum implements ArrayValuable<Integer> { public enum IotAlertReceiveTypeEnum implements ArrayValuable<Integer> {
SMS(1), // 短信 SMS(1), // 短信
MAIL(2), // 邮箱 MAIL(2), // 邮箱
NOTIFY(3); // 通知 NOTIFY(3); // 站内信
// TODO 待实现欢迎 pull requestwebhook 4
private final Integer type; private final Integer type;
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotAlertConfigReceiveTypeEnum::getType).toArray(Integer[]::new); public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotAlertReceiveTypeEnum::getType).toArray(Integer[]::new);
@Override @Override
public Integer[] array() { public Integer[] array() {

View File

@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.iot.controller.admin.alert.vo.IotAlertConfigPageR
import cn.iocoder.yudao.module.iot.controller.admin.alert.vo.IotAlertConfigSaveReqVO; import cn.iocoder.yudao.module.iot.controller.admin.alert.vo.IotAlertConfigSaveReqVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertConfigDO; 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.dal.mysql.alert.IotAlertConfigMapper;
import cn.iocoder.yudao.module.iot.service.rule.scene.IotRuleSceneService;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -25,8 +27,18 @@ public class IotAlertConfigServiceImpl implements IotAlertConfigService {
@Resource @Resource
private IotAlertConfigMapper alertConfigMapper; private IotAlertConfigMapper alertConfigMapper;
@Resource
private IotRuleSceneService ruleSceneService;
@Resource
private AdminUserApi adminUserApi;
@Override @Override
public Long createAlertConfig(IotAlertConfigSaveReqVO createReqVO) { public Long createAlertConfig(IotAlertConfigSaveReqVO createReqVO) {
// 校验关联数据是否存在
ruleSceneService.validateRuleSceneList(createReqVO.getSceneRuleIds());
adminUserApi.validateUserList(createReqVO.getReceiveUserIds());
IotAlertConfigDO alertConfig = BeanUtils.toBean(createReqVO, IotAlertConfigDO.class); IotAlertConfigDO alertConfig = BeanUtils.toBean(createReqVO, IotAlertConfigDO.class);
alertConfigMapper.insert(alertConfig); alertConfigMapper.insert(alertConfig);
return alertConfig.getId(); return alertConfig.getId();
@ -36,6 +48,10 @@ public class IotAlertConfigServiceImpl implements IotAlertConfigService {
public void updateAlertConfig(IotAlertConfigSaveReqVO updateReqVO) { public void updateAlertConfig(IotAlertConfigSaveReqVO updateReqVO) {
// 校验存在 // 校验存在
validateAlertConfigExists(updateReqVO.getId()); validateAlertConfigExists(updateReqVO.getId());
// 校验关联数据是否存在
ruleSceneService.validateRuleSceneList(updateReqVO.getSceneRuleIds());
adminUserApi.validateUserList(updateReqVO.getReceiveUserIds());
// 更新 // 更新
IotAlertConfigDO updateObj = BeanUtils.toBean(updateReqVO, IotAlertConfigDO.class); IotAlertConfigDO updateObj = BeanUtils.toBean(updateReqVO, IotAlertConfigDO.class);
alertConfigMapper.updateById(updateObj); alertConfigMapper.updateById(updateObj);

View File

@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum; import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import java.util.Collection;
import java.util.List; import java.util.List;
/** /**
@ -55,6 +56,22 @@ public interface IotRuleSceneService {
*/ */
PageResult<IotRuleSceneDO> getRuleScenePage(IotRuleScenePageReqVO pageReqVO); PageResult<IotRuleSceneDO> getRuleScenePage(IotRuleScenePageReqVO pageReqVO);
/**
* 校验规则场景编号们是否存在如下情况视为无效
* 1. 规则场景编号不存在
*
* @param ids 规则场景编号数组
*/
void validateRuleSceneList(Collection<Long> ids);
/**
* 获得指定状态的场景联动列表
*
* @param status 状态
* @return 场景联动列表
*/
List<IotRuleSceneDO> getRuleSceneListByStatus(Integer status);
/** /**
* 缓存获得指定设备的场景列表 * 缓存获得指定设备的场景列表
* *

View File

@ -42,9 +42,12 @@ import org.springframework.validation.annotation.Validated;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Collection;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.RULE_SCENE_NOT_EXISTS; import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.RULE_SCENE_NOT_EXISTS;
@ -109,6 +112,22 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
return ruleSceneMapper.selectPage(pageReqVO); return ruleSceneMapper.selectPage(pageReqVO);
} }
@Override
public void validateRuleSceneList(Collection<Long> ids) {
if (CollUtil.isEmpty(ids)) {
return;
}
// 批量查询存在的规则场景
List<IotRuleSceneDO> existingScenes = ruleSceneMapper.selectByIds(ids);
if (existingScenes.size() != ids.size()) {
throw exception(RULE_SCENE_NOT_EXISTS);
}
}
@Override
public List<IotRuleSceneDO> getRuleSceneListByStatus(Integer status) {
return ruleSceneMapper.selectListByStatus(status);
}
// TODO 芋艿缓存待实现 // TODO 芋艿缓存待实现
@Override @Override