【代码评审】IoT:物模型的管理

This commit is contained in:
YunaiV 2025-01-28 22:24:28 +08:00
parent 0b16f1678c
commit 76ab64a255
11 changed files with 42 additions and 83 deletions

View File

@ -5,6 +5,7 @@ import lombok.Data;
import java.util.List; import java.util.List;
// TODO @puhui999必要的参数校验
/** /**
* 物模型中的事件 * 物模型中的事件
* *

View File

@ -6,6 +6,7 @@ import lombok.Data;
import java.util.List; import java.util.List;
// TODO @puhui999必要的参数校验
/** /**
* IOT 产品物模型中的参数 * IOT 产品物模型中的参数
* *

View File

@ -6,6 +6,7 @@ import lombok.Data;
import java.util.List; import java.util.List;
// TODO @puhui999必要的参数校验
/** /**
* 物模型中的属性 * 物模型中的属性
* *

View File

@ -1,50 +0,0 @@
package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model;
import lombok.*;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class ThingModelRespVO {
/**
* 产品编号
*/
private Long id;
/**
* 产品标识
*/
private String productKey;
/**
* 物模型
*/
private Model model;
/**
* 物模型
*/
@Data
public static class Model {
/**
* 属性列表
*/
private List<ThingModelProperty> properties;
/**
* 服务列表
*/
private List<ThingModelService> services;
/**
* 事件列表
*/
private List<ThingModelEvent> events;
}
}

View File

@ -5,6 +5,7 @@ import lombok.Data;
import java.util.List; import java.util.List;
// TODO @puhui999必要的参数校验
/** /**
* 物模型中的服务 * 物模型中的服务
* *

View File

@ -6,10 +6,15 @@ import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
@Schema(description = "管理后台 - IoT 产品物模型List Request VO") // TODO @puhui999部分字段可以用 cursor 加上 example
@Schema(description = "管理后台 - IoT 产品物模型 List Request VO")
@Data @Data
public class IotThingModelListReqVO { public class IotThingModelListReqVO {
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "产品编号不能为空")
private Long productId;
@Schema(description = "功能标识") @Schema(description = "功能标识")
private String identifier; private String identifier;
@ -20,8 +25,4 @@ public class IotThingModelListReqVO {
@InEnum(IotThingModelTypeEnum.class) @InEnum(IotThingModelTypeEnum.class)
private Integer type; private Integer type;
@Schema(description = "产品 ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "产品 ID 不能为空")
private Long productId;
} }

View File

@ -9,12 +9,17 @@ import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString; import lombok.ToString;
// TODO @puhui999部分字段可以用 cursor 加上 example
@Schema(description = "管理后台 - IoT 产品物模型分页 Request VO") @Schema(description = "管理后台 - IoT 产品物模型分页 Request VO")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)
public class IotThingModelPageReqVO extends PageParam { public class IotThingModelPageReqVO extends PageParam {
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "产品编号不能为空")
private Long productId;
@Schema(description = "功能标识") @Schema(description = "功能标识")
private String identifier; private String identifier;
@ -25,8 +30,4 @@ public class IotThingModelPageReqVO extends PageParam {
@InEnum(IotThingModelTypeEnum.class) @InEnum(IotThingModelTypeEnum.class)
private Integer type; private Integer type;
@Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "产品ID不能为空")
private Long productId;
} }

View File

@ -10,6 +10,7 @@ import lombok.Data;
import java.time.LocalDateTime; import java.time.LocalDateTime;
// TODO @puhui999部分字段可以用 cursor 加上 example
@Schema(description = "管理后台 - IoT 产品物模型 Response VO") @Schema(description = "管理后台 - IoT 产品物模型 Response VO")
@Data @Data
@ExcelIgnoreUnannotated @ExcelIgnoreUnannotated

View File

@ -10,6 +10,7 @@ import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
// TODO @puhui999部分字段可以用 cursor 加上 example
@Schema(description = "管理后台 - IoT 产品物模型新增/修改 Request VO") @Schema(description = "管理后台 - IoT 产品物模型新增/修改 Request VO")
@Data @Data
public class IotThingModelSaveReqVO { public class IotThingModelSaveReqVO {

View File

@ -79,4 +79,5 @@ public interface IotThingModelService {
* @return 产品物模型列表 * @return 产品物模型列表
*/ */
List<IotThingModelDO> getThingModelList(IotThingModelListReqVO reqVO); List<IotThingModelDO> getThingModelList(IotThingModelListReqVO reqVO);
} }

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.iot.service.thingmodel;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil; import cn.hutool.extra.spring.SpringUtil;
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;
@ -54,29 +55,26 @@ public class IotThingModelServiceImpl implements IotThingModelService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Long createThingModel(IotThingModelSaveReqVO createReqVO) { public Long createThingModel(IotThingModelSaveReqVO createReqVO) {
// 1. 校验功能标识符在同一产品下是否唯一 // 1.1 校验功能标识符在同一产品下是否唯一
validateIdentifierUnique(createReqVO.getProductId(), createReqVO.getIdentifier()); validateIdentifierUnique(createReqVO.getProductId(), createReqVO.getIdentifier());
// 1.2 功能名称在同一产品下是否唯一
// 2. 功能名称在同一产品下是否唯一
validateNameUnique(createReqVO.getProductId(), createReqVO.getName()); validateNameUnique(createReqVO.getProductId(), createReqVO.getName());
// 1.3 系统保留字段不能用于标识符定义
// 3. 系统保留字段不能用于标识符定义
validateNotDefaultEventAndService(createReqVO.getIdentifier()); validateNotDefaultEventAndService(createReqVO.getIdentifier());
// 1.4 校验产品状态发布状态下不允许新增功能
// 4. 校验产品状态发布状态下不允许新增功能
validateProductStatus(createReqVO.getProductId()); validateProductStatus(createReqVO.getProductId());
// 5. 插入数据库 // 2. 插入数据库
IotThingModelDO thingModel = IotThingModelConvert.INSTANCE.convert(createReqVO); IotThingModelDO thingModel = IotThingModelConvert.INSTANCE.convert(createReqVO);
thingModelMapper.insert(thingModel); thingModelMapper.insert(thingModel);
// 6. 如果创建的是属性需要更新默认的事件和服务 // 3. 如果创建的是属性需要更新默认的事件和服务
if (Objects.equals(createReqVO.getType(), IotThingModelTypeEnum.PROPERTY.getType())) { if (Objects.equals(createReqVO.getType(), IotThingModelTypeEnum.PROPERTY.getType())) {
createDefaultEventsAndServices(createReqVO.getProductId(), createReqVO.getProductKey()); createDefaultEventsAndServices(createReqVO.getProductId(), createReqVO.getProductKey());
} }
// TODO @puhui999: 服务和事件的情况 method 怎么设置在前端设置还是后端设置 // TODO @puhui999: 服务和事件的情况 method 怎么设置在前端设置还是后端设置
// 7. 删除缓存 // 4. 删除缓存
deleteThingModelListCache(createReqVO.getProductKey()); deleteThingModelListCache(createReqVO.getProductKey());
return thingModel.getId(); return thingModel.getId();
} }
@ -84,38 +82,35 @@ public class IotThingModelServiceImpl implements IotThingModelService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateThingModel(IotThingModelSaveReqVO updateReqVO) { public void updateThingModel(IotThingModelSaveReqVO updateReqVO) {
// 1. 校验功能是否存在 // 1.1 校验功能是否存在
validateProductThingModelMapperExists(updateReqVO.getId()); validateProductThingModelMapperExists(updateReqVO.getId());
// 1.2 校验功能标识符是否唯一
// 2. 校验功能标识符是否唯一
validateIdentifierUniqueForUpdate(updateReqVO.getId(), updateReqVO.getProductId(), updateReqVO.getIdentifier()); validateIdentifierUniqueForUpdate(updateReqVO.getId(), updateReqVO.getProductId(), updateReqVO.getIdentifier());
// 1.3 校验产品状态发布状态下不允许操作功能
// 3. 校验产品状态发布状态下不允许操作功能
validateProductStatus(updateReqVO.getProductId()); validateProductStatus(updateReqVO.getProductId());
// 4. 更新数据库 // 2. 更新数据库
IotThingModelDO thingModel = IotThingModelConvert.INSTANCE.convert(updateReqVO); IotThingModelDO thingModel = IotThingModelConvert.INSTANCE.convert(updateReqVO);
thingModelMapper.updateById(thingModel); thingModelMapper.updateById(thingModel);
// 5. 如果更新的是属性需要更新默认的事件和服务 // 3. 如果更新的是属性需要更新默认的事件和服务
if (Objects.equals(updateReqVO.getType(), IotThingModelTypeEnum.PROPERTY.getType())) { if (Objects.equals(updateReqVO.getType(), IotThingModelTypeEnum.PROPERTY.getType())) {
createDefaultEventsAndServices(updateReqVO.getProductId(), updateReqVO.getProductKey()); createDefaultEventsAndServices(updateReqVO.getProductId(), updateReqVO.getProductKey());
} }
// 6. 删除缓存 // 4. 删除缓存
deleteThingModelListCache(updateReqVO.getProductKey()); deleteThingModelListCache(updateReqVO.getProductKey());
} }
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void deleteThingModel(Long id) { public void deleteThingModel(Long id) {
// 1. 校验功能是否存在 // 1.1 校验功能是否存在
IotThingModelDO thingModel = thingModelMapper.selectById(id); IotThingModelDO thingModel = thingModelMapper.selectById(id);
if (thingModel == null) { if (thingModel == null) {
throw exception(THING_MODEL_NOT_EXISTS); throw exception(THING_MODEL_NOT_EXISTS);
} }
// 1.2 校验产品状态发布状态下不允许操作功能
// 3. 校验产品状态发布状态下不允许操作功能
validateProductStatus(thingModel.getProductId()); validateProductStatus(thingModel.getProductId());
// 2. 删除功能 // 2. 删除功能
@ -168,6 +163,7 @@ public class IotThingModelServiceImpl implements IotThingModelService {
} }
} }
// TODO @puhui999这个方法 validateIdentifierUnique 可以融合下
private void validateIdentifierUniqueForUpdate(Long id, Long productId, String identifier) { private void validateIdentifierUniqueForUpdate(Long id, Long productId, String identifier) {
IotThingModelDO thingModel = thingModelMapper.selectByProductIdAndIdentifier(productId, identifier); IotThingModelDO thingModel = thingModelMapper.selectByProductIdAndIdentifier(productId, identifier);
if (thingModel != null && ObjectUtil.notEqual(thingModel.getId(), id)) { if (thingModel != null && ObjectUtil.notEqual(thingModel.getId(), id)) {
@ -176,15 +172,16 @@ public class IotThingModelServiceImpl implements IotThingModelService {
} }
private void validateProductStatus(Long createReqVO) { private void validateProductStatus(Long createReqVO) {
IotProductDO product = productService.getProduct(createReqVO); IotProductDO product = productService.validateProductExists(createReqVO);
if (Objects.equals(product.getStatus(), IotProductStatusEnum.PUBLISHED.getStatus())) { if (Objects.equals(product.getStatus(), IotProductStatusEnum.PUBLISHED.getStatus())) {
throw exception(PRODUCT_STATUS_NOT_ALLOW_THING_MODEL); throw exception(PRODUCT_STATUS_NOT_ALLOW_THING_MODEL);
} }
} }
// TODO @芋艿 review
private void validateNotDefaultEventAndService(String identifier) { private void validateNotDefaultEventAndService(String identifier) {
// set, get, post, property, event, time, value 系统保留字段不能用于标识符定义 // 系统保留字段不能用于标识符定义
if (CollUtil.containsAny(Arrays.asList("set", "get", "post", "property", "event", "time", "value"), Collections.singletonList(identifier))) { if (StrUtil.equalsAny(identifier, "set", "get", "post", "property", "event", "time", "value")) {
throw exception(THING_MODEL_IDENTIFIER_INVALID); throw exception(THING_MODEL_IDENTIFIER_INVALID);
} }
} }
@ -205,6 +202,9 @@ public class IotThingModelServiceImpl implements IotThingModelService {
/** /**
* 创建默认的事件和服务 * 创建默认的事件和服务
*
* @param productId 产品编号
* @param productKey 产品标识
*/ */
public void createDefaultEventsAndServices(Long productId, String productKey) { public void createDefaultEventsAndServices(Long productId, String productKey) {
// 1. 获取当前属性列表 // 1. 获取当前属性列表