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;
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.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
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.controller.admin.alert.vo.IotAlertConfigPageReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.alert.vo.IotAlertConfigRespVO;
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.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 告警配置")
@RestController
@@ -38,6 +35,9 @@ public class IotAlertConfigController {
@Resource
private IotAlertConfigService alertConfigService;
@Resource
private AdminUserApi adminUserApi;
@PostMapping("/create")
@Operation(summary = "创建告警配置")
@PreAuthorize("@ss.hasPermission('iot:alert-config:create')")
@@ -76,7 +76,12 @@ public class IotAlertConfigController {
@PreAuthorize("@ss.hasPermission('iot:alert-config:query')")
public CommonResult<PageResult<IotAlertConfigRespVO>> getAlertConfigPage(@Valid IotAlertConfigPageReqVO 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")
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")
private List<Integer> receiveTypes;

View File

@@ -1,5 +1,6 @@
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.PageResult;
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.web.bind.annotation.*;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
@Tag(name = "管理后台 - IoT 场景联动")
@RestController
@@ -70,6 +74,14 @@ public class IotRuleSceneController {
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 -> // 只返回 id、name 字段
new IotRuleSceneRespVO().setId(scene.getId()).setName(scene.getName())));
}
@GetMapping("/test")
@PermitAll
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.module.iot.dal.dataobject.rule.IotRuleSceneDO;
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 com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
@@ -24,7 +24,7 @@ import java.util.List;
*
* @author 芋道源码
*/
@TableName("iot_alert_config")
@TableName(value = "iot_alert_config", autoResultMap = true)
@KeySequence("iot_alert_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@Builder
@@ -76,7 +76,7 @@ public class IotAlertConfigDO extends BaseDO {
/**
* 接收的类型数组
*
* 枚举 {@link IotAlertConfigReceiveTypeEnum}
* 枚举 {@link IotAlertReceiveTypeEnum}
*/
@TableField(typeHandler = IntegerListTypeHandler.class)
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 org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* IoT 场景联动 Mapper
*
@@ -24,4 +26,8 @@ public interface IotRuleSceneMapper extends BaseMapperX<IotRuleSceneDO> {
.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;
/**
* IoT 告警配置的接收方式枚举
* IoT 告警的接收方式枚举
*
* @author 芋道源码
*/
@RequiredArgsConstructor
@Getter
public enum IotAlertConfigReceiveTypeEnum implements ArrayValuable<Integer> {
public enum IotAlertReceiveTypeEnum implements ArrayValuable<Integer> {
SMS(1), // 短信
MAIL(2), // 邮箱
NOTIFY(3); // 通知
NOTIFY(3); // 站内信
// TODO 待实现欢迎 pull requestwebhook 4
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
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.dal.dataobject.alert.IotAlertConfigDO;
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 org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@@ -25,8 +27,18 @@ public class IotAlertConfigServiceImpl implements IotAlertConfigService {
@Resource
private IotAlertConfigMapper alertConfigMapper;
@Resource
private IotRuleSceneService ruleSceneService;
@Resource
private AdminUserApi adminUserApi;
@Override
public Long createAlertConfig(IotAlertConfigSaveReqVO createReqVO) {
// 校验关联数据是否存在
ruleSceneService.validateRuleSceneList(createReqVO.getSceneRuleIds());
adminUserApi.validateUserList(createReqVO.getReceiveUserIds());
IotAlertConfigDO alertConfig = BeanUtils.toBean(createReqVO, IotAlertConfigDO.class);
alertConfigMapper.insert(alertConfig);
return alertConfig.getId();
@@ -36,6 +48,10 @@ public class IotAlertConfigServiceImpl implements IotAlertConfigService {
public void updateAlertConfig(IotAlertConfigSaveReqVO updateReqVO) {
// 校验存在
validateAlertConfigExists(updateReqVO.getId());
// 校验关联数据是否存在
ruleSceneService.validateRuleSceneList(updateReqVO.getSceneRuleIds());
adminUserApi.validateUserList(updateReqVO.getReceiveUserIds());
// 更新
IotAlertConfigDO updateObj = BeanUtils.toBean(updateReqVO, IotAlertConfigDO.class);
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 jakarta.validation.Valid;
import java.util.Collection;
import java.util.List;
/**
@@ -55,6 +56,22 @@ public interface IotRuleSceneService {
*/
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.List;
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.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.module.iot.enums.ErrorCodeConstants.RULE_SCENE_NOT_EXISTS;
@@ -109,6 +112,22 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
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 芋艿,缓存待实现
@Override