Kaynağa Gözat

开发空间、建筑、区域相关接口

james 2 hafta önce
ebeveyn
işleme
dd572ee53f
49 değiştirilmiş dosya ile 953 ekleme ve 1051 silme
  1. 1 1
      service-ems/service-ems-biz/src/main/java/com/usky/ems/controller/web/BaseSpaceController.java
  2. 2 2
      service-ems/service-ems-biz/src/main/java/com/usky/ems/controller/web/DmpGatewayController.java
  3. 2 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/controller/web/EmsAnalysisController.java
  4. 0 38
      service-ems/service-ems-biz/src/main/java/com/usky/ems/controller/web/EmsGatewayController.java
  5. 31 12
      service-ems/service-ems-biz/src/main/java/com/usky/ems/controller/web/EmsModelController.java
  6. 3 2
      service-ems/service-ems-biz/src/main/java/com/usky/ems/controller/web/EmsOverviewController.java
  7. 0 64
      service-ems/service-ems-biz/src/main/java/com/usky/ems/controller/web/EmsProjectController.java
  8. 18 19
      service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/BaseArea.java
  9. 97 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/BaseBuild.java
  10. 2 2
      service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/BaseSpace.java
  11. 10 20
      service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/BaseSpaceArea.java
  12. 34 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/BaseSpaceBuild.java
  13. 34 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/BaseSpaceGateway.java
  14. 4 2
      service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/DmpGateway.java
  15. 0 64
      service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/EmsGateway.java
  16. 0 71
      service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/EmsProject.java
  17. 0 59
      service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/EmsProjectConversionFactor.java
  18. 10 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/BaseAreaMapper.java
  19. 10 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/BaseBuildMapper.java
  20. 10 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/BaseSpaceAreaMapper.java
  21. 10 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/BaseSpaceBuildMapper.java
  22. 10 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/BaseSpaceGatewayMapper.java
  23. 0 10
      service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/EmsGatewayMapper.java
  24. 0 11
      service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/EmsProjectConfigurationMapper.java
  25. 0 11
      service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/EmsProjectConversionFactorMapper.java
  26. 0 11
      service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/EmsProjectDeviceSystemMapper.java
  27. 0 10
      service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/EmsProjectMapper.java
  28. 0 22
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/EmsGatewayQueryService.java
  29. 15 1
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/EmsModelService.java
  30. 0 11
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/EmsProjectConfigurationService.java
  31. 0 36
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/EmsProjectService.java
  32. 10 1
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/BaseSpaceServiceImpl.java
  33. 3 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/DmpGatewayServiceImpl.java
  34. 11 18
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsAnalysisServiceImpl.java
  35. 36 17
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsDeviceEventServiceImpl.java
  36. 3 3
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsDeviceReportServiceImpl.java
  37. 0 87
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsGatewayQueryServiceImpl.java
  38. 516 243
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsModelServiceImpl.java
  39. 15 22
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsOverviewServiceImpl.java
  40. 0 16
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsProjectConfigurationServiceImpl.java
  41. 0 63
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsProjectServiceImpl.java
  42. 0 3
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsReportServiceImpl.java
  43. 2 2
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/vo/DmpGatewayDetailResponse.java
  44. 2 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/vo/DmpGatewayPageRequest.java
  45. 0 24
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/vo/EmsGatewayDetailResponse.java
  46. 0 22
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/vo/EmsGatewayListItem.java
  47. 0 21
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/vo/EmsGatewayPageRequest.java
  48. 30 30
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/vo/EmsModelSaveRequest.java
  49. 22 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/vo/SpaceGatewayBindRequest.java

+ 1 - 1
service-ems/service-ems-biz/src/main/java/com/usky/ems/controller/web/BaseSpaceController.java

@@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RestController;
  * GET /base-space/tree  获取空间树
  */
 @RestController
-@RequestMapping("/base-space")
+@RequestMapping("/space")
 public class BaseSpaceController {
 
     @Autowired

+ 2 - 2
service-ems/service-ems-biz/src/main/java/com/usky/ems/controller/web/DmpGatewayController.java

@@ -11,11 +11,11 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 /**
- * dmp_gateway 网关维护 API(REST 风格对齐 IoT 模块 DmpDeviceInfoController 的增删改,列表与详情对齐 EmsGatewayController
+ * dmp_gateway 网关维护 API(REST 风格对齐 IoT 模块 DmpDeviceInfoController 的增删改)
  * 基础路径:/dmp/gateway(网关前缀如 /prod-api/service-ems 依部署而定)
  */
 @RestController
-@RequestMapping("/dmp/gateway")
+@RequestMapping("/gateway")
 public class DmpGatewayController {
 
     @Autowired

+ 2 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/controller/web/EmsAnalysisController.java

@@ -9,6 +9,8 @@ import org.springframework.web.bind.annotation.*;
 /**
  * 能耗分析接口
  * 趋势、指标、分类占比、区域分析、对比分析
+ * 区域与面积相关统计在 {@link com.usky.ems.service.impl.EmsAnalysisServiceImpl} 中基于
+ * base_space、base_area、base_space_area、base_space_build 等表查询。
  * 基础路径前缀:/analysis(网关再加 /prod-api/service-ems)
  */
 @RestController

+ 0 - 38
service-ems/service-ems-biz/src/main/java/com/usky/ems/controller/web/EmsGatewayController.java

@@ -1,38 +0,0 @@
-package com.usky.ems.controller.web;
-
-import com.usky.common.core.bean.ApiResult;
-import com.usky.common.core.bean.CommonPage;
-import com.usky.ems.service.EmsGatewayQueryService;
-import com.usky.ems.service.vo.EmsGatewayDetailResponse;
-import com.usky.ems.service.vo.EmsGatewayListItem;
-import com.usky.ems.service.vo.EmsGatewayPageRequest;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
-
-/**
- * 能源能耗 - 网关/设备查询模块 API
- * 基础路径前缀:/device/gateway(网关再加 /prod-api/service-ems)
- */
-@RestController
-@RequestMapping("/device/gateway")
-public class EmsGatewayController {
-
-    @Autowired
-    private EmsGatewayQueryService emsGatewayQueryService;
-
-    /**
-     * 网关列表(分页)
-     */
-    @GetMapping("/list")
-    public ApiResult<CommonPage<EmsGatewayListItem>> gatewayList(EmsGatewayPageRequest request) {
-        return ApiResult.success(emsGatewayQueryService.listGateways(request));
-    }
-
-    /**
-     * 网关详情
-     */
-    @GetMapping("/{id}")
-    public ApiResult<EmsGatewayDetailResponse> getGateway(@PathVariable String id) {
-        return ApiResult.success(emsGatewayQueryService.getGatewayById(id));
-    }
-}

+ 31 - 12
service-ems/service-ems-biz/src/main/java/com/usky/ems/controller/web/EmsModelController.java

@@ -10,6 +10,8 @@ import java.util.List;
 
 /**
  * 能源能耗 - 模型/结构模块 API(项目层级树、能源类型、建筑/区域/网关/通道/设备/属性点位 CRUD)
+ * 空间与建筑/区域/网关分别通过 base_space、base_build、base_area 及
+ * base_space_build、base_space_area、base_space_gateway 关联;网关在 dmp_gateway。
  * 基础路径前缀:/model(网关再加 /prod-api/service-ems)
  */
 @RestController
@@ -19,15 +21,15 @@ public class EmsModelController {
     @Autowired
     private EmsModelService emsModelService;
 
-    /**
-     * 获取项目层级树(建筑、区域、网关)
-     */
-    @GetMapping("/structure/tree")
-    public ApiResult<EmsStructureTreeNode> getStructureTree(
-            @RequestParam(required = false) Long projectId,
-            @RequestParam(required = false, defaultValue = "true") Boolean includeGateway) {
-        return ApiResult.success(emsModelService.getStructureTree(projectId, includeGateway));
-    }
+//    /**
+//     * 获取项目层级树(建筑、区域、网关)
+//     */
+//    @GetMapping("/structure/tree")
+//    public ApiResult<EmsStructureTreeNode> getStructureTree(
+//            @RequestParam(required = false) Long projectId,
+//            @RequestParam(required = false, defaultValue = "true") Boolean includeGateway) {
+//        return ApiResult.success(emsModelService.getStructureTree(projectId, includeGateway));
+//    }
 
     /**
      * 能源类型列表(电、水、气)
@@ -156,11 +158,11 @@ public class EmsModelController {
 
     /**
      * 网关-通道-设备树(中间面板)
-     * GET /prod-api/service-ems/model/gateway-device/tree
+     * GET /prod-api/service-ems/model/gateway-device/tree(与类上 /model 前缀组合,勿再嵌套 /model)
      * @param spaceId 空间ID(可选,不传返回全部网关)
      * @param keyword 网关名称关键字(可选,模糊)
      */
-    @GetMapping("/model/gateway-device/tree")
+    @GetMapping("/gateway-device/tree")
     public ApiResult<List<EmsGatewayDeviceTreeNode>> getGatewayDeviceTree(
             @RequestParam(required = false) Long spaceId,
             @RequestParam(required = false) String keyword) {
@@ -172,11 +174,28 @@ public class EmsModelController {
      * GET /prod-api/service-ems/model/attribute-point/list
      * @param deviceId 设备ID(必填)
      */
-    @GetMapping("/model/attribute-point/list")
+    @GetMapping("/attribute-point/list")
     public ApiResult<List<EmsAttributePointVO>> getAttributePointList(
             @RequestParam String deviceId) {
         return ApiResult.success(emsModelService.getAttributePointList(deviceId));
     }
 
+    /**
+     * 空间绑定网关(一个空间绑定一个或多个网关)
+     */
+    @PostMapping("/space/gateway/bind")
+    public ApiResult<Void> bindSpaceGateways(@RequestBody SpaceGatewayBindRequest request) {
+        emsModelService.bindSpaceGateways(request.getSpaceId(), request.getGatewayUuids());
+        return ApiResult.success();
+    }
+
+    /**
+     * 根据空间ID查询网关列表
+     */
+    @GetMapping("/space/{spaceId}/gateway/list")
+    public ApiResult<List<DmpGatewayDetailResponse>> getGatewayListBySpaceId(@PathVariable Long spaceId) {
+        return ApiResult.success(emsModelService.getGatewayListBySpaceId(spaceId));
+    }
+
 
 }

+ 3 - 2
service-ems/service-ems-biz/src/main/java/com/usky/ems/controller/web/EmsOverviewController.java

@@ -12,6 +12,7 @@ import org.springframework.web.bind.annotation.*;
 
 /**
  * 能源能耗 - 概览模块 API
+ * 建筑排名等涉及空间树的数据来自 base_space(见 {@link com.usky.ems.service.impl.EmsOverviewServiceImpl})。
  * 基础路径前缀:/overview(网关再加 /prod-api/service-ems)
  */
 @RestController
@@ -78,7 +79,7 @@ public class EmsOverviewController {
      * 参数说明:
      * - dateType:时间类型(1-日,2-月,3-年)
      * - itemCode:能耗条目编码
-     * - spaceId:空间ID(可选,当前模拟实现未使用
+     * - spaceId:空间ID(可选,当前仍为模拟数据占位
      */
     @GetMapping("/energy-trend")
     public ApiResult<java.util.List<java.util.Map<String, Object>>> queryEnergyTrend(
@@ -93,7 +94,7 @@ public class EmsOverviewController {
      * 参数说明:
      * - dateType:时间类型(1-日,2-月,3-年)
      * - itemCode:能耗条目编码
-     * - spaceId:空间ID(可选,当前模拟实现未使用
+     * - spaceId:空间ID(可选;下钻时与 base_space 子节点一致
      */
     @GetMapping("/building-ranking")
     public ApiResult<java.util.List<java.util.Map<String, Object>>> queryBuildingRanking(

+ 0 - 64
service-ems/service-ems-biz/src/main/java/com/usky/ems/controller/web/EmsProjectController.java

@@ -1,64 +0,0 @@
-package com.usky.ems.controller.web;
-
-import com.usky.common.core.bean.ApiResult;
-import com.usky.ems.domain.EmsProject;
-import com.usky.ems.service.EmsProjectService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
-
-/**
- * 项目管理接口(ems_project)
- *
- * POST   /project       新增项目
- * PUT    /project/{id}  修改项目
- * DELETE /project/{id}  删除项目
- * GET    /project/config/status  获取项目配置开关状态
- */
-@RestController
-@RequestMapping("/project")
-public class EmsProjectController {
-
-    @Autowired
-    private EmsProjectService emsProjectService;
-
-    /**
-     * 新增项目
-     */
-    @PostMapping
-    public ApiResult<Long> create(@RequestBody EmsProject project) {
-        Long id = emsProjectService.create(project);
-        return ApiResult.success(id);
-    }
-
-    /**
-     * 修改项目
-     */
-    @PutMapping("/{id}")
-    public ApiResult<Void> update(@PathVariable Long id, @RequestBody EmsProject project) {
-        project.setId(id);
-        emsProjectService.update(project);
-        return ApiResult.success();
-    }
-
-    /**
-     * 删除项目
-     */
-    @DeleteMapping("/{id}")
-    public ApiResult<Void> delete(@PathVariable Long id) {
-        emsProjectService.delete(id);
-        return ApiResult.success();
-    }
-
-    /**
-     * 获取项目配置开关状态
-     *
-     * @param projectId 项目ID
-     * @param name      配置名称
-     */
-    @GetMapping("/config/status")
-    public ApiResult<Boolean> getConfigurationsStatus(@RequestParam Long projectId,
-                                                      @RequestParam String name) {
-        return ApiResult.success(emsProjectService.getConfigurationsStatus(projectId, name));
-    }
-}
-

+ 18 - 19
service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/EmsProjectConfiguration.java → service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/BaseArea.java

@@ -8,40 +8,39 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 
 import java.io.Serializable;
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
 
 /**
- * 项目配置信息(leo.ems_project_configuration
+ * 区域(base_area
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
-@TableName("ems_project_configuration")
-public class EmsProjectConfiguration implements Serializable {
+@TableName("base_area")
+public class BaseArea implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @TableField("project_id")
-    private Long projectId;
-
     private String name;
-
-    private String value;
-
-    private String remark;
-
-    @TableField("updated_by")
-    private Long updatedBy;
-
+    private Integer type;
+    private BigDecimal area;
+    @TableField("common_area")
+    private BigDecimal commonArea;
+    @TableField("air_conditioned_area")
+    private BigDecimal airConditionedArea;
+    @TableField("resident_population")
+    private Integer residentPopulation;
+    @TableField("tenant_id")
+    private Integer tenantId;
+    @TableField("update_by")
+    private String updateBy;
+    @TableField("create_by")
+    private String createBy;
     @TableField("update_time")
     private LocalDateTime updateTime;
-
-    @TableField("created_by")
-    private Long createdBy;
-
     @TableField("create_time")
     private LocalDateTime createTime;
 }
-

+ 97 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/BaseBuild.java

@@ -0,0 +1,97 @@
+package com.usky.ems.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 建筑信息(base_build),字段与表结构一致
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("base_build")
+public class BaseBuild implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @TableField("build_num")
+    private String buildNum;
+    @TableField("build_name")
+    private String buildName;
+    private String address;
+    @TableField("model_address")
+    private String modelAddress;
+    @TableField("above_floor")
+    private Integer aboveFloor;
+    @TableField("under_floor")
+    private Integer underFloor;
+    @TableField("build_area")
+    private Double buildArea;
+    @TableField("cover_area")
+    private Double coverArea;
+    @TableField("fire_rating")
+    private Integer fireRating;
+    @TableField("use_character")
+    private Integer useCharacter;
+    @TableField("build_structure")
+    private Integer buildStructure;
+    @TableField("build_high")
+    private Double buildHigh;
+    @TableField("high_type")
+    private Integer highType;
+    @TableField("complete_year")
+    private LocalDate completeYear;
+    @TableField("safe_person")
+    private String safePerson;
+    @TableField("manage_person")
+    private String managePerson;
+    @TableField("fire_risk")
+    private Integer fireRisk;
+    @TableField("fire_control_room")
+    private String fireControlRoom;
+    @TableField("build_inside")
+    private String buildInside;
+    @TableField("build_plan")
+    private String buildPlan;
+    @TableField("facility_id")
+    private Integer facilityId;
+    @TableField("bim_url")
+    private String bimUrl;
+    @TableField("contact_phone")
+    private String contactPhone;
+    @TableField("build_desc")
+    private String buildDesc;
+    @TableField("create_time")
+    private LocalDateTime createTime;
+    @TableField("update_time")
+    private LocalDateTime updateTime;
+    @TableField("update_by")
+    private String updateBy;
+    @TableField("create_by")
+    private String createBy;
+    @TableField("delete_flag")
+    private Integer deleteFlag;
+    @TableField("under_space")
+    private Double underSpace;
+    /** 防火涂层:0 无、1 有 */
+    @TableField("fireproof_coat")
+    private Integer fireproofCoat;
+    @TableField("dept_id")
+    private Integer deptId;
+    @TableField("tenant_id")
+    private Integer tenantId;
+    private String longitude;
+    private String latitude;
+    @TableField("unit_count")
+    private Integer unitCount;
+}

+ 2 - 2
service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/BaseSpace.java

@@ -35,11 +35,11 @@ public class BaseSpace implements Serializable {
     private String pathName;
     private Integer deep;
     @TableField("updated_by")
-    private Long updatedBy;
+    private String updatedBy;
     @TableField("update_time")
     private LocalDateTime updateTime;
     @TableField("created_by")
-    private Long createdBy;
+    private String createdBy;
     @TableField("create_time")
     private LocalDateTime createTime;
     @TableField("tenant_id")

+ 10 - 20
service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/EmsProjectDeviceSystem.java → service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/BaseSpaceArea.java

@@ -11,34 +11,24 @@ import java.io.Serializable;
 import java.time.LocalDateTime;
 
 /**
- * 项目设备系统(leo.ems_project_device_system
+ * 空间-区域关联(base_space_area
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
-@TableName("ems_project_device_system")
-public class EmsProjectDeviceSystem implements Serializable {
+@TableName("base_space_area")
+public class BaseSpaceArea implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @TableField("project_id")
-    private Long projectId;
-
-    @TableField("device_system")
-    private Integer deviceSystem;
-
-    @TableField("updated_by")
-    private Long updatedBy;
-
-    @TableField("update_time")
-    private LocalDateTime updateTime;
-
+    @TableField("space_id")
+    private Long spaceId;
+    @TableField("area_id")
+    private Long areaId;
     @TableField("created_by")
-    private Long createdBy;
-
-    @TableField("create_time")
-    private LocalDateTime createTime;
+    private String createdBy;
+    @TableField("created_time")
+    private LocalDateTime createdTime;
 }
-

+ 34 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/BaseSpaceBuild.java

@@ -0,0 +1,34 @@
+package com.usky.ems.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 空间-建筑关联(base_space_build)
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("base_space_build")
+public class BaseSpaceBuild implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @TableField("space_id")
+    private Long spaceId;
+    @TableField("build_id")
+    private Integer buildId;
+    @TableField("created_by")
+    private String createdBy;
+    @TableField("created_time")
+    private LocalDateTime createdTime;
+}

+ 34 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/BaseSpaceGateway.java

@@ -0,0 +1,34 @@
+package com.usky.ems.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 空间-网关关联(base_space_gateway)
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("base_space_gateway")
+public class BaseSpaceGateway implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @TableField("space_id")
+    private Long spaceId;
+    @TableField("gateway_uuid")
+    private String gatewayUuid;
+    @TableField("created_by")
+    private String createdBy;
+    @TableField("created_time")
+    private LocalDateTime createdTime;
+}

+ 4 - 2
service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/DmpGateway.java

@@ -32,6 +32,8 @@ public class DmpGateway implements Serializable {
 
     private Integer port;
 
+    private String installAddress;
+
     @TableField("comm_status")
     private Integer commStatus;
 
@@ -56,13 +58,13 @@ public class DmpGateway implements Serializable {
     private String remark;
 
     @TableField("updated_by")
-    private Long updatedBy;
+    private String updatedBy;
 
     @TableField("update_time")
     private LocalDateTime updateTime;
 
     @TableField("created_by")
-    private Long createdBy;
+    private String createdBy;
 
     @TableField("create_time")
     private LocalDateTime createTime;

+ 0 - 64
service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/EmsGateway.java

@@ -1,64 +0,0 @@
-package com.usky.ems.domain;
-
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-/**
- * 网关(leo.ems_gateway)
- */
-@Data
-@EqualsAndHashCode(callSuper = false)
-@TableName("ems_gateway")
-public class EmsGateway implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.INPUT)
-    private String id;
-
-    @TableField("project_id")
-    private Long projectId;
-    private String name;
-    @TableField("space_id")
-    private Long spaceId;
-    private String version;
-    private String type;
-    private String ip;
-    private Integer port;
-    @TableField("comm_status")
-    private Integer commStatus;
-    @TableField("online_time")
-    private LocalDateTime onlineTime;
-    @TableField("offline_time")
-    private LocalDateTime offlineTime;
-    @TableField("update_config_time")
-    private LocalDateTime updateConfigTime;
-    @TableField("update_protocol_time")
-    private LocalDateTime updateProtocolTime;
-    @TableField("upgrade_time")
-    private LocalDateTime upgradeTime;
-    @TableField("data_center_id")
-    private Long dataCenterId;
-    private String iccid;
-    private Integer rssi;
-    @TableField("secret_key")
-    private String secretKey;
-    @TableField("virtual_device")
-    private Integer virtualDevice;
-    private String remark;
-    @TableField("updated_by")
-    private Long updatedBy;
-    @TableField("update_time")
-    private LocalDateTime updateTime;
-    @TableField("created_by")
-    private Long createdBy;
-    @TableField("create_time")
-    private LocalDateTime createTime;
-}

+ 0 - 71
service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/EmsProject.java

@@ -1,71 +0,0 @@
-package com.usky.ems.domain;
-
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-
-/**
- * 项目(leo.ems_project)
- */
-@Data
-@EqualsAndHashCode(callSuper = false)
-@TableName("ems_project")
-public class EmsProject implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    @TableField("space_id")
-    private Long spaceId;
-    private String name;
-    @TableField("platform_name")
-    private String platformName;
-    private String abbreviation;
-    private BigDecimal area;
-    @TableField("common_area")
-    private BigDecimal commonArea;
-    @TableField("air_conditioned_area")
-    private BigDecimal airConditionedArea;
-    @TableField("resident_population")
-    private Integer residentPopulation;
-    @TableField("province_code")
-    private String provinceCode;
-    @TableField("province_name")
-    private String provinceName;
-    @TableField("city_code")
-    private String cityCode;
-    @TableField("city_name")
-    private String cityName;
-    @TableField("district_code")
-    private String districtCode;
-    @TableField("district_name")
-    private String districtName;
-    private String location;
-    private String address;
-    @TableField("type_id")
-    private Integer typeId;
-    @TableField("type_name")
-    private String typeName;
-    private String image;
-    private String introduction;
-    private String logo;
-    @TableField("logo_min")
-    private String logoMin;
-    @TableField("updated_by")
-    private Long updatedBy;
-    @TableField("update_time")
-    private LocalDateTime updateTime;
-    @TableField("created_by")
-    private Long createdBy;
-    @TableField("create_time")
-    private LocalDateTime createTime;
-}

+ 0 - 59
service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/EmsProjectConversionFactor.java

@@ -1,59 +0,0 @@
-package com.usky.ems.domain;
-
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-
-/**
- * 项目能耗折算系数(leo.ems_project_conversion_factor)
- * 用于将不同能源类型折算为标准煤等统一口径。
- */
-@Data
-@EqualsAndHashCode(callSuper = false)
-@TableName("ems_project_conversion_factor")
-public class EmsProjectConversionFactor implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    @TableField("project_id")
-    private Long projectId;
-
-    /**
-     * 能源类型编码,对应能源类型 ID(如 1=电,2=水,3=气)
-     */
-    @TableField("energy_type")
-    private Integer energyType;
-
-    /**
-     * 系数名称,例如 "coal"、"price" 等
-     */
-    private String name;
-
-    /**
-     * 系数数值
-     */
-    private BigDecimal value;
-
-    @TableField("updated_by")
-    private Long updatedBy;
-
-    @TableField("update_time")
-    private LocalDateTime updateTime;
-
-    @TableField("created_by")
-    private Long createdBy;
-
-    @TableField("create_time")
-    private LocalDateTime createTime;
-}
-

+ 10 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/BaseAreaMapper.java

@@ -0,0 +1,10 @@
+package com.usky.ems.mapper;
+
+import com.usky.common.mybatis.core.CrudMapper;
+import com.usky.ems.domain.BaseArea;
+
+/**
+ * 区域 Mapper(base_area)
+ */
+public interface BaseAreaMapper extends CrudMapper<BaseArea> {
+}

+ 10 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/BaseBuildMapper.java

@@ -0,0 +1,10 @@
+package com.usky.ems.mapper;
+
+import com.usky.common.mybatis.core.CrudMapper;
+import com.usky.ems.domain.BaseBuild;
+
+/**
+ * 建筑 Mapper(base_build)
+ */
+public interface BaseBuildMapper extends CrudMapper<BaseBuild> {
+}

+ 10 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/BaseSpaceAreaMapper.java

@@ -0,0 +1,10 @@
+package com.usky.ems.mapper;
+
+import com.usky.common.mybatis.core.CrudMapper;
+import com.usky.ems.domain.BaseSpaceArea;
+
+/**
+ * 空间-区域关联 Mapper(base_space_area)
+ */
+public interface BaseSpaceAreaMapper extends CrudMapper<BaseSpaceArea> {
+}

+ 10 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/BaseSpaceBuildMapper.java

@@ -0,0 +1,10 @@
+package com.usky.ems.mapper;
+
+import com.usky.common.mybatis.core.CrudMapper;
+import com.usky.ems.domain.BaseSpaceBuild;
+
+/**
+ * 空间-建筑关联 Mapper(base_space_build)
+ */
+public interface BaseSpaceBuildMapper extends CrudMapper<BaseSpaceBuild> {
+}

+ 10 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/BaseSpaceGatewayMapper.java

@@ -0,0 +1,10 @@
+package com.usky.ems.mapper;
+
+import com.usky.common.mybatis.core.CrudMapper;
+import com.usky.ems.domain.BaseSpaceGateway;
+
+/**
+ * 空间-网关关联 Mapper(base_space_gateway)
+ */
+public interface BaseSpaceGatewayMapper extends CrudMapper<BaseSpaceGateway> {
+}

+ 0 - 10
service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/EmsGatewayMapper.java

@@ -1,10 +0,0 @@
-package com.usky.ems.mapper;
-
-import com.usky.common.mybatis.core.CrudMapper;
-import com.usky.ems.domain.EmsGateway;
-
-/**
- * 网关 Mapper(leo.ems_gateway)
- */
-public interface EmsGatewayMapper extends CrudMapper<EmsGateway> {
-}

+ 0 - 11
service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/EmsProjectConfigurationMapper.java

@@ -1,11 +0,0 @@
-package com.usky.ems.mapper;
-
-import com.usky.common.mybatis.core.CrudMapper;
-import com.usky.ems.domain.EmsProjectConfiguration;
-
-/**
- * 项目配置信息 Mapper(leo.ems_project_configuration)
- */
-public interface EmsProjectConfigurationMapper extends CrudMapper<EmsProjectConfiguration> {
-}
-

+ 0 - 11
service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/EmsProjectConversionFactorMapper.java

@@ -1,11 +0,0 @@
-package com.usky.ems.mapper;
-
-import com.usky.common.mybatis.core.CrudMapper;
-import com.usky.ems.domain.EmsProjectConversionFactor;
-
-/**
- * 项目能耗折算系数 Mapper(leo.ems_project_conversion_factor)
- */
-public interface EmsProjectConversionFactorMapper extends CrudMapper<EmsProjectConversionFactor> {
-}
-

+ 0 - 11
service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/EmsProjectDeviceSystemMapper.java

@@ -1,11 +0,0 @@
-package com.usky.ems.mapper;
-
-import com.usky.common.mybatis.core.CrudMapper;
-import com.usky.ems.domain.EmsProjectDeviceSystem;
-
-/**
- * 项目设备系统 Mapper(leo.ems_project_device_system)
- */
-public interface EmsProjectDeviceSystemMapper extends CrudMapper<EmsProjectDeviceSystem> {
-}
-

+ 0 - 10
service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/EmsProjectMapper.java

@@ -1,10 +0,0 @@
-package com.usky.ems.mapper;
-
-import com.usky.common.mybatis.core.CrudMapper;
-import com.usky.ems.domain.EmsProject;
-
-/**
- * 项目 Mapper(leo.ems_project)
- */
-public interface EmsProjectMapper extends CrudMapper<EmsProject> {
-}

+ 0 - 22
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/EmsGatewayQueryService.java

@@ -1,22 +0,0 @@
-package com.usky.ems.service;
-
-import com.usky.common.core.bean.CommonPage;
-import com.usky.ems.service.vo.EmsGatewayDetailResponse;
-import com.usky.ems.service.vo.EmsGatewayListItem;
-import com.usky.ems.service.vo.EmsGatewayPageRequest;
-
-/**
- * 网关列表与详情查询服务
- */
-public interface EmsGatewayQueryService {
-
-    /**
-     * 分页查询网关列表
-     */
-    CommonPage<EmsGatewayListItem> listGateways(EmsGatewayPageRequest request);
-
-    /**
-     * 网关详情
-     */
-    EmsGatewayDetailResponse getGatewayById(String id);
-}

+ 15 - 1
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/EmsModelService.java

@@ -6,6 +6,7 @@ import com.usky.ems.service.vo.EmsGatewayDeviceTreeNode;
 import com.usky.ems.service.vo.EmsModelSaveRequest;
 import com.usky.ems.service.vo.EmsStructureTreeNode;
 import com.usky.ems.service.vo.EnergyTypeWrapperProductVO;
+import com.usky.ems.service.vo.DmpGatewayDetailResponse;
 
 import java.util.List;
 
@@ -17,7 +18,7 @@ public interface EmsModelService {
     /**
      * 获取项目层级树(建筑、区域、网关)
      */
-    EmsStructureTreeNode getStructureTree(Long projectId, Boolean includeGateway);
+//    EmsStructureTreeNode getStructureTree(Long projectId, Boolean includeGateway);
 
     /**
      * 能源类型列表(电、水、气)
@@ -84,4 +85,17 @@ public interface EmsModelService {
      * @param deviceId 设备ID
      */
     List<EmsAttributePointVO> getAttributePointList(String deviceId);
+
+    /**
+     * 空间绑定网关(一个空间可绑定多个网关)
+     * @param spaceId 空间ID
+     * @param gatewayUuids 网关uuid列表
+     */
+    void bindSpaceGateways(Long spaceId, List<String> gatewayUuids);
+
+    /**
+     * 根据空间ID查询绑定的网关列表
+     * @param spaceId 空间ID
+     */
+    List<DmpGatewayDetailResponse> getGatewayListBySpaceId(Long spaceId);
 }

+ 0 - 11
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/EmsProjectConfigurationService.java

@@ -1,11 +0,0 @@
-package com.usky.ems.service;
-
-import com.usky.common.mybatis.core.CrudService;
-import com.usky.ems.domain.EmsProjectConfiguration;
-
-/**
- * 项目配置信息服务
- */
-public interface EmsProjectConfigurationService extends CrudService<EmsProjectConfiguration> {
-}
-

+ 0 - 36
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/EmsProjectService.java

@@ -1,36 +0,0 @@
-package com.usky.ems.service;
-
-import com.usky.common.mybatis.core.CrudService;
-import com.usky.ems.domain.EmsProject;
-import com.usky.ems.domain.EmsProjectConfiguration;
-
-/**
- * 项目服务(leo.ems_project)
- */
-public interface EmsProjectService extends CrudService<EmsProject> {
-
-    /**
-     * 新增项目
-     */
-    Long create(EmsProject project);
-
-    /**
-     * 修改项目
-     */
-    void update(EmsProject project);
-
-    /**
-     * 删除项目
-     */
-    void delete(Long id);
-
-    /**
-     * 获取项目配置开关状态:根据当前项目ID与配置名称,判断 value 是否为 "1"
-     *
-     * @param projectId 项目 ID
-     * @param name      配置名称
-     * @return true 表示开启(value="1"),false 表示未开启/未配置
-     */
-    Boolean getConfigurationsStatus(Long projectId, String name);
-}
-

+ 10 - 1
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/BaseSpaceServiceImpl.java

@@ -11,9 +11,11 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -86,7 +88,14 @@ public class BaseSpaceServiceImpl extends AbstractCrudService<BaseSpaceMapper, B
         if (spaceId == null) {
             return Collections.emptyList();
         }
-        return Collections.singletonList(spaceId);
+        Set<Long> ids = new LinkedHashSet<>();
+        ids.add(spaceId);
+        for (BaseSpace child : recursiveAllChildrenNode(spaceId)) {
+            if (child != null && child.getId() != null) {
+                ids.add(child.getId());
+            }
+        }
+        return new ArrayList<>(ids);
     }
 
     @Override

+ 3 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/DmpGatewayServiceImpl.java

@@ -87,6 +87,9 @@ public class DmpGatewayServiceImpl extends AbstractCrudService<DmpGatewayMapper,
         if (StringUtils.hasText(request.getName())) {
             q.like(DmpGateway::getName, request.getName());
         }
+        if (StringUtils.hasText(request.getInstallAddress())) {
+            q.like(DmpGateway::getInstallAddress, request.getInstallAddress());
+        }
         if (StringUtils.hasText(request.getDeviceUuid())) {
             q.eq(DmpGateway::getDeviceUuid, request.getDeviceUuid());
         }

+ 11 - 18
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsAnalysisServiceImpl.java

@@ -3,8 +3,6 @@ package com.usky.ems.service.impl;
 import com.baomidou.dynamic.datasource.annotation.DS;
 import com.usky.ems.mapper.EmsDeviceMapper;
 import com.usky.ems.mapper.EmsEnergyItemCodeMapper;
-import com.usky.ems.mapper.EmsProjectMapper;
-import com.usky.ems.mapper.EmsSpaceMapper;
 import com.usky.ems.service.EmsAnalysisService;
 import com.usky.ems.service.TdengineService;
 import com.usky.ems.service.vo.*;
@@ -17,10 +15,6 @@ import java.math.RoundingMode;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
-import java.text.SimpleDateFormat;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -60,11 +54,6 @@ public class EmsAnalysisServiceImpl implements EmsAnalysisService {
     @Autowired
     private TdengineService tdengineService;
     
-    @Autowired
-    private EmsProjectMapper emsProjectMapper;
-    
-    @Autowired
-    private EmsSpaceMapper emsSpaceMapper;
     
     @Autowired
     private EmsDeviceMapper emsDeviceMapper;
@@ -575,9 +564,11 @@ public class EmsAnalysisServiceImpl implements EmsAnalysisService {
         System.out.println("Getting project area and population for projectId: " + projectId);
         
         try (Connection conn = mysqlDataSource.getConnection()) {
-            String sql = "SELECT SUM(area) as total_area, SUM(resident_population) as total_population " +
-                        "FROM ems_space_building " +
-                        "WHERE space_id IN (SELECT id FROM ems_space WHERE root_id = ?)";
+            String sql = "SELECT COALESCE(SUM(ba.area),0) as total_area, COALESCE(SUM(ba.resident_population),0) as total_population " +
+                        "FROM base_area ba " +
+                        "INNER JOIN base_space_area bsa ON bsa.area_id = ba.id " +
+                        "INNER JOIN base_space bs ON bs.id = bsa.space_id " +
+                        "WHERE bs.root_id = (SELECT space_id FROM ems_project WHERE id = ?)";
             
             System.out.println("Project area SQL: " + sql);
             System.out.println("Setting projectId parameter: " + projectId);
@@ -702,7 +693,8 @@ public class EmsAnalysisServiceImpl implements EmsAnalysisService {
              // 如果没有指定区域ID,则获取项目下的所有区域
              try (Connection conn = mysqlDataSource.getConnection()) {
                  // 查找该项目下的所有区域(type=2表示区域类型)
-                 String sql = "SELECT id FROM ems_space WHERE root_id = ? AND type = 2";
+                 String sql = "SELECT id FROM base_space WHERE type = 2 AND root_id = " +
+                         "(SELECT space_id FROM ems_project WHERE id = ?)";
                  
                  try (PreparedStatement stmt = conn.prepareStatement(sql)) {
                      stmt.setLong(1, projectId);
@@ -776,7 +768,7 @@ public class EmsAnalysisServiceImpl implements EmsAnalysisService {
       */
      private String getRegionName(Long regionId, Connection conn) {
          try {
-             String sql = "SELECT name FROM ems_space WHERE id = ?";
+             String sql = "SELECT name FROM base_space WHERE id = ?";
              try (PreparedStatement stmt = conn.prepareStatement(sql)) {
                  stmt.setLong(1, regionId);
                  try (ResultSet rs = stmt.executeQuery()) {
@@ -796,7 +788,8 @@ public class EmsAnalysisServiceImpl implements EmsAnalysisService {
       */
      private BigDecimal getRegionArea(Long regionId, Connection conn) {
          try {
-             String sql = "SELECT SUM(area) as total_area FROM ems_space_building WHERE space_id = ?";
+             String sql = "SELECT COALESCE(SUM(ba.area),0) as total_area FROM base_area ba " +
+                     "INNER JOIN base_space_area bsa ON bsa.area_id = ba.id WHERE bsa.space_id = ?";
              try (PreparedStatement stmt = conn.prepareStatement(sql)) {
                  stmt.setLong(1, regionId);
                  try (ResultSet rs = stmt.executeQuery()) {
@@ -831,7 +824,7 @@ public class EmsAnalysisServiceImpl implements EmsAnalysisService {
              
              // 查找该区域下的建筑,然后在这些建筑中查找设备
              sql.append("WHERE ed.monitoring_location IN ");
-             sql.append("(SELECT id FROM ems_space_building WHERE space_id = ?) ");
+             sql.append("(SELECT build_id FROM base_space_build WHERE space_id = ?) ");
              
              if (energyTypeId != null) {
                  sql.append("AND epe.energy_type = ? ");

+ 36 - 17
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsDeviceEventServiceImpl.java

@@ -2,15 +2,17 @@ package com.usky.ems.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.usky.common.core.exception.BusinessException;
+import com.usky.ems.domain.BaseSpace;
+import com.usky.ems.domain.BaseSpaceGateway;
+import com.usky.ems.domain.DmpGateway;
 import com.usky.ems.domain.EmsDevice;
 import com.usky.ems.domain.EmsDeviceEvent;
-import com.usky.ems.domain.EmsGateway;
-import com.usky.ems.domain.EmsSpace;
+import com.usky.ems.mapper.BaseSpaceGatewayMapper;
+import com.usky.ems.mapper.DmpGatewayMapper;
 import com.usky.ems.mapper.EmsDeviceEventMapper;
 import com.usky.ems.mapper.EmsDeviceMapper;
-import com.usky.ems.mapper.EmsGatewayMapper;
+import com.usky.ems.service.BaseSpaceService;
 import com.usky.ems.service.EmsDeviceEventService;
-import com.usky.ems.service.EmsSpaceService;
 import com.usky.ems.service.vo.DeviceEventDTO;
 import com.usky.ems.service.vo.DeviceEventVO;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -35,13 +37,16 @@ import java.util.stream.Collectors;
 public class EmsDeviceEventServiceImpl implements EmsDeviceEventService {
 
     @Autowired
-    private EmsSpaceService emsSpaceService;
+    private BaseSpaceService baseSpaceService;
 
     @Autowired
     private EmsDeviceMapper emsDeviceMapper;
 
     @Autowired
-    private EmsGatewayMapper emsGatewayMapper;
+    private BaseSpaceGatewayMapper baseSpaceGatewayMapper;
+
+    @Autowired
+    private DmpGatewayMapper dmpGatewayMapper;
 
     @Autowired
     private EmsDeviceEventMapper emsDeviceEventMapper;
@@ -52,23 +57,23 @@ public class EmsDeviceEventServiceImpl implements EmsDeviceEventService {
             throw new BusinessException("安装位置不存在");
         }
 
-        EmsSpace space = emsSpaceService.getById(dto.getInstallationLocation());
+        BaseSpace space = baseSpaceService.getById(dto.getInstallationLocation());
         if (space == null) {
             throw new BusinessException("安装位置不存在");
         }
 
         // 1) 递归获取所有子空间 + 本空间
-        List<EmsSpace> spaceList = new ArrayList<>(emsSpaceService.recursiveAllChildrenNode(dto.getInstallationLocation()));
+        List<BaseSpace> spaceList = new ArrayList<>(baseSpaceService.recursiveAllChildrenNode(dto.getInstallationLocation()));
         spaceList.add(space);
 
         List<Long> spaceIds = spaceList.stream()
-                .map(EmsSpace::getId)
+                .map(BaseSpace::getId)
                 .filter(Objects::nonNull)
                 .collect(Collectors.toList());
 
         Map<Long, String> spaceMap = spaceList.stream()
                 .filter(s -> s.getId() != null)
-                .collect(Collectors.toMap(EmsSpace::getId, EmsSpace::getName, (a, b) -> a));
+                .collect(Collectors.toMap(BaseSpace::getId, BaseSpace::getName, (a, b) -> a));
 
         // 2) 根据 deviceType 取设备/网关列表及其名称、空间映射
         Integer deviceType = dto.getDeviceType();
@@ -92,16 +97,30 @@ public class EmsDeviceEventServiceImpl implements EmsDeviceEventService {
             spaceIdMap = devices.stream().filter(d -> d.getId() != null)
                     .collect(Collectors.toMap(EmsDevice::getId, EmsDevice::getInstallationLocation, (a, b) -> a));
         } else {
-            List<EmsGateway> gateways = emsGatewayMapper.selectList(new LambdaQueryWrapper<EmsGateway>()
-                    .in(EmsGateway::getSpaceId, spaceIds));
+            List<BaseSpaceGateway> links = baseSpaceGatewayMapper.selectList(
+                    new LambdaQueryWrapper<BaseSpaceGateway>().in(BaseSpaceGateway::getSpaceId, spaceIds));
+            if (links == null || links.isEmpty()) {
+                return Collections.emptyList();
+            }
+            java.util.Map<String, Long> uuidToSpace = new java.util.HashMap<>();
+            for (BaseSpaceGateway link : links) {
+                if (link.getGatewayUuid() != null && link.getSpaceId() != null) {
+                    uuidToSpace.putIfAbsent(link.getGatewayUuid(), link.getSpaceId());
+                }
+            }
+            if (uuidToSpace.isEmpty()) {
+                return Collections.emptyList();
+            }
+            List<DmpGateway> gateways = dmpGatewayMapper.selectList(
+                    new LambdaQueryWrapper<DmpGateway>().in(DmpGateway::getDeviceUuid, uuidToSpace.keySet()));
             if (gateways == null || gateways.isEmpty()) {
                 return Collections.emptyList();
             }
-            ids = gateways.stream().map(EmsGateway::getId).filter(Objects::nonNull).collect(Collectors.toList());
-            nameMap = gateways.stream().filter(g -> g.getId() != null)
-                    .collect(Collectors.toMap(EmsGateway::getId, EmsGateway::getName, (a, b) -> a));
-            spaceIdMap = gateways.stream().filter(g -> g.getId() != null)
-                    .collect(Collectors.toMap(EmsGateway::getId, EmsGateway::getSpaceId, (a, b) -> a));
+            ids = gateways.stream().map(DmpGateway::getDeviceUuid).filter(Objects::nonNull).collect(Collectors.toList());
+            nameMap = gateways.stream().filter(g -> g.getDeviceUuid() != null)
+                    .collect(Collectors.toMap(DmpGateway::getDeviceUuid, DmpGateway::getName, (a, b) -> a));
+            spaceIdMap = gateways.stream().filter(g -> g.getDeviceUuid() != null)
+                    .collect(Collectors.toMap(DmpGateway::getDeviceUuid, g -> uuidToSpace.get(g.getDeviceUuid()), (a, b) -> a));
         }
 
         if (ids.isEmpty()) {

+ 3 - 3
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsDeviceReportServiceImpl.java

@@ -6,8 +6,8 @@ import com.usky.ems.domain.EmsDeviceFunction;
 import com.usky.ems.enums.TemporalTypeEnum;
 import com.usky.ems.mapper.EmsDeviceFunctionMapper;
 import com.usky.ems.mapper.EmsDeviceMapper;
+import com.usky.ems.service.BaseSpaceService;
 import com.usky.ems.service.EmsDeviceReportService;
-import com.usky.ems.service.EmsSpaceService;
 import com.usky.ems.service.vo.*;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -23,7 +23,7 @@ import java.util.stream.Collectors;
 public class EmsDeviceReportServiceImpl implements EmsDeviceReportService {
 
     @Autowired
-    private EmsSpaceService emsSpaceService;
+    private BaseSpaceService baseSpaceService;
 
     @Autowired
     private EmsDeviceMapper emsDeviceMapper;
@@ -38,7 +38,7 @@ public class EmsDeviceReportServiceImpl implements EmsDeviceReportService {
         }
 
         // 1. 授权空间
-        List<Long> spaceIds = emsSpaceService.getAuthorizedSpaceIds(dto.getSpaceId());
+        List<Long> spaceIds = baseSpaceService.getAuthorizedSpaceIds(dto.getSpaceId());
 
         // 2. 在 Service 层用 LambdaQueryWrapper 查 ems_device
         LambdaQueryWrapper<EmsDevice> wrapper = new LambdaQueryWrapper<>();

+ 0 - 87
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsGatewayQueryServiceImpl.java

@@ -1,87 +0,0 @@
-package com.usky.ems.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.usky.common.core.bean.CommonPage;
-import com.usky.ems.domain.EmsGateway;
-import com.usky.ems.mapper.EmsGatewayMapper;
-import com.usky.ems.mapper.EmsSpaceMapper;
-import com.usky.ems.service.EmsGatewayQueryService;
-import com.usky.ems.service.vo.EmsGatewayDetailResponse;
-import com.usky.ems.service.vo.EmsGatewayListItem;
-import com.usky.ems.service.vo.EmsGatewayPageRequest;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.util.StringUtils;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * 网关列表与详情查询服务实现
- */
-@Service
-public class EmsGatewayQueryServiceImpl implements EmsGatewayQueryService {
-
-    @Autowired
-    private EmsGatewayMapper emsGatewayMapper;
-    @Autowired
-    private EmsSpaceMapper emsSpaceMapper;
-
-    @Override
-    public CommonPage<EmsGatewayListItem> listGateways(EmsGatewayPageRequest request) {
-        int current = request.getCurrent() == null ? 1 : request.getCurrent();
-        int size = request.getSize() == null ? 10 : request.getSize();
-        Page<EmsGateway> p = new Page<>(current, size);
-        LambdaQueryWrapper<EmsGateway> q = new LambdaQueryWrapper<>();
-        if (request.getCommunicationStatus() != null) {
-            q.eq(EmsGateway::getCommStatus, request.getCommunicationStatus());
-        }
-        if (StringUtils.hasText(request.getName())) {
-            q.like(EmsGateway::getName, request.getName());
-        }
-        if (StringUtils.hasText(request.getCode())) {
-            q.eq(EmsGateway::getId, request.getCode());
-        }
-        Page<EmsGateway> page = emsGatewayMapper.selectPage(p, q);
-        List<EmsGatewayListItem> list = page.getRecords().stream().map(this::toListItem).collect(Collectors.toList());
-        return new CommonPage<>(list, page.getTotal(), size, current);
-    }
-
-    @Override
-    public EmsGatewayDetailResponse getGatewayById(String id) {
-        EmsGateway g = emsGatewayMapper.selectById(id);
-        if (g == null) return null;
-        EmsGatewayDetailResponse resp = new EmsGatewayDetailResponse();
-        resp.setId(g.getId());
-        resp.setName(g.getName());
-        resp.setSpaceId(g.getSpaceId());
-        resp.setCommunicationStatus(g.getCommStatus());
-        resp.setOnlineTime(g.getOnlineTime());
-        resp.setCreateTime(g.getCreateTime());
-        resp.setUpdateTime(g.getUpdateTime());
-        if (g.getSpaceId() != null) {
-            com.usky.ems.domain.EmsSpace space = emsSpaceMapper.selectById(g.getSpaceId());
-            if (space != null) {
-                resp.setSpaceName(space.getName());
-            }
-        }
-        return resp;
-    }
-
-    private EmsGatewayListItem toListItem(EmsGateway g) {
-        EmsGatewayListItem item = new EmsGatewayListItem();
-        item.setId(g.getId());
-        item.setName(g.getName());
-        item.setSpaceId(g.getSpaceId());
-        item.setCommunicationStatus(g.getCommStatus());
-        item.setOnlineTime(g.getOnlineTime());
-        item.setCreateTime(g.getCreateTime());
-        item.setUpdateTime(g.getUpdateTime());
-        if (g.getSpaceId() != null) {
-            com.usky.ems.domain.EmsSpace space = emsSpaceMapper.selectById(g.getSpaceId());
-            if (space != null) item.setSpaceName(space.getName());
-        }
-        return item;
-    }
-}

+ 516 - 243
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsModelServiceImpl.java

@@ -1,9 +1,11 @@
 package com.usky.ems.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.usky.common.security.utils.SecurityUtils;
 import com.usky.ems.domain.*;
 import com.usky.ems.mapper.*;
 import com.usky.ems.service.EmsModelService;
+import com.usky.ems.service.vo.DmpGatewayDetailResponse;
 import com.usky.ems.service.vo.EnergyTypeWrapperProductVO;
 import com.usky.ems.service.vo.EmsAttributePointVO;
 import com.usky.ems.service.vo.EmsEnergyTypeVO;
@@ -15,28 +17,38 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
 import java.util.stream.Collectors;
 
 /**
  * 基础建模服务实现(结构树、能源类型、建筑/区域/网关/通道/设备/属性点位 CRUD)
+ * 空间:base_space;建筑/区域实体:base_build、base_area;关联:base_space_build、base_space_area、base_space_gateway;网关:dmp_gateway
  */
 @Service
 public class EmsModelServiceImpl implements EmsModelService {
 
     @Autowired
-    private EmsProjectMapper emsProjectMapper;
+    private BaseSpaceMapper baseSpaceMapper;
     @Autowired
-    private EmsSpaceMapper emsSpaceMapper;
+    private BaseBuildMapper baseBuildMapper;
     @Autowired
-    private EmsSpaceBuildingMapper emsSpaceBuildingMapper;
+    private BaseAreaMapper baseAreaMapper;
     @Autowired
-    private EmsSpaceAreaMapper emsSpaceAreaMapper;
+    private BaseSpaceBuildMapper baseSpaceBuildMapper;
     @Autowired
-    private EmsGatewayMapper emsGatewayMapper;
+    private BaseSpaceAreaMapper baseSpaceAreaMapper;
+    @Autowired
+    private BaseSpaceGatewayMapper baseSpaceGatewayMapper;
+    @Autowired
+    private DmpGatewayMapper dmpGatewayMapper;
     @Autowired
     private EmsChannelMapper emsChannelMapper;
     @Autowired
@@ -50,61 +62,91 @@ public class EmsModelServiceImpl implements EmsModelService {
     private static final int SPACE_TYPE_REGION = 2;
     private static final int SPACE_TYPE_BUILDING = 3;
 
-    private EmsProject firstProject() {
-        List<EmsProject> list = emsProjectMapper.selectList(null);
-        return list.isEmpty() ? null : list.get(0);
-    }
-
-    @Override
-    public EmsStructureTreeNode getStructureTree(Long projectId, Boolean includeGateway) {
-        EmsProject project = projectId != null ? emsProjectMapper.selectById(projectId) : firstProject();
-        if (project == null) {
+    /** base_build.create_by / update_by 为 varchar(25) */
+    private static String trimAuditUser(String username) {
+        if (username == null) {
             return null;
         }
-        EmsStructureTreeNode root = new EmsStructureTreeNode();
-        root.setId(project.getId());
-        root.setName(project.getName());
-        root.setType("project");
-        root.setChildren(buildSpaceChildren(project.getSpaceId(), includeGateway == null || includeGateway));
-        return root;
+        return username.length() > 25 ? username.substring(0, 25) : username;
     }
 
-    private List<EmsStructureTreeNode> buildSpaceChildren(Long parentId, boolean includeGateway) {
-        if (parentId == null) return Collections.emptyList();
-        List<EmsSpace> list = emsSpaceMapper.selectList(new LambdaQueryWrapper<EmsSpace>().eq(EmsSpace::getParentId, parentId));
-        List<EmsStructureTreeNode> children = new ArrayList<>();
-        for (EmsSpace s : list) {
-            EmsStructureTreeNode node = new EmsStructureTreeNode();
-            node.setId(s.getId());
-            node.setName(s.getName());
-            if (s.getType() == SPACE_TYPE_BUILDING) {
-                node.setType("building");
-                EmsSpaceBuilding b = emsSpaceBuildingMapper.selectOne(new LambdaQueryWrapper<EmsSpaceBuilding>().eq(EmsSpaceBuilding::getSpaceId, s.getId()));
-                if (b != null) node.setName(b.getName());
-            } else if (s.getType() == SPACE_TYPE_REGION) {
-                node.setType("region");
-                EmsSpaceArea a = emsSpaceAreaMapper.selectOne(new LambdaQueryWrapper<EmsSpaceArea>().eq(EmsSpaceArea::getSpaceId, s.getId()));
-                if (a != null) node.setName(a.getName());
-            } else {
-                node.setType("space");
-            }
-            List<EmsStructureTreeNode> sub = buildSpaceChildren(s.getId(), includeGateway);
-            // 网关挂在非「建筑」空间下(区域、历史遗留子空间等),不包含建筑节点本身
-            if (includeGateway && s.getType() != SPACE_TYPE_BUILDING) {
-                List<EmsGateway> gateways = emsGatewayMapper.selectList(new LambdaQueryWrapper<EmsGateway>().eq(EmsGateway::getSpaceId, s.getId()));
-                for (EmsGateway g : gateways) {
-                    EmsStructureTreeNode gw = new EmsStructureTreeNode();
-                    gw.setId(g.getId());
-                    gw.setName(g.getName());
-                    gw.setType("gateway");
-                    sub.add(gw);
-                }
-            }
-            node.setChildren(sub);
-            children.add(node);
-        }
-        return children;
-    }
+//    private EmsProject firstProject() {
+//        List<EmsProject> list = emsProjectMapper.selectList(null);
+//        return list.isEmpty() ? null : list.get(0);
+//    }
+//
+//    @Override
+//    public EmsStructureTreeNode getStructureTree(Long projectId, Boolean includeGateway) {
+//        EmsProject project = projectId != null ? emsProjectMapper.selectById(projectId) : firstProject();
+//        if (project == null) {
+//            return null;
+//        }
+//        EmsStructureTreeNode root = new EmsStructureTreeNode();
+//        root.setId(project.getId());
+//        root.setName(project.getName());
+//        root.setType("project");
+//        root.setChildren(buildSpaceChildren(project.getSpaceId(), includeGateway == null || includeGateway));
+//        return root;
+//    }
+//
+//    private List<EmsStructureTreeNode> buildSpaceChildren(Long parentId, boolean includeGateway) {
+//        if (parentId == null) {
+//            return Collections.emptyList();
+//        }
+//        List<BaseSpace> list = baseSpaceMapper.selectList(new LambdaQueryWrapper<BaseSpace>().eq(BaseSpace::getParentId, parentId));
+//        List<EmsStructureTreeNode> children = new ArrayList<>();
+//        for (BaseSpace s : list) {
+//            EmsStructureTreeNode node = new EmsStructureTreeNode();
+//            node.setId(s.getId());
+//            node.setName(s.getName());
+//            if (s.getType() != null && s.getType() == SPACE_TYPE_BUILDING) {
+//                node.setType("building");
+//                BaseSpaceBuild link = baseSpaceBuildMapper.selectOne(
+//                        new LambdaQueryWrapper<BaseSpaceBuild>().eq(BaseSpaceBuild::getSpaceId, s.getId()).last("LIMIT 1"));
+//                if (link != null && link.getBuildId() != null) {
+//                    BaseBuild b = baseBuildMapper.selectById(link.getBuildId());
+//                    if (b != null && b.getBuildName() != null) {
+//                        node.setName(b.getBuildName());
+//                    }
+//                }
+//            } else if (s.getType() != null && s.getType() == SPACE_TYPE_REGION) {
+//                node.setType("region");
+//                BaseSpaceArea sa = baseSpaceAreaMapper.selectOne(
+//                        new LambdaQueryWrapper<BaseSpaceArea>().eq(BaseSpaceArea::getSpaceId, s.getId()).last("LIMIT 1"));
+//                if (sa != null && sa.getAreaId() != null) {
+//                    BaseArea a = baseAreaMapper.selectById(sa.getAreaId());
+//                    if (a != null && a.getName() != null) {
+//                        node.setName(a.getName());
+//                    }
+//                }
+//            } else {
+//                node.setType("space");
+//            }
+//            List<EmsStructureTreeNode> sub = buildSpaceChildren(s.getId(), includeGateway);
+//            if (includeGateway && (s.getType() == null || s.getType() != SPACE_TYPE_BUILDING)) {
+//                List<BaseSpaceGateway> links = baseSpaceGatewayMapper.selectList(
+//                        new LambdaQueryWrapper<BaseSpaceGateway>().eq(BaseSpaceGateway::getSpaceId, s.getId()));
+//                for (BaseSpaceGateway link : links) {
+//                    if (link.getGatewayUuid() == null) {
+//                        continue;
+//                    }
+//                    DmpGateway g = dmpGatewayMapper.selectOne(
+//                            new LambdaQueryWrapper<DmpGateway>().eq(DmpGateway::getDeviceUuid, link.getGatewayUuid()).last("LIMIT 1"));
+//                    if (g == null) {
+//                        continue;
+//                    }
+//                    EmsStructureTreeNode gw = new EmsStructureTreeNode();
+//                    gw.setId(g.getDeviceUuid());
+//                    gw.setName(g.getName());
+//                    gw.setType("gateway");
+//                    sub.add(gw);
+//                }
+//            }
+//            node.setChildren(sub);
+//            children.add(node);
+//        }
+//        return children;
+//    }
 
     @Override
     public List<EmsEnergyTypeVO> getEnergyTypeList() {
@@ -124,15 +166,12 @@ public class EmsModelServiceImpl implements EmsModelService {
         return result;
     }
 
-    /**
-     * 展示已关联的类型及其下属产品列表
-     * 这里按 dmp_product.deviceType 进行分组,每个产品作为一个 SimpleProductVO 返回。
-     */
     @Override
     public List<EnergyTypeWrapperProductVO> showAssociatedEnergyTypes() {
         List<DmpProduct> products = dmpProductMapper.selectList(
                 new LambdaQueryWrapper<DmpProduct>()
                         .eq(DmpProduct::getDeleteFlag, 0)
+                        .eq(DmpProduct::getTenantId, SecurityUtils.getTenantId())
         );
         if (products == null || products.isEmpty()) {
             return Collections.emptyList();
@@ -156,14 +195,17 @@ public class EmsModelServiceImpl implements EmsModelService {
         });
 
         result.sort((o1, o2) -> {
-            if (o1.getEnergyType() == null) return -1;
-            if (o2.getEnergyType() == null) return 1;
+            if (o1.getEnergyType() == null) {
+                return -1;
+            }
+            if (o2.getEnergyType() == null) {
+                return 1;
+            }
             return o1.getEnergyType().compareTo(o2.getEnergyType());
         });
         return result;
     }
 
-    /** 根据 dmp_product.deviceType 获取类型名称 */
     private String deviceTypeName(Integer deviceType) {
         if (deviceType == null) {
             return "";
@@ -189,20 +231,39 @@ public class EmsModelServiceImpl implements EmsModelService {
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Long createBuilding(EmsModelSaveRequest request) {
-        Long projectId = request.getProjectId();
-        String name = request.getName();
-        EmsProject project = projectId != null ? emsProjectMapper.selectById(projectId) : firstProject();
-        if (project == null) return null;
-        EmsSpace space = new EmsSpace();
-        space.setName(name);
-        space.setParentId(project.getSpaceId());
+        Long parentSpaceId = request.getParentSpaceId();
+        LocalDateTime now = LocalDateTime.now();
+        String auditUser = trimAuditUser(SecurityUtils.getUsername());
+        Integer tenantId = SecurityUtils.getTenantId();
+        BaseBuild build = new BaseBuild();
+        build.setTenantId(tenantId);
+        build.setCreateBy(auditUser);
+        build.setUpdateBy(auditUser);
+        build.setCreateTime(now);
+        build.setUpdateTime(now);
+        baseBuildMapper.insert(build);
+
+        BaseSpace space = new BaseSpace();
+        space.setName(request.getBuildName());
+        space.setParentId(request.getParentSpaceId());
         space.setType(SPACE_TYPE_BUILDING);
-        space.setRootId(project.getSpaceId());
-        emsSpaceMapper.insert(space);
-        EmsSpaceBuilding building = new EmsSpaceBuilding();
-        building.setSpaceId(space.getId());
-        building.setName(name);
-        emsSpaceBuildingMapper.insert(building);
+        BaseSpace parent = parentSpaceId != null ? baseSpaceMapper.selectById(parentSpaceId) : null;
+        space.setRootId(parent != null ? parent.getRootId() : parentSpaceId);
+        space.setTenantId(tenantId);
+        space.setCreatedBy(auditUser);
+        space.setUpdatedBy(auditUser);
+        space.setCreateTime(now);
+        space.setUpdateTime(now);
+        space.setPath(parent.getPath()+"/"+parentSpaceId);
+        space.setPathName(parent.getPathName()+"/"+parent.getName());
+        space.setDeep(parent.getDeep()+1);
+        baseSpaceMapper.insert(space);
+
+        BaseSpaceBuild rel = new BaseSpaceBuild();
+        rel.setSpaceId(space.getId());
+        rel.setBuildId(build.getId());
+        rel.setCreatedTime(now);
+        baseSpaceBuildMapper.insert(rel);
         return space.getId();
     }
 
@@ -210,41 +271,90 @@ public class EmsModelServiceImpl implements EmsModelService {
     @Transactional(rollbackFor = Exception.class)
     public void updateBuilding(Long id, EmsModelSaveRequest request) {
         String name = request.getName();
-        EmsSpace space = emsSpaceMapper.selectById(id);
+        BaseSpace space = baseSpaceMapper.selectById(id);
         if (space != null && name != null) {
             space.setName(name);
-            emsSpaceMapper.updateById(space);
+            space.setUpdatedBy(SecurityUtils.getUsername());
+            space.setUpdateTime(LocalDateTime.now());
+            baseSpaceMapper.updateById(space);
         }
-        EmsSpaceBuilding b = emsSpaceBuildingMapper.selectOne(new LambdaQueryWrapper<EmsSpaceBuilding>().eq(EmsSpaceBuilding::getSpaceId, id));
-        if (b != null && name != null) {
-            b.setName(name);
-            emsSpaceBuildingMapper.updateById(b);
+        BaseSpaceBuild b = baseSpaceBuildMapper.selectOne(new LambdaQueryWrapper<BaseSpaceBuild>().eq(BaseSpaceBuild::getSpaceId, id).last("LIMIT 1"));
+        if (b != null && b.getBuildId() != null && name != null) {
+            BaseBuild build = baseBuildMapper.selectById(b.getBuildId());
+            if (build != null) {
+                build.setUpdateBy(trimAuditUser(SecurityUtils.getUsername()));
+                build.setUpdateTime(LocalDateTime.now());
+                baseBuildMapper.updateById(build);
+            }
         }
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void deleteBuilding(Long id) {
-        emsSpaceBuildingMapper.delete(new LambdaQueryWrapper<EmsSpaceBuilding>().eq(EmsSpaceBuilding::getSpaceId, id));
-        emsSpaceMapper.deleteById(id);
+        List<BaseSpaceBuild> links = baseSpaceBuildMapper.selectList(
+                new LambdaQueryWrapper<BaseSpaceBuild>().eq(BaseSpaceBuild::getSpaceId, id));
+        for (BaseSpaceBuild link : links) {
+            if (link.getBuildId() != null) {
+                baseBuildMapper.deleteById(link.getBuildId());
+            }
+        }
+        baseSpaceBuildMapper.delete(new LambdaQueryWrapper<BaseSpaceBuild>().eq(BaseSpaceBuild::getSpaceId, id));
+        baseSpaceMapper.deleteById(id);
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Long createRegion(EmsModelSaveRequest request) {
-        Long buildingId = request.getBuildingId();
+        Long parentSpaceId = request.getParentSpaceId();
         String name = request.getName();
-        EmsSpace space = new EmsSpace();
+        LocalDateTime now = LocalDateTime.now();
+        Integer tenantId = SecurityUtils.getTenantId();
+        String auditUser = trimAuditUser(SecurityUtils.getUsername());
+
+        BaseArea area = new BaseArea();
+        area.setName(name);
+        area.setType(request.getType());
+        if (request.getArea() != null) {
+            area.setArea(request.getArea());
+        }
+        if(request.getCommonArea() != null) {
+            area.setCommonArea(request.getCommonArea());
+        }
+        if(request.getAirConditionedArea() != null) {
+            area.setAirConditionedArea(request.getAirConditionedArea());
+        }
+        if(request.getResidentPopulation() != null) {
+            area.setResidentPopulation(request.getResidentPopulation());
+        }
+        area.setCreateBy(auditUser);
+        area.setUpdateBy(auditUser);
+        area.setCreateTime(now);
+        area.setUpdateTime(now);
+        area.setTenantId(tenantId);
+        baseAreaMapper.insert(area);
+
+        BaseSpace space = new BaseSpace();
         space.setName(name);
-        space.setParentId(buildingId);
-        EmsSpace parent = emsSpaceMapper.selectById(buildingId);
-        space.setRootId(parent != null ? parent.getRootId() : buildingId);
+        space.setParentId(parentSpaceId);
+        BaseSpace parent = parentSpaceId != null ? baseSpaceMapper.selectById(parentSpaceId) : null;
+        space.setRootId(parent != null ? parent.getRootId() : parentSpaceId);
         space.setType(SPACE_TYPE_REGION);
-        emsSpaceMapper.insert(space);
-        EmsSpaceArea area = new EmsSpaceArea();
-        area.setSpaceId(space.getId());
-        area.setName(name);
-        if (request.getArea() != null) area.setArea(request.getArea());
+        space.setPath(parent.getPath()+"/"+parentSpaceId);
+        space.setPathName(parent.getPathName()+"/"+parent.getName());
+        space.setDeep(parent.getDeep()+1);
+        space.setCreatedBy(auditUser);
+        space.setUpdatedBy(auditUser);
+        space.setCreateTime(now);
+        space.setUpdateTime(now);
+        space.setTenantId(tenantId);
+        baseSpaceMapper.insert(space);
+
+        BaseSpaceArea rel = new BaseSpaceArea();
+        rel.setSpaceId(space.getId());
+        rel.setAreaId(area.getId());
+        rel.setCreatedTime(now);
+        baseSpaceAreaMapper.insert(rel);
         return space.getId();
     }
 
@@ -252,24 +362,51 @@ public class EmsModelServiceImpl implements EmsModelService {
     @Transactional(rollbackFor = Exception.class)
     public void updateRegion(Long id, EmsModelSaveRequest request) {
         String name = request.getName();
-        EmsSpace space = emsSpaceMapper.selectById(id);
+        BaseSpace space = baseSpaceMapper.selectById(id);
         if (space != null && name != null) {
             space.setName(name);
-            emsSpaceMapper.updateById(space);
+            space.setUpdateTime(LocalDateTime.now());
+            baseSpaceMapper.updateById(space);
         }
-        EmsSpaceArea a = emsSpaceAreaMapper.selectOne(new LambdaQueryWrapper<EmsSpaceArea>().eq(EmsSpaceArea::getSpaceId, id));
-        if (a != null) {
-            if (name != null) a.setName(name);
-            if (request.getArea() != null) a.setArea(request.getArea());
-            emsSpaceAreaMapper.updateById(a);
+        BaseSpaceArea sa = baseSpaceAreaMapper.selectOne(new LambdaQueryWrapper<BaseSpaceArea>().eq(BaseSpaceArea::getSpaceId, id).last("LIMIT 1"));
+        if (sa != null && sa.getAreaId() != null) {
+            BaseArea area = baseAreaMapper.selectById(sa.getAreaId());
+            if (area != null) {
+                if (name != null) {
+                    area.setName(name);
+                }
+
+                if(request.getType() != null) {
+                    area.setType(request.getType());
+                }
+
+                if (request.getArea() != null) {
+                    area.setArea(request.getArea());
+                }
+                if(request.getCommonArea() != null) {
+                    area.setCommonArea(request.getCommonArea());
+                }
+                if(request.getAirConditionedArea() != null) {
+                    area.setAirConditionedArea(request.getAirConditionedArea());
+                }
+                if(request.getResidentPopulation() != null) {
+                    area.setResidentPopulation(request.getResidentPopulation());
+                }
+                area.setUpdateTime(LocalDateTime.now());
+                baseAreaMapper.updateById(area);
+            }
         }
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void deleteRegion(Long id) {
-        emsSpaceAreaMapper.delete(new LambdaQueryWrapper<EmsSpaceArea>().eq(EmsSpaceArea::getSpaceId, id));
-        emsSpaceMapper.deleteById(id);
+        BaseSpaceArea sa = baseSpaceAreaMapper.selectOne(new LambdaQueryWrapper<BaseSpaceArea>().eq(BaseSpaceArea::getSpaceId, id).last("LIMIT 1"));
+        baseSpaceAreaMapper.delete(new LambdaQueryWrapper<BaseSpaceArea>().eq(BaseSpaceArea::getSpaceId, id));
+        if (sa != null && sa.getAreaId() != null) {
+            baseAreaMapper.deleteById(sa.getAreaId());
+        }
+        baseSpaceMapper.deleteById(id);
     }
 
     @Override
@@ -277,171 +414,219 @@ public class EmsModelServiceImpl implements EmsModelService {
     public String createGateway(EmsModelSaveRequest request) {
         Long spaceId = request.getSpaceId();
         String name = request.getName();
-        String gwId = "GW" + System.currentTimeMillis();
-        if (gwId.length() > 13) gwId = gwId.substring(0, 13);
-        EmsGateway g = new EmsGateway();
-        g.setId(gwId);
-        g.setName(name);
-        g.setSpaceId(spaceId);
-        g.setProjectId(0L);
-        EmsSpace space = spaceId != null ? emsSpaceMapper.selectById(spaceId) : null;
-        if (space != null) {
-            EmsProject p = firstProject();
-            if (p != null) g.setProjectId(p.getId());
+        String uuid = UUID.randomUUID().toString().replace("-", "");
+        if (uuid.length() > 50) {
+            uuid = uuid.substring(0, 50);
         }
+        LocalDateTime now = LocalDateTime.now();
+        DmpGateway g = new DmpGateway();
+        g.setDeviceUuid(uuid);
+        g.setName(name != null ? name : "gateway");
         g.setCommStatus(0);
-        g.setDataCenterId(0L);
-        g.setSecretKey("");
         g.setVirtualDevice(0);
-        emsGatewayMapper.insert(g);
-        return g.getId();
+        g.setCreateTime(now);
+        g.setUpdateTime(now);
+        dmpGatewayMapper.insert(g);
+
+        if (spaceId != null) {
+            BaseSpaceGateway rel = new BaseSpaceGateway();
+            rel.setSpaceId(spaceId);
+            rel.setGatewayUuid(uuid);
+            rel.setCreatedTime(now);
+            baseSpaceGatewayMapper.insert(rel);
+        }
+        return uuid;
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void updateGateway(String id, EmsModelSaveRequest request) {
-        EmsGateway g = emsGatewayMapper.selectById(id);
-        if (g == null) return;
-        if (request.getName() != null) g.setName(request.getName());
-        if (request.getSpaceId() != null) g.setSpaceId(request.getSpaceId());
-        emsGatewayMapper.updateById(g);
+        DmpGateway g = dmpGatewayMapper.selectOne(
+                new LambdaQueryWrapper<DmpGateway>().eq(DmpGateway::getDeviceUuid, id).last("LIMIT 1"));
+        if (g == null) {
+            return;
+        }
+        if (request.getName() != null) {
+            g.setName(request.getName());
+        }
+        g.setUpdateTime(LocalDateTime.now());
+        dmpGatewayMapper.updateById(g);
+
+        if (request.getSpaceId() != null) {
+            baseSpaceGatewayMapper.delete(new LambdaQueryWrapper<BaseSpaceGateway>().eq(BaseSpaceGateway::getGatewayUuid, id));
+            BaseSpaceGateway rel = new BaseSpaceGateway();
+            rel.setSpaceId(request.getSpaceId());
+            rel.setGatewayUuid(id);
+            rel.setCreatedTime(LocalDateTime.now());
+            baseSpaceGatewayMapper.insert(rel);
+        }
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void deleteGateway(String id) {
-        emsGatewayMapper.deleteById(id);
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public Long createChannel(EmsModelSaveRequest request) {
-        String gatewayId = request.getGatewayId();
-        String name = request.getName();
-        EmsChannel c = new EmsChannel();
-        c.setGatewayId(gatewayId);
-        c.setName(name);
-        c.setChannelTypeId(request.getChannelTypeId());
-        emsChannelMapper.insert(c);
-        return c.getId();
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void updateChannel(Long id, EmsModelSaveRequest request) {
-        EmsChannel c = emsChannelMapper.selectById(id);
-        if (c == null) return;
-        if (request.getName() != null) c.setName(request.getName());
-        if (request.getGatewayId() != null) c.setGatewayId(request.getGatewayId());
-        emsChannelMapper.updateById(c);
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void deleteChannel(Long id) {
-        emsChannelMapper.deleteById(id);
+        baseSpaceGatewayMapper.delete(new LambdaQueryWrapper<BaseSpaceGateway>().eq(BaseSpaceGateway::getGatewayUuid, id));
+        dmpGatewayMapper.delete(new LambdaQueryWrapper<DmpGateway>().eq(DmpGateway::getDeviceUuid, id));
     }
 
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public String createDevice(EmsModelSaveRequest request) {
-        Long channelId = request.getChannelId();
-        String name = request.getName();
-        String devId = "DV" + System.currentTimeMillis();
-        if (devId.length() > 13) devId = devId.substring(0, 13);
-        EmsDevice d = new EmsDevice();
-        d.setId(devId);
-        d.setName(name);
-        d.setProjectId(0L);
-        d.setChannelId(channelId != null ? channelId : 0L);
-        d.setGatewayId("");
-        EmsChannel ch = channelId != null ? emsChannelMapper.selectById(channelId) : null;
-        if (ch != null) d.setGatewayId(ch.getGatewayId());
-        d.setProductId(0L);
-        d.setInstallationLocation(0L);
-        d.setMonitoringLocation(0L);
-        d.setCommAddress("");
-        d.setVirtualDevice(0);
-        d.setFocus(0);
-        d.setDeviceSystem(0);
-        d.setStatus(1);
-        d.setCommStatus(0);
-        emsDeviceMapper.insert(d);
-        return d.getId();
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void updateDevice(String id, EmsModelSaveRequest request) {
-        EmsDevice d = emsDeviceMapper.selectById(id);
-        if (d == null) return;
-        if (request.getName() != null) d.setName(request.getName());
-        if (request.getChannelId() != null) d.setChannelId(request.getChannelId());
-        emsDeviceMapper.updateById(d);
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void deleteDevice(String id) {
-        emsDeviceMapper.deleteById(id);
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public Long createAttributePoint(EmsModelSaveRequest request) {
-        String deviceId = request.getDeviceId();
-        String name = request.getName();
-        String code = request.getCode();
-        EmsDeviceFunction f = new EmsDeviceFunction();
-        f.setDeviceId(deviceId);
-        f.setName(name);
-        f.setIdentifier(code != null ? code : name);
-        f.setProductId(0L);
-        f.setProductTemplateId(0L);
-        f.setPreservable(1);
-        f.setBindingAcq(0);
-        emsDeviceFunctionMapper.insert(f);
-        return f.getId();
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void updateAttributePoint(Long id, EmsModelSaveRequest request) {
-        EmsDeviceFunction f = emsDeviceFunctionMapper.selectById(id);
-        if (f == null) return;
-        if (request.getName() != null) f.setName(request.getName());
-        if (request.getCode() != null) f.setIdentifier(request.getCode());
-        emsDeviceFunctionMapper.updateById(f);
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void deleteAttributePoint(Long id) {
-        emsDeviceFunctionMapper.deleteById(id);
-    }
+//    @Override
+//    @Transactional(rollbackFor = Exception.class)
+//    public Long createChannel(EmsModelSaveRequest request) {
+//        String gatewayId = request.getGatewayId();
+//        String name = request.getName();
+//        EmsChannel c = new EmsChannel();
+//        c.setGatewayId(gatewayId);
+//        c.setName(name);
+//        c.setChannelTypeId(request.getChannelTypeId());
+//        emsChannelMapper.insert(c);
+//        return c.getId();
+//    }
+//
+//    @Override
+//    @Transactional(rollbackFor = Exception.class)
+//    public void updateChannel(Long id, EmsModelSaveRequest request) {
+//        EmsChannel c = emsChannelMapper.selectById(id);
+//        if (c == null) {
+//            return;
+//        }
+//        if (request.getName() != null) {
+//            c.setName(request.getName());
+//        }
+//        if (request.getGatewayId() != null) {
+//            c.setGatewayId(request.getGatewayId());
+//        }
+//        emsChannelMapper.updateById(c);
+//    }
+//
+//    @Override
+//    @Transactional(rollbackFor = Exception.class)
+//    public void deleteChannel(Long id) {
+//        emsChannelMapper.deleteById(id);
+//    }
+//
+//    @Override
+//    @Transactional(rollbackFor = Exception.class)
+//    public String createDevice(EmsModelSaveRequest request) {
+//        Long channelId = request.getChannelId();
+//        String name = request.getName();
+//        String devId = "DV" + System.currentTimeMillis();
+//        if (devId.length() > 13) {
+//            devId = devId.substring(0, 13);
+//        }
+//        EmsDevice d = new EmsDevice();
+//        d.setId(devId);
+//        d.setName(name);
+//        d.setProjectId(0L);
+//        d.setChannelId(channelId != null ? channelId : 0L);
+//        d.setGatewayId("");
+//        EmsChannel ch = channelId != null ? emsChannelMapper.selectById(channelId) : null;
+//        if (ch != null) {
+//            d.setGatewayId(ch.getGatewayId());
+//        }
+//        d.setProductId(0L);
+//        d.setInstallationLocation(0L);
+//        d.setMonitoringLocation(0L);
+//        d.setCommAddress("");
+//        d.setVirtualDevice(0);
+//        d.setFocus(0);
+//        d.setDeviceSystem(0);
+//        d.setStatus(1);
+//        d.setCommStatus(0);
+//        emsDeviceMapper.insert(d);
+//        return d.getId();
+//    }
+//
+//    @Override
+//    @Transactional(rollbackFor = Exception.class)
+//    public void updateDevice(String id, EmsModelSaveRequest request) {
+//        EmsDevice d = emsDeviceMapper.selectById(id);
+//        if (d == null) {
+//            return;
+//        }
+//        if (request.getName() != null) {
+//            d.setName(request.getName());
+//        }
+//        if (request.getChannelId() != null) {
+//            d.setChannelId(request.getChannelId());
+//        }
+//        emsDeviceMapper.updateById(d);
+//    }
+//
+//    @Override
+//    @Transactional(rollbackFor = Exception.class)
+//    public void deleteDevice(String id) {
+//        emsDeviceMapper.deleteById(id);
+//    }
+//
+//    @Override
+//    @Transactional(rollbackFor = Exception.class)
+//    public Long createAttributePoint(EmsModelSaveRequest request) {
+//        String deviceId = request.getDeviceId();
+//        String name = request.getName();
+//        String code = request.getCode();
+//        EmsDeviceFunction f = new EmsDeviceFunction();
+//        f.setDeviceId(deviceId);
+//        f.setName(name);
+//        f.setIdentifier(code != null ? code : name);
+//        f.setProductId(0L);
+//        f.setProductTemplateId(0L);
+//        f.setPreservable(1);
+//        f.setBindingAcq(0);
+//        emsDeviceFunctionMapper.insert(f);
+//        return f.getId();
+//    }
+//
+//    @Override
+//    @Transactional(rollbackFor = Exception.class)
+//    public void updateAttributePoint(Long id, EmsModelSaveRequest request) {
+//        EmsDeviceFunction f = emsDeviceFunctionMapper.selectById(id);
+//        if (f == null) {
+//            return;
+//        }
+//        if (request.getName() != null) {
+//            f.setName(request.getName());
+//        }
+//        if (request.getCode() != null) {
+//            f.setIdentifier(request.getCode());
+//        }
+//        emsDeviceFunctionMapper.updateById(f);
+//    }
+//
+//    @Override
+//    @Transactional(rollbackFor = Exception.class)
+//    public void deleteAttributePoint(Long id) {
+//        emsDeviceFunctionMapper.deleteById(id);
+//    }
 
     @Override
     public List<EmsGatewayDeviceTreeNode> getGatewayDeviceTree(Long spaceId, String keyword) {
-        // 1. 查询网关列表
-        LambdaQueryWrapper<EmsGateway> gwWrapper = new LambdaQueryWrapper<>();
+        LambdaQueryWrapper<DmpGateway> gwWrapper = new LambdaQueryWrapper<>();
         if (spaceId != null) {
-            gwWrapper.eq(EmsGateway::getSpaceId, spaceId);
+            List<BaseSpaceGateway> links = baseSpaceGatewayMapper.selectList(
+                    new LambdaQueryWrapper<BaseSpaceGateway>().eq(BaseSpaceGateway::getSpaceId, spaceId));
+            Set<String> uuids = links.stream()
+                    .map(BaseSpaceGateway::getGatewayUuid)
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toSet());
+            if (uuids.isEmpty()) {
+                return Collections.emptyList();
+            }
+            gwWrapper.in(DmpGateway::getDeviceUuid, uuids);
         }
         if (keyword != null && !keyword.trim().isEmpty()) {
-            gwWrapper.like(EmsGateway::getName, keyword.trim());
+            gwWrapper.like(DmpGateway::getName, keyword.trim());
         }
-        List<EmsGateway> gateways = emsGatewayMapper.selectList(gwWrapper);
+        List<DmpGateway> gateways = dmpGatewayMapper.selectList(gwWrapper);
 
         List<EmsGatewayDeviceTreeNode> result = new ArrayList<>();
-        for (EmsGateway gw : gateways) {
+        for (DmpGateway gw : gateways) {
             EmsGatewayDeviceTreeNode gwNode = new EmsGatewayDeviceTreeNode();
-            gwNode.setId(gw.getId());
+            gwNode.setId(gw.getDeviceUuid());
             gwNode.setName(gw.getName());
             gwNode.setType("gateway");
 
-            // 2. 查询该网关下的通道
             List<EmsChannel> channels = emsChannelMapper.selectList(
-                    new LambdaQueryWrapper<EmsChannel>().eq(EmsChannel::getGatewayId, gw.getId()));
+                    new LambdaQueryWrapper<EmsChannel>().eq(EmsChannel::getGatewayId, gw.getDeviceUuid()));
             List<EmsGatewayDeviceTreeNode> channelNodes = new ArrayList<>();
             for (EmsChannel ch : channels) {
                 EmsGatewayDeviceTreeNode chNode = new EmsGatewayDeviceTreeNode();
@@ -449,7 +634,6 @@ public class EmsModelServiceImpl implements EmsModelService {
                 chNode.setName(ch.getName());
                 chNode.setType("channel");
 
-                // 3. 查询该通道下的设备
                 List<EmsDevice> devices = emsDeviceMapper.selectList(
                         new LambdaQueryWrapper<EmsDevice>().eq(EmsDevice::getChannelId, ch.getId()));
                 List<EmsGatewayDeviceTreeNode> deviceNodes = new ArrayList<>();
@@ -461,14 +645,12 @@ public class EmsModelServiceImpl implements EmsModelService {
                     deviceNodes.add(devNode);
                 }
 
-                // 只有当设备列表不为空时,才设置通道的 children
                 if (!deviceNodes.isEmpty()) {
                     chNode.setChildren(deviceNodes);
                     channelNodes.add(chNode);
                 }
             }
 
-            // 只有当通道列表不为空时,才设置网关的 children
             if (!channelNodes.isEmpty()) {
                 gwNode.setChildren(channelNodes);
                 result.add(gwNode);
@@ -477,7 +659,6 @@ public class EmsModelServiceImpl implements EmsModelService {
         return result;
     }
 
-
     @Override
     public List<EmsAttributePointVO> getAttributePointList(String deviceId) {
         if (deviceId == null || deviceId.trim().isEmpty()) {
@@ -507,4 +688,96 @@ public class EmsModelServiceImpl implements EmsModelService {
         }
         return result;
     }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void bindSpaceGateways(Long spaceId, List<String> gatewayUuids) {
+        if (spaceId == null) {
+            return;
+        }
+        baseSpaceGatewayMapper.delete(new LambdaQueryWrapper<BaseSpaceGateway>().eq(BaseSpaceGateway::getSpaceId, spaceId));
+        if (gatewayUuids == null || gatewayUuids.isEmpty()) {
+            return;
+        }
+
+        Set<String> normalizedUuids = gatewayUuids.stream()
+                .filter(Objects::nonNull)
+                .map(String::trim)
+                .filter(s -> !s.isEmpty())
+                .collect(Collectors.toCollection(LinkedHashSet::new));
+        if (normalizedUuids.isEmpty()) {
+            return;
+        }
+
+        List<DmpGateway> gateways = dmpGatewayMapper.selectList(
+                new LambdaQueryWrapper<DmpGateway>().in(DmpGateway::getDeviceUuid, normalizedUuids));
+        Set<String> existsGatewayUuids = gateways.stream()
+                .map(DmpGateway::getDeviceUuid)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+        if (existsGatewayUuids.isEmpty()) {
+            return;
+        }
+
+        LocalDateTime now = LocalDateTime.now();
+        String auditUser = trimAuditUser(SecurityUtils.getUsername());
+        for (String gatewayUuid : normalizedUuids) {
+            if (!existsGatewayUuids.contains(gatewayUuid)) {
+                continue;
+            }
+            BaseSpaceGateway relation = new BaseSpaceGateway();
+            relation.setSpaceId(spaceId);
+            relation.setGatewayUuid(gatewayUuid);
+            relation.setCreatedBy(auditUser);
+            relation.setCreatedTime(now);
+            baseSpaceGatewayMapper.insert(relation);
+        }
+    }
+
+    @Override
+    public List<DmpGatewayDetailResponse> getGatewayListBySpaceId(Long spaceId) {
+        if (spaceId == null) {
+            return Collections.emptyList();
+        }
+        List<BaseSpaceGateway> links = baseSpaceGatewayMapper.selectList(
+                new LambdaQueryWrapper<BaseSpaceGateway>().eq(BaseSpaceGateway::getSpaceId, spaceId));
+        if (links == null || links.isEmpty()) {
+            return Collections.emptyList();
+        }
+        Set<String> gatewayUuids = links.stream()
+                .map(BaseSpaceGateway::getGatewayUuid)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toCollection(LinkedHashSet::new));
+        if (gatewayUuids.isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        List<DmpGateway> gateways = dmpGatewayMapper.selectList(
+                new LambdaQueryWrapper<DmpGateway>().in(DmpGateway::getDeviceUuid, gatewayUuids));
+        if (gateways == null || gateways.isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        return gateways.stream().map(item -> {
+            DmpGatewayDetailResponse resp = new DmpGatewayDetailResponse();
+            resp.setId(item.getId());
+            resp.setDeviceUuid(item.getDeviceUuid());
+            resp.setName(item.getName());
+            resp.setIp(item.getIp());
+            resp.setPort(item.getPort());
+            resp.setCommunicationStatus(item.getCommStatus());
+            resp.setOnlineTime(item.getOnlineTime());
+            resp.setOfflineTime(item.getOfflineTime());
+            resp.setUpdateConfigTime(item.getUpdateConfigTime());
+            resp.setUpdateProtocolTime(item.getUpdateProtocolTime());
+            resp.setUpgradeTime(item.getUpgradeTime());
+            resp.setVirtualDevice(item.getVirtualDevice());
+            resp.setRemark(item.getRemark());
+            resp.setUpdatedBy(item.getUpdatedBy());
+            resp.setUpdateTime(item.getUpdateTime());
+            resp.setCreatedBy(item.getCreatedBy());
+            resp.setCreateTime(item.getCreateTime());
+            return resp;
+        }).collect(Collectors.toList());
+    }
 }

+ 15 - 22
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsOverviewServiceImpl.java

@@ -2,19 +2,13 @@ package com.usky.ems.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.usky.ems.domain.EmsDevice;
-import com.usky.ems.domain.EmsProject;
-import com.usky.ems.domain.EmsSpace;
-import com.usky.ems.domain.EmsProjectDeviceSystem;
-import com.usky.ems.domain.EmsProjectConversionFactor;
+import com.usky.ems.domain.BaseSpace;
 import com.usky.ems.domain.EmsEnergyItemCode;
 import com.usky.ems.mapper.EmsDeviceMapper;
-import com.usky.ems.mapper.EmsProjectMapper;
-import com.usky.ems.mapper.EmsProjectDeviceSystemMapper;
-import com.usky.ems.mapper.EmsProjectConversionFactorMapper;
 import com.usky.ems.mapper.EmsEnergyItemCodeMapper;
 import com.usky.ems.service.EmsModelService;
 import com.usky.ems.service.EmsOverviewService;
-import com.usky.ems.service.EmsSpaceService;
+import com.usky.ems.service.BaseSpaceService;
 import com.usky.ems.service.vo.EmsEnergyTypeVO;
 import com.usky.ems.service.vo.EmsOverviewDeviceSystemStatVO;
 import com.usky.ems.service.vo.EmsOverviewEnergyItemVO;
@@ -54,7 +48,7 @@ public class EmsOverviewServiceImpl implements EmsOverviewService {
     private EmsDeviceMapper emsDeviceMapper;
 
     @Autowired
-    private EmsSpaceService emsSpaceService;
+    private BaseSpaceService baseSpaceService;
 
     @Autowired
     private EmsProjectConversionFactorMapper emsProjectConversionFactorMapper;
@@ -341,7 +335,7 @@ public class EmsOverviewServiceImpl implements EmsOverviewService {
     /**
      * 建筑能耗分析(模拟数据版本)
      * 参考原系统 queryBuildingRanking:按指定时间维度与能耗条目,对建筑/楼层进行能耗排名。
-     * 当前实现:空间信息(建筑/楼层)从 leo.ems_space 表真实查询,仅能耗值使用规则模拟。
+     * 当前实现:空间信息从 base_space 真实查询(建筑 type=3;指定 spaceId 时取子节点),仅能耗值使用规则模拟。
      */
     @Override
     public List<Map<String, Object>> queryBuildingRanking(Integer dateType, String itemCode, Long spaceId) {
@@ -363,20 +357,19 @@ public class EmsOverviewServiceImpl implements EmsOverviewService {
         Long rootSpaceId = project.getSpaceId();
 
         // 2. 查询空间列表:
-        // - 未指定 spaceId:取根空间下 type=3 的建筑
-        // - 指定 spaceId:取该空间下 type=4 的楼层
-        List<EmsSpace> spaceList;
+        // - 未指定 spaceId:取根空间下 type=3 的建筑(base_space)
+        // - 指定 spaceId:取该空间下直接子节点(新表无独立楼层类型时,用子空间展示排名)
+        List<BaseSpace> spaceList;
         if (spaceId == null) {
-            spaceList = emsSpaceService.list(
-                    new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<EmsSpace>()
-                            .eq(EmsSpace::getRootId, rootSpaceId)
-                            .eq(EmsSpace::getType, 3) // 3 = 建筑
+            spaceList = baseSpaceService.list(
+                    new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<BaseSpace>()
+                            .eq(BaseSpace::getRootId, rootSpaceId)
+                            .eq(BaseSpace::getType, 3)
             );
         } else {
-            spaceList = emsSpaceService.list(
-                    new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<EmsSpace>()
-                            .eq(EmsSpace::getParentId, spaceId)
-                            .eq(EmsSpace::getType, 4) // 4 = 楼层
+            spaceList = baseSpaceService.list(
+                    new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<BaseSpace>()
+                            .eq(BaseSpace::getParentId, spaceId)
             );
         }
         if (spaceList == null || spaceList.isEmpty()) {
@@ -398,7 +391,7 @@ public class EmsOverviewServiceImpl implements EmsOverviewService {
         }
 
         for (int i = 0; i < spaceList.size(); i++) {
-            EmsSpace space = spaceList.get(i);
+            BaseSpace space = spaceList.get(i);
             if (space == null) {
                 continue;
             }

+ 0 - 16
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsProjectConfigurationServiceImpl.java

@@ -1,16 +0,0 @@
-package com.usky.ems.service.impl;
-
-import com.usky.common.mybatis.core.AbstractCrudService;
-import com.usky.ems.domain.EmsProjectConfiguration;
-import com.usky.ems.mapper.EmsProjectConfigurationMapper;
-import com.usky.ems.service.EmsProjectConfigurationService;
-import org.springframework.stereotype.Service;
-
-/**
- * 项目配置信息服务实现
- */
-@Service
-public class EmsProjectConfigurationServiceImpl extends AbstractCrudService<EmsProjectConfigurationMapper, EmsProjectConfiguration>
-        implements EmsProjectConfigurationService {
-}
-

+ 0 - 63
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsProjectServiceImpl.java

@@ -1,63 +0,0 @@
-package com.usky.ems.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.usky.common.mybatis.core.AbstractCrudService;
-import com.usky.ems.domain.EmsProject;
-import com.usky.ems.domain.EmsProjectConfiguration;
-import com.usky.ems.mapper.EmsProjectMapper;
-import com.usky.ems.mapper.EmsProjectConfigurationMapper;
-import com.usky.ems.service.EmsProjectService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.time.LocalDateTime;
-
-/**
- * 项目服务实现(leo.ems_project)
- */
-@Service
-public class EmsProjectServiceImpl extends AbstractCrudService<EmsProjectMapper, EmsProject> implements EmsProjectService {
-
-    @Autowired
-    private EmsProjectConfigurationMapper emsProjectConfigurationMapper;
-
-    @Override
-    public Long create(EmsProject project) {
-        LocalDateTime now = LocalDateTime.now();
-        project.setCreateTime(now);
-        project.setUpdateTime(now);
-        this.save(project);
-        return project.getId();
-    }
-
-    @Override
-    public void update(EmsProject project) {
-        if (project.getId() == null) {
-            return;
-        }
-        project.setUpdateTime(LocalDateTime.now());
-        this.updateById(project);
-    }
-
-    @Override
-    public void delete(Long id) {
-        if (id == null) {
-            return;
-        }
-        this.removeById(id);
-    }
-
-    @Override
-    public Boolean getConfigurationsStatus(Long projectId, String name) {
-        if (projectId == null || name == null) {
-            return false;
-        }
-        LambdaQueryWrapper<EmsProjectConfiguration> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(EmsProjectConfiguration::getProjectId, projectId)
-                .eq(EmsProjectConfiguration::getName, name)
-                .last("LIMIT 1");
-        EmsProjectConfiguration cfg = emsProjectConfigurationMapper.selectOne(wrapper);
-        return cfg != null && "1".equals(cfg.getValue());
-    }
-}
-

+ 0 - 3
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsReportServiceImpl.java

@@ -3,10 +3,8 @@ package com.usky.ems.service.impl;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.usky.ems.domain.EmsDevice;
 import com.usky.ems.domain.EmsDeviceFunction;
-import com.usky.ems.domain.EmsProject;
 import com.usky.ems.mapper.EmsDeviceFunctionMapper;
 import com.usky.ems.mapper.EmsDeviceMapper;
-import com.usky.ems.mapper.EmsProjectMapper;
 import com.usky.ems.service.EmsReportService;
 import com.usky.ems.service.vo.*;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -16,7 +14,6 @@ import org.springframework.util.StringUtils;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.math.BigDecimal;
 import java.nio.charset.StandardCharsets;
 import java.util.*;
 import java.util.stream.Collectors;

+ 2 - 2
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/vo/DmpGatewayDetailResponse.java

@@ -23,8 +23,8 @@ public class DmpGatewayDetailResponse {
     private LocalDateTime upgradeTime;
     private Integer virtualDevice;
     private String remark;
-    private Long updatedBy;
+    private String updatedBy;
     private LocalDateTime updateTime;
-    private Long createdBy;
+    private String createdBy;
     private LocalDateTime createTime;
 }

+ 2 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/vo/DmpGatewayPageRequest.java

@@ -10,6 +10,8 @@ public class DmpGatewayPageRequest {
 
     private Integer current = 1;
     private Integer size = 10;
+    /** 安装位置 */
+    private String installAddress;
     /** 网关名称(模糊) */
     private String name;
     /** 设备 uuid(精确) */

+ 0 - 24
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/vo/EmsGatewayDetailResponse.java

@@ -1,24 +0,0 @@
-package com.usky.ems.service.vo;
-
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-/**
- * 网关详情响应
- */
-@Data
-public class EmsGatewayDetailResponse {
-
-    private String id;
-    private String name;
-    private Long spaceId;
-    private String spaceName;
-    private String regionName;
-    private String buildingName;
-    private String installLocation;
-    private Integer communicationStatus;
-    private LocalDateTime onlineTime;
-    private LocalDateTime createTime;
-    private LocalDateTime updateTime;
-}

+ 0 - 22
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/vo/EmsGatewayListItem.java

@@ -1,22 +0,0 @@
-package com.usky.ems.service.vo;
-
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-/**
- * 网关列表项(字段与 leo.ems_gateway 对应)
- */
-@Data
-public class EmsGatewayListItem {
-
-    private String id;
-    private String name;
-    private Long spaceId;
-    private String spaceName;
-    private String installLocation;
-    private Integer communicationStatus;
-    private LocalDateTime onlineTime;
-    private LocalDateTime createTime;
-    private LocalDateTime updateTime;
-}

+ 0 - 21
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/vo/EmsGatewayPageRequest.java

@@ -1,21 +0,0 @@
-package com.usky.ems.service.vo;
-
-import lombok.Data;
-
-/**
- * 网关列表分页请求
- */
-@Data
-public class EmsGatewayPageRequest {
-
-    private Integer current = 1;
-    private Integer size = 10;
-    /** 安装位置(模糊) */
-    private String installLocation;
-    /** 网关名称(模糊) */
-    private String name;
-    /** 网关编码(模糊) */
-    private String code;
-    /** 通讯状态:0-离线 1-在线,不传为全部 */
-    private Integer communicationStatus;
-}

+ 30 - 30
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/vo/EmsModelSaveRequest.java

@@ -1,8 +1,11 @@
 package com.usky.ems.service.vo;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import lombok.Data;
 
 import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
 
 /**
  * 基础建模 - 建筑/区域/网关/通道/设备/属性点位 新增与编辑请求(通用字段)
@@ -10,37 +13,34 @@ import java.math.BigDecimal;
  */
 @Data
 public class EmsModelSaveRequest {
+    private Long id;
 
-    private Long projectId;
-    private Long buildingId;
-    private Long regionId;
-    /** 网关绑定的空间 ID(一般为区域) */
-    private Long spaceId;
-
-    private Long channelId;
-    // 通道类型ID(1:Serial Port,2:TCP)
-    private Integer channelTypeId;
-
-    private String deviceId;
-    private Long energyTypeId;
-
-    private String gatewayId;
-    // 备注
-    private String remark;
-    // 是否虚拟设备 0:否 1:是
-    private Integer virtualDevice;
-    // 数据中心ID 0:默认(本地数据中心)
-    private Long dataCenterId;
-
+    /** area */
     private String name;
-    private String code;
+    /** 区域类型 1:区域 2:部门 3:科室 */
+    private Integer type;
     private BigDecimal area;
-    private Integer sortOrder;
-    private String installLocation;
-    private String configJson;
-    private Integer channelNo;
-    private String model;
-    private String dataType;
-    private String unit;
-    private String pointAddress;
+    private BigDecimal commonArea;
+    private BigDecimal airConditionedArea;
+    private Integer residentPopulation;
+
+
+    /** build */
+    private String buildName;
+    private String address;
+    private Integer aboveFloor;
+    private Integer underFloor;
+    private Double buildArea;
+    private Double coverArea;
+    private Double buildHigh;
+    private LocalDate completeYear;
+    private String buildDesc;
+    private String longitude;
+    private String latitude;
+
+    /**  共用 */
+    private Long parentSpaceId;
+    private String parentSpaceName;
+    private Long spaceId;
+
 }

+ 22 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/vo/SpaceGatewayBindRequest.java

@@ -0,0 +1,22 @@
+package com.usky.ems.service.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 空间绑定网关请求
+ */
+@Data
+public class SpaceGatewayBindRequest {
+
+    /**
+     * 空间ID
+     */
+    private Long spaceId;
+
+    /**
+     * 网关uuid列表
+     */
+    private List<String> gatewayUuids;
+}