Ver código fonte

修改:IOT 物模型接口优化

安浩浩 9 meses atrás
pai
commit
2932314ee0
12 arquivos alterados com 400 adições e 569 exclusões
  1. 1 0
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java
  2. 47 0
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotThingModelTypeEnum.java
  3. 49 262
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http
  4. 10 8
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.java
  5. 21 9
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionRespVO.java
  6. 24 9
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionSaveReqVO.java
  7. 24 54
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/convert/thinkmodelfunction/IotThinkModelFunctionConvert.java
  8. 43 14
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thinkmodelfunction/IotThinkModelFunctionDO.java
  9. 0 85
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thinkmodelfunction/IotThinkModelFunctionDO2.java
  10. 11 4
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java
  11. 16 13
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java
  12. 154 111
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java

+ 1 - 0
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java

@@ -17,4 +17,5 @@ public interface ErrorCodeConstants {
     // ========== IoT 产品物模型 1-050-002-000 ============
     ErrorCode THINK_MODEL_FUNCTION_NOT_EXISTS = new ErrorCode(1_050_002_000, "产品物模型不存在");
     ErrorCode THINK_MODEL_FUNCTION_EXISTS_BY_PRODUCT_KEY = new ErrorCode(1_050_002_001, "ProductKey 对应的产品物模型已存在");
+    ErrorCode THINK_MODEL_FUNCTION_EXISTS_BY_IDENTIFIER = new ErrorCode(1_050_002_002, "产品物模型标识已存在");
 }

+ 47 - 0
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotThingModelTypeEnum.java

@@ -0,0 +1,47 @@
+package cn.iocoder.yudao.module.iot.enums.product;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * IOT 物模型功能类型枚举类
+ *
+ * @author ahh
+ */
+@AllArgsConstructor
+@Getter
+public enum IotThingModelTypeEnum implements IntArrayValuable {
+
+    /**
+     * 属性
+     */
+    PROPERTY(1, "属性"),
+    /**
+     * 服务
+     */
+    SERVICE(2, "服务"),
+    /**
+     * 事件
+     */
+    EVENT(3, "事件");
+
+    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(IotThingModelTypeEnum::getType).toArray();
+
+    /**
+     * 类型
+     */
+    private final Integer type;
+    /**
+     * 描述
+     */
+    private final String description;
+
+    @Override
+    public int[] array() {
+        return ARRAYS;
+    }
+
+}

+ 49 - 262
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http

@@ -5,137 +5,28 @@ tenant-id: {{adminTenentId}}
 Authorization: Bearer {{token}}
 
 {
-  "productId": 1002,
-  "productKey": "smart-sensor-002",
-  "properties": [
-    {
-      "identifier": "Temperature",
-      "name": "温度",
-      "accessMode": "r",
-      "required": true,
-      "dataType": {
-        "type": "float",
-        "specs": {
-          "min": -40.0,
-          "max": 125.0,
-          "step": 0.1,
-          "unit": "℃"
-        }
-      },
-      "description": "当前温度值"
+  "productId": 1001,
+  "productKey": "smart-sensor-001",
+  "identifier": "Temperature",
+  "name": "温度",
+  "description": "当前温度值",
+  "type": 1,
+  "property": {
+    "identifier": "Temperature",
+    "name": "温度",
+    "accessMode": "r",
+    "required": true,
+    "dataType": {
+      "type": "float",
+      "specs": {
+        "min": -40.0,
+        "max": 125.0,
+        "step": 0.1,
+        "unit": "℃"
+      }
     },
-    {
-      "identifier": "Humidity",
-      "name": "湿度",
-      "accessMode": "r",
-      "required": true,
-      "dataType": {
-        "type": "float",
-        "specs": {
-          "min": 0.0,
-          "max": 100.0,
-          "step": 0.1,
-          "unit": "%"
-        }
-      },
-      "description": "当前湿度值"
-    },
-    {
-      "identifier": "GeoLocation",
-      "name": "地理位置",
-      "accessMode": "r",
-      "required": false,
-      "dataType": {
-        "type": "struct",
-        "specs": [
-          {
-            "identifier": "Longitude",
-            "name": "经度",
-            "dataType": {
-              "type": "double",
-              "specs": {
-                "min": -180.0,
-                "max": 180.0,
-                "step": 0.000001,
-                "unit": "°"
-              }
-            },
-            "description": "设备所在位置的经度"
-          },
-          {
-            "identifier": "Latitude",
-            "name": "纬度",
-            "dataType": {
-              "type": "double",
-              "specs": {
-                "min": -90.0,
-                "max": 90.0,
-                "step": 0.000001,
-                "unit": "°"
-              }
-            },
-            "description": "设备所在位置的纬度"
-          }
-        ]
-      },
-      "description": "设备的地理位置信息"
-    }
-  ],
-  "services": [
-    {
-      "identifier": "Reboot",
-      "name": "重启设备",
-      "callType": "async",
-      "inputData": [],
-      "description": "远程重启设备",
-      "method": "thing.service.reboot"
-    },
-    {
-      "identifier": "SetThreshold",
-      "name": "设置温度阈值",
-      "callType": "sync",
-      "inputData": [
-        {
-          "identifier": "Threshold",
-          "name": "阈值",
-          "dataType": {
-            "type": "float",
-            "specs": {
-              "min": -40.0,
-              "max": 125.0,
-              "step": 0.1,
-              "unit": "℃"
-            }
-          },
-          "description": "报警温度阈值"
-        }
-      ],
-      "description": "设置设备的温度报警阈值",
-      "method": "thing.service.setThreshold"
-    }
-  ],
-  "events": [
-    {
-      "identifier": "HighTemperatureAlert",
-      "name": "高温报警",
-      "type": "alert",
-      "outputData": [
-        {
-          "identifier": "CurrentTemperature",
-          "name": "当前温度",
-          "dataType": {
-            "type": "float",
-            "specs": {
-              "unit": "℃"
-            }
-          },
-          "description": "触发报警时的温度值"
-        }
-      ],
-      "description": "当温度超过阈值时触发高温报警事件",
-      "method": "thing.event.highTemperatureAlert"
-    }
-  ]
+    "description": "当前温度值"
+  }
 }
 
 
@@ -147,141 +38,37 @@ Authorization: Bearer {{token}}
 
 {
   "id": 3,
-  "productId": 1002,
-  "productKey": "smart-sensor-002",
-  "properties": [
-    {
-      "identifier": "Temperature",
-      "name": "温度",
-      "accessMode": "r",
-      "required": true,
-      "dataType": {
-        "type": "float",
-        "specs": {
-          "min": -100.0,
-          "max": 200.0,
-          "step": 0.1,
-          "unit": "℃"
-        }
-      },
-      "description": "当前温度值"
-    },
-    {
-      "identifier": "Humidity",
-      "name": "湿度",
-      "accessMode": "r",
-      "required": true,
-      "dataType": {
-        "type": "float",
-        "specs": {
-          "min": 0.0,
-          "max": 100.0,
-          "step": 0.1,
-          "unit": "%"
-        }
-      },
-      "description": "当前湿度值"
-    },
-    {
-      "identifier": "GeoLocation",
-      "name": "地理位置",
-      "accessMode": "r",
-      "required": false,
-      "dataType": {
-        "type": "struct",
-        "specs": [
-          {
-            "identifier": "Longitude",
-            "name": "经度",
-            "dataType": {
-              "type": "double",
-              "specs": {
-                "min": -180.0,
-                "max": 180.0,
-                "step": 0.000001,
-                "unit": "°"
-              }
-            },
-            "description": "设备所在位置的经度"
-          },
-          {
-            "identifier": "Latitude",
-            "name": "纬度",
-            "dataType": {
-              "type": "double",
-              "specs": {
-                "min": -90.0,
-                "max": 90.0,
-                "step": 0.000001,
-                "unit": "°"
-              }
-            },
-            "description": "设备所在位置的纬度"
-          }
-        ]
-      },
-      "description": "设备的地理位置信息"
-    }
-  ],
-  "services": [
-    {
-      "identifier": "Reboot",
-      "name": "重启设备",
-      "callType": "async",
-      "inputData": [],
-      "description": "远程重启设备",
-      "method": "thing.service.reboot"
+  "productId": 1001,
+  "productKey": "smart-sensor-001",
+  "identifier": "Temperature",
+  "name": "温度",
+  "description": "当前温度值",
+  "type": 1,
+  "property": {
+    "identifier": "Temperature",
+    "name": "温度",
+    "accessMode": "r",
+    "required": true,
+    "dataType": {
+      "type": "float",
+      "specs": {
+        "min": -10.0,
+        "max": 100.0,
+        "step": 0.1,
+        "unit": "℃"
+      }
     },
-    {
-      "identifier": "SetThreshold",
-      "name": "设置温度阈值",
-      "callType": "sync",
-      "inputData": [
-        {
-          "identifier": "Threshold",
-          "name": "阈值",
-          "dataType": {
-            "type": "float",
-            "specs": {
-              "min": -40.0,
-              "max": 125.0,
-              "step": 0.1,
-              "unit": "℃"
-            }
-          },
-          "description": "报警温度阈值"
-        }
-      ],
-      "description": "设置设备的温度报警阈值",
-      "method": "thing.service.setThreshold"
-    }
-  ],
-  "events": [
-    {
-      "identifier": "HighTemperatureAlert",
-      "name": "高温报警",
-      "type": "alert",
-      "outputData": [
-        {
-          "identifier": "CurrentTemperature",
-          "name": "当前温度",
-          "dataType": {
-            "type": "float",
-            "specs": {
-              "unit": "℃"
-            }
-          },
-          "description": "触发报警时的温度值"
-        }
-      ],
-      "description": "当温度超过阈值时触发高温报警事件",
-      "method": "thing.event.highTemperatureAlert"
-    }
-  ]
+    "description": "当前温度值"
+  }
 }
 
+### 请求 /iot/think-model-function/get 接口 => 成功
+GET {{baseUrl}}/iot/think-model-function/get?id=3
+tenant-id: {{adminTenentId}}
+Authorization: Bearer {{token}}
+
 
-### 请求 /iot/think-model-function/get-by-product-key 接口 => 成功
-GET {{baseUrl}}/iot/think-model-function/get-by-product-key?productKey=smart-sensor-002
+### 请求 /iot/think-model-function/list-by-product-id 接口 => 成功
+GET {{baseUrl}}/iot/think-model-function/list-by-product-id?productId=1001
 tenant-id: {{adminTenentId}}
 Authorization: Bearer {{token}}

+ 10 - 8
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.java

@@ -15,6 +15,8 @@ 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;
 
 @Tag(name = "管理后台 - IoT 产品物模型")
@@ -50,23 +52,23 @@ public class IotThinkModelFunctionController {
         return success(true);
     }
 
-    @GetMapping("/get-by-product-key")
+    @GetMapping("/get")
     @Operation(summary = "获得IoT 产品物模型")
-    @Parameter(name = "productKey", description = "产品Key", required = true, example = "1024")
+    @Parameter(name = "id", description = "编号", required = true)
     @PreAuthorize("@ss.hasPermission('iot:think-model-function:query')")
-    public CommonResult<IotThinkModelFunctionRespVO> getThinkModelFunctionByProductKey(@RequestParam("productKey") String productKey) {
-        IotThinkModelFunctionDO thinkModelFunction = thinkModelFunctionService.getThinkModelFunctionByProductKey(productKey);
+    public CommonResult<IotThinkModelFunctionRespVO> getThinkModelFunction(@RequestParam("id") Long id) {
+        IotThinkModelFunctionDO thinkModelFunction = thinkModelFunctionService.getThinkModelFunction(id);
         IotThinkModelFunctionRespVO respVO = IotThinkModelFunctionConvert.INSTANCE.convert(thinkModelFunction);
         return success(respVO);
     }
 
-    @GetMapping("/get-by-product-id")
+    @GetMapping("/list-by-product-id")
     @Operation(summary = "获得IoT 产品物模型")
     @Parameter(name = "productId", description = "产品ID", required = true, example = "1024")
     @PreAuthorize("@ss.hasPermission('iot:think-model-function:query')")
-    public CommonResult<IotThinkModelFunctionRespVO> getThinkModelFunctionByProductId(@RequestParam("productId") Long productId) {
-        IotThinkModelFunctionDO thinkModelFunction = thinkModelFunctionService.getThinkModelFunctionByProductId(productId);
-        IotThinkModelFunctionRespVO respVO = IotThinkModelFunctionConvert.INSTANCE.convert(thinkModelFunction);
+    public CommonResult<List<IotThinkModelFunctionRespVO>> getThinkModelFunctionListByProductId(@RequestParam("productId") Long productId) {
+        List<IotThinkModelFunctionDO> thinkModelFunctionListByProductId = thinkModelFunctionService.getThinkModelFunctionListByProductId(productId);
+        List<IotThinkModelFunctionRespVO> respVO = IotThinkModelFunctionConvert.INSTANCE.convertList(thinkModelFunctionListByProductId);
         return success(respVO);
     }
 }

+ 21 - 9
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionRespVO.java

@@ -20,21 +20,33 @@ public class IotThinkModelFunctionRespVO {
     @ExcelProperty("产品ID")
     private Long id;
 
+    @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Long productId;
+
     @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED)
     @ExcelProperty("产品标识")
     private String productKey;
 
-    @Schema(description = "属性列表", requiredMode = Schema.RequiredMode.REQUIRED)
-    @ExcelProperty("属性列表")
-    private List<ThingModelProperty> properties;
+    @Schema(description = "功能标识", requiredMode = Schema.RequiredMode.REQUIRED)
+    private String identifier;
+
+    @Schema(description = "功能名称", requiredMode = Schema.RequiredMode.REQUIRED)
+    private String name;
+
+    @Schema(description = "功能描述", requiredMode = Schema.RequiredMode.REQUIRED)
+    private String description;
+
+    @Schema(description = "功能类型", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Integer type;
+
+    @Schema(description = "属性", requiredMode = Schema.RequiredMode.REQUIRED)
+    private ThingModelProperty property;
 
-    @Schema(description = "服务列表")
-    @ExcelProperty("服务列表")
-    private List<ThingModelService> services;
+    @Schema(description = "服务", requiredMode = Schema.RequiredMode.REQUIRED)
+    private ThingModelEvent event;
 
-    @Schema(description = "事件列表")
-    @ExcelProperty("事件列表")
-    private List<ThingModelEvent> events;
+    @Schema(description = "事件", requiredMode = Schema.RequiredMode.REQUIRED)
+    private ThingModelService service;
 
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
     @ExcelProperty("创建时间")

+ 24 - 9
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionSaveReqVO.java

@@ -1,15 +1,15 @@
 package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo;
 
+import cn.iocoder.yudao.framework.common.validation.InEnum;
 import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelEvent;
 import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty;
 import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelService;
+import cn.iocoder.yudao.module.iot.enums.product.IotThingModelTypeEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.constraints.NotEmpty;
 import jakarta.validation.constraints.NotNull;
 import lombok.Data;
 
-import java.util.List;
-
 @Schema(description = "管理后台 - IoT 产品物模型新增/修改 Request VO")
 @Data
 public class IotThinkModelFunctionSaveReqVO {
@@ -25,14 +25,29 @@ public class IotThinkModelFunctionSaveReqVO {
     @NotEmpty(message = "产品标识不能为空")
     private String productKey;
 
-    @Schema(description = "属性列表", requiredMode = Schema.RequiredMode.REQUIRED)
-    @NotEmpty(message = "属性列表不能为空")
-    private List<ThingModelProperty> properties;
+    @Schema(description = "功能标识", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotEmpty(message = "功能标识不能为空")
+    private String identifier;
+
+    @Schema(description = "功能名称", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotEmpty(message = "功能名称不能为空")
+    private String name;
+
+    @Schema(description = "功能描述", requiredMode = Schema.RequiredMode.REQUIRED)
+    private String description;
+
+    @Schema(description = "功能类型", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "功能类型不能为空")
+    @InEnum(IotThingModelTypeEnum.class)
+    private Integer type;
+
+    @Schema(description = "属性", requiredMode = Schema.RequiredMode.REQUIRED)
+    private ThingModelProperty property;
 
-    @Schema(description = "服务列表")
-    private List<ThingModelService> services;
+    @Schema(description = "服务", requiredMode = Schema.RequiredMode.REQUIRED)
+    private ThingModelService service;
 
-    @Schema(description = "事件列表")
-    private List<ThingModelEvent> events;
+    @Schema(description = "事件", requiredMode = Schema.RequiredMode.REQUIRED)
+    private ThingModelEvent event;
 
 }

+ 24 - 54
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/convert/thinkmodelfunction/IotThinkModelFunctionConvert.java

@@ -6,82 +6,52 @@ import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingMode
 import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionRespVO;
 import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionSaveReqVO;
 import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import cn.iocoder.yudao.module.iot.enums.product.IotThingModelTypeEnum;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 import org.mapstruct.factory.Mappers;
 
-import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 @Mapper
 public interface IotThinkModelFunctionConvert {
 
     IotThinkModelFunctionConvert INSTANCE = Mappers.getMapper(IotThinkModelFunctionConvert.class);
 
-    ObjectMapper objectMapper = new ObjectMapper();
-
-    // 将 SaveReqVO 转换为 DO 对象,处理 properties, services, events 字段
-    @Mapping(target = "properties", expression = "java(convertPropertiesToJson(bean.getProperties()))")
-    @Mapping(target = "services", expression = "java(convertServicesToJson(bean.getServices()))")
-    @Mapping(target = "events", expression = "java(convertEventsToJson(bean.getEvents()))")
+    // 将 SaveReqVO 转换为 DO
+    @Mapping(target = "property", expression = "java(convertToProperty(bean))")
+    @Mapping(target = "event", expression = "java(convertToEvent(bean))")
+    @Mapping(target = "service", expression = "java(convertToService(bean))")
     IotThinkModelFunctionDO convert(IotThinkModelFunctionSaveReqVO bean);
 
-    default String convertPropertiesToJson(List<ThingModelProperty> properties) {
-        try {
-            return properties != null ? objectMapper.writeValueAsString(properties) : "[]";
-        } catch (JsonProcessingException e) {
-            throw new RuntimeException("序列化 properties 时发生错误", e);
+    default ThingModelProperty convertToProperty(IotThinkModelFunctionSaveReqVO bean) {
+        if (Objects.equals(bean.getType(), IotThingModelTypeEnum.PROPERTY.getType())) {
+            return bean.getProperty();
         }
+        return null;
     }
 
-    default String convertServicesToJson(List<ThingModelService> services) {
-        try {
-            return services != null ? objectMapper.writeValueAsString(services) : "[]";
-        } catch (JsonProcessingException e) {
-            throw new RuntimeException("序列化 services 时发生错误", e);
+    default ThingModelEvent convertToEvent(IotThinkModelFunctionSaveReqVO bean) {
+        if (Objects.equals(bean.getType(), IotThingModelTypeEnum.EVENT.getType())) {
+            return bean.getEvent();
         }
+        return null;
     }
 
-    default String convertEventsToJson(List<ThingModelEvent> events) {
-        try {
-            return events != null ? objectMapper.writeValueAsString(events) : "[]";
-        } catch (JsonProcessingException e) {
-            throw new RuntimeException("序列化 events 时发生错误", e);
+    default ThingModelService convertToService(IotThinkModelFunctionSaveReqVO bean) {
+        if (Objects.equals(bean.getType(), IotThingModelTypeEnum.SERVICE.getType())) {
+            return bean.getService();
         }
+        return null;
     }
 
-    // 将 DO 转换为 RespVO 对象,处理 properties, services, events 字段
-    @Mapping(target = "properties", expression = "java(convertJsonToProperties(bean.getProperties()))")
-    @Mapping(target = "services", expression = "java(convertJsonToServices(bean.getServices()))")
-    @Mapping(target = "events", expression = "java(convertJsonToEvents(bean.getEvents()))")
+    // 将 DO 转换为 RespVO
+    @Mapping(target = "property", source = "property")
+    @Mapping(target = "event", source = "event")
+    @Mapping(target = "service", source = "service")
     IotThinkModelFunctionRespVO convert(IotThinkModelFunctionDO bean);
 
-    default List<ThingModelProperty> convertJsonToProperties(String propertiesJson) {
-        try {
-            return propertiesJson != null ? objectMapper.readValue(propertiesJson, objectMapper.getTypeFactory().constructCollectionType(List.class, ThingModelProperty.class)) : new ArrayList<>();
-        } catch (JsonProcessingException e) {
-            throw new RuntimeException("反序列化 properties 时发生错误", e);
-        }
-    }
-
-    default List<ThingModelService> convertJsonToServices(String servicesJson) {
-        try {
-            return servicesJson != null ? objectMapper.readValue(servicesJson, objectMapper.getTypeFactory().constructCollectionType(List.class, ThingModelService.class)) : new ArrayList<>();
-        } catch (JsonProcessingException e) {
-            throw new RuntimeException("反序列化 services 时发生错误", e);
-        }
-    }
-
-    default List<ThingModelEvent> convertJsonToEvents(String eventsJson) {
-        try {
-            return eventsJson != null ? objectMapper.readValue(eventsJson, objectMapper.getTypeFactory().constructCollectionType(List.class, ThingModelEvent.class)) : new ArrayList<>();
-        } catch (JsonProcessingException e) {
-            throw new RuntimeException("反序列化 events 时发生错误", e);
-        }
-    }
-
-    // 批量转换 DO 列表到 RespVO 列表
+    // 批量转换
     List<IotThinkModelFunctionRespVO> convertList(List<IotThinkModelFunctionDO> list);
-}
+}

+ 43 - 14
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thinkmodelfunction/IotThinkModelFunctionDO.java

@@ -1,20 +1,28 @@
 package cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelEvent;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelService;
 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
 import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.*;
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
 
 /**
  * IoT 产品物模型功能 DO
- *
+ * <p>
  * 每个 {@link IotProductDO} 和 {@link IotThinkModelFunctionDO} 是“一对多”的关系,它的每个属性、事件、服务都对应一条记录
  *
  * @author 芋道源码
  */
-@TableName("iot_think_model_function")
+@TableName(value = "iot_think_model_function", autoResultMap = true)
 @KeySequence("iot_think_model_function_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
 @Data
 @Builder
@@ -27,35 +35,56 @@ public class IotThinkModelFunctionDO extends BaseDO {
      */
     @TableId
     private Long id;
-    // TODO @haohao:是不是有一个 identifier,需要要有哈
-    // TODO @haohao:name、description 属性,还有个类型
+
+    /**
+     * 功能标识
+     */
+    private String identifier;
+    /**
+     * 功能名称
+     */
+    private String name;
+    /**
+     * 功能描述
+     */
+    private String description;
+
     /**
      * 产品标识
-     *
+     * <p>
      * 关联 {@link IotProductDO#getId()}
      */
     private Long productId;
     /**
      * 产品标识
-     *
+     * <p>
      * 关联 {@link IotProductDO#getProductKey()}
      */
     private String productKey;
 
-    // TODO @haohao:是不是可以搞成 ThingModelProperty、ThingModelEvent、ThingModelService 进行存储
     /**
-     * 属性列表
+     * 功能类型
+     * <p>
+     * 枚举 {@link cn.iocoder.yudao.module.iot.enums.product.IotThingModelTypeEnum}
+     */
+    private Integer type;
+
+    /**
+     * 属性
      */
-    private String properties;
+    @TableField(typeHandler = JacksonTypeHandler.class)
+    private ThingModelProperty property;
 
     /**
-     * 服务列表
+     * 事件
      */
-    private String services;
+    @TableField(typeHandler = JacksonTypeHandler.class)
+    private ThingModelEvent event;
 
     /**
-     * 事件列表
+     * 服务
      */
-    private String events;
+    @TableField(typeHandler = JacksonTypeHandler.class)
+    private ThingModelService service;
 
 }

+ 0 - 85
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thinkmodelfunction/IotThinkModelFunctionDO2.java

@@ -1,85 +0,0 @@
-package cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction;
-
-import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelEvent;
-import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty;
-import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
-import com.baomidou.mybatisplus.annotation.KeySequence;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * IoT 产品物模型功能 DO
- *
- * 每个 {@link IotProductDO} 和 {@link IotThinkModelFunctionDO2} 是“一对多”的关系,它的每个属性、事件、服务都对应一条记录
- *
- * @author 芋道源码
- */
-@TableName("iot_think_model_function")
-@KeySequence("iot_think_model_function_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class IotThinkModelFunctionDO2 extends BaseDO {
-
-    /**
-     * 物模型功能编号
-     */
-    @TableId
-    private Long id;
-
-    /**
-     * 功能标识
-     */
-    private String identifier;
-    /**
-     * 功能名称
-     */
-    private String name;
-    /**
-     * 功能描述
-     */
-    private String description;
-
-    /**
-     * 产品标识
-     *
-     * 关联 {@link IotProductDO#getId()}
-     */
-    private Long productId;
-    /**
-     * 产品标识
-     *
-     * 关联 {@link IotProductDO#getProductKey()}
-     */
-    private String productKey;
-
-    /**
-     * 功能类型
-     *
-     * 1 - 属性
-     * 2 - 服务
-     * 3 - 事件
-     */
-    // TODO @haohao:枚举
-    private Integer type;
-
-    /**
-     * 属性
-     */
-    private ThingModelProperty property;
-    /**
-     * 事件
-     */
-    private ThingModelEvent event;
-    /**
-     * 服务
-     */
-    private String service;
-
-}

+ 11 - 4
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java

@@ -5,6 +5,8 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.util.List;
+
 /**
  * IoT 产品物模型 Mapper
  *
@@ -13,12 +15,17 @@ import org.apache.ibatis.annotations.Mapper;
 @Mapper
 public interface IotThinkModelFunctionMapper extends BaseMapperX<IotThinkModelFunctionDO> {
 
-    default IotThinkModelFunctionDO selectByProductKey(String productKey) {
-        return selectOne(new LambdaQueryWrapperX<IotThinkModelFunctionDO>().eq(IotThinkModelFunctionDO::getProductKey, productKey));
+    default IotThinkModelFunctionDO selectByProductIdAndIdentifier(Long productId, String identifier) {
+        return selectOne(new LambdaQueryWrapperX<IotThinkModelFunctionDO>().eq(IotThinkModelFunctionDO::getProductId, productId)
+                .eq(IotThinkModelFunctionDO::getIdentifier, identifier));
     }
 
-    default IotThinkModelFunctionDO selectByProductId(Long productId){
-        return selectOne(new LambdaQueryWrapperX<IotThinkModelFunctionDO>().eq(IotThinkModelFunctionDO::getProductId, productId));
+    default List<IotThinkModelFunctionDO> selectListByProductId(Long productId) {
+        return selectList(new LambdaQueryWrapperX<IotThinkModelFunctionDO>().eq(IotThinkModelFunctionDO::getProductId, productId));
     }
 
+    default List<IotThinkModelFunctionDO> selectListByProductIdAndType(Long productId, Integer type) {
+        return selectList(new LambdaQueryWrapperX<IotThinkModelFunctionDO>().eq(IotThinkModelFunctionDO::getProductId, productId)
+                .eq(IotThinkModelFunctionDO::getType, type));
+    }
 }

+ 16 - 13
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java

@@ -4,6 +4,8 @@ import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThi
 import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
 import jakarta.validation.Valid;
 
+import java.util.List;
+
 /**
  * IoT 产品物模型 Service 接口
  *
@@ -19,33 +21,34 @@ public interface IotThinkModelFunctionService {
      */
     Long createThinkModelFunction(@Valid IotThinkModelFunctionSaveReqVO createReqVO);
 
+
     /**
-     * 删除IoT 产品物模型
+     * 更新IoT 产品物模型
      *
-     * @param id 编号
+     * @param updateReqVO 更新信息
      */
-    void deleteThinkModelFunction(Long id);
+    void updateThinkModelFunction(@Valid IotThinkModelFunctionSaveReqVO updateReqVO);
 
     /**
-     * 获得IoT 产品物模型,通过产品Key
+     * 删除IoT 产品物模型
      *
-     * @param productKey 产品Key
-     * @return IoT 产品物模型
+     * @param id 编号
      */
-    IotThinkModelFunctionDO getThinkModelFunctionByProductKey(String productKey);
+    void deleteThinkModelFunction(Long id);
 
     /**
-     * 获得IoT 产品物模型,通过产品ID
+     * 获得IoT 产品物模型
      *
-     * @param productId 产品ID
+     * @param id 编号
      * @return IoT 产品物模型
      */
-    IotThinkModelFunctionDO getThinkModelFunctionByProductId(Long productId);
+    IotThinkModelFunctionDO getThinkModelFunction(Long id);
 
     /**
-     * 更新IoT 产品物模型
+     * 获得IoT 产品物模型列表
      *
-     * @param updateReqVO 更新信息
+     * @param productId 产品编号
+     * @return IoT 产品物模型列表
      */
-    void updateThinkModelFunction(@Valid IotThinkModelFunctionSaveReqVO updateReqVO);
+    List<IotThinkModelFunctionDO> getThinkModelFunctionListByProductId(Long productId);
 }

+ 154 - 111
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java

@@ -1,6 +1,9 @@
 package cn.iocoder.yudao.module.iot.service.thinkmodelfunction;
 
-import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.*;
+import cn.iocoder.yudao.framework.common.validation.Telephone;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelEvent;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelService;
 import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType.ThingModelArgument;
 import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType.ThingModelArraySpecs;
 import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType.ThingModelArrayType;
@@ -9,19 +12,20 @@ import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThi
 import cn.iocoder.yudao.module.iot.convert.thinkmodelfunction.IotThinkModelFunctionConvert;
 import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
 import cn.iocoder.yudao.module.iot.dal.mysql.thinkmodelfunction.IotThinkModelFunctionMapper;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import cn.iocoder.yudao.module.iot.enums.product.IotThingModelTypeEnum;
 import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.THINK_MODEL_FUNCTION_EXISTS_BY_PRODUCT_KEY;
+import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.THINK_MODEL_FUNCTION_EXISTS_BY_IDENTIFIER;
 import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.THINK_MODEL_FUNCTION_NOT_EXISTS;
 
 @Slf4j
@@ -32,153 +36,133 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe
     @Resource
     private IotThinkModelFunctionMapper thinkModelFunctionMapper;
 
-    private ObjectMapper objectMapper = new ObjectMapper();
-
     @Override
     public Long createThinkModelFunction(IotThinkModelFunctionSaveReqVO createReqVO) {
-        log.info("创建物模型,参数:{}", createReqVO);
-        // 验证 ProductKey 对应的产品物模型是否已存在
-        validateThinkModelFunctionNotExistsByProductKey(createReqVO.getProductKey());
+        // 校验功能标识符在同一产品下是否唯一
+        validateIdentifierUnique(createReqVO.getProductId(), createReqVO.getIdentifier());
+
         // 转换请求对象为数据对象
         IotThinkModelFunctionDO thinkModelFunction = IotThinkModelFunctionConvert.INSTANCE.convert(createReqVO);
-        // 自动生成属性上报事件和属性设置、获取服务
-        generateDefaultEventsAndServices(createReqVO, thinkModelFunction);
+
         // 插入数据库
         thinkModelFunctionMapper.insert(thinkModelFunction);
-        // 返回生成的 ID
-        return thinkModelFunction.getId();
-    }
 
-    private void validateThinkModelFunctionNotExistsByProductKey(String productKey) {
-        if (thinkModelFunctionMapper.selectByProductKey(productKey) != null) {
-            throw exception(THINK_MODEL_FUNCTION_EXISTS_BY_PRODUCT_KEY);
+        // 如果创建的是属性,需要更新默认的事件和服务
+        if (Objects.equals(createReqVO.getType(), IotThingModelTypeEnum.PROPERTY.getType())) {
+            generateDefaultEventsAndServices(createReqVO.getProductId(), createReqVO.getProductKey());
         }
-    }
 
-    @Override
-    public void deleteThinkModelFunction(Long id) {
-        log.info("删除物模型,id:{}", id);
-        // 校验物模型是否存在
-        validateThinkModelFunctionExists(id);
-        // 删除物模型
-        thinkModelFunctionMapper.deleteById(id);
+        // 返回生成的 ID
+        return thinkModelFunction.getId();
     }
 
-    private void validateThinkModelFunctionExists(Long id) {
-        if (thinkModelFunctionMapper.selectById(id) == null) {
-            throw exception(THINK_MODEL_FUNCTION_NOT_EXISTS);
+    private void validateIdentifierUnique(Long productId, String identifier) {
+        IotThinkModelFunctionDO existingFunction = thinkModelFunctionMapper.selectByProductIdAndIdentifier(productId, identifier);
+        if (existingFunction != null) {
+            throw exception(THINK_MODEL_FUNCTION_EXISTS_BY_IDENTIFIER);
         }
     }
 
-    @Override
-    public IotThinkModelFunctionDO getThinkModelFunctionByProductKey(String productKey) {
-        return thinkModelFunctionMapper.selectByProductKey(productKey);
-    }
-
-    @Override
-    public IotThinkModelFunctionDO getThinkModelFunctionByProductId(Long productId) {
-        return thinkModelFunctionMapper.selectByProductId(productId);
-    }
-
     @Override
     public void updateThinkModelFunction(IotThinkModelFunctionSaveReqVO updateReqVO) {
-        log.info("更新物模型,参数:{}", updateReqVO);
-        // 校验物模型是否存在
+        // 校验功能是否存在
         validateThinkModelFunctionExists(updateReqVO.getId());
-        // 校验 ProductKey 是否唯一
-        validateProductKeyUnique(updateReqVO.getId(), updateReqVO.getProductKey());
+
+        // 校验功能标识符是否唯一
+        validateIdentifierUniqueForUpdate(updateReqVO.getId(), updateReqVO.getProductId(), updateReqVO.getIdentifier());
+
         // 转换请求对象为数据对象
         IotThinkModelFunctionDO thinkModelFunction = IotThinkModelFunctionConvert.INSTANCE.convert(updateReqVO);
-        // 自动生成或更新属性上报事件和属性设置、获取服务
-        generateDefaultEventsAndServices(updateReqVO, thinkModelFunction);
+
         // 更新数据库
         thinkModelFunctionMapper.updateById(thinkModelFunction);
-    }
 
-    private void validateProductKeyUnique(Long id, String productKey) {
-        IotThinkModelFunctionDO existingFunction = thinkModelFunctionMapper.selectByProductKey(productKey);
-        if (existingFunction != null && !existingFunction.getId().equals(id)) {
-            throw exception(THINK_MODEL_FUNCTION_EXISTS_BY_PRODUCT_KEY);
+        // 如果更新的是属性,需要更新默认的事件和服务
+        if (Objects.equals(updateReqVO.getType(), IotThingModelTypeEnum.PROPERTY.getType())) {
+            generateDefaultEventsAndServices(updateReqVO.getProductId(), updateReqVO.getProductKey());
         }
     }
 
-    /**
-     * 根据属性列表,自动生成属性上报事件和属性设置、获取服务
-     */
-    private void generateDefaultEventsAndServices(IotThinkModelFunctionSaveReqVO reqVO, IotThinkModelFunctionDO thinkModelFunction) {
-        // 获取属性列表
-        List<ThingModelProperty> properties = reqVO.getProperties();
-        if (properties == null) {
-            properties = new ArrayList<>();
+    private void validateIdentifierUniqueForUpdate(Long id, Long productId, String identifier) {
+        IotThinkModelFunctionDO existingFunction = thinkModelFunctionMapper.selectByProductIdAndIdentifier(productId, identifier);
+        if (existingFunction != null && !existingFunction.getId().equals(id)) {
+            throw exception(THINK_MODEL_FUNCTION_EXISTS_BY_IDENTIFIER);
         }
+    }
 
-        // 获取现有的事件和服务
-        List<ThingModelEvent> existingEvents = reqVO.getEvents() != null ? new ArrayList<>(reqVO.getEvents()) : new ArrayList<>();
-        List<ThingModelService> existingServices = reqVO.getServices() != null ? new ArrayList<>(reqVO.getServices()) : new ArrayList<>();
-
-        // 生成或更新属性上报事件
-        ThingModelEvent propertyPostEvent = generatePropertyPostEvent(properties);
-        updateEventInList(existingEvents, propertyPostEvent);
 
-        // 生成或更新属性设置和获取服务
-        ThingModelService propertySetService = generatePropertySetService(properties);
-        updateServiceInList(existingServices, propertySetService);
+    @Override
+    public void deleteThinkModelFunction(Long id) {
+        // 校验功能是否存在
+        IotThinkModelFunctionDO functionDO = thinkModelFunctionMapper.selectById(id);
+        if (functionDO == null) {
+            throw exception(THINK_MODEL_FUNCTION_NOT_EXISTS);
+        }
 
-        ThingModelService propertyGetService = generatePropertyGetService(properties);
-        updateServiceInList(existingServices, propertyGetService);
+        // 删除功能
+        thinkModelFunctionMapper.deleteById(id);
 
-        // 更新 thinkModelFunction 对象的 events 和 services 字段
-        try {
-            thinkModelFunction.setEvents(objectMapper.writeValueAsString(existingEvents));
-            thinkModelFunction.setServices(objectMapper.writeValueAsString(existingServices));
-        } catch (JsonProcessingException e) {
-            throw new RuntimeException("序列化事件和服务时发生错误", e);
+        // 如果删除的是属性,需要更新默认的事件和服务
+        if (Objects.equals(functionDO.getType(), IotThingModelTypeEnum.PROPERTY.getType())) {
+            generateDefaultEventsAndServices(functionDO.getProductId(), functionDO.getProductKey());
         }
     }
 
     /**
-     * 在事件列表中更新或添加事件
+     * 校验功能是否存在
+     *
+     * @param id 功能编号
      */
-    private void updateEventInList(List<ThingModelEvent> events, ThingModelEvent newEvent) {
-        if (newEvent == null) {
-            return;
-        }
-        for (int i = 0; i < events.size(); i++) {
-            ThingModelEvent event = events.get(i);
-            if (event.getIdentifier().equals(newEvent.getIdentifier())) {
-                // 更新已有的事件
-                events.set(i, newEvent);
-                return;
-            }
+    private void validateThinkModelFunctionExists(Long id) {
+        if (thinkModelFunctionMapper.selectById(id) == null) {
+            throw exception(THINK_MODEL_FUNCTION_NOT_EXISTS);
         }
-        // 如果不存在,则添加新的事件
-        events.add(newEvent);
+    }
+
+    @Override
+    public IotThinkModelFunctionDO getThinkModelFunction(Long id) {
+        return thinkModelFunctionMapper.selectById(id);
+    }
+
+    @Override
+    public List<IotThinkModelFunctionDO> getThinkModelFunctionListByProductId(Long productId) {
+        return thinkModelFunctionMapper.selectListByProductId(productId);
     }
 
     /**
-     * 在服务列表中更新或添加服务
+     * 生成默认的事件和服务
      */
-    private void updateServiceInList(List<ThingModelService> services, ThingModelService newService) {
-        if (newService == null) {
-            return;
+    public void generateDefaultEventsAndServices(Long productId, String productKey) {
+        // 获取当前产品的所有属性列表
+        List<IotThinkModelFunctionDO> propertyList = thinkModelFunctionMapper.selectListByProductIdAndType(productId, IotThingModelTypeEnum.PROPERTY.getType());
+
+        // 生成属性上报事件
+        ThingModelEvent propertyPostEvent = generatePropertyPostEvent(propertyList);
+        if (propertyPostEvent != null) {
+            saveOrUpdateEvent(productId, productKey, propertyPostEvent);
         }
-        for (int i = 0; i < services.size(); i++) {
-            ThingModelService service = services.get(i);
-            if (service.getIdentifier().equals(newService.getIdentifier())) {
-                // 更新已有的服务
-                services.set(i, newService);
-                return;
-            }
+
+        // 生成属性设置服务
+        ThingModelService propertySetService = generatePropertySetService(propertyList);
+        if (propertySetService != null) {
+            saveOrUpdateService(productId, productKey, propertySetService);
         }
-        // 如果不存在,则添加新的服务
-        services.add(newService);
-    }
 
+        // 生成属性获取服务
+        ThingModelService propertyGetService = generatePropertyGetService(propertyList);
+        if (propertyGetService != null) {
+            saveOrUpdateService(productId, productKey, propertyGetService);
+        }
+    }
 
     /**
      * 生成属性上报事件
      */
-    private ThingModelEvent generatePropertyPostEvent(List<ThingModelProperty> properties) {
+    private ThingModelEvent generatePropertyPostEvent(List<IotThinkModelFunctionDO> propertyList) {
+        if (propertyList == null || propertyList.isEmpty()) {
+            return null;
+        }
+
         ThingModelEvent event = new ThingModelEvent();
         event.setIdentifier("post");
         event.setName("属性上报");
@@ -188,7 +172,8 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe
 
         // 将属性列表转换为事件的输出参数
         List<ThingModelArgument> outputData = new ArrayList<>();
-        for (ThingModelProperty property : properties) {
+        for (IotThinkModelFunctionDO functionDO : propertyList) {
+            ThingModelProperty property = functionDO.getProperty();
             ThingModelArgument arg = new ThingModelArgument();
             arg.setIdentifier(property.getIdentifier());
             arg.setName(property.getName());
@@ -205,9 +190,14 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe
     /**
      * 生成属性设置服务
      */
-    private ThingModelService generatePropertySetService(List<ThingModelProperty> properties) {
+    private ThingModelService generatePropertySetService(List<IotThinkModelFunctionDO> propertyList) {
+        if (propertyList == null || propertyList.isEmpty()) {
+            return null;
+        }
+
         List<ThingModelArgument> inputData = new ArrayList<>();
-        for (ThingModelProperty property : properties) {
+        for (IotThinkModelFunctionDO functionDO : propertyList) {
+            ThingModelProperty property = functionDO.getProperty();
             if ("w".equals(property.getAccessMode()) || "rw".equals(property.getAccessMode())) {
                 ThingModelArgument arg = new ThingModelArgument();
                 arg.setIdentifier(property.getIdentifier());
@@ -239,9 +229,14 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe
     /**
      * 生成属性获取服务
      */
-    private ThingModelService generatePropertyGetService(List<ThingModelProperty> properties) {
+    private ThingModelService generatePropertyGetService(List<IotThinkModelFunctionDO> propertyList) {
+        if (propertyList == null || propertyList.isEmpty()) {
+            return null;
+        }
+
         List<ThingModelArgument> outputData = new ArrayList<>();
-        for (ThingModelProperty property : properties) {
+        for (IotThinkModelFunctionDO functionDO : propertyList) {
+            ThingModelProperty property = functionDO.getProperty();
             if ("r".equals(property.getAccessMode()) || "rw".equals(property.getAccessMode())) {
                 ThingModelArgument arg = new ThingModelArgument();
                 arg.setIdentifier(property.getIdentifier());
@@ -275,10 +270,8 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe
         ThingModelArrayType arrayType = new ThingModelArrayType();
         arrayType.setType("array");
         ThingModelArraySpecs arraySpecs = new ThingModelArraySpecs();
-        // 不指定数组长度,size 可以为 0 或者省略
         ThingModelTextType textType = new ThingModelTextType();
         textType.setType("text");
-        // 如果有需要,可以设置 TextType 的 specs,如长度限制
         arraySpecs.setItem(textType);
         arrayType.setSpecs(arraySpecs);
 
@@ -289,4 +282,54 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe
 
         return service;
     }
+
+    /**
+     * 保存或更新事件
+     */
+    private void saveOrUpdateEvent(Long productId, String productKey, ThingModelEvent event) {
+        // 检查是否已存在相同的事件
+        IotThinkModelFunctionDO existingEvent = thinkModelFunctionMapper.selectByProductIdAndIdentifier(productId, event.getIdentifier());
+        IotThinkModelFunctionDO functionDO = new IotThinkModelFunctionDO();
+        functionDO.setProductId(productId);
+        functionDO.setProductKey(productKey);
+        functionDO.setIdentifier(event.getIdentifier());
+        functionDO.setName(event.getName());
+        functionDO.setDescription(event.getDescription());
+        functionDO.setType(IotThingModelTypeEnum.EVENT.getType());
+        functionDO.setEvent(event);
+
+        if (existingEvent != null) {
+            // 更新事件
+            functionDO.setId(existingEvent.getId());
+            thinkModelFunctionMapper.updateById(functionDO);
+        } else {
+            // 创建新的事件
+            thinkModelFunctionMapper.insert(functionDO);
+        }
+    }
+
+    /**
+     * 保存或更新事服务
+     */
+    private void saveOrUpdateService(Long productId, String productKey, ThingModelService service) {
+        // 检查是否已存在相同的服务
+        IotThinkModelFunctionDO existingService = thinkModelFunctionMapper.selectByProductIdAndIdentifier(productId, service.getIdentifier());
+        IotThinkModelFunctionDO functionDO = new IotThinkModelFunctionDO();
+        functionDO.setProductId(productId);
+        functionDO.setProductKey(productKey);
+        functionDO.setIdentifier(service.getIdentifier());
+        functionDO.setName(service.getName());
+        functionDO.setDescription(service.getDescription());
+        functionDO.setType(IotThingModelTypeEnum.SERVICE.getType());
+        functionDO.setService(service);
+
+        if (existingService != null) {
+            // 更新服务
+            functionDO.setId(existingService.getId());
+            thinkModelFunctionMapper.updateById(functionDO);
+        } else {
+            // 创建新的服务
+            thinkModelFunctionMapper.insert(functionDO);
+        }
+    }
 }