Kaynağa Gözat

开发项目(ems_project)新增、修改、删除三个接口

james 2 hafta önce
ebeveyn
işleme
c0ab6f2a99
25 değiştirilmiş dosya ile 945 ekleme ve 65 silme
  1. 37 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/controller/web/EmsProjectController.java
  2. 54 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/controller/web/EmsSystemDictController.java
  3. 74 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/EmsProject.java
  4. 39 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/EmsProjectDeviceSystem.java
  5. 37 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/EmsSystemDictCode.java
  6. 37 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/EmsSystemDictRegion.java
  7. 43 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/EmsSystemDictValue.java
  8. 10 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/EmsProjectDeviceSystemMapper.java
  9. 10 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/EmsProjectMapper.java
  10. 10 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/EmsSystemDictCodeMapper.java
  11. 10 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/EmsSystemDictRegionMapper.java
  12. 10 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/mapper/EmsSystemDictValueMapper.java
  13. 10 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/BaseSpaceService.java
  14. 16 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/EmsProjectService.java
  15. 10 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/EmsSystemDictCodeService.java
  16. 22 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/EmsSystemDictRegionService.java
  17. 10 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/EmsSystemDictValueService.java
  18. 26 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/BaseSpaceServiceImpl.java
  19. 72 63
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsOverviewServiceImpl.java
  20. 241 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsProjectServiceImpl.java
  21. 15 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsSystemDictCodeServiceImpl.java
  22. 61 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsSystemDictRegionServiceImpl.java
  23. 15 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsSystemDictValueServiceImpl.java
  24. 2 2
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/vo/EmsProjectResponse.java
  25. 74 0
      service-ems/service-ems-biz/src/main/java/com/usky/ems/service/vo/EmsProjectSaveRequest.java

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

@@ -0,0 +1,37 @@
+package com.usky.ems.controller.web;
+
+import com.usky.common.core.bean.ApiResult;
+import com.usky.ems.service.EmsProjectService;
+import com.usky.ems.service.vo.EmsProjectResponse;
+import com.usky.ems.service.vo.EmsProjectSaveRequest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 项目(ems_project)新增、修改、删除
+ * 基础路径前缀:/project(网关再加 /prod-api/service-ems)
+ */
+@RestController
+@RequestMapping("/project")
+public class EmsProjectController {
+
+    @Autowired
+    private EmsProjectService emsProjectService;
+
+    @PostMapping
+    public ApiResult<EmsProjectResponse> create(@RequestBody EmsProjectSaveRequest request) {
+        return ApiResult.success(emsProjectService.save(request));
+    }
+
+    @PutMapping
+    public ApiResult<Void> update(@RequestBody EmsProjectSaveRequest request) {
+        emsProjectService.update(request);
+        return ApiResult.success();
+    }
+
+    @DeleteMapping("/{id}")
+    public ApiResult<Void> delete(@PathVariable Long id) {
+        emsProjectService.remove(id);
+        return ApiResult.success();
+    }
+}

+ 54 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/controller/web/EmsSystemDictController.java

@@ -0,0 +1,54 @@
+package com.usky.ems.controller.web;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.usky.common.core.bean.ApiResult;
+import com.usky.ems.domain.EmsSystemDictCode;
+import com.usky.ems.domain.EmsSystemDictRegion;
+import com.usky.ems.domain.EmsSystemDictValue;
+import com.usky.ems.service.EmsSystemDictCodeService;
+import com.usky.ems.service.EmsSystemDictRegionService;
+import com.usky.ems.service.EmsSystemDictValueService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * 系统字典(ems_system_dict_code / ems_system_dict_region / ems_system_dict_value)查询接口
+ * 基础路径前缀:/system-dict
+ */
+@RestController
+@RequestMapping("/system-dict")
+public class EmsSystemDictController {
+
+    @Autowired
+    private EmsSystemDictCodeService emsSystemDictCodeService;
+    @Autowired
+    private EmsSystemDictRegionService emsSystemDictRegionService;
+    @Autowired
+    private EmsSystemDictValueService emsSystemDictValueService;
+
+    @GetMapping("/code/list")
+    public ApiResult<List<EmsSystemDictCode>> listCodes() {
+        return ApiResult.success(emsSystemDictCodeService.list());
+    }
+
+    /**
+     * @param parent 父级区域编码(如国标省市区上一级 code;省级可传约定根编码,需与字典数据一致)
+     */
+    @GetMapping("/region/list")
+    public ApiResult<List<EmsSystemDictRegion>> listRegions(@RequestParam String parent) {
+        return ApiResult.success(emsSystemDictRegionService.listByParentCode(parent));
+    }
+
+    @GetMapping("/value/list")
+    public ApiResult<List<EmsSystemDictValue>> listValues(@RequestParam String dictCode) {
+        return ApiResult.success(emsSystemDictValueService.list(
+                new LambdaQueryWrapper<EmsSystemDictValue>()
+                        .eq(EmsSystemDictValue::getDictCode, dictCode)
+                        .orderByAsc(EmsSystemDictValue::getSort)));
+    }
+}

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

@@ -0,0 +1,74 @@
+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;
+
+/**
+ * 项目(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("tenant_id")
+    private Integer tenantId;
+    @TableField("updated_by")
+    private String updatedBy;
+    @TableField("update_time")
+    private LocalDateTime updateTime;
+    @TableField("created_by")
+    private String createdBy;
+    @TableField("create_time")
+    private LocalDateTime createTime;
+}

+ 39 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/EmsProjectDeviceSystem.java

@@ -0,0 +1,39 @@
+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;
+
+/**
+ * 项目与设备系统关联(ems_project_device_system)
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("ems_project_device_system")
+public class EmsProjectDeviceSystem implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @TableField("project_id")
+    private Long projectId;
+
+    @TableField("device_system")
+    private Integer deviceSystem;
+    @TableField("updated_by")
+    private String updatedBy;
+    @TableField("update_time")
+    private LocalDateTime updateTime;
+    @TableField("created_by")
+    private String createdBy;
+    @TableField("create_time")
+    private LocalDateTime createTime;
+}

+ 37 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/EmsSystemDictCode.java

@@ -0,0 +1,37 @@
+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;
+
+/**
+ * 系统字典编码(ems_system_dict_code)
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("ems_system_dict_code")
+public class EmsSystemDictCode implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    private String name;
+    private String code;
+    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;
+}

+ 37 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/EmsSystemDictRegion.java

@@ -0,0 +1,37 @@
+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;
+
+/**
+ * 省市区字典(ems_system_dict_region)
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("ems_system_dict_region")
+public class EmsSystemDictRegion implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    private String code;
+    private String name;
+    private String parent;
+    @TableField("updated_by")
+    private Long updatedBy;
+    @TableField("update_time")
+    private LocalDateTime updateTime;
+    @TableField("created_by")
+    private Long createdBy;
+    @TableField("create_time")
+    private LocalDateTime createTime;
+}

+ 43 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/domain/EmsSystemDictValue.java

@@ -0,0 +1,43 @@
+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;
+
+/**
+ * 系统字典值(ems_system_dict_value)
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("ems_system_dict_value")
+public class EmsSystemDictValue implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @TableField("dict_code")
+    private String dictCode;
+    @TableField("parent_id")
+    private Integer parentId;
+    private String name;
+    private String value;
+    private String icon;
+    private Integer sort;
+    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;
+}

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

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

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

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

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

@@ -0,0 +1,10 @@
+package com.usky.ems.mapper;
+
+import com.usky.common.mybatis.core.CrudMapper;
+import com.usky.ems.domain.EmsSystemDictCode;
+
+/**
+ * 系统字典编码 Mapper(ems_system_dict_code)
+ */
+public interface EmsSystemDictCodeMapper extends CrudMapper<EmsSystemDictCode> {
+}

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

@@ -0,0 +1,10 @@
+package com.usky.ems.mapper;
+
+import com.usky.common.mybatis.core.CrudMapper;
+import com.usky.ems.domain.EmsSystemDictRegion;
+
+/**
+ * 省市区字典 Mapper(ems_system_dict_region)
+ */
+public interface EmsSystemDictRegionMapper extends CrudMapper<EmsSystemDictRegion> {
+}

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

@@ -0,0 +1,10 @@
+package com.usky.ems.mapper;
+
+import com.usky.common.mybatis.core.CrudMapper;
+import com.usky.ems.domain.EmsSystemDictValue;
+
+/**
+ * 系统字典值 Mapper(ems_system_dict_value)
+ */
+public interface EmsSystemDictValueMapper extends CrudMapper<EmsSystemDictValue> {
+}

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

@@ -28,4 +28,14 @@ public interface BaseSpaceService extends CrudService<BaseSpace> {
      * 递归获取某空间节点下的所有子节点(不包含自身)
      */
     List<BaseSpace> recursiveAllChildrenNode(Long spaceId);
+
+    /**
+     * 更新项目根空间名称(与 ems_project 名称同步)
+     */
+    void updateProjectSpaceName(Long spaceId, String newName);
+
+    /**
+     * 是否叶子节点:无子空间
+     */
+    boolean isLeafSpace(Long spaceId);
 }

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

@@ -0,0 +1,16 @@
+package com.usky.ems.service;
+
+import com.usky.ems.service.vo.EmsProjectResponse;
+import com.usky.ems.service.vo.EmsProjectSaveRequest;
+
+/**
+ * 项目(ems_project)维护:新增、修改、删除(含空间树、省市区校验、设备系统关联)
+ */
+public interface EmsProjectService {
+
+    EmsProjectResponse save(EmsProjectSaveRequest request);
+
+    EmsProjectResponse update(EmsProjectSaveRequest request);
+
+    void remove(Long id);
+}

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

@@ -0,0 +1,10 @@
+package com.usky.ems.service;
+
+import com.usky.common.mybatis.core.CrudService;
+import com.usky.ems.domain.EmsSystemDictCode;
+
+/**
+ * 系统字典编码(ems_system_dict_code)
+ */
+public interface EmsSystemDictCodeService extends CrudService<EmsSystemDictCode> {
+}

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

@@ -0,0 +1,22 @@
+package com.usky.ems.service;
+
+import com.usky.ems.domain.EmsSystemDictRegion;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 省市区字典(ems_system_dict_region)
+ */
+public interface EmsSystemDictRegionService {
+
+    /**
+     * 校验省市区编码并返回 code -&gt; name;非法时抛出业务异常
+     */
+    Map<String, String> checkAndBuildMap(String provinceCode, String cityCode, String districtCode);
+
+    /**
+     * 按父级编码查询子级区域列表
+     */
+    List<EmsSystemDictRegion> listByParentCode(String parentCode);
+}

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

@@ -0,0 +1,10 @@
+package com.usky.ems.service;
+
+import com.usky.common.mybatis.core.CrudService;
+import com.usky.ems.domain.EmsSystemDictValue;
+
+/**
+ * 系统字典值(ems_system_dict_value)
+ */
+public interface EmsSystemDictValueService extends CrudService<EmsSystemDictValue> {
+}

+ 26 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/BaseSpaceServiceImpl.java

@@ -1,12 +1,15 @@
 package com.usky.ems.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.usky.common.mybatis.core.AbstractCrudService;
+import com.usky.common.security.utils.SecurityUtils;
 import com.usky.ems.domain.BaseSpace;
 import com.usky.ems.mapper.BaseSpaceMapper;
 import com.usky.ems.service.BaseSpaceService;
 import com.usky.ems.service.vo.BaseSpaceForestNodeVO;
 import org.springframework.stereotype.Service;
 
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -133,4 +136,27 @@ public class BaseSpaceServiceImpl extends AbstractCrudService<BaseSpaceMapper, B
         vo.setDeep(space.getDeep());
         return vo;
     }
+
+    @Override
+    public void updateProjectSpaceName(Long spaceId, String newName) {
+        if (spaceId == null || newName == null) {
+            return;
+        }
+        BaseSpace space = this.getById(spaceId);
+        if (space == null) {
+            return;
+        }
+        space.setName(newName);
+        space.setUpdatedBy(SecurityUtils.getUsername());
+        space.setUpdateTime(LocalDateTime.now());
+        this.updateById(space);
+    }
+
+    @Override
+    public boolean isLeafSpace(Long spaceId) {
+        if (spaceId == null) {
+            return true;
+        }
+        return this.count(new LambdaQueryWrapper<BaseSpace>().eq(BaseSpace::getParentId, spaceId)) == 0;
+    }
 }

+ 72 - 63
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsOverviewServiceImpl.java

@@ -5,8 +5,12 @@ import com.usky.common.security.utils.SecurityUtils;
 import com.usky.ems.domain.EmsDevice;
 import com.usky.ems.domain.BaseSpace;
 import com.usky.ems.domain.EmsEnergyItemCode;
+import com.usky.ems.domain.EmsProject;
+import com.usky.ems.domain.EmsProjectDeviceSystem;
 import com.usky.ems.mapper.EmsDeviceMapper;
 import com.usky.ems.mapper.EmsEnergyItemCodeMapper;
+import com.usky.ems.mapper.EmsProjectDeviceSystemMapper;
+import com.usky.ems.mapper.EmsProjectMapper;
 import com.usky.ems.service.EmsModelService;
 import com.usky.ems.service.EmsOverviewService;
 import com.usky.ems.service.BaseSpaceService;
@@ -15,7 +19,6 @@ import com.usky.ems.service.vo.EmsOverviewDeviceSystemStatVO;
 import com.usky.ems.service.vo.EmsOverviewEnergyItemVO;
 import com.usky.ems.service.vo.EmsProjectResponse;
 import com.usky.ems.service.vo.EmsSummaryResponse;
-import io.swagger.models.auth.In;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -49,71 +52,77 @@ public class EmsOverviewServiceImpl implements EmsOverviewService {
     @Autowired
     private EmsEnergyItemCodeMapper emsEnergyItemCodeMapper;
 
+    @Autowired
+    private EmsProjectMapper emsProjectMapper;
+
+    @Autowired
+    private EmsProjectDeviceSystemMapper emsProjectDeviceSystemMapper;
+
     @Override
     public EmsProjectResponse getProject(Integer projectId) {
-//        EmsProject project;
-//        if (projectId != null) {
-//            project = emsProjectMapper.selectById(projectId);
-//        } else {
-//            List<EmsProject> list = emsProjectMapper.selectList(null);
-//            project = list.isEmpty() ? null : list.get(0);
-//        }
-//        if (project == null) {
-//            return null;
-//        }
+        EmsProject project;
+        if (projectId != null) {
+            project = emsProjectMapper.selectById(projectId);
+        } else {
+            List<EmsProject> list = emsProjectMapper.selectList(null);
+            project = list.isEmpty() ? null : list.get(0);
+        }
+        if (project == null) {
+            return null;
+        }
         EmsProjectResponse resp = new EmsProjectResponse();
-//        resp.setId(project.getId());
-//        resp.setSpaceId(project.getSpaceId());
-//        resp.setName(project.getName());
-//        resp.setAbbreviation(project.getAbbreviation());
-//        resp.setArea(project.getArea());
-//        resp.setCommonArea(project.getCommonArea());
-//        resp.setAirConditionedArea(project.getAirConditionedArea());
-//        // 源字段为 Integer,这里转为 BigDecimal 以匹配 VO 定义
-//        if (project.getResidentPopulation() != null) {
-//            resp.setResidentPopulation(java.math.BigDecimal.valueOf(project.getResidentPopulation()));
-//        }
-//
-//        // 设备系统集合
-//        List<EmsProjectDeviceSystem> sysList = emsProjectDeviceSystemMapper.selectList(
-//                new LambdaQueryWrapper<EmsProjectDeviceSystem>()
-//                        .eq(EmsProjectDeviceSystem::getProjectId, project.getId())
-//        );
-//        if (sysList != null && !sysList.isEmpty()) {
-//            resp.setDeviceSystemList(sysList.stream()
-//                    .map(EmsProjectDeviceSystem::getDeviceSystem)
-//                    .collect(Collectors.toList()));
-//        }
-//
-//        resp.setProvinceCode(project.getProvinceCode());
-//        resp.setCityCode(project.getCityCode());
-//        resp.setDistrictCode(project.getDistrictCode());
-//        resp.setProvinceName(project.getProvinceName());
-//        resp.setCityName(project.getCityName());
-//        resp.setDistrictName(project.getDistrictName());
-//        resp.setLocation(project.getLocation());
-//        resp.setAddress(project.getAddress());
-//        resp.setTypeId(project.getTypeId());
-//        resp.setTypeName(project.getTypeName());
-//        resp.setImage(project.getImage());
-//        // imageUrl 视实际文件服务而定,这里暂不拼接,直接沿用 image 字段或留空
-//        resp.setImageUrl(project.getImage());
-//        resp.setIntroduction(project.getIntroduction());
-//        resp.setPlatformName(project.getPlatformName());
-//        resp.setLogo(project.getLogo());
-//        resp.setLogoUrl(project.getLogo());
-//        resp.setLogoMin(project.getLogoMin());
-//        resp.setLogoMinUrl(project.getLogoMin());
-//        resp.setUpdatedBy(project.getUpdatedBy());
-//        resp.setCreatedBy(project.getCreatedBy());
-//        if (project.getUpdateTime() != null) {
-//            resp.setUpdateTime(project.getUpdateTime().toString());
-//        }
-//        if (project.getCreateTime() != null) {
-//            resp.setCreateTime(project.getCreateTime().toString());
-//        }
-//        // 单位能耗暂无法从现有表直接计算,先置为空,后续可按业务补充
-//        resp.setAreaCoal(null);
+        resp.setId(project.getId());
+        resp.setSpaceId(project.getSpaceId());
+        resp.setName(project.getName());
+        resp.setAbbreviation(project.getAbbreviation());
+        resp.setArea(project.getArea());
+        resp.setCommonArea(project.getCommonArea());
+        resp.setAirConditionedArea(project.getAirConditionedArea());
+        // 源字段为 Integer,这里转为 BigDecimal 以匹配 VO 定义
+        if (project.getResidentPopulation() != null) {
+            resp.setResidentPopulation(java.math.BigDecimal.valueOf(project.getResidentPopulation()));
+        }
+
+        // 设备系统集合
+        List<EmsProjectDeviceSystem> sysList = emsProjectDeviceSystemMapper.selectList(
+                new LambdaQueryWrapper<EmsProjectDeviceSystem>()
+                        .eq(EmsProjectDeviceSystem::getProjectId, project.getId())
+        );
+        if (sysList != null && !sysList.isEmpty()) {
+            resp.setDeviceSystemList(sysList.stream()
+                    .map(EmsProjectDeviceSystem::getDeviceSystem)
+                    .collect(Collectors.toList()));
+        }
+
+        resp.setProvinceCode(project.getProvinceCode());
+        resp.setCityCode(project.getCityCode());
+        resp.setDistrictCode(project.getDistrictCode());
+        resp.setProvinceName(project.getProvinceName());
+        resp.setCityName(project.getCityName());
+        resp.setDistrictName(project.getDistrictName());
+        resp.setLocation(project.getLocation());
+        resp.setAddress(project.getAddress());
+        resp.setTypeId(project.getTypeId());
+        resp.setTypeName(project.getTypeName());
+        resp.setImage(project.getImage());
+        // imageUrl 视实际文件服务而定,这里暂不拼接,直接沿用 image 字段或留空
+        resp.setImageUrl(project.getImage());
+        resp.setIntroduction(project.getIntroduction());
+        resp.setPlatformName(project.getPlatformName());
+        resp.setLogo(project.getLogo());
+        resp.setLogoUrl(project.getLogo());
+        resp.setLogoMin(project.getLogoMin());
+        resp.setLogoMinUrl(project.getLogoMin());
+        resp.setUpdatedBy(project.getUpdatedBy());
+        resp.setCreatedBy(project.getCreatedBy());
+        if (project.getUpdateTime() != null) {
+            resp.setUpdateTime(project.getUpdateTime().toString());
+        }
+        if (project.getCreateTime() != null) {
+            resp.setCreateTime(project.getCreateTime().toString());
+        }
+        // 单位能耗暂无法从现有表直接计算,先置为空,后续可按业务补充
+        resp.setAreaCoal(null);
         return resp;
     }
 

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

@@ -0,0 +1,241 @@
+package com.usky.ems.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.usky.common.core.exception.BusinessException;
+import com.usky.common.security.utils.SecurityUtils;
+import com.usky.ems.domain.BaseSpace;
+import com.usky.ems.domain.EmsProject;
+import com.usky.ems.domain.EmsProjectDeviceSystem;
+import com.usky.ems.mapper.EmsProjectDeviceSystemMapper;
+import com.usky.ems.mapper.EmsProjectMapper;
+import com.usky.ems.service.BaseSpaceService;
+import com.usky.ems.service.EmsProjectService;
+import com.usky.ems.service.EmsSystemDictRegionService;
+import com.usky.ems.service.vo.EmsProjectResponse;
+import com.usky.ems.service.vo.EmsProjectSaveRequest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * 项目维护实现(逻辑参考原 ProjectServiceImpl:省市区校验、创建项目空间、设备系统关联、删除前校验叶子节点等)
+ */
+@Service
+public class EmsProjectServiceImpl implements EmsProjectService {
+
+    private static final int SPACE_TYPE_PROJECT = 1;
+
+    @Autowired
+    private EmsProjectMapper emsProjectMapper;
+    @Autowired
+    private EmsProjectDeviceSystemMapper emsProjectDeviceSystemMapper;
+    @Autowired
+    private BaseSpaceService baseSpaceService;
+    @Autowired
+    private EmsSystemDictRegionService emsSystemDictRegionService;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public EmsProjectResponse save(EmsProjectSaveRequest request) {
+        validateSaveRequest(request, false);
+        Integer currentTenantId = SecurityUtils.getTenantId();
+        Map<String, String> regionMap = emsSystemDictRegionService.checkAndBuildMap(
+                request.getProvinceCode(), request.getCityCode(), request.getDistrictCode());
+        Long spaceId = createProjectSpace(request.getName());
+        EmsProject po = new EmsProject();
+        copyRequestToEntity(request, po, regionMap);
+        po.setSpaceId(spaceId);
+        po.setTenantId(currentTenantId);
+        fillAuditOnCreate(po);
+        emsProjectMapper.insert(po);
+        replaceDeviceSystems(po.getId(), request.getDeviceSystemList());
+        return toResponse(po, request.getDeviceSystemList());
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public EmsProjectResponse update(EmsProjectSaveRequest request) {
+        if (request.getId() == null) {
+            throw new BusinessException("修改项目时 id 不能为空");
+        }
+        EmsProject old = emsProjectMapper.selectById(request.getId());
+        if (old == null) {
+            throw new BusinessException("错误的项目id值");
+        }
+        Map<String, String> regionMap = emsSystemDictRegionService.checkAndBuildMap(
+                request.getProvinceCode(), request.getCityCode(), request.getDistrictCode());
+        EmsProject po = new EmsProject();
+        copyRequestToEntity(request, po, regionMap);
+        po.setSpaceId(old.getSpaceId());
+        po.setTenantId(old.getTenantId());
+        fillAuditOnUpdate(po);
+        emsProjectMapper.updateById(po);
+        baseSpaceService.updateProjectSpaceName(old.getSpaceId(), po.getName());
+        replaceDeviceSystems(po.getId(), request.getDeviceSystemList());
+        return toResponse(po, request.getDeviceSystemList());
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void remove(Long id) {
+        EmsProject project = emsProjectMapper.selectById(id);
+        if (project == null) {
+            throw new BusinessException("错误的项目id值");
+        }
+        if (!baseSpaceService.isLeafSpace(project.getSpaceId())) {
+            throw new BusinessException("当前项目下有空间节点不允许删除");
+        }
+        if (hasLoggedUserForProject(project.getId())) {
+            throw new BusinessException("当前项目有关联的用户使用;不允许删除");
+        }
+        emsProjectDeviceSystemMapper.delete(
+                new LambdaQueryWrapper<EmsProjectDeviceSystem>().eq(EmsProjectDeviceSystem::getProjectId, id));
+        emsProjectMapper.deleteById(id);
+        baseSpaceService.removeById(project.getSpaceId());
+    }
+
+    /**
+     * 对应原 UserService.hasLoggedUser(projectId)。接入统一用户/权限模块后可在此查询用户与项目绑定关系。
+     */
+    private boolean hasLoggedUserForProject(Long projectId) {
+        return false;
+    }
+
+    private void validateSaveRequest(EmsProjectSaveRequest request, boolean update) {
+        if (!StringUtils.hasText(request.getName())) {
+            throw new BusinessException("项目名称不能为空");
+        }
+        if (request.getTypeId() == null || !StringUtils.hasText(request.getTypeName())) {
+            throw new BusinessException("项目类型不能为空");
+        }
+    }
+
+    private Long createProjectSpace(String projectName) {
+        LocalDateTime now = LocalDateTime.now();
+        String audit = SecurityUtils.getUsername();
+        BaseSpace space = new BaseSpace();
+        space.setName(projectName);
+        space.setDeep(1);
+        space.setRootId(0L);
+        space.setParentId(0L);
+        space.setType(SPACE_TYPE_PROJECT);
+        space.setPath("");
+        space.setTenantId(SecurityUtils.getTenantId());
+        space.setCreatedBy(audit);
+        space.setUpdatedBy(audit);
+        space.setCreateTime(now);
+        space.setUpdateTime(now);
+        baseSpaceService.save(space);
+        return space.getId();
+    }
+
+    private void copyRequestToEntity(EmsProjectSaveRequest request, EmsProject po, Map<String, String> regionMap) {
+        po.setId(request.getId());
+        po.setName(request.getName());
+        po.setPlatformName(request.getPlatformName());
+        po.setAbbreviation(request.getAbbreviation());
+        po.setArea(request.getArea());
+        po.setCommonArea(request.getCommonArea());
+        po.setAirConditionedArea(request.getAirConditionedArea());
+        po.setResidentPopulation(request.getResidentPopulation());
+        po.setProvinceCode(request.getProvinceCode());
+        po.setCityCode(request.getCityCode());
+        po.setDistrictCode(request.getDistrictCode());
+        po.setProvinceName(regionMap.get(request.getProvinceCode()));
+        po.setCityName(regionMap.get(request.getCityCode()));
+        po.setDistrictName(regionMap.get(request.getDistrictCode()));
+        po.setLocation(request.getLocation());
+        po.setAddress(request.getAddress());
+        po.setTypeId(request.getTypeId());
+        po.setTypeName(request.getTypeName());
+        po.setImage(request.getImage());
+        po.setIntroduction(request.getIntroduction());
+        po.setLogo(request.getLogo());
+        po.setLogoMin(request.getLogoMin());
+    }
+
+    private void fillAuditOnCreate(EmsProject po) {
+        LocalDateTime now = LocalDateTime.now();
+        String uname = SecurityUtils.getUsername();
+        po.setCreatedBy(uname);
+        po.setUpdatedBy(uname);
+        po.setCreateTime(now);
+        po.setUpdateTime(now);
+    }
+
+    private void fillAuditOnUpdate(EmsProject po) {
+        LocalDateTime now = LocalDateTime.now();
+        String uname = SecurityUtils.getUsername();
+        po.setUpdatedBy(uname);
+        po.setUpdateTime(now);
+    }
+
+    private void replaceDeviceSystems(Long projectId, List<Integer> deviceSystemList) {
+        emsProjectDeviceSystemMapper.delete(
+                new LambdaQueryWrapper<EmsProjectDeviceSystem>().eq(EmsProjectDeviceSystem::getProjectId, projectId));
+        if (CollectionUtils.isEmpty(deviceSystemList)) {
+            return;
+        }
+        for (Integer code : deviceSystemList) {
+            if (code == null) {
+                continue;
+            }
+            EmsProjectDeviceSystem row = new EmsProjectDeviceSystem();
+            row.setProjectId(projectId);
+            row.setDeviceSystem(code);
+            LocalDateTime now = LocalDateTime.now();
+            String uname = SecurityUtils.getUsername();
+            row.setUpdatedBy(uname);
+            row.setUpdateTime(now);
+            row.setCreatedBy(uname);
+            row.setCreateTime(now);
+            emsProjectDeviceSystemMapper.insert(row);
+        }
+    }
+
+    private EmsProjectResponse toResponse(EmsProject po, List<Integer> deviceSystemList) {
+        EmsProjectResponse resp = new EmsProjectResponse();
+        resp.setId(po.getId());
+        resp.setSpaceId(po.getSpaceId());
+        resp.setName(po.getName());
+        resp.setAbbreviation(po.getAbbreviation());
+        resp.setArea(po.getArea());
+        resp.setCommonArea(po.getCommonArea());
+        resp.setAirConditionedArea(po.getAirConditionedArea());
+        if (po.getResidentPopulation() != null) {
+            resp.setResidentPopulation(java.math.BigDecimal.valueOf(po.getResidentPopulation()));
+        }
+        resp.setDeviceSystemList(deviceSystemList);
+        resp.setProvinceCode(po.getProvinceCode());
+        resp.setCityCode(po.getCityCode());
+        resp.setDistrictCode(po.getDistrictCode());
+        resp.setProvinceName(po.getProvinceName());
+        resp.setCityName(po.getCityName());
+        resp.setDistrictName(po.getDistrictName());
+        resp.setLocation(po.getLocation());
+        resp.setAddress(po.getAddress());
+        resp.setTypeId(po.getTypeId());
+        resp.setTypeName(po.getTypeName());
+        resp.setImage(po.getImage());
+        resp.setIntroduction(po.getIntroduction());
+        resp.setPlatformName(po.getPlatformName());
+        resp.setLogo(po.getLogo());
+        resp.setLogoMin(po.getLogoMin());
+        resp.setUpdatedBy(po.getUpdatedBy());
+        resp.setCreatedBy(po.getCreatedBy());
+        if (po.getUpdateTime() != null) {
+            resp.setUpdateTime(po.getUpdateTime().toString());
+        }
+        if (po.getCreateTime() != null) {
+            resp.setCreateTime(po.getCreateTime().toString());
+        }
+        return resp;
+    }
+}

+ 15 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsSystemDictCodeServiceImpl.java

@@ -0,0 +1,15 @@
+package com.usky.ems.service.impl;
+
+import com.usky.common.mybatis.core.AbstractCrudService;
+import com.usky.ems.domain.EmsSystemDictCode;
+import com.usky.ems.mapper.EmsSystemDictCodeMapper;
+import com.usky.ems.service.EmsSystemDictCodeService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 系统字典编码服务
+ */
+@Service
+public class EmsSystemDictCodeServiceImpl extends AbstractCrudService<EmsSystemDictCodeMapper, EmsSystemDictCode>
+        implements EmsSystemDictCodeService {
+}

+ 61 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsSystemDictRegionServiceImpl.java

@@ -0,0 +1,61 @@
+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.EmsSystemDictRegion;
+import com.usky.ems.mapper.EmsSystemDictRegionMapper;
+import com.usky.ems.service.EmsSystemDictRegionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * 省市区字典服务
+ */
+@Service
+public class EmsSystemDictRegionServiceImpl implements EmsSystemDictRegionService {
+
+    @Autowired
+    private EmsSystemDictRegionMapper emsSystemDictRegionMapper;
+
+    @Override
+    public Map<String, String> checkAndBuildMap(String provinceCode, String cityCode, String districtCode) {
+        if (!StringUtils.hasText(provinceCode) || !StringUtils.hasText(cityCode) || !StringUtils.hasText(districtCode)) {
+            throw new BusinessException("省市区编码不能为空");
+        }
+        EmsSystemDictRegion province = emsSystemDictRegionMapper.selectOne(
+                new LambdaQueryWrapper<EmsSystemDictRegion>().eq(EmsSystemDictRegion::getCode, provinceCode).last("LIMIT 1"));
+        EmsSystemDictRegion city = emsSystemDictRegionMapper.selectOne(
+                new LambdaQueryWrapper<EmsSystemDictRegion>().eq(EmsSystemDictRegion::getCode, cityCode).last("LIMIT 1"));
+        EmsSystemDictRegion district = emsSystemDictRegionMapper.selectOne(
+                new LambdaQueryWrapper<EmsSystemDictRegion>().eq(EmsSystemDictRegion::getCode, districtCode).last("LIMIT 1"));
+        if (province == null || city == null || district == null) {
+            throw new BusinessException("省市区编码无效");
+        }
+        if (!Objects.equals(city.getParent(), province.getCode())) {
+            throw new BusinessException("市级编码与省级不匹配");
+        }
+        if (!Objects.equals(district.getParent(), city.getCode())) {
+            throw new BusinessException("区级编码与市级不匹配");
+        }
+        Map<String, String> map = new HashMap<>(4);
+        map.put(provinceCode, province.getName());
+        map.put(cityCode, city.getName());
+        map.put(districtCode, district.getName());
+        return map;
+    }
+
+    @Override
+    public List<EmsSystemDictRegion> listByParentCode(String parentCode) {
+        if (!StringUtils.hasText(parentCode)) {
+            throw new BusinessException("父级编码不能为空");
+        }
+        return emsSystemDictRegionMapper.selectList(
+                new LambdaQueryWrapper<EmsSystemDictRegion>().eq(EmsSystemDictRegion::getParent, parentCode));
+    }
+}

+ 15 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/impl/EmsSystemDictValueServiceImpl.java

@@ -0,0 +1,15 @@
+package com.usky.ems.service.impl;
+
+import com.usky.common.mybatis.core.AbstractCrudService;
+import com.usky.ems.domain.EmsSystemDictValue;
+import com.usky.ems.mapper.EmsSystemDictValueMapper;
+import com.usky.ems.service.EmsSystemDictValueService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 系统字典值服务
+ */
+@Service
+public class EmsSystemDictValueServiceImpl extends AbstractCrudService<EmsSystemDictValueMapper, EmsSystemDictValue>
+        implements EmsSystemDictValueService {
+}

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

@@ -94,13 +94,13 @@ public class EmsProjectResponse {
     private String logoMinUrl;
 
     @ApiModelProperty("更新人")
-    private Long updatedBy;
+    private String updatedBy;
 
     @ApiModelProperty("记录更新时间")
     private String updateTime;
 
     @ApiModelProperty("创建人")
-    private Long createdBy;
+    private String createdBy;
 
     @ApiModelProperty("记录创建时间")
     private String createTime;

+ 74 - 0
service-ems/service-ems-biz/src/main/java/com/usky/ems/service/vo/EmsProjectSaveRequest.java

@@ -0,0 +1,74 @@
+package com.usky.ems.service.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 项目新增/修改请求(对齐 ems_project + 设备系统列表)
+ */
+@Data
+public class EmsProjectSaveRequest {
+
+    @ApiModelProperty("主键,修改时必填")
+    private Long id;
+
+    @ApiModelProperty(value = "名称", required = true)
+    private String name;
+
+    @ApiModelProperty("平台名称")
+    private String platformName;
+
+    @ApiModelProperty("简称")
+    private String abbreviation;
+
+    @ApiModelProperty("项目面积")
+    private BigDecimal area;
+
+    @ApiModelProperty("公区面积")
+    private BigDecimal commonArea;
+
+    @ApiModelProperty("空调面积")
+    private BigDecimal airConditionedArea;
+
+    @ApiModelProperty("常驻人数")
+    private Integer residentPopulation;
+
+    @ApiModelProperty(value = "省编码", required = true)
+    private String provinceCode;
+
+    @ApiModelProperty(value = "市编码", required = true)
+    private String cityCode;
+
+    @ApiModelProperty(value = "区编码", required = true)
+    private String districtCode;
+
+    @ApiModelProperty("地理位置")
+    private String location;
+
+    @ApiModelProperty("项目地址")
+    private String address;
+
+    @ApiModelProperty(value = "项目类型ID", required = true)
+    private Integer typeId;
+
+    @ApiModelProperty(value = "项目类型名称", required = true)
+    private String typeName;
+
+    @ApiModelProperty("项目图片")
+    private String image;
+
+    @ApiModelProperty("项目简介")
+    private String introduction;
+
+    @ApiModelProperty("LOGO(大)")
+    private String logo;
+
+    @ApiModelProperty("LOGO(小)")
+    private String logoMin;
+
+    @ApiModelProperty("设备系统字典值列表(对应 ems_system_dict_value.value,字典编码如 device_system)")
+    private List<Integer> deviceSystemList;
+}