Browse Source

从原adm-poc-backgroud项目中代码迁移

yanguofeng 3 years ago
parent
commit
9668f7b3bc
100 changed files with 5849 additions and 0 deletions
  1. 9 0
      adm-business/adm-server/pom.xml
  2. 30 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/aop/ExceptionAspect.java
  3. 35 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/client/DicClient.java
  4. 17 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/client/ImageServiceClient.java
  5. 60 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/client/OldAdmClient.java
  6. 79 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/client/RwdClient.java
  7. 61 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/common/AdmConst.java
  8. 25 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/common/AdmMessageConst.java
  9. 37 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/common/AdmRequest.java
  10. 36 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/common/AdmResult.java
  11. 23 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/config/AdmCommonConfig.java
  12. 46 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/config/AdmRabbitConfig.java
  13. 27 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/config/TestConfig.java
  14. 164 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/controller/AppController.java
  15. 43 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/controller/ManageController.java
  16. 359 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/controller/ToolController.java
  17. 10 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmClientFlagMapper.java
  18. 10 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmComponentMapper.java
  19. 8 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmConfigMapper.java
  20. 10 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmContainerConfigMapper.java
  21. 8 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmFileMapper.java
  22. 10 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmInfosConfigMapper.java
  23. 8 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmJobSpaceMapper.java
  24. 8 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmM2dEquipMapper.java
  25. 11 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmMessagePMapper.java
  26. 10 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmObjectMapper.java
  27. 10 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmPipeConfigMapper.java
  28. 10 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmPipeMapper.java
  29. 8 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmProblemArchMapper.java
  30. 8 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmProblemEquipMapper.java
  31. 8 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmQrCodeMapper.java
  32. 8 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmRelationMapper.java
  33. 10 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmRelsConfigMapper.java
  34. 8 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmServeAreaMapper.java
  35. 10 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmUploadJobMapper.java
  36. 14 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmUploadLogMapper.java
  37. 53 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/datatx/DataTxHandler.java
  38. 8 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/datatx/ObjectForTx.java
  39. 55 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/datatx/ObjectMapper4Tx.java
  40. 53 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/BuildingData.java
  41. 58 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/D2mMessage.java
  42. 25 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/Dict.java
  43. 55 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/DownLoadData.java
  44. 43 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/InfoDef.java
  45. 31 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/Pagination.java
  46. 22 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/ProjectData.java
  47. 30 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/TypeDef.java
  48. 52 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/UploadData.java
  49. 42 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/UploadRtn.java
  50. 21 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmClientFlag.java
  51. 18 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmComponent.java
  52. 59 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmConfig.java
  53. 14 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmContainerConfig.java
  54. 29 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmFile.java
  55. 67 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmInfosConfig.java
  56. 71 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmJobSpace.java
  57. 18 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmM2dEquip.java
  58. 35 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmMessageP.java
  59. 90 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmObject.java
  60. 98 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmPipe.java
  61. 24 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmPipeConfig.java
  62. 67 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmProblemArch.java
  63. 20 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmProblemEquip.java
  64. 61 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmQrCode.java
  65. 28 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmRelation.java
  66. 30 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmRelsConfig.java
  67. 26 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmServeArea.java
  68. 22 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmUploadJob.java
  69. 68 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmUploadLog.java
  70. 50 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/BaseAdmDataEntity.java
  71. 23 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/BaseAdmEntity.java
  72. 23 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/BaseDeliveryEntity.java
  73. 27 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/oldadm/OBase.java
  74. 19 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/oldadm/OBuilding.java
  75. 99 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/oldadm/OEquip.java
  76. 51 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/oldadm/OFloor.java
  77. 17 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/oldadm/OProject.java
  78. 79 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/oldadm/OSpace.java
  79. 20 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/oldadm/OldAdmResult.java
  80. 74 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/handler/M2DMessageHandler.java
  81. 17 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/CallException.java
  82. 13 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/IAdmLogService.java
  83. 53 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/IAdmObjectService.java
  84. 29 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/IConfigService.java
  85. 29 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/IQueryFromOldAdm.java
  86. 32 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/ISyncApp.java
  87. 15 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/ISyncModel.java
  88. 16 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/ISyncOldAdm.java
  89. 21 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/ISyncSpace.java
  90. 81 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/ServiceUtil.java
  91. 30 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/impl/AdmLogServiceImpl.java
  92. 65 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/impl/AdmObjectServiceImpl.java
  93. 106 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/impl/ConfigServiceImpl.java
  94. 111 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/impl/QueryFromOldAdmImpl.java
  95. 758 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/impl/SyncAppImpl.java
  96. 498 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/impl/SyncAppImpl0.java
  97. 27 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/impl/SyncModelImpl.java
  98. 571 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/impl/SyncOldAdmImpl.java
  99. 264 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/impl/SyncSpaceImpl.java
  100. 0 0
      adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/util/AdmMessageHelper.java

+ 9 - 0
adm-business/adm-server/pom.xml

@@ -34,5 +34,14 @@
             <groupId>com.persagy</groupId>
             <artifactId>dmp-file-starter</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.persagy</groupId>
+            <artifactId>dmp-amqp-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.locationtech.jts</groupId>
+            <artifactId>jts-core</artifactId>
+            <version>1.16.1</version>
+        </dependency>
     </dependencies>
 </project>

+ 30 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/aop/ExceptionAspect.java

@@ -0,0 +1,30 @@
+package com.persagy.bdtp.adm.aop;
+
+import com.persagy.bdtp.adm.service.CallException;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.stereotype.Component;
+
+@Component
+@Aspect
+@Slf4j
+public class ExceptionAspect {
+
+    @Pointcut("execution(public * com.persagy.bdtp.adm.controller.AppController.*(..))")
+    public void handle(){
+
+    }
+
+    @Around("handle()")
+    public Object aroundInvoke(ProceedingJoinPoint point) throws Throwable {
+        try{
+            return point.proceed();
+        } catch (CallException e) {
+            return e.getErrorResult();
+        }
+    }
+
+}

+ 35 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/client/DicClient.java

@@ -0,0 +1,35 @@
+package com.persagy.bdtp.adm.client;
+
+import com.persagy.dmp.basic.config.DigitalFeignConfig;
+import com.persagy.dmp.basic.model.QueryCriteria;
+import com.persagy.dmp.common.model.response.CommonResult;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+import java.util.Map;
+
+@FeignClient(name = "dmp-dic", configuration = DigitalFeignConfig.class,
+		url = "${persagy.bdtp.dic.service:}")
+public interface DicClient {
+
+	/**
+	 * 查询类型定义
+	 * @param groupCode 集团编码
+	 * @param projectId 项目ID
+	 * @param appId 应用ID
+	 * @param userId 用户ID
+	 * @param criteria 查询条件
+	 * @return 类型定义
+	 */
+	@PostMapping("/dic/dt/data/query")
+	CommonResult<List<Map<String, Object>>> dataQuery(
+			@RequestParam("groupCode") String groupCode,
+			@RequestParam("projectId") String projectId,
+			@RequestParam("appId") String appId,
+			@RequestParam("userId") String userId,
+			@RequestBody QueryCriteria criteria);
+
+}

+ 17 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/client/ImageServiceClient.java

@@ -0,0 +1,17 @@
+package com.persagy.bdtp.adm.client;
+
+import com.persagy.dmp.basic.config.DigitalFeignConfig;
+import feign.Response;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@FeignClient(name = "image-service", configuration = DigitalFeignConfig.class,
+		url = "http://api.sagacloud.cn/dp-auxiliary/image-service")
+public interface ImageServiceClient {
+
+	@GetMapping(value = "/common/file_get", consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE)
+	Response fileGet(@RequestParam String key, @RequestParam String systemId);
+
+}

+ 60 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/client/OldAdmClient.java

@@ -0,0 +1,60 @@
+package com.persagy.bdtp.adm.client;
+
+import com.persagy.bdtp.adm.entity.oldadm.*;
+import com.persagy.dmp.basic.config.DigitalFeignConfig;
+import feign.Response;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Map;
+
+@FeignClient(name = "amd-old", configuration = DigitalFeignConfig.class,
+		url = "${persagy.adm.oldPlatformUrl}")
+public interface OldAdmClient {
+
+	@PostMapping("/persagy-sso-server/users/login")
+	Map<String, Object> login(
+			@RequestBody Map<String, Object> params);
+
+	@PostMapping("/datacenter/object/project/query")
+	OldAdmResult<List<OProject>> queryProject(
+			@RequestHeader("groupCode") String groupCode,
+			@RequestHeader("projectId") String projectId,
+			@RequestHeader("appId") String appId,
+			@RequestHeader("userId") String userId,
+			@RequestHeader("token") String token,
+			@RequestBody Map<String, Object> params);
+
+	@PostMapping("/datacenter/object/building/query")
+	OldAdmResult<List<OBuilding>> queryBuilding(
+			@RequestHeader("groupCode") String groupCode,
+			@RequestHeader("projectId") String projectId,
+			@RequestHeader("appId") String appId,
+			@RequestHeader("userId") String userId,
+			@RequestHeader("token") String token,
+			@RequestBody Map<String, Object> params);
+
+	@PostMapping("/datacenter/object/zone/query")
+	OldAdmResult<List<OSpace>> querySpace(
+			@RequestHeader("groupCode") String groupCode,
+			@RequestHeader("projectId") String projectId,
+			@RequestHeader("appId") String appId,
+			@RequestHeader("userId") String userId,
+			@RequestHeader("token") String token,
+			@RequestBody Map<String, Object> params);
+
+	@PostMapping("/datacenter/object/equip/query")
+	OldAdmResult<List<OEquip>> queryEquip(
+			@RequestHeader("groupCode") String groupCode,
+			@RequestHeader("projectId") String projectId,
+			@RequestHeader("appId") String appId,
+			@RequestHeader("userId") String userId,
+			@RequestHeader("token") String token,
+			@RequestBody Map<String, Object> params);
+
+	@GetMapping(value = "/image-service/common/file_get",consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE)
+	Response getFloorMap(@RequestParam String key, @RequestParam String systemId);
+
+}

+ 79 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/client/RwdClient.java

@@ -0,0 +1,79 @@
+package com.persagy.bdtp.adm.client;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.bdtp.adm.entity.InfoDef;
+import com.persagy.bdtp.adm.entity.TypeDef;
+import com.persagy.dmp.basic.config.DigitalFeignConfig;
+import com.persagy.dmp.basic.model.QueryCriteria;
+import com.persagy.dmp.common.model.response.CommonResult;
+import com.persagy.dmp.define.entity.GraphDefine;
+import com.persagy.dmp.define.entity.RelationDefine;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+
+@FeignClient(name = "dmp-rwd", configuration = DigitalFeignConfig.class,
+		url = "${persagy.bdtp.rwd.service:}")
+public interface RwdClient {
+
+	/**
+	 * 查询类型定义
+	 * @param groupCode 集团编码
+	 * @param projectId 项目ID
+	 * @param appId 应用ID
+	 * @param userId 用户ID
+	 * @param criteria 查询条件
+	 * @return 类型定义
+	 */
+	@PostMapping("/rwd/def/class")
+	CommonResult<List<TypeDef>> queryObjectType(
+			@RequestParam("groupCode") String groupCode,
+			@RequestParam("projectId") String projectId,
+			@RequestParam("appId") String appId,
+			@RequestParam("userId") String userId,
+			@RequestBody QueryCriteria criteria);
+
+	@PostMapping("/rwd/def/funcid")
+	CommonResult<List<InfoDef>> queryFunc(
+			@RequestParam("groupCode") String groupCode,
+			@RequestParam("projectId") String projectId,
+			@RequestParam("appId") String appId,
+			@RequestParam("userId") String userId,
+			@RequestBody QueryCriteria criteria);
+
+	/**
+	 * 查询边类型
+	 * @param groupCode: 集团编码
+	 * @param projectId: 项目ID
+	 * @param appId: 应用ID
+	 * @param userId: 用户ID
+	 * @param criteria: 查询条件
+	 * @return 边类型数组
+	 */
+	@PostMapping("/rwd/def/rel/query")
+	CommonResult<List<RelationDefine>> queryRelDef(@RequestParam("groupCode") String groupCode,
+											 @RequestParam("projectId") String projectId,
+											 @RequestParam("appId") String appId,
+											 @RequestParam("userId") String userId,
+											 @RequestBody QueryCriteria criteria);
+
+	@PostMapping("/rwd/def/graph/query")
+	CommonResult<List<GraphDefine>> queryGraphDef(@RequestParam("groupCode") String groupCode,
+														 @RequestParam("projectId") String projectId,
+														 @RequestParam("appId") String appId,
+														 @RequestParam("userId") String userId,
+														 @RequestBody QueryCriteria criteria);
+
+	/**
+	 * 查询关系
+	 */
+	@PostMapping({"/rwd/instance/relation/query"})
+	CommonResult<List<ObjectNode>> queryRelation(@RequestParam("groupCode") String groupCode,
+										 @RequestParam("projectId") String projectId,
+										 @RequestParam("appId") String appId,
+										 @RequestParam("userId") String userId,
+										 @RequestBody QueryCriteria criteria);
+}

+ 61 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/common/AdmConst.java

@@ -0,0 +1,61 @@
+package com.persagy.bdtp.adm.common;
+
+public interface AdmConst {
+
+	String APP_ID = "adm";
+
+	int JOB_STATE_TODO = 0;
+
+	int JOB_STATE_PROCESSING = 1;
+
+	int JOB_STATE_FINISHED = 2;
+
+
+	String OBJ_TYPE_PROJECT = "project";
+
+	String OBJ_TYPE_BUILDING = "building";
+
+	String OBJ_TYPE_FLOOR = "floor";
+
+	String OBJ_TYPE_SPACE = "space";
+
+	String OBJ_TYPE_SHAFT = "shaft";
+
+	String OBJ_TYPE_SYSTEM = "system";
+
+	String OBJ_TYPE_EQUIPMENT = "equipment";
+
+
+	/** 数据创建者,数据同步服务 */
+	String CREATOR_SYNC = APP_ID + "_sync";
+
+	/** 数据创建者,手机app */
+	String CREATOR_APP = APP_ID + "_app";
+
+	/** 数据创建者,web端管理 */
+	String CREATOR_WEB = APP_ID + "_web";
+
+	/** 数据创建者,系统自动计算 */
+	String CREATOR_AUTO = APP_ID + "_auto";
+
+	/** 数据创建者,模型服务(Revit解析) */
+	String CREATOR_M2D_INIT = APP_ID + "_m2d_init";
+
+	/** 数据创建者,模型服务 */
+	String CREATOR_M2D = APP_ID + "_m2d";
+
+
+	String UPLOAD_PROCESSING = "processing";
+
+	String UPLOAD_FINISHED = "finished";
+
+	String UPLOAD_ERROR = "error";
+
+
+	int PIPE_DIRECTION_NONE = 0;
+
+	int PIPE_DIRECTION_FORWARD = 1;
+
+	int PIPE_DIRECTION_BACK = -1;
+
+}

+ 25 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/common/AdmMessageConst.java

@@ -0,0 +1,25 @@
+package com.persagy.bdtp.adm.common;
+
+public interface AdmMessageConst {
+
+    /** 消息-exchange */
+    String ADM_EXCHANGE = "bdtp.adm.topic";
+
+    /** 消息-路由Key 数据->模型 */
+    String ADM_D2M_ROUTING = "bdtp.adm.d2m.routing";
+    /** 队列 数据->模型 */
+    String ADM_D2M_QUEUE = "bdtp.adm.d2m.queue";
+
+
+    /** 消息-路由Key 模型->数据 */
+    String M2D_ROUTING = "bdtp.adm.m2d.routing";
+    /** 队列 模型->数据 */
+    String M2D_QUEUE = "bdtp.adm.m2d.queue";
+
+    String OPERATOR_ADD = "add";
+
+    String OPERATOR_MODIFY = "modify";
+
+    String OPERATOR_REMOVE = "remove";
+
+}

+ 37 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/common/AdmRequest.java

@@ -0,0 +1,37 @@
+package com.persagy.bdtp.adm.common;
+
+import com.persagy.bdtp.adm.entity.UploadData;
+import lombok.Data;
+
+@Data
+public class AdmRequest {
+
+	private String userId;
+
+	private String clientId;
+
+	private String groupCode;
+
+	private String projectId;
+
+
+	private String buildingId;
+
+	private String floorId;
+
+
+	private Long bdtpDownloadTs;
+
+	private Long admDownloadTs;
+
+
+	private UploadData uploadData;
+
+
+	/** 待废弃 */
+	private String lastDownloadTime;
+
+	/** 待废弃 */
+	private String uploadFlag;
+
+}

+ 36 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/common/AdmResult.java

@@ -0,0 +1,36 @@
+package com.persagy.bdtp.adm.common;
+
+import com.persagy.dmp.common.constant.ResponseCode;
+import com.persagy.dmp.common.model.response.CommonResult;
+import lombok.Data;
+
+@Data
+public class AdmResult<T> {
+
+	private String code;
+
+	private String message;
+
+	private T data;
+
+	public AdmResult(String code, String message) {
+		this(code, message, null);
+	}
+
+	public AdmResult(String code, String message, T data) {
+		this.code = code;
+		this.message = message;
+		this.data = data;
+	}
+
+	public AdmResult(CommonResult<T> commonResult) {
+		this.code = commonResult.getResult();
+		this.message = commonResult.getMessage();
+		this.data = commonResult.getData();
+	}
+
+	public static <T> AdmResult<T> success(T data){
+		return new AdmResult<>(ResponseCode.A00000.getCode(), null, data);
+	}
+
+}

+ 23 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/config/AdmCommonConfig.java

@@ -0,0 +1,23 @@
+package com.persagy.bdtp.adm.config;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class AdmCommonConfig {
+
+	/**
+	 *	ObjectMapper默认不输出null值字段
+	 */
+//	@Bean(name = "objectMapper")
+//	public ObjectMapper getObjectMapper(){
+//		ObjectMapper mapper = new ObjectMapper();
+//		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+//		mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+//		return mapper;
+//	}
+
+}

+ 46 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/config/AdmRabbitConfig.java

@@ -0,0 +1,46 @@
+package com.persagy.bdtp.adm.config;
+
+import com.persagy.bdtp.adm.common.AdmMessageConst;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.BindingBuilder;
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.core.TopicExchange;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Slf4j
+@Configuration
+public class AdmRabbitConfig {
+
+    @Bean
+    public TopicExchange m2dExchange() {
+        return new TopicExchange(AdmMessageConst.ADM_EXCHANGE);
+    }
+
+    @Bean
+    public Queue m2dQueue(){
+        return new Queue(AdmMessageConst.M2D_QUEUE);
+    }
+
+    @Bean
+    public Binding m2dBinding() {
+        return BindingBuilder.bind(m2dQueue()).to(m2dExchange()).with(AdmMessageConst.M2D_ROUTING);
+    }
+
+    @Bean
+    public TopicExchange admExchange() {
+        return new TopicExchange(AdmMessageConst.ADM_EXCHANGE);
+    }
+
+    @Bean
+    public Queue admD2mQueue(){
+        return new Queue(AdmMessageConst.ADM_D2M_QUEUE);
+    }
+
+    @Bean
+    public Binding admD2mBinding() {
+        return BindingBuilder.bind(admD2mQueue()).to(admExchange()).with(AdmMessageConst.ADM_D2M_ROUTING);
+    }
+
+}

+ 27 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/config/TestConfig.java

@@ -0,0 +1,27 @@
+package com.persagy.bdtp.adm.config;
+
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.sql.DataSource;
+import java.util.Map;
+
+@Configuration
+@AutoConfigureAfter({DataSourceAutoConfiguration.class})
+public class TestConfig {
+
+	@Bean
+	public String test(ApplicationContext ctx){
+		try {
+			Map map = ctx.getBeansOfType(DataSource.class);
+			System.out.println(map);
+		} catch (Exception var4) {
+
+		}
+		return "";
+	}
+
+}

+ 164 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/controller/AppController.java

@@ -0,0 +1,164 @@
+package com.persagy.bdtp.adm.controller;
+
+import cn.hutool.core.util.StrUtil;
+import com.persagy.bdtp.adm.client.ImageServiceClient;
+import com.persagy.bdtp.adm.client.OldAdmClient;
+import com.persagy.bdtp.adm.common.AdmRequest;
+import com.persagy.bdtp.adm.common.AdmResult;
+import com.persagy.bdtp.adm.datatx.DataTxHandler;
+import com.persagy.bdtp.adm.entity.Dict;
+import com.persagy.bdtp.adm.entity.DownLoadData;
+import com.persagy.bdtp.adm.entity.UploadRtn;
+import com.persagy.bdtp.adm.service.ISyncApp;
+import com.persagy.bdtp.adm.service.ServiceUtil;
+import feign.Response;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/adm")
+public class AppController {
+
+	@Autowired
+	private ImageServiceClient imageServiceClient;
+
+	@Autowired
+	private OldAdmClient admClient;
+
+	@Autowired
+	@Qualifier(ServiceUtil.SYNC_APP_IMPL)
+	private ISyncApp syncApp;
+
+	@Autowired
+	private DataTxHandler dataTxHandler;
+
+	@RequestMapping("/clientId")
+	public AdmResult<Map<String, Object>> clientId(@RequestBody AdmRequest req){
+		HashMap<String, Object> rtn = new HashMap<>();
+		rtn.put("clientId", syncApp.getClientId(req.getUserId()));
+		return AdmResult.success(rtn);
+	}
+
+	@RequestMapping("/dict")
+	public AdmResult<Dict> dict(@RequestBody AdmRequest req){
+		return AdmResult.success(syncApp.downloadDict(req.getGroupCode(), req.getProjectId(), req.getUserId()));
+	}
+
+	@RequestMapping("/config")
+	public AdmResult<Map<String, Object>> config(@RequestBody AdmRequest req){
+		return AdmResult.success(syncApp.downloadConfig(req.getGroupCode(), req.getProjectId(), req.getUserId()));
+	}
+
+	@RequestMapping("/frame")
+	public AdmResult<Map<String, Object>> frame(@RequestBody AdmRequest req){
+//		ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+//
+//		List<ObjectNode> prjList = ServiceUtil.call(() -> objClient.query(req.getGroupCode(), req.getProjectId(), AdmConst.APP_ID, req.getUserId(), getQueryCriteria("project", objectMapper)));
+//
+//		//建筑和楼层,暂时从dbtp获取
+//		List<ObjectNode> bdList = ServiceUtil.call(() -> objClient.query(req.getGroupCode(), req.getProjectId(), AdmConst.APP_ID, req.getUserId(), getQueryCriteria("building", objectMapper)));
+//
+//		QueryCriteria flCriteria = getQueryCriteria("floor", objectMapper);
+//		flCriteria.getCriteria().putObject("relationTo").put("graphCode", "ArchSubset").put("relCode", "Bd2Fl");
+//		List<ObjectNode> flList = ServiceUtil.call(() -> objClient.query(req.getGroupCode(), req.getProjectId(), AdmConst.APP_ID, req.getUserId(), flCriteria));
+//
+//		QueryCriteria relCriteria = getQueryCriteria(null, objectMapper);
+//		relCriteria.getCriteria().put("graphCode", "ArchSubset").put("relCode", "Bd2Fl");
+//		List<ObjectRelation> relList = ServiceUtil.call(() -> relationClient.query(req.getGroupCode(), req.getProjectId(), AdmConst.APP_ID, req.getUserId(), relCriteria));
+//
+//		//为楼层数据设置buildingId
+//		for(ObjectNode n : flList){
+//			String flId = n.get("id").asText();
+//			for(ObjectRelation r : relList){
+//				if(r.getObjTo().equals(flId)){
+//					n.put("buildingId", r.getObjFrom());
+//					relList.remove(r);
+//					break;
+//				}
+//			}
+//		}
+//
+//		HashMap<String, Object> data = new HashMap<>();
+//		data.put("projects", prjList);
+//		data.put("buildings", bdList);
+//		data.put("floors", flList);
+//		return AdmResult.success(data);
+
+		return AdmResult.success(syncApp.downloadFrameData(req.getGroupCode(), req.getProjectId(), req.getUserId()));
+	}
+
+	@RequestMapping("/download")
+	public AdmResult<DownLoadData> download(@RequestBody AdmRequest req){
+		DownLoadData data;
+		if(StrUtil.isNotBlank(req.getBuildingId())) {
+			if(ServiceUtil.SYNC_APP_IMPL.equals("syncAppImpl")) //临时兼容
+				data = syncApp.downloadBuildingData(req.getGroupCode(), req.getProjectId(), req.getUserId(), req.getClientId(), req.getBuildingId(), req.getBdtpDownloadTs(), req.getAdmDownloadTs());
+			else
+				data = syncApp.downloadBuildingData(req.getProjectId(), req.getBuildingId(), req.getUploadFlag(), req.getLastDownloadTime());
+		} else
+			data = syncApp.downloadProjectData(req.getGroupCode(), req.getProjectId(), req.getUserId(), req.getClientId(), req.getBdtpDownloadTs(), req.getAdmDownloadTs());
+		return AdmResult.success(data);
+	}
+
+//	@RequestMapping("/downloadFl")
+//	public AdmResult<Map<String, Object>> downloadFl(@RequestBody AdmRequest req){
+//		return AdmResult.success(syncApp.downloadFloorData(req.getProjectId(), req.getFloorId(), req.getUploadFlag(), req.getLastDownloadTime()));
+//	}
+
+	@RequestMapping("/downloadMap")
+	public void downloadMap(HttpServletRequest request, HttpServletResponse response, @RequestParam String key){
+		InputStream inputStream = null;
+		try {
+			Response serviceResponse;
+			if(ServiceUtil.SYNC_APP_IMPL.equals("syncAppImpl")) //临时兼容
+				serviceResponse = imageServiceClient.fileGet(key, "revit");
+			else
+				serviceResponse = admClient.getFloorMap(key, "revit");
+
+			Response.Body body = serviceResponse.body();
+
+			inputStream = body.asInputStream();
+			BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
+			Object o = serviceResponse.headers().get("Content-Disposition");
+			String contentDisposition = o != null ? o.toString().replace("[","").replace("]","") : "attachment;filename=map.jsonz";
+			response.setHeader("Content-Disposition", contentDisposition);
+			BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(response.getOutputStream());
+			int length = 0;
+			byte[] temp = new byte[1024 * 10];
+			while ((length = bufferedInputStream.read(temp)) != -1) {
+				bufferedOutputStream.write(temp, 0, length);
+			}
+			bufferedOutputStream.flush();
+			bufferedOutputStream.close();
+			bufferedInputStream.close();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+	@RequestMapping("/upload")
+	public AdmResult<UploadRtn> upload(HttpServletRequest request){
+		AdmRequest admRequest = dataTxHandler.handleRequest(request);
+		if(ServiceUtil.SYNC_APP_IMPL.equals("syncAppImpl")) //临时兼容
+			return AdmResult.success(syncApp.uploadData(admRequest.getUploadData(), admRequest.getGroupCode(), admRequest.getProjectId(), admRequest.getUserId(), admRequest.getClientId()));
+		else
+			return AdmResult.success(syncApp.uploadData(admRequest.getUploadData(), admRequest.getGroupCode(), admRequest.getProjectId(), admRequest.getUserId(), admRequest.getUploadFlag()));
+	}
+
+	@PostMapping("/uploadFile")
+	public AdmResult uploadFile(){
+		//TODO
+		return null;
+	}
+
+}

+ 43 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/controller/ManageController.java

@@ -0,0 +1,43 @@
+package com.persagy.bdtp.adm.controller;
+
+import com.persagy.bdtp.adm.common.AdmRequest;
+import com.persagy.bdtp.adm.common.AdmResult;
+import com.persagy.bdtp.adm.service.ISyncOldAdm;
+import com.persagy.bdtp.adm.service.ISyncSpace;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+@CrossOrigin
+@RestController
+@RequestMapping("/manage")
+public class ManageController {
+
+	@Autowired
+	private ISyncOldAdm syncOldAdm;
+
+	@Autowired
+	private ISyncSpace syncSpace;
+
+	@RequestMapping("/syncOldAdm")
+	public AdmResult<Object> syncOldAdm(@RequestBody AdmRequest req){
+		String groupCode = req.getGroupCode();
+		String projectId = req.getProjectId();
+
+		Map<String, Object> syncResult = syncOldAdm.syncData(groupCode, projectId);
+		syncOldAdm.handleJobSpace(projectId);
+		syncOldAdm.uploadFloorMap(groupCode, projectId);
+		return AdmResult.success(syncResult);
+	}
+
+	@RequestMapping("/syncSpace")
+	public AdmResult<Object> syncSpace(@RequestBody AdmRequest req){
+		Map<String, Object> syncResult = syncSpace.sync(req.getGroupCode(), req.getProjectId(), req.getUserId(), req.getFloorId(), "GeneralZone");
+		return AdmResult.success(syncResult);
+	}
+
+}

+ 359 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/controller/ToolController.java

@@ -0,0 +1,359 @@
+package com.persagy.bdtp.adm.controller;
+
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.bdtp.adm.client.RwdClient;
+import com.persagy.bdtp.adm.common.AdmConst;
+import com.persagy.bdtp.adm.common.AdmRequest;
+import com.persagy.bdtp.adm.common.AdmResult;
+import com.persagy.bdtp.adm.dao.*;
+import com.persagy.bdtp.adm.entity.*;
+import com.persagy.bdtp.adm.entity.db.*;
+import com.persagy.bdtp.adm.service.IConfigService;
+import com.persagy.bdtp.adm.service.ISyncApp;
+import com.persagy.bdtp.adm.service.ServiceUtil;
+import com.persagy.dmp.basic.model.QueryCriteria;
+import com.persagy.dmp.common.constant.ResponseCode;
+import com.persagy.dmp.common.exception.BusinessException;
+import com.persagy.dmp.define.entity.GraphDefine;
+import com.persagy.dmp.define.entity.RelationDefine;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.*;
+
+@CrossOrigin
+@RestController
+@RequestMapping("/tool")
+public class ToolController {
+
+	@Autowired
+	private ObjectMapper objectMapper;
+
+	@Autowired
+	@Qualifier(ServiceUtil.SYNC_APP_IMPL)
+	private ISyncApp syncApp;
+
+	@Autowired
+	private RwdClient rwdClient;
+
+	@Autowired
+	private IConfigService configService;
+
+	@Autowired
+	private AdmM2dEquipMapper m2dEquipMapper;
+
+	@GetMapping("/hello")
+	public AdmResult<Integer> hello(){
+		return AdmResult.success(configService.queryCommonConfig(null).size());
+	}
+
+	@RequestMapping("/dict")
+	public AdmResult<Dict> dict(@RequestBody AdmRequest req, @RequestParam(required = false) String module){
+		Dict map = syncApp.queryDict(req.getGroupCode(), req.getProjectId(), req.getUserId(), !"infos".equals(module), false);
+
+		List<Map<String, Object>> majorList = map.getMajor();
+		List<TypeDef> sysList = map.getSystem();
+		List<TypeDef> equipList = map.getEquipment();
+		distinct(sysList);
+		distinct(equipList);
+
+		clearTime(majorList);
+		clearTime(sysList);
+		clearTime(equipList);
+
+		//设置正向交付类型
+		List<AdmM2dEquip> m2dList = configService.queryM2dEquip(req.getProjectId());
+		HashSet<String> m2dSet = new HashSet<>();
+		m2dList.forEach(item -> m2dSet.add(item.getClassCode()));
+		for(TypeDef eqType : equipList) {
+			if(m2dSet.contains(eqType.getCode()))
+				eqType.setM2d(true);
+		}
+
+		//组织专业-系统树形结构
+		for(Map<String, Object> major : majorList){
+			ArrayList<TypeDef> childrenSys = new ArrayList<>();
+			major.put("children", childrenSys);
+			String majorCode = (String) major.get("code");
+			for(Iterator<TypeDef> sysIter = sysList.iterator(); sysIter.hasNext();){
+				TypeDef sysDef = sysIter.next();
+				if(sysDef.getMajorCode() != null && sysDef.getMajorCode().equals(majorCode)){
+					childrenSys.add(sysDef);
+					sysIter.remove();
+				}
+			}
+		}
+		map.setSystem(null);
+
+		if("infos".equals(module)) { //信息点配置
+
+		} else { //关系、管道、无模型设备
+			List<RelationDefine> relDefs = (List<RelationDefine>)map.getRelation();
+			List<GraphDefine> graph = ServiceUtil.call (() -> rwdClient.queryGraphDef(req.getGroupCode(), req.getProjectId(), AdmConst.APP_ID, req.getUserId(), new QueryCriteria()));
+			List<Map<String, Object>> rels = new ArrayList<>();
+			for(GraphDefine gd : graph){
+				HashMap<String, Object> m = new HashMap<>();
+				m.put("code", gd.getCode());
+				m.put("name", gd.getName());
+				m.put("type", "graph");
+				rels.add(m);
+
+				ArrayList<RelationDefine> chidren = new ArrayList<>();
+				m.put("children", chidren);
+				for(RelationDefine relDef : relDefs) {
+					if(relDef.getGraphCode().equals(gd.getCode()))
+						chidren.add(relDef);
+				}
+			}
+			map.setRelation(rels);
+		}
+
+		return AdmResult.success(map);
+	}
+
+	private <T> void distinct(List<T> list){
+		List<T> result = new ArrayList<>();
+		HashSet<String> codes = new HashSet<>();
+		for(T def : list) {
+			String code = null;
+			if(def instanceof TypeDef)
+				code = ((TypeDef) def).getCode();
+			else if(def instanceof InfoDef)
+				code = ((InfoDef) def).getCode();
+			if(!codes.contains(code)) {
+				codes.add(code);
+				result.add(def);
+			}
+		}
+		list.clear();
+		list.addAll(result);
+	}
+
+	private void clearTime(List<?> list){
+		for(Object o : list) {
+			if(o instanceof TypeDef) {
+				((TypeDef) o).setCreationTime(null);
+				((TypeDef) o).setModifiedTime(null);
+			} else if(o instanceof Map) {
+				((Map) o).put("creationTime", null);
+				((Map) o).put("modifiedTime", null);
+				((Map) o).put("name", ((Map) o).get("label")); //handle major
+			}
+		}
+	}
+
+	@RequestMapping("/cfgs")
+	public AdmResult<Object> cfgs(@RequestBody AdmRequest req, @RequestParam(required = false) String module){
+		String projectId = req.getProjectId();
+		HashMap<String, Object> data = new HashMap<>();
+
+		//配置数据查询
+		if("infos".equals(module)) { //信息点配置
+			List<AdmInfosConfig> infoConfig = configService.queryInfosConfig(projectId);
+			data.put("infoConfig", infoConfig);
+		} else {
+			List<AdmRelsConfig> relConfig = configService.queryRelsConfig(projectId);
+			List<AdmPipeConfig> pipeConfig = configService.queryPipeConfig(projectId);
+			List<AdmContainerConfig> containerConfig = configService.queryContainerConfig(projectId);
+
+			data.put("relConfig", relConfig);
+			data.put("pipeConfig", pipeConfig);
+			data.put("containerConfig", containerConfig);
+		}
+
+		return AdmResult.success(data);
+	}
+
+	@RequestMapping("/typeInfos")
+	public AdmResult<Object> typeInfos(@RequestBody AdmRequest req, @RequestParam String typeCode){
+		QueryCriteria criteria = new QueryCriteria();
+		ObjectNode node = objectMapper.createObjectNode();
+		node.put("classCode", typeCode);
+		criteria.setCriteria(node);
+
+		List<Object> roots = new ArrayList<>();
+
+		List<InfoDef> funcList = ServiceUtil.call(() -> rwdClient.queryFunc(req.getGroupCode(), req.getProjectId(), AdmConst.APP_ID, req.getUserId(), criteria));
+		distinct(funcList);
+		for(InfoDef infoDef : funcList) {
+			if("交付工具".equals(infoDef.getFirstTag()))
+				continue;
+			buildInfosTree(roots, infoDef);
+		}
+
+		return AdmResult.success(roots);
+	}
+
+	private void buildInfosTree(List<Object> roots, InfoDef infoDef){
+		Map<String, Object> folder = null;
+		if(StrUtil.isNotBlank(infoDef.getFirstTag())) {
+			folder = findParent(roots, infoDef.getFirstTag());
+			if(StrUtil.isNotBlank(infoDef.getSecondTag())){
+				folder = findParent((List<Object>) folder.get("children"), infoDef.getSecondTag());
+			}
+		}
+		if(folder == null)
+			roots.add(infoDef);
+		else
+			((List<Object>) folder.get("children")).add(infoDef);
+	}
+
+	private Map<String, Object> findParent(List<Object> list, String tag){
+		for(Object o : list){
+			if(o instanceof Map){
+				if(tag.equals(((Map) o).get("code")))
+					return (Map<String, Object>) o;
+			}
+		}
+
+		Map<String, Object> p = new HashMap<>();
+		p.put("code", tag);
+		p.put("name", tag);
+		p.put("info_tag", true);
+		p.put("children", new ArrayList<>());
+		list.add(p);
+		return p;
+	}
+
+	@Autowired
+	private AdmRelsConfigMapper relsConfigMapper;
+	@Autowired
+	private AdmPipeConfigMapper pipeConfigMapper;
+	@Autowired
+	private AdmContainerConfigMapper containerConfigMapper;
+
+	@PostMapping("/updateCfgItem")
+	public AdmResult<Object> updateCfgItem(@RequestBody Map<String, Object> content) {
+		String type = (String) content.get("type");
+		Map<String, Object> itemMap = (Map<String, Object>) content.get("item");
+		String delId = (String) content.get("delId");
+		String newId = null;
+		if(itemMap != null && !itemMap.containsKey("id")){
+			newId = IdUtil.fastSimpleUUID();
+			itemMap.put("id", newId);
+		}
+
+		boolean create = newId != null;
+		if("rel".equals(type)) {
+			doUpdateItem(delId, itemMap, create, AdmRelsConfig.class, relsConfigMapper);
+		} else if ("pipe".equals(type)) {
+			doUpdateItem(delId, itemMap, create, AdmPipeConfig.class, pipeConfigMapper);
+		} else if("container".equals(type)) {
+			doUpdateItem(delId, itemMap, create, AdmContainerConfig.class, containerConfigMapper);
+		}
+
+		return AdmResult.success(newId);
+	}
+	
+	private <T extends BaseAdmEntity> void doUpdateItem(String delId, Map<String, Object> itemMap, boolean create, Class<T> cls, BaseMapper<T> mapper){
+		if(StrUtil.isNotBlank(delId))
+			mapper.deleteById(delId);
+		else {
+			T cfg = mapToObj(itemMap, cls);
+			if(create)
+				mapper.insert(cfg);
+			else
+				mapper.updateById(cfg);
+		}
+	}
+
+	private <T extends BaseAdmEntity> T mapToObj(Map<String, Object> map, Class<T> cls){
+		try {
+			String json = objectMapper.writeValueAsString(map);
+			return objectMapper.readValue(json, cls);
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw new BusinessException(ResponseCode.A0427.getCode(), ResponseCode.A0427.getDesc());
+		}
+	}
+
+	@Autowired
+	private AdmInfosConfigMapper infosConfigMapper;
+
+	@PostMapping("/updateInfos")
+	public AdmResult<Object> updateInfos(@RequestBody AdmInfosConfig cfg) {
+		String newId = null;
+		if(StrUtil.isBlank(cfg.getId())){
+			newId = IdUtil.fastSimpleUUID();
+			cfg.setId(newId);
+		}
+		if(cfg.getInfos() != null) {
+			for(Object o : cfg.getInfos()) {
+				if(o instanceof Map){
+					((Map<?, ?>) o).remove("name");
+					((Map<?, ?>) o).remove("cfgItemType");
+				}
+			}
+		}
+
+		if(newId != null)
+			infosConfigMapper.insert(cfg);
+		else
+			infosConfigMapper.updateById(cfg);
+
+		return AdmResult.success(newId);
+	}
+
+	@PostMapping("/updateM2d")
+	public AdmResult<Object> updateM2d(@RequestBody Map<String, Object> cfg){
+		String code = (String) cfg.get("code");
+		boolean m2d = (Boolean)cfg.get("m2d");
+		AdmM2dEquip item = m2dEquipMapper.selectOne(new QueryWrapper<AdmM2dEquip>().eq("class_code", code));
+		if(m2d){
+			if(item == null){
+				item = new AdmM2dEquip();
+				item.setId(IdUtil.simpleUUID());
+				item.setClassCode(code);
+				m2dEquipMapper.insert(item);
+			}
+		} else {
+			if(item != null)
+				m2dEquipMapper.deleteById(item.getId());
+		}
+		return AdmResult.success(null);
+	}
+
+	@PostMapping("/bdAndFls")
+	public AdmResult<List<ObjectNode>> bdAndFls(@RequestBody AdmRequest req){
+		Map<String, Object> data = syncApp.downloadFrameData(req.getGroupCode(), req.getProjectId(), req.getUserId());
+		List<ObjectNode> bdAndFls = (List<ObjectNode>)data.get("buildingsAndFloors");
+
+		List<ObjectNode> bds = new ArrayList<>();
+		Iterator<ObjectNode> iter = bdAndFls.iterator();
+		while (iter.hasNext()){
+			ObjectNode node = iter.next();
+			if(AdmConst.OBJ_TYPE_BUILDING.equals(node.get("objType").asText())) {
+				bds.add(node);
+				iter.remove();
+			}
+		}
+
+		for(ObjectNode bd : bds) {
+			String id = bd.get("id").asText();
+			for(ObjectNode fl : bdAndFls) {
+				JsonNode node = fl.get("buildingId");
+				if(node != null){
+					String bdId = node.asText();
+					if(bdId.equals(id)){
+						ArrayNode children = (ArrayNode)bd.get("children");
+						if(children == null)
+							children = bd.putArray("children");
+						children.add(fl);
+					}
+				}
+			}
+		}
+
+		return AdmResult.success(bds);
+	}
+
+}

+ 10 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmClientFlagMapper.java

@@ -0,0 +1,10 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmClientFlag;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface AdmClientFlagMapper extends BaseMapper<AdmClientFlag> {
+
+}

+ 10 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmComponentMapper.java

@@ -0,0 +1,10 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmComponent;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface AdmComponentMapper extends BaseMapper<AdmComponent> {
+
+}

+ 8 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmConfigMapper.java

@@ -0,0 +1,8 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmConfig;
+
+public interface AdmConfigMapper extends BaseMapper<AdmConfig> {
+
+}

+ 10 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmContainerConfigMapper.java

@@ -0,0 +1,10 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmContainerConfig;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface AdmContainerConfigMapper extends BaseMapper<AdmContainerConfig> {
+
+}

+ 8 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmFileMapper.java

@@ -0,0 +1,8 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmFile;
+
+public interface AdmFileMapper extends BaseMapper<AdmFile> {
+
+}

+ 10 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmInfosConfigMapper.java

@@ -0,0 +1,10 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmInfosConfig;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface AdmInfosConfigMapper extends BaseMapper<AdmInfosConfig> {
+
+}

+ 8 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmJobSpaceMapper.java

@@ -0,0 +1,8 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmJobSpace;
+
+public interface AdmJobSpaceMapper extends BaseMapper<AdmJobSpace> {
+
+}

+ 8 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmM2dEquipMapper.java

@@ -0,0 +1,8 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmM2dEquip;
+
+public interface AdmM2dEquipMapper extends BaseMapper<AdmM2dEquip> {
+
+}

+ 11 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmMessagePMapper.java

@@ -0,0 +1,11 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmJobSpace;
+import com.persagy.bdtp.adm.entity.db.AdmMessageP;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface AdmMessagePMapper extends BaseMapper<AdmMessageP> {
+
+}

+ 10 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmObjectMapper.java

@@ -0,0 +1,10 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmObject;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface AdmObjectMapper extends BaseMapper<AdmObject> {
+
+}

+ 10 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmPipeConfigMapper.java

@@ -0,0 +1,10 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmPipeConfig;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface AdmPipeConfigMapper extends BaseMapper<AdmPipeConfig> {
+
+}

+ 10 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmPipeMapper.java

@@ -0,0 +1,10 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmPipe;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface AdmPipeMapper extends BaseMapper<AdmPipe> {
+
+}

+ 8 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmProblemArchMapper.java

@@ -0,0 +1,8 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmProblemArch;
+
+public interface AdmProblemArchMapper extends BaseMapper<AdmProblemArch> {
+
+}

+ 8 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmProblemEquipMapper.java

@@ -0,0 +1,8 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmProblemEquip;
+
+public interface AdmProblemEquipMapper extends BaseMapper<AdmProblemEquip> {
+
+}

+ 8 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmQrCodeMapper.java

@@ -0,0 +1,8 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmQrCode;
+
+public interface AdmQrCodeMapper extends BaseMapper<AdmQrCode> {
+
+}

+ 8 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmRelationMapper.java

@@ -0,0 +1,8 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmRelation;
+
+public interface AdmRelationMapper extends BaseMapper<AdmRelation> {
+
+}

+ 10 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmRelsConfigMapper.java

@@ -0,0 +1,10 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmRelsConfig;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface AdmRelsConfigMapper extends BaseMapper<AdmRelsConfig> {
+
+}

+ 8 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmServeAreaMapper.java

@@ -0,0 +1,8 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmServeArea;
+
+public interface AdmServeAreaMapper extends BaseMapper<AdmServeArea> {
+
+}

+ 10 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmUploadJobMapper.java

@@ -0,0 +1,10 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmUploadJob;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface AdmUploadJobMapper extends BaseMapper<AdmUploadJob> {
+
+}

+ 14 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/dao/AdmUploadLogMapper.java

@@ -0,0 +1,14 @@
+package com.persagy.bdtp.adm.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.bdtp.adm.entity.db.AdmUploadLog;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface AdmUploadLogMapper extends BaseMapper<AdmUploadLog> {
+
+//	@Override
+//	@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
+//	int insert(AdmUploadLog entity);
+
+}

+ 53 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/datatx/DataTxHandler.java

@@ -0,0 +1,53 @@
+package com.persagy.bdtp.adm.datatx;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.persagy.bdtp.adm.common.AdmRequest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.GZIPInputStream;
+
+/**
+ * 数据传输帮助类
+ */
+@Component
+public class DataTxHandler {
+
+	private final ObjectMapper objectMapper;
+
+	@Autowired
+	public DataTxHandler(ObjectMapper objectMapper) {
+		this.objectMapper = objectMapper;
+	}
+
+	/**
+	 * 处理上传请求的gzip压缩数据
+	 */
+	public AdmRequest handleRequest(HttpServletRequest req) {
+		try {
+			InputStream in = req.getInputStream();
+			String contentEncoding = req.getHeader("Content-Encoding");
+			if (contentEncoding != null && contentEncoding.indexOf("gzip") >= 0) {
+				GZIPInputStream gzipInputStream = new GZIPInputStream(in);
+				in = gzipInputStream;
+			}
+
+			ByteArrayOutputStream out = new ByteArrayOutputStream();
+			byte[] buffer = new byte[1024];
+			int n;
+			while ((n = in.read(buffer)) >= 0) {
+				out.write(buffer, 0, n);
+			}
+
+			String json = new String(out.toByteArray(), "UTF-8");
+			return objectMapper.readValue(json, AdmRequest.class);
+		} catch (IOException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+}

+ 8 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/datatx/ObjectForTx.java

@@ -0,0 +1,8 @@
+package com.persagy.bdtp.adm.datatx;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+@JsonIgnoreProperties({"grouping", "groupCode", "projectId", "buildingId", "uploadFlag", "clientDevice", "clientId", "d2mState", "deliveryState"})
+public interface ObjectForTx {
+
+}

+ 55 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/datatx/ObjectMapper4Tx.java

@@ -0,0 +1,55 @@
+package com.persagy.bdtp.adm.datatx;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.persagy.bdtp.adm.entity.db.AdmObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 针对数据传输的ObjectMapper,过滤字段
+ */
+@Component
+public class ObjectMapper4Tx {
+
+	private final ObjectMapper objectMapper;
+
+	private ObjectMapper mapper;
+
+	@Autowired
+	public ObjectMapper4Tx(ObjectMapper objectMapper) {
+		this.objectMapper = objectMapper;
+		configCommonMapper();
+
+		this.mapper = new ObjectMapper();
+		configMapper();
+	}
+
+	private void configCommonMapper(){
+		objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+	}
+
+	private void configMapper(){
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
+
+		//设置实体的传输字段
+		mapper.addMixIn(AdmObject.class, ObjectForTx.class);
+
+	}
+
+	public ObjectMapper mapper() {
+		return mapper;
+	}
+
+	public String toJson(Object obj){
+		try{
+			return mapper.writeValueAsString(obj);
+		}catch (JsonProcessingException e){
+			throw new RuntimeException(e);
+		}
+	}
+
+}

+ 53 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/BuildingData.java

@@ -0,0 +1,53 @@
+package com.persagy.bdtp.adm.entity;
+
+import cn.hutool.core.collection.CollUtil;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.bdtp.adm.entity.db.*;
+import com.persagy.dmp.common.model.entity.BaseEntity;
+import com.persagy.dmp.digital.entity.ObjectRelation;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 按建筑下载的数据结构
+ */
+@Data
+public class BuildingData extends DownLoadData {
+
+	private String buildingId;
+
+	private List objects;
+
+	/** 按建筑筛选关系比较困难,待定 */
+	private List relations;
+
+	private List<AdmPipe> pipes;
+
+	private List<AdmJobSpace> jobSpace;
+
+	private List<AdmProblemArch> problemArch;
+
+	private List<AdmProblemEquip> problemEquip;
+
+	private List<AdmFile> file;
+
+	private List<AdmQrCode> qrCode;
+
+	private List<AdmServeArea> serveArea;
+
+	/** 待废弃 */
+	private String timestamp;
+
+	@Override
+	public void buildDownloadTs() {
+		long ts = getMaxTs(objects, relations);
+		if(ts > 0)
+			bdtpDownloadTs = ts;
+
+		ts = getMaxTs(pipes, jobSpace, problemArch, problemEquip, file, qrCode, serveArea);
+		if(ts > 0)
+			admDownloadTs = ts;
+	}
+
+}

+ 58 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/D2mMessage.java

@@ -0,0 +1,58 @@
+package com.persagy.bdtp.adm.entity;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.IdUtil;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+public class D2mMessage {
+
+	private String groupCode;
+
+	private String projectId;
+
+	private String id;
+
+	private String itemType; //object|relation|pipe
+
+	private List<Object> addItems;
+
+	private List<Object> modifyItems;
+
+	private List<Object> removeItems;
+
+	public D2mMessage(String itemType, String groupCode, String projectId) {
+		this.id = IdUtil.simpleUUID();
+		this.itemType = itemType;
+		this.groupCode = groupCode;
+		this.projectId = projectId;
+	}
+
+	public void appendAddItem(Object item){
+		if (addItems == null)
+			addItems = new ArrayList<>();
+		addItems.add(item);
+	}
+
+	public void appendModifyItem(Object item){
+		if (modifyItems == null)
+			modifyItems = new ArrayList<>();
+		modifyItems.add(item);
+	}
+
+	public void appendRemoveItem(Object item){
+		if (removeItems == null)
+			removeItems = new ArrayList<>();
+		removeItems.add(item);
+	}
+
+	@JsonIgnore
+	public boolean isNotEmpty(){
+		return CollUtil.isNotEmpty(addItems) || CollUtil.isNotEmpty(modifyItems) || CollUtil.isNotEmpty(removeItems);
+	}
+
+}

+ 25 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/Dict.java

@@ -0,0 +1,25 @@
+package com.persagy.bdtp.adm.entity;
+
+import com.persagy.dmp.define.entity.RelationDefine;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 下载数据字典
+ */
+@Data
+public class Dict {
+
+	private List<Map<String, Object>> major;
+
+	private List<TypeDef> system;
+
+	private List<TypeDef> equipment;
+
+	private List<? extends Object> relation;
+
+	private List<InfoDef> infos;
+
+}

+ 55 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/DownLoadData.java

@@ -0,0 +1,55 @@
+package com.persagy.bdtp.adm.entity;
+
+import cn.hutool.core.collection.CollUtil;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.bdtp.adm.entity.db.BaseAdmDataEntity;
+import com.persagy.dmp.common.model.entity.BaseEntity;
+import com.persagy.dmp.digital.entity.ObjectRelation;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 下载数据结构基类
+ */
+@Data
+abstract public class DownLoadData {
+
+	/** bdtp数据库下载同步时间戳 */
+	protected Long bdtpDownloadTs;
+
+	/** adm数据库下载同步时间戳 */
+	protected Long admDownloadTs;
+
+	abstract public void buildDownloadTs();
+
+	private long max(List<?> list, long maxTs) {
+		if(CollUtil.isNotEmpty(list)) {
+			for (Object data : list) {
+				long ts = -1;
+				if(data instanceof BaseAdmDataEntity) {
+					if(((BaseAdmDataEntity) data).getTs() != null )
+						ts = ((BaseAdmDataEntity) data).getTs().getTime();
+				} else if(data instanceof ObjectNode){
+					if(((ObjectNode) data).get("ts") != null)
+						ts = ((ObjectNode) data).get("ts").asLong();
+				} else if(data instanceof BaseEntity) {
+					if(((ObjectRelation) data).getTs() != null)
+						ts = ((ObjectRelation) data).getTs().getTime();
+				}
+				if(ts > maxTs)
+					maxTs = ts;
+			}
+		}
+		return maxTs;
+	}
+
+	protected long getMaxTs(List<?>... lists) {
+		long maxTs = -1;
+		for(List<?> list : lists) {
+			maxTs = max(list, maxTs);
+		}
+		return maxTs;
+	}
+
+}

+ 43 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/InfoDef.java

@@ -0,0 +1,43 @@
+package com.persagy.bdtp.adm.entity;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import lombok.Data;
+
+@Data
+public class InfoDef {
+
+	private String groupCode;
+
+	private String projectId;
+
+	private String code;
+
+	private String name;
+
+	private String aliasCode;
+
+//	private String aliasName;
+
+	private String classCode;
+
+	private String firstTag;
+
+	private String secondTag;
+
+//	private String inputMode;
+
+	private String unit;
+
+	private String dataType;
+
+//	private Boolean isMultiple = false;
+
+//	private Boolean isRegion = false;
+
+	private ArrayNode dataSource;
+
+	private Long showOrder;
+
+	private String version;
+
+}

+ 31 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/Pagination.java

@@ -0,0 +1,31 @@
+package com.persagy.bdtp.adm.entity;
+
+import lombok.Data;
+
+/**
+ * 调用服务时记录分页信息
+ */
+@Data
+public class Pagination {
+
+	private int pageNum = 1;
+
+	private int pageSize;
+
+	private int total = -1;
+
+	private boolean hasNext = true;
+
+	public Pagination(int pageSize) {
+		this.pageSize = pageSize;
+	}
+
+	public void next() {
+		pageNum++;
+		if ((pageNum - 1) * pageSize >= total)
+			hasNext = false;
+		else
+			hasNext = true;
+	}
+
+}

+ 22 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/ProjectData.java

@@ -0,0 +1,22 @@
+package com.persagy.bdtp.adm.entity;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 按项目下载的数据结构
+ */
+@Data
+public class ProjectData extends DownLoadData {
+
+	/** 项目下的关系数据 */
+	private List<?> relations;
+
+	public void buildDownloadTs() {
+		long ts = getMaxTs(relations);
+		if(ts > 0)
+			bdtpDownloadTs = ts;
+	}
+
+}

+ 30 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/TypeDef.java

@@ -0,0 +1,30 @@
+package com.persagy.bdtp.adm.entity;
+
+import com.persagy.dmp.define.entity.ObjectTypeDefine;
+import lombok.Data;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * 类型定义,封装children操作,支持树形结构
+ */
+@Data
+public class TypeDef extends ObjectTypeDefine {
+
+	/** 正向交付设备类标注 */
+	private boolean m2d;
+
+	private List<TypeDef> children;
+
+	public void addChild(TypeDef child){
+		if(children == null)
+			children = new LinkedList<>();
+		children.add(child);
+	}
+
+	public List<? extends TypeDef> getChildren() {
+		return children;
+	}
+
+}

+ 52 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/UploadData.java

@@ -0,0 +1,52 @@
+package com.persagy.bdtp.adm.entity;
+
+import cn.hutool.core.collection.CollUtil;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.bdtp.adm.entity.db.*;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 上传的数据结构
+ */
+@Data
+public class UploadData {
+
+	/** 上传任务id */
+	private String uploadJobId;
+
+	private List<ObjectNode> objects;
+
+	private List<ObjectNode> relations;
+
+	private List<AdmPipe> pipes;
+
+	private List<AdmJobSpace> jobSpace;
+
+	private List<AdmProblemArch> problemArch;
+
+	private List<AdmProblemEquip> problemEquip;
+
+	private List<AdmFile> file;
+
+	private List<AdmQrCode> qrCode;
+
+
+	/** 待废弃 */
+	private List<AdmServeArea> serveArea;
+
+	/** 待废弃 */
+	private String buildingId;
+
+
+	public boolean notEmpty() {
+		return CollUtil.isNotEmpty(objects) || CollUtil.isNotEmpty(relations)
+				|| CollUtil.isNotEmpty(pipes)
+				|| CollUtil.isNotEmpty(jobSpace)
+				|| CollUtil.isNotEmpty(problemArch) || CollUtil.isNotEmpty(problemEquip)
+				|| CollUtil.isNotEmpty(file) || CollUtil.isNotEmpty(qrCode)
+				|| CollUtil.isNotEmpty(serveArea);
+	}
+
+}

+ 42 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/UploadRtn.java

@@ -0,0 +1,42 @@
+package com.persagy.bdtp.adm.entity;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class UploadRtn {
+
+	private List<String> expiredObjectIds;
+
+	private List<String> expiredRelationIds;
+
+	private List<String> expiredPipeIds;
+
+	private List<String> expiredJobSpaceIds;
+
+	private List<String> expiredProblemArchIds;
+
+	private List<String> expiredProblemEquipIds;
+
+	private List<String> expiredFileIds;
+
+	private List<String> expiredQrCodeIds;
+
+	private List<String> expiredServeAreaIds;
+
+	private String timestamp;
+
+	private String buildingId;
+
+	private String status;
+
+	public UploadRtn() {
+
+	}
+
+	public UploadRtn(String status) {
+		this.status = status;
+	}
+
+}

+ 21 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmClientFlag.java

@@ -0,0 +1,21 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.sql.Timestamp;
+
+@Data
+@TableName(value = "adm_client_flag", autoResultMap = true)
+public class AdmClientFlag {
+
+	@TableId(type = IdType.AUTO)
+	private Integer id;
+
+	private String userId;
+
+	private Timestamp ts;
+
+}

+ 18 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmComponent.java

@@ -0,0 +1,18 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+@Data
+@TableName(value = "adm_component",autoResultMap = true)
+public class AdmComponent extends BaseAdmEntity {
+
+	private String compCode;
+
+	private String compName;
+
+	private String systemCode;
+
+	private String classCode;
+
+}

+ 59 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmConfig.java

@@ -0,0 +1,59 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.persagy.dmp.common.helper.SpringHelper;
+import lombok.Data;
+
+import java.io.IOException;
+
+@Data
+@TableName(value = "adm_config",autoResultMap = true)
+public class AdmConfig extends BaseAdmEntity {
+
+	private String name;
+
+	private String code;
+
+	@TableField(
+			typeHandler = JacksonTypeHandler.class
+	)
+	private JsonNode data;
+
+	@TableField(
+			exist = false
+	)
+	private String strData;
+
+	@Override
+	public void serializeJsonProp() {
+		if(data != null) {
+			ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+			try {
+				strData = objectMapper.writeValueAsString(data);
+			} catch (JsonProcessingException e) {
+
+			}
+			//data = null;
+		}
+	}
+
+	@Override
+	public void deserializeJsonProp() {
+		if(StrUtil.isNotBlank(strData)) {
+			ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+			try {
+				data = objectMapper.readValue(strData, JsonNode.class);
+			} catch (IOException e) {
+
+			}
+			strData = null;
+		}
+	}
+
+}

+ 14 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmContainerConfig.java

@@ -0,0 +1,14 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+@Data
+@TableName(value = "adm_container_config", autoResultMap = true)
+public class AdmContainerConfig extends BaseAdmEntity {
+
+	private String containerCode;
+
+	private String widgetCode;
+
+}

+ 29 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmFile.java

@@ -0,0 +1,29 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+@Data
+@TableName(value = "adm_file",autoResultMap = true)
+public class AdmFile extends BaseAdmDataEntity {
+
+    private String fileType;
+
+    private String bizType;
+
+    private String filePath;
+
+    private String clientPath;
+
+    private String refObjId;
+
+    private String refInfoCode;
+
+    private String remark;
+
+    private Integer orderNum;
+
+    /** 文件服务中对应的存储id */
+    private String fileId;
+
+}

+ 67 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmInfosConfig.java

@@ -0,0 +1,67 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.persagy.dmp.common.helper.SpringHelper;
+import lombok.Data;
+
+import java.io.IOException;
+import java.util.List;
+
+@Data
+@TableName(value = "adm_infos_config",autoResultMap = true)
+public class AdmInfosConfig extends BaseAdmEntity {
+
+    private String objType;
+
+    private String name;
+
+    private String classCode;
+
+    private String majorCode;
+
+    private String systemCode;
+
+    @TableField(
+            typeHandler = JacksonTypeHandler.class
+    )
+    private List<Object> infos;
+
+    private String flag;
+
+    @TableField(
+            exist = false
+    )
+    private String strInfos;
+
+    @Override
+    public void serializeJsonProp() {
+        if(infos != null) {
+            ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+            try {
+                strInfos = objectMapper.writeValueAsString(infos);
+            } catch (JsonProcessingException e) {
+
+            }
+            //infos = null;
+        }
+    }
+
+    @Override
+    public void deserializeJsonProp() {
+        if(StrUtil.isNotBlank(strInfos)) {
+            ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+            try {
+                infos = objectMapper.readValue(strInfos, List.class);
+            } catch (IOException e) {
+
+            }
+            strInfos = null;
+        }
+    }
+
+}

+ 71 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmJobSpace.java

@@ -0,0 +1,71 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.persagy.dmp.common.helper.SpringHelper;
+import lombok.Data;
+
+import java.io.IOException;
+
+@Data
+@TableName(value = "adm_job_space",autoResultMap = true)
+public class AdmJobSpace extends BaseAdmDataEntity {
+
+    private String workId;
+
+    private String spaceId;
+
+//    private String bimId; 业务空间没有bimId
+
+    private String spaceType;
+
+    private String parentSpaceId;
+
+    private Integer archState;
+
+    private Integer equipState;
+
+    @JsonIgnore
+    @TableField(
+            typeHandler = JacksonTypeHandler.class
+    )
+    private ArrayNode outline;
+
+    @TableField(
+            exist = false
+    )
+    private String strOutline;
+
+    @Override
+    public void serializeJsonProp() {
+        if(outline != null) {
+            ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+            try {
+                strOutline = objectMapper.writeValueAsString(outline);
+            } catch (JsonProcessingException e) {
+
+            }
+            //outline = null;
+        }
+    }
+
+    @Override
+    public void deserializeJsonProp() {
+        if(StrUtil.isNotBlank(strOutline)) {
+            ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+            try {
+                outline = objectMapper.readValue(strOutline, ArrayNode.class);
+            } catch (IOException e) {
+
+            }
+            strOutline = null;
+        }
+    }
+
+}

+ 18 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmM2dEquip.java

@@ -0,0 +1,18 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+@Data
+@TableName(value = "adm_m2d_equip",autoResultMap = true)
+public class AdmM2dEquip extends BaseAdmEntity {
+
+    private String name;
+
+    private String majorCode;
+
+    private String systemCode;
+
+    private String classCode;
+
+}

+ 35 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmMessageP.java

@@ -0,0 +1,35 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import com.fasterxml.jackson.databind.JsonNode;
+import lombok.Data;
+
+import java.sql.Timestamp;
+
+@Data
+@TableName(value = "adm_message_p", autoResultMap = true)
+public class AdmMessageP extends BaseAdmEntity {
+
+	private String triggerType;
+
+	private String sender;
+
+	private String status;
+
+	private Timestamp sendTime;
+
+	private Timestamp returnTime;
+
+	@TableField(
+			typeHandler = JacksonTypeHandler.class
+	)
+	private Object content;
+
+	@TableField(
+			typeHandler = JacksonTypeHandler.class
+	)
+	private Object returnContent;
+
+}

+ 90 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmObject.java

@@ -0,0 +1,90 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.dmp.common.helper.SpringHelper;
+import lombok.Data;
+
+import java.io.IOException;
+import java.util.List;
+
+@Data
+@TableName(value = "adm_object",autoResultMap = true)
+public class AdmObject extends BaseDeliveryEntity {
+
+	private String name;
+
+	private String localId;
+
+	private String localName;
+
+	private String objType;
+
+	private String classCode;
+
+	private String groupCode;
+
+	@TableField("`grouping`")
+	private Integer grouping;
+
+	@TableField(
+			typeHandler = JacksonTypeHandler.class
+	)
+	private List<String> virtualCodes;
+
+	private String createApp;
+
+	private String updateApp;
+
+	private String containerId;
+
+	@TableField(
+			typeHandler = JacksonTypeHandler.class
+	)
+	private ObjectNode infos;
+
+	@TableField(
+			exist = false
+	)
+	private String strInfos;
+
+	public JsonNode getInfo(String infoCode){
+		ObjectNode node = infos;
+		if(node != null)
+			return node.get(infoCode);
+		return null;
+	}
+
+	@Override
+	public void serializeJsonProp() {
+		if(infos != null) {
+			ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+			try {
+				strInfos = objectMapper.writeValueAsString(infos);
+			} catch (JsonProcessingException e) {
+
+			}
+			//infos = null;
+		}
+	}
+
+	@Override
+	public void deserializeJsonProp() {
+		if(StrUtil.isNotBlank(strInfos)) {
+			ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+			try {
+				infos = objectMapper.readValue(strInfos, ObjectNode.class);
+			} catch (IOException e) {
+
+			}
+			strInfos = null;
+		}
+	}
+
+}

+ 98 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmPipe.java

@@ -0,0 +1,98 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.dmp.common.helper.SpringHelper;
+import lombok.Data;
+
+import java.io.IOException;
+import java.util.List;
+
+@Data
+@TableName(value = "adm_pipe",autoResultMap = true)
+public class AdmPipe extends BaseAdmDataEntity {
+
+    private String objFrom;
+
+    private String typeFrom;
+
+    private String objTo;
+
+    private String typeTo;
+
+    private Integer direction;
+
+    private String pipeType;
+
+    private String pipeSubType;
+
+    @TableField(
+            typeHandler = JacksonTypeHandler.class
+    )
+    private List<Object> route;
+
+    @TableField(
+            typeHandler = JacksonTypeHandler.class
+    )
+    private ObjectNode infos;
+
+    @TableField(
+            exist = false
+    )
+    private String strRoute;
+
+    @TableField(
+            exist = false
+    )
+    private String strInfos;
+
+    @Override
+    public void serializeJsonProp() {
+        if(route != null) {
+            ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+            try {
+                strRoute = objectMapper.writeValueAsString(route);
+            } catch (JsonProcessingException e) {
+
+            }
+            //route = null;
+        }
+        if(infos != null) {
+            ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+            try {
+                strInfos = objectMapper.writeValueAsString(infos);
+            } catch (JsonProcessingException e) {
+
+            }
+            //infos = null;
+        }
+    }
+
+    @Override
+    public void deserializeJsonProp() {
+        if(StrUtil.isNotBlank(strRoute)) {
+            ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+            try {
+                route = objectMapper.readValue(strRoute, List.class);
+            } catch (IOException e) {
+
+            }
+            strRoute = null;
+        }
+        if(StrUtil.isNotBlank(strInfos)) {
+            ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+            try {
+                infos = objectMapper.readValue(strInfos, ObjectNode.class);
+            } catch (IOException e) {
+
+            }
+            strInfos = null;
+        }
+    }
+
+}

+ 24 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmPipeConfig.java

@@ -0,0 +1,24 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+@Data
+@TableName(value = "adm_pipe_config",autoResultMap = true)
+public class AdmPipeConfig extends BaseAdmEntity {
+
+    private String classCodeFrom;
+
+    private String pipeType;
+
+    private String pipeSubType;
+
+    private Integer pipeDirection;
+
+    private String pipeDescription;
+
+    private String classCodeTo;
+
+    private String flag;
+
+}

+ 67 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmProblemArch.java

@@ -0,0 +1,67 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.dmp.common.helper.SpringHelper;
+import lombok.Data;
+
+import java.io.IOException;
+import java.util.List;
+
+@Data
+@TableName(value = "adm_problem_arch",autoResultMap = true)
+public class AdmProblemArch extends BaseAdmDataEntity {
+
+    private String workId;
+
+    private String geomType;
+
+    @TableField(
+            typeHandler = JacksonTypeHandler.class
+    )
+    private List<ObjectNode> geom;
+
+    private String problemType;
+
+    private String message;
+
+    private Integer problemState;
+
+    @TableField(
+            exist = false
+    )
+    private String strGeom;
+
+    @Override
+    public void serializeJsonProp() {
+        if(geom != null) {
+            ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+            try {
+                strGeom = objectMapper.writeValueAsString(geom);
+            } catch (JsonProcessingException e) {
+
+            }
+            //geom = null;
+        }
+    }
+
+    @Override
+    public void deserializeJsonProp() {
+        if(StrUtil.isNotBlank(strGeom)) {
+            ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+            try {
+                geom = objectMapper.readValue(strGeom, new TypeReference<List<ObjectNode>>(){});
+            } catch (IOException e) {
+
+            }
+            strGeom = null;
+        }
+    }
+
+}

+ 20 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmProblemEquip.java

@@ -0,0 +1,20 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+@Data
+@TableName(value = "adm_problem_equip",autoResultMap = true)
+public class AdmProblemEquip extends BaseAdmDataEntity {
+
+    private String workId;
+
+    private String equipId;
+
+    private String problemType;
+
+    private String message;
+
+    private Integer problemState;
+
+}

+ 61 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmQrCode.java

@@ -0,0 +1,61 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.dmp.common.helper.SpringHelper;
+import lombok.Data;
+
+import java.io.IOException;
+
+@Data
+@TableName(value = "adm_qr_code",autoResultMap = true)
+public class AdmQrCode extends BaseAdmDataEntity {
+
+    private String qrCode;
+
+    private String objId;
+
+    @TableField(
+            typeHandler = JacksonTypeHandler.class
+    )
+    private ObjectNode location;
+
+    private String remark;
+
+    @TableField(
+            exist = false
+    )
+    private String strLocation;
+
+    @Override
+    public void serializeJsonProp() {
+        if(location != null) {
+            ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+            try {
+                strLocation = objectMapper.writeValueAsString(location);
+            } catch (JsonProcessingException e) {
+
+            }
+            //location = null;
+        }
+    }
+
+    @Override
+    public void deserializeJsonProp() {
+        if(StrUtil.isNotBlank(strLocation)) {
+            ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+            try {
+                location = objectMapper.readValue(strLocation, ObjectNode.class);
+            } catch (IOException e) {
+
+            }
+            strLocation = null;
+        }
+    }
+
+}

+ 28 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmRelation.java

@@ -0,0 +1,28 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+@Data
+@TableName(value = "adm_relation",autoResultMap = true)
+public class AdmRelation extends BaseDeliveryEntity {
+
+    private String groupCode;
+
+    private String graphId;
+
+    private String graphCode;
+
+    private String relCode;
+
+    private String relValue;
+
+    private String objFrom;
+
+    private String objTo;
+
+    private String createApp;
+
+    private String updateApp;
+
+}

+ 30 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmRelsConfig.java

@@ -0,0 +1,30 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+@Data
+@TableName(value = "adm_rels_config",autoResultMap = true)
+public class AdmRelsConfig extends BaseAdmEntity {
+
+    private String objTypeFrom;
+
+    private String classCodeFrom;
+
+    private String graphCode;
+
+    private String graphName;
+
+    private String relCode;
+
+    private String relName;
+
+    private String objTypeTo;
+
+    private String classCodeTo;
+
+    private String direction;
+
+    private String flag;
+
+}

+ 26 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmServeArea.java

@@ -0,0 +1,26 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import com.fasterxml.jackson.databind.JsonNode;
+import lombok.Data;
+
+@Data
+@TableName(value = "adm_serve_area",autoResultMap = true)
+public class AdmServeArea extends BaseAdmDataEntity {
+
+    private String objId;
+
+    private String geomType;
+
+    @TableField(
+            typeHandler = JacksonTypeHandler.class
+    )
+    private JsonNode geom;
+
+    private String serveType;
+
+    private String remark;
+
+}

+ 22 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmUploadJob.java

@@ -0,0 +1,22 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.sql.Timestamp;
+
+@Data
+@TableName(value = "adm_upload_job", autoResultMap = true)
+public class AdmUploadJob extends BaseAdmEntity {
+
+	private String operator;
+
+	private String status;
+
+	private Timestamp startTime;
+
+	private Timestamp finishTime;
+
+}

+ 68 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/AdmUploadLog.java

@@ -0,0 +1,68 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import cn.hutool.extra.spring.SpringUtil;
+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 com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import lombok.Data;
+
+import java.sql.Timestamp;
+
+@Data
+@TableName(value = "adm_upload_log",autoResultMap = true)
+public class AdmUploadLog {
+
+	public static final String ADD = "add";
+
+	public static final String MODIFY = "modify";
+
+	public static final String REMOVE = "remove";
+
+	private String operator;
+
+	private String jobId;
+
+	private String entityType;
+
+	private String operation;
+
+	private String data; //数据库中json类型
+
+	private Timestamp ts;
+
+	public AdmUploadLog() {
+
+	}
+
+	public AdmUploadLog(String jobId, String operator, String operation) {
+		this.jobId = jobId;
+		this.operator = operator;
+		this.operation = operation;
+	}
+
+	public void setData(Object data, ObjectMapper objectMapper){
+		this.entityType = getLogEntityType(data);
+		try {
+			this.data = objectMapper.writeValueAsString(data);
+		} catch (Exception e) {
+
+		}
+	}
+
+	private String getLogEntityType(Object o){
+		if (o instanceof ObjectNode) {
+			JsonNode ot = ((ObjectNode) o).get("objType");
+			if(ot != null)
+				return ot.asText();
+			if(((ObjectNode) o).get("relCode") != null)
+				return "relation";
+		}
+		return o.getClass().getSimpleName();
+	}
+
+}

+ 50 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/BaseAdmDataEntity.java

@@ -0,0 +1,50 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import lombok.Data;
+
+import java.io.IOException;
+import java.sql.Timestamp;
+import java.util.Date;
+
+/**
+ * 数据实体基类
+ */
+@Data
+abstract public class BaseAdmDataEntity extends BaseAdmEntity {
+
+	protected String buildingId;
+
+	protected String floorId;
+
+	protected String creator;
+
+	protected String creationTime;
+
+	protected String modifier;
+
+	protected String modifiedTime;
+
+	protected Integer valid;
+
+	@JsonSerialize(using = DateToLongSerializer.class)
+	protected Timestamp ts;
+
+	/** APP端上传的数据状态,可以判断是否为新增数据 */
+	@TableField(exist = false)
+	protected Integer state;
+
+}
+
+class DateToLongSerializer extends JsonSerializer<Date> {
+
+	@Override
+	public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
+		jsonGenerator.writeNumber(date.getTime());
+	}
+
+}

+ 23 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/BaseAdmEntity.java

@@ -0,0 +1,23 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import lombok.Data;
+
+/**
+ * 实体基类
+ */
+@Data
+abstract public class BaseAdmEntity {
+
+	protected String id;
+
+	protected String projectId;
+
+	public void serializeJsonProp() {
+
+	}
+
+	public void deserializeJsonProp() {
+
+	}
+
+}

+ 23 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/db/BaseDeliveryEntity.java

@@ -0,0 +1,23 @@
+package com.persagy.bdtp.adm.entity.db;
+
+import lombok.Data;
+
+/**
+ * 需要交付给BDTP的实体基类
+ */
+@Data
+abstract public class BaseDeliveryEntity extends BaseAdmDataEntity {
+
+	/** 创建对象的本地设备(移动端) */
+	protected String clientDevice;
+
+	/** 由本地设备生成的对象id */
+	protected String clientId;
+
+	/**  数模同步状态:0未同步, 1已同步 */
+	protected Integer d2mState;
+
+	/** 交付BDTP状态:1已交付,0待交付 */
+	protected Integer deliveryState;
+
+}

+ 27 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/oldadm/OBase.java

@@ -0,0 +1,27 @@
+package com.persagy.bdtp.adm.entity.oldadm;
+
+import lombok.Data;
+
+import java.util.Date;
+import java.util.Map;
+
+@Data
+abstract public class OBase {
+
+	private String id;
+
+	private String name;
+
+	private String localId;
+
+	private String localName;
+
+	private String objectType;
+
+	private Map<String, Object> infos;
+
+	private String createTime;
+
+	private String lastUpdate;
+
+}

+ 19 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/oldadm/OBuilding.java

@@ -0,0 +1,19 @@
+package com.persagy.bdtp.adm.entity.oldadm;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class OBuilding extends OBase {
+
+	/** 项目ID */
+	private String projectId;
+	/** 平台默认二维码 */
+	private String defaultQRCode;
+	/** 建筑二维码图片 */
+	private String buildQRCode;
+
+	private List<OFloor> floor;
+
+}

+ 99 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/oldadm/OEquip.java

@@ -0,0 +1,99 @@
+package com.persagy.bdtp.adm.entity.oldadm;
+
+import com.fasterxml.jackson.annotation.JsonAlias;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class OEquip extends OBase {
+
+	/** 二维码内容 */
+	private String defaultQRCode;
+	/** 设计图纸中编码 */
+	private String cadId;
+	/** RFID标识 */
+	private String rfId;
+
+
+	/** BIM模型中编码 */
+	private String bimId;
+	/** BIM构建编码 */
+	private String bimTypeId;
+	/** BIM模型中坐标 */
+	private String bimLocation;
+	/** 坐标对象数据 */
+	@JsonProperty("location")
+	@JsonAlias("locationJson")
+	private Map<String, Double> location;
+	/** 现场发现人员 */
+	private String findPeople;
+
+	/** 项目ID */
+	private String projectId;
+	/** 设备类型code */
+	private String classCode;
+	/** 设备所在建筑ID */
+	private String buildingId;
+	/** 设备所在楼层id */
+	private String floorId;
+	/** 设备关联的资产id */
+	private String propertyId;
+
+	/** 参见 EquipmentProSy **/
+	/** 品牌型号id */
+	private String dpManufacturerId;
+
+	/** 供应商信息id */
+	private String dpSupplierId;
+
+	/** 维修商信息id */
+	private String dpMaintainerId;
+
+	/** 保险公司信息id */
+	private String dpInsurerId;
+
+	/** 设备型号id */
+	private String dpSpecificationId;
+
+	/** 品牌id */
+	private String dpBrandId;
+
+	/** Revit族 */
+	private String bimFamilyName;
+	/** Revit族类型 */
+	private String bimFamilySymbol;
+	/** 设备序号 */
+	private Double equipSerial;
+
+	/** 部件关联设备的id */
+	private String parentId;
+	/** 系统id集合 */
+	private List<String> systemList;
+	/** 项目自定义类型 */
+	private String customCategory;
+	/** 任务状态 */
+	private Integer taskState;
+	/** 模型id */
+	private String modelId;
+	/** 贴码状态 */
+	private Integer codeType;
+	/** 备注 */
+	private String note;
+
+	/** 客户端id */
+	private String appId;
+	/** 方案id */
+	private String schemeId;
+
+	/** 系统编码 */
+	private String systemCode;
+	/** 系统名称 */
+	private String systemName;
+	/** 二维码图片 */
+	private String qrcodePic;
+
+}

+ 51 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/oldadm/OFloor.java

@@ -0,0 +1,51 @@
+package com.persagy.bdtp.adm.entity.oldadm;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class OFloor extends OBase {
+
+	/** 平台默认二维码 */
+	private String defaultQRCode;
+	/** 项目ID */
+	private String projectId;
+	/** 建筑ID */
+	private String buildingId;
+	/** 坐标 */
+	private String bimLocation;
+	/** BIM模型中编码 */
+	private String bimId;
+	/** BIMID前缀 */
+	private String bimIdPre;
+	/** 楼层顺序号 */
+	private Integer floorSequenceID;
+	/** 楼层常驻人数 */
+	private Integer permanentPeopleNum;
+	/** 楼层编码 */
+	private String floorIdentity;
+
+	/** 模型文件id */
+	private String modelId;
+
+	/** 楼层选定区域轮廓线 */
+	private List<ObjectNode> outline;
+
+	/** 数量 */
+	private String count;
+
+	/** 自定义信息点 */
+	private Map<String, Object> properties;
+
+	/** 二维码图片 */
+	private String qrcodePic;
+
+	public String getFloorMap(){
+		Map<String, Object> infos = getInfos();
+		return infos != null ? (String) infos.get("floorMap") : null;
+	}
+
+}

+ 17 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/oldadm/OProject.java

@@ -0,0 +1,17 @@
+package com.persagy.bdtp.adm.entity.oldadm;
+
+import lombok.Data;
+
+@Data
+public class OProject extends OBase {
+
+	/** 项目介绍 */
+	private String introduction;
+	/** 集团编码 */
+	private String groupCode;
+	/** 商业层数 */
+	private String businessFloorNum;
+	/** 办公层数 */
+	private String officeFloorNum;
+
+}

+ 79 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/oldadm/OSpace.java

@@ -0,0 +1,79 @@
+package com.persagy.bdtp.adm.entity.oldadm;
+
+import cn.hutool.core.map.CaseInsensitiveMap;
+import lombok.Data;
+
+import java.util.ArrayList;
+
+@Data
+public class OSpace extends OBase {
+
+	/** 项目ID */
+	private String projectId;
+	/** 建筑ID */
+	private String buildingId;
+	/** 楼层ID */
+	private String floorId;
+	/** 平台二维码 */
+	private String defaultQRCode;
+	/** BIM模型中编码 */
+	private String bimId;
+
+	/** 楼层选定区域轮廓线 */
+	private ArrayList<ArrayList<ArrayList<CaseInsensitiveMap>>> outline;
+	/** 轮廓线2 未使用*/
+	private ArrayList<ArrayList<ArrayList<CaseInsensitiveMap>>> outline2;
+//	/** 图片 */
+//	private ArrayList<AdmTaskPic> pic;
+	/** 空间是否受影响 */
+	private String state;
+	/** 空间常驻人数 */
+	private Integer permanentPeopleNum;
+
+	/** 井深 */
+	private Float depth;
+	/** 面宽 */
+	private Float width;
+	/** 建筑面积 */
+	private Float buildArea;
+	/** 使用面积 */
+	private Float netArea;
+	/** 高 */
+	private Float height;
+	/** 备注文字 */
+	private String intro;
+	/** 设计供冷功率 */
+	private Float ratedCoolingp;
+	/** 设计供热功率 */
+	private Float ratedHeatingp;
+	/** 空调形式 */
+	private String acType;
+	/** 空间朝向 */
+	private String zoneOrientation;
+	/** 空间功能区类型 */
+	private String roomFuncType;
+
+	/** 空间序号 */
+	private Float roomSerial;
+	/** 项目空间功能区类型 */
+	private String projRoomFuncType;
+	/** 设计照明功率 */
+	private Float ratedLightp;
+	/** 内外区分类 */
+	private String zoneType;
+	/** 租赁业态类型 */
+	private Integer tenantType;
+	/** 所属租户 */
+	private String tenant;
+	/** 配电容量 */
+	private Float elecCap;
+	/** 污染等级 */
+	private String pollutionDegree;
+
+	/** 对象类型code */
+	private String classCode;
+
+	/** 二维码图片 */
+	private String qrcodePic;
+
+}

+ 20 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/entity/oldadm/OldAdmResult.java

@@ -0,0 +1,20 @@
+package com.persagy.bdtp.adm.entity.oldadm;
+
+import lombok.Data;
+
+@Data
+public class OldAdmResult<T> {
+
+	private String result;
+
+	private String Message;
+
+	private T content;
+
+	private int pageNumber;
+
+	private int pageSize;
+
+	private int total;
+
+}

+ 74 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/handler/M2DMessageHandler.java

@@ -0,0 +1,74 @@
+package com.persagy.bdtp.adm.handler;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.persagy.bdtp.adm.common.AdmConst;
+import com.persagy.bdtp.adm.common.AdmMessageConst;
+import com.persagy.bdtp.adm.dao.AdmMessagePMapper;
+import com.persagy.bdtp.adm.entity.db.AdmMessageP;
+import com.persagy.dmp.amqp.handler.AbstractRabbitHandlerTemplate;
+import com.rabbitmq.client.Channel;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.sql.Timestamp;
+import java.util.Date;
+import java.util.Map;
+
+@Slf4j
+@Component
+@RabbitListener(queues = AdmMessageConst.M2D_QUEUE)
+public class M2DMessageHandler extends AbstractRabbitHandlerTemplate {
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @Autowired
+    private AdmMessagePMapper messageMapper;
+
+    /**
+     * 消费
+     * @param message 消息体字符串
+     * @param channel 通道对象
+     * @param vo     消息对象
+     */
+    @Override
+    protected void handler(String message, Channel channel, Message vo) {
+        Map<String, Object> msg = null;
+        try {
+            msg = objectMapper.readValue(message, Map.class);
+        }catch (IOException e){
+            throw new RuntimeException(e);
+        }
+
+        if(msg != null)
+            handleD2mReply(msg);
+    }
+
+    private void handleD2mReply(Map<String, Object> reply){
+        String id = (String) reply.get("id");
+        String result = (String) reply.get("result");
+        Object content = reply.get("content");
+
+        AdmMessageP message = messageMapper.selectById(id);
+        if (message != null) {
+            boolean flag = "success".equals(result);
+
+            message.setStatus(flag ? AdmConst.UPLOAD_FINISHED : AdmConst.UPLOAD_ERROR);
+            message.setReturnContent(content);
+            message.setReturnTime(new Timestamp(new Date().getTime()));
+            messageMapper.updateById(message);
+
+            if(!flag)
+                handleD2mError();
+        }
+    }
+
+    private void handleD2mError(){
+        //TODO
+    }
+
+}

+ 17 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/CallException.java

@@ -0,0 +1,17 @@
+package com.persagy.bdtp.adm.service;
+
+import com.persagy.bdtp.adm.common.AdmResult;
+
+public class CallException extends RuntimeException {
+
+	private AdmResult<Object> errorResult;
+
+	public CallException(AdmResult<Object> errorResult) {
+		this.errorResult = errorResult;
+	}
+
+	public AdmResult<Object> getErrorResult() {
+		return errorResult;
+	}
+
+}

+ 13 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/IAdmLogService.java

@@ -0,0 +1,13 @@
+package com.persagy.bdtp.adm.service;
+
+import com.persagy.bdtp.adm.entity.db.AdmUploadLog;
+
+import java.util.List;
+
+public interface IAdmLogService {
+
+	void saveUploadLog(List<AdmUploadLog> logs);
+
+	void saveUploadLog(AdmUploadLog log);
+
+}

+ 53 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/IAdmObjectService.java

@@ -0,0 +1,53 @@
+package com.persagy.bdtp.adm.service;
+
+import com.persagy.bdtp.adm.entity.db.AdmObject;
+
+import java.util.List;
+
+/**
+ * 操作对象实体的服务
+ */
+public interface IAdmObjectService {
+
+	/**
+	 * 批量新增对象
+	 */
+	List<AdmObject> insert(List<AdmObject> voList);
+
+	/**
+	 * 批量更新对象
+	 */
+	List<AdmObject> update(List<AdmObject> voList);
+
+	/**
+	 * 查询建筑和楼层数据
+	 * @param projectIds 项目id
+	 * @return
+	 */
+	List<AdmObject> queryBdAndFl(String... projectIds);
+
+//	/**
+//	 * 查询楼层下的数据(空间、设备)
+//	 * @param projectId 项目id
+//	 * @param floorId 楼层id
+//	 * @return
+//	 */
+//	List<AdmObject> queryByFloor(String projectId, String floorId);
+//
+//	/**
+//	 * 查询建筑下的数据(空间、设备)
+//	 * @param projectId 项目id
+//	 * @param buildingId 楼层id
+//	 * @return
+//	 */
+//	List<AdmObject> queryByBuilding(String projectId, String buildingId);
+
+	/**
+	 * 按类型查询正向交付的实体对象
+	 * @param projectId 项目id
+	 * @param objType 对象类型
+	 * @return
+	 */
+	List<AdmObject> queryM2dByObjType(String projectId, String objType);
+
+}

+ 29 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/IConfigService.java

@@ -0,0 +1,29 @@
+package com.persagy.bdtp.adm.service;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.bdtp.adm.entity.db.*;
+
+import java.util.List;
+
+public interface IConfigService {
+
+	List<AdmM2dEquip> queryM2dEquip(String projectId);
+
+	List<AdmInfosConfig> queryInfosConfig(String projectId);
+
+	List<AdmRelsConfig> queryRelsConfig(String projectId);
+
+	List<AdmPipeConfig> queryPipeConfig(String projectId);
+
+	List<AdmConfig> queryCommonConfig(String projectId);
+
+	List<AdmComponent> queryComponent(String projectId);
+
+	List<AdmContainerConfig> queryContainerConfig(String projectId);
+
+	ArrayNode queryNewEquipTypes(String projectId);
+
+	ObjectNode queryRenameEquipTypes(String projectId);
+
+}

+ 29 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/IQueryFromOldAdm.java

@@ -0,0 +1,29 @@
+package com.persagy.bdtp.adm.service;
+
+import com.persagy.bdtp.adm.entity.oldadm.OBuilding;
+import com.persagy.bdtp.adm.entity.oldadm.OEquip;
+import com.persagy.bdtp.adm.entity.oldadm.OProject;
+import com.persagy.bdtp.adm.entity.oldadm.OSpace;
+
+import java.util.List;
+
+/**
+ * 从老adm查询数据
+ */
+public interface IQueryFromOldAdm {
+
+	/**
+	 * 登录系统
+	 * @return token
+	 */
+	String login();
+
+	List<OProject> queryProject(String token, String groupCode, String projectId);
+
+	List<OBuilding> queryBdAnFl(String token, String groupCode, String projectId);
+
+	List<OSpace> querySpace(String token, String groupCode, String projectId);
+
+	List<OEquip> queryEquip(String token, String groupCode, String projectId);
+
+}

+ 32 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/ISyncApp.java

@@ -0,0 +1,32 @@
+package com.persagy.bdtp.adm.service;
+
+import com.persagy.bdtp.adm.entity.*;
+
+import java.util.Map;
+
+/**
+ * 与APP端进行数据同步的服务
+ */
+public interface ISyncApp {
+
+	String getClientId(String userId);
+
+	Dict queryDict(String groupCode, String projectId, String userId, boolean includeRel, boolean includeInfos);
+
+	Dict downloadDict(String groupCode, String projectId, String userId);
+
+	Map<String, Object> downloadConfig(String groupCode, String projectId, String userId);
+
+	Map<String, Object> downloadFrameData(String groupCode, String projectId, String userId);
+
+	/*Map<String, Object> downloadFloorData(String projectId, String floorId, String uploadFlag, String lastDownloadTime);*/
+
+	BuildingData downloadBuildingData(String projectId, String buildingId, String uploadFlag, String lastDownloadTime);
+
+	BuildingData downloadBuildingData(String groupCode, String projectId, String userId, String clientId, String buildingId, Long bdtpDownloadTs, Long admDownloadTs);
+
+	ProjectData downloadProjectData(String groupCode, String projectId, String userId, String clientId, Long bdtpDownloadTs, Long admDownloadTs);
+
+	UploadRtn uploadData(UploadData uploadData, String groupCode, String projectId, String userId, String clientId);
+
+}

+ 15 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/ISyncModel.java

@@ -0,0 +1,15 @@
+package com.persagy.bdtp.adm.service;
+
+import com.persagy.bdtp.adm.entity.D2mMessage;
+import org.springframework.amqp.core.Message;
+
+/**
+ * 与模型服务端进行数据同步的服务
+ */
+public interface ISyncModel {
+
+	void sendMessageToModel(D2mMessage message);
+
+	void handleModelMessage(String message, Message vo);
+
+}

+ 16 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/ISyncOldAdm.java

@@ -0,0 +1,16 @@
+package com.persagy.bdtp.adm.service;
+
+import java.util.Map;
+
+/**
+ * 从老adm同步正向交付数据和建筑楼层等初始化数据
+ */
+public interface ISyncOldAdm {
+
+	Map<String, Object> syncData(String groupCode, String projectId);
+
+	void handleJobSpace(String projectId);
+
+	void uploadFloorMap(String groupCode, String projectId);
+
+}

+ 21 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/ISyncSpace.java

@@ -0,0 +1,21 @@
+package com.persagy.bdtp.adm.service;
+
+import java.util.Map;
+
+/**
+ * 空间数据同步服务
+ * 数字化交付的工作空间(目前为物业分区)发生改变时,与任务空间进行同步操作
+ */
+public interface ISyncSpace {
+
+	/**
+	 * 按楼层同步
+	 */
+	Map<String, Object> sync(String groupCode, String projectId, String userId, String floorId, String zone);
+
+	/**
+	 * 按项目同步
+	 */
+	Map<String, Object> sync(String groupCode, String projectId, String userId, String zone);
+
+}

+ 81 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/ServiceUtil.java

@@ -0,0 +1,81 @@
+package com.persagy.bdtp.adm.service;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.bdtp.adm.common.AdmResult;
+import com.persagy.bdtp.adm.entity.Pagination;
+import com.persagy.bdtp.adm.entity.oldadm.OldAdmResult;
+import com.persagy.dmp.basic.model.QueryCriteria;
+import com.persagy.dmp.common.model.response.CommonResult;
+
+import java.util.List;
+import java.util.function.Supplier;
+
+public class ServiceUtil {
+
+	public static final String SYNC_APP_IMPL = "syncAppImpl";
+
+	private static final String SUCCESS = "success";
+
+	public static QueryCriteria getQueryCriteria(ObjectMapper objectMapper, String... objType){
+		QueryCriteria queryCriteria = new QueryCriteria();
+
+		ObjectNode objectNode = objectMapper.createObjectNode();
+		if(objType.length  == 1)
+			objectNode.put("objType", objType[0]);
+		else if(objType.length > 1) {
+			ArrayNode arrayNode = objectNode.putArray("objType");
+			for(String type : objType) {
+				arrayNode.add(type);
+			}
+		}
+
+		queryCriteria.setCriteria(objectNode);
+		return queryCriteria;
+	}
+
+	public static <T> T call(Supplier<CommonResult<T>> action) {
+		return call(action, null);
+	}
+
+	private static <T> T call(Supplier<CommonResult<T>> action, Pagination pagination) {
+		CommonResult<T> result = action.get();
+		if(SUCCESS.equals(result.getResult())) {
+			if(pagination != null)
+				pagination.setTotal(result.getCount().intValue());
+			return result.getData();
+		}
+		throw new CallException(new AdmResult<>(result.getResult(), result.getMessage()));
+	}
+
+	public static <T> List<T> queryAllPage(Supplier<CommonResult<List<T>>> action, QueryCriteria criteria, Pagination pagination){
+		List<T> list = null;
+		while (pagination.isHasNext()){
+			criteria.setPage((long)pagination.getPageNum());
+			criteria.setSize((long)pagination.getPageSize());
+			if(list == null)
+				list = ServiceUtil.call(action, pagination);
+			else
+				list.addAll(ServiceUtil.call(action, pagination));
+			pagination.next();
+		}
+		return list;
+	}
+
+
+	public static <T> T callOldAdm(Supplier<OldAdmResult<T>> action, Pagination pagination) {
+		OldAdmResult<T> result = action.get();
+		if(SUCCESS.equals(result.getResult())) {
+			if(pagination != null)
+				pagination.setTotal(result.getTotal());
+			return result.getContent();
+		}
+		throw new CallException(new AdmResult<>(result.getResult(), result.getMessage()));
+	}
+
+	public static <T> T callOldAdm(Supplier<OldAdmResult<T>> action) {
+		return callOldAdm(action, null);
+	}
+
+}

+ 30 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/impl/AdmLogServiceImpl.java

@@ -0,0 +1,30 @@
+package com.persagy.bdtp.adm.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.persagy.bdtp.adm.dao.AdmUploadLogMapper;
+import com.persagy.bdtp.adm.entity.db.AdmUploadLog;
+import com.persagy.bdtp.adm.service.IAdmLogService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+@Service
+@Transactional(rollbackFor = Exception.class)
+@RequiredArgsConstructor
+public class AdmLogServiceImpl extends ServiceImpl<AdmUploadLogMapper, AdmUploadLog> implements IAdmLogService {
+
+	private final AdmUploadLogMapper uploadLogMapper;
+
+	@Override
+	public void saveUploadLog(List<AdmUploadLog> logs) {
+		saveBatch(logs);
+	}
+
+	@Override
+	public void saveUploadLog(AdmUploadLog log) {
+		save(log);
+	}
+
+}

+ 65 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/impl/AdmObjectServiceImpl.java

@@ -0,0 +1,65 @@
+package com.persagy.bdtp.adm.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.persagy.bdtp.adm.common.AdmConst;
+import com.persagy.bdtp.adm.dao.AdmObjectMapper;
+import com.persagy.bdtp.adm.entity.db.AdmObject;
+import com.persagy.bdtp.adm.service.IAdmObjectService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+@Service
+@Transactional(rollbackFor = Exception.class)
+@RequiredArgsConstructor
+public class AdmObjectServiceImpl extends ServiceImpl<AdmObjectMapper, AdmObject> implements IAdmObjectService {
+
+	private final AdmObjectMapper admObjMapper;
+
+	@Override
+	public List<AdmObject> insert(List<AdmObject> voList) {
+		if(CollUtil.isEmpty(voList))
+			return null;
+
+		for(AdmObject obj : voList) {
+			admObjMapper.insert(obj);
+			// 新增后消息
+			//messageSender.sendMessage(DigitalMessageConstant.OPERATE_AFTER_INSERT, null, vo, false);
+		}
+
+		return voList;
+	}
+
+	@Override
+	public List<AdmObject> update(List<AdmObject> voList) {
+		if(CollUtil.isEmpty(voList))
+			return null;
+
+		for(AdmObject obj : voList) {
+			admObjMapper.updateById(obj);
+			// 更新后消息
+			//messageSender.sendMessage(DigitalMessageConstant.OPERATE_AFTER_INSERT, null, vo, false);
+		}
+
+		return voList;
+	}
+
+	@Override
+	public List<AdmObject> queryBdAndFl(String... projectIds) {
+		QueryWrapper<AdmObject> queryWrapper = new QueryWrapper<>();
+		queryWrapper.in("project_id", projectIds).in("obj_type", AdmConst.OBJ_TYPE_BUILDING, AdmConst.OBJ_TYPE_FLOOR);
+		return admObjMapper.selectList(queryWrapper);
+	}
+
+	@Override
+	public List<AdmObject> queryM2dByObjType(String projectId, String objType) {
+		QueryWrapper<AdmObject> queryWrapper = new QueryWrapper<>();
+		queryWrapper.eq("project_id", projectId).eq("obj_type", objType).isNull("client_id");
+		return admObjMapper.selectList(queryWrapper);
+	}
+
+}

+ 106 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/impl/ConfigServiceImpl.java

@@ -0,0 +1,106 @@
+package com.persagy.bdtp.adm.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.bdtp.adm.dao.*;
+import com.persagy.bdtp.adm.entity.db.*;
+import com.persagy.bdtp.adm.service.IConfigService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class ConfigServiceImpl implements IConfigService {
+
+	@Autowired
+	private AdmM2dEquipMapper m2dEquipMapper;
+
+	@Autowired
+	private AdmInfosConfigMapper infosConfigMapper;
+
+	@Autowired
+	private AdmRelsConfigMapper relsConfigMapper;
+
+	@Autowired
+	private AdmPipeConfigMapper pipeConfigMapper;
+
+	@Autowired
+	private AdmConfigMapper commonConfigMapper;
+
+	@Autowired
+	private AdmComponentMapper componentMapper;
+
+	@Autowired
+	private AdmContainerConfigMapper containerConfigMapper;
+
+	@Override
+	public List<AdmM2dEquip> queryM2dEquip(String projectId) {
+		return m2dEquipMapper.selectList(null);
+	}
+
+	@Override
+	public List<AdmInfosConfig> queryInfosConfig(String projectId) {
+		return infosConfigMapper.selectList(null);
+	}
+
+//	private void addInfoCfg(String code, String label, String group, String inputType, List<Object> cfgInfos){
+//		HashMap<String, Object> item = new HashMap<>();
+//		item.put("code", code);
+//		item.put("label", label);
+//		if(StrUtil.isNotBlank(group))
+//			item.put("group", group);
+//		if(StrUtil.isNotBlank(inputType))
+//			item.put("inputType", inputType);
+//		cfgInfos.add(item);
+//	}
+
+	@Override
+	public List<AdmRelsConfig> queryRelsConfig(String projectId) {
+		return relsConfigMapper.selectList(new QueryWrapper<AdmRelsConfig>().orderByAsc("graph_code", "rel_code"));
+	}
+
+	@Override
+	public List<AdmPipeConfig> queryPipeConfig(String projectId) {
+		return pipeConfigMapper.selectList(new QueryWrapper<AdmPipeConfig>().orderByAsc("pipe_type", "pipe_sub_type"));
+	}
+
+	@Override
+	public List<AdmConfig> queryCommonConfig(String projectId) {
+		return commonConfigMapper.selectList(null);
+	}
+
+	@Override
+	public List<AdmComponent> queryComponent(String projectId) {
+		return componentMapper.selectList(null);
+	}
+
+	@Override
+	public List<AdmContainerConfig> queryContainerConfig(String projectId) {
+		return containerConfigMapper.selectList(null);
+	}
+
+	@Override
+	public ArrayNode queryNewEquipTypes(String projectId) {
+		List<AdmConfig> list = commonConfigMapper.selectList(new QueryWrapper<AdmConfig>().eq("code", "new_equip_types"));
+		if(CollUtil.isNotEmpty(list)){
+			AdmConfig cfg = list.get(0);
+			return (ArrayNode) cfg.getData();
+		}
+		return null;
+	}
+
+	@Override
+	public ObjectNode queryRenameEquipTypes(String projectId) {
+		List<AdmConfig> list = commonConfigMapper.selectList(new QueryWrapper<AdmConfig>().eq("code", "rename_equip_types"));
+		if(CollUtil.isNotEmpty(list)){
+			AdmConfig cfg = list.get(0);
+			return (ObjectNode) cfg.getData();
+		}
+		return null;
+	}
+
+
+}

+ 111 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/impl/QueryFromOldAdmImpl.java

@@ -0,0 +1,111 @@
+package com.persagy.bdtp.adm.service.impl;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.persagy.bdtp.adm.client.OldAdmClient;
+import com.persagy.bdtp.adm.entity.db.AdmM2dEquip;
+import com.persagy.bdtp.adm.entity.Pagination;
+import com.persagy.bdtp.adm.entity.oldadm.*;
+import com.persagy.bdtp.adm.service.IConfigService;
+import com.persagy.bdtp.adm.service.IQueryFromOldAdm;
+import com.persagy.bdtp.adm.service.ServiceUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.util.*;
+import java.util.function.Supplier;
+
+@Service
+public class QueryFromOldAdmImpl implements IQueryFromOldAdm {
+
+	private static String user = "bdtp";
+
+	private static String password = "123456";
+
+	private static String appId = "adm";
+
+	@Autowired
+	private OldAdmClient admClient;
+
+	@Autowired
+	private IConfigService configService;
+
+	@Autowired
+	private ObjectMapper objectMapper;
+
+	@Override
+	public String login() {
+		HashMap<String, Object> params = new HashMap<>();
+		params.put("name", user);
+		params.put("password", password);
+		Map<String, Object> longinInfo = admClient.login(params);
+		if("Success".equals(longinInfo.get("code"))){
+			Map data = (Map)longinInfo.get("data");
+			return (String) data.get("token");
+		}
+		return null;
+	}
+
+	@Override
+	public List<OProject> queryProject(String token, String groupCode, String projectId) {
+		return ServiceUtil.callOldAdm(() -> admClient.queryProject(groupCode, projectId, appId, user, token, new HashMap<>()));
+	}
+
+	@Override
+	public List<OBuilding> queryBdAnFl(String token, String groupCode, String projectId) {
+		HashMap<String,Object> params = new HashMap<>();
+		HashMap<String, Object> cascade = new HashMap<>();
+		cascade.put("name", "floor");
+		cascade.put("orders", "floorSequenceID asc");
+		params.put("cascade", Arrays.asList(cascade));
+		return ServiceUtil.callOldAdm(() -> admClient.queryBuilding(groupCode, projectId, appId, user, token, params));
+	}
+
+	@Override
+	public List<OSpace> querySpace(String token, String groupCode, String projectId) {
+		HashMap<String,Object> params = new HashMap<>();
+		params.put("zoneTypeList", Arrays.asList("GeneralZone", "OtherZone"));
+		//params.put("zoneType", "GeneralZone");
+
+		Pagination pagination = new Pagination(1000);
+		return queryAllPage(() -> admClient.querySpace(groupCode, projectId, appId, user, token, params), params, pagination);
+	}
+
+	private <T> List<T> queryAllPage(Supplier<OldAdmResult<List<T>>> action, Map<String,Object> params, Pagination pagination){
+		List<T> list = null;
+		while (pagination.isHasNext()){
+			params.put("pageNumber", pagination.getPageNum());
+			params.put("pageSize", pagination.getPageSize());
+			if(list == null)
+				list = ServiceUtil.callOldAdm(action, pagination);
+			else
+				list.addAll(ServiceUtil.callOldAdm(action, pagination));
+			pagination.next();
+		}
+		return list;
+	}
+
+	@Override
+	public List<OEquip> queryEquip(String token, String groupCode, String projectId) {
+		HashMap<String,Object> params = new HashMap<>();
+		Pagination pagination = new Pagination(1000);
+
+		//TODO 暂时仅同步正向交付的设备,按设备类过滤
+		List<AdmM2dEquip> equips = configService.queryM2dEquip(projectId);
+		List<String> classCodeList = new ArrayList<>(equips.size());
+		for (AdmM2dEquip equip : equips) {
+			classCodeList.add(equip.getClassCode());
+		}
+		if (classCodeList.size() > 0) {
+			try {
+				String filter = "classCode in " + objectMapper.writeValueAsString(classCodeList);
+				params.put("filters", filter);
+			} catch (IOException e) {
+
+			}
+		}
+
+		return queryAllPage(() -> admClient.queryEquip(groupCode, projectId, appId, user, token, params), params, pagination);
+	}
+
+}

+ 758 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/impl/SyncAppImpl.java

@@ -0,0 +1,758 @@
+package com.persagy.bdtp.adm.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.bdtp.adm.client.DicClient;
+import com.persagy.bdtp.adm.client.RwdClient;
+import com.persagy.bdtp.adm.common.AdmConst;
+import com.persagy.bdtp.adm.dao.*;
+import com.persagy.bdtp.adm.datatx.ObjectMapper4Tx;
+import com.persagy.bdtp.adm.entity.*;
+import com.persagy.bdtp.adm.entity.db.*;
+import com.persagy.bdtp.adm.service.*;
+import com.persagy.bdtp.adm.util.DataExtrasUtil;
+import com.persagy.dmp.basic.model.QueryCriteria;
+import com.persagy.dmp.common.constant.ValidEnum;
+import com.persagy.dmp.define.entity.RelationDefine;
+import com.persagy.dmp.digital.client.DigitalObjectClient;
+import com.persagy.dmp.digital.client.DigitalRelationClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.sql.Timestamp;
+import java.util.*;
+
+@Service
+public class SyncAppImpl implements ISyncApp {
+
+	@Autowired
+	private RwdClient rwdClient;
+
+	@Autowired
+	private DicClient dicClient;
+
+	@Autowired
+	private DigitalObjectClient objectClient;
+
+	@Autowired
+	private DigitalRelationClient relationClient;
+
+	@Autowired
+	private AdmClientFlagMapper clientFlagMapper;
+
+	@Autowired
+	private IConfigService configService;
+
+	@Autowired
+	private AdmPipeMapper pipeMapper;
+
+	@Autowired
+	private AdmJobSpaceMapper jobSpaceMapper;
+
+	@Autowired
+	private AdmProblemArchMapper problemArchMapper;
+
+	@Autowired
+	private AdmProblemEquipMapper problemEquipMapper;
+
+	@Autowired
+	private AdmFileMapper fileMapper;
+
+	@Autowired
+	private AdmQrCodeMapper qrCodeMapper;
+
+	@Autowired
+	private AdmServeAreaMapper serveAreaMapper;
+
+	@Autowired
+	private ISyncModel syncModel;
+
+	@Autowired
+	private ObjectMapper objectMapper;
+
+	@Autowired
+	private IAdmLogService logService;
+
+	@Autowired
+	private AdmUploadJobMapper uploadJobMapper;
+
+	@Autowired
+	private AdmMessagePMapper messageMapper;
+
+	private final ObjectMapper4Tx mapper4Tx;
+
+	@Autowired
+	public SyncAppImpl(ObjectMapper4Tx mapper4Tx) {
+		this.mapper4Tx = mapper4Tx;
+	}
+
+	@Override
+	public String getClientId(String userId) {
+		AdmClientFlag flagEntity = new AdmClientFlag();
+		flagEntity.setUserId(userId);
+		clientFlagMapper.insert(flagEntity);
+		return String.valueOf(flagEntity.getId());
+	}
+
+	@Override
+	public Dict downloadDict(String groupCode, String projectId, String userId) {
+		return queryDict(groupCode, projectId, userId, true, true);
+	}
+
+	@Override
+	public Dict queryDict(String groupCode, String projectId, String userId, boolean includeRel, boolean includeInfos){
+		//从知识库服务获取专业分类
+		QueryCriteria majorCriteria = ServiceUtil.getQueryCriteria(objectMapper);
+		majorCriteria.getCriteria().put("type", "major");
+		List<Map<String, Object>> majorList = ServiceUtil.call (() -> dicClient.dataQuery(groupCode, projectId, AdmConst.APP_ID, userId, majorCriteria));
+
+		//查询系统和设备定义
+		QueryCriteria criteria = ServiceUtil.getQueryCriteria(objectMapper, AdmConst.OBJ_TYPE_SYSTEM, AdmConst.OBJ_TYPE_EQUIPMENT);
+		List<TypeDef> typeList = ServiceUtil.queryAllPage(() -> rwdClient.queryObjectType(groupCode, projectId, AdmConst.APP_ID, userId, criteria), criteria, new Pagination(500));
+
+		LinkedList<TypeDef> sysList = new LinkedList<>();
+		LinkedList<TypeDef> equipList = new LinkedList<>();
+		for(TypeDef def : typeList){
+			if(def.getObjType().equals(AdmConst.OBJ_TYPE_SYSTEM))
+				sysList.add(def);
+			else if(def.getObjType().equals(AdmConst.OBJ_TYPE_EQUIPMENT))
+				equipList.add(def);
+		}
+
+		Dict data = new Dict();
+		data.setMajor(majorList);
+		data.setSystem(sysList);
+		data.setEquipment(equipList);
+
+		//查询关系定义
+		if(includeRel) {
+			List<RelationDefine> relList = ServiceUtil.call(() -> rwdClient.queryRelDef(groupCode, projectId, AdmConst.APP_ID, userId, new QueryCriteria()));
+			data.setRelation(relList);
+		}
+
+		//查询信息点定义
+		if(includeInfos) {
+			QueryCriteria qc = new QueryCriteria();
+			qc.setCriteria(objectMapper.createObjectNode());
+			List<InfoDef> funcList = ServiceUtil.call(() -> rwdClient.queryFunc(groupCode, projectId, AdmConst.APP_ID, userId, qc));
+			data.setInfos(funcList);
+		}
+
+		return data;
+	}
+
+	@Override
+	public Map<String, Object> downloadConfig(String groupCode, String projectId, String userId) {
+		//配置数据查询
+		List<AdmM2dEquip> m2dTypes = configService.queryM2dEquip(projectId);
+		List<AdmInfosConfig> infosConfig = configService.queryInfosConfig(projectId);
+		List<AdmRelsConfig> relConfig = configService.queryRelsConfig(projectId);
+		List<AdmPipeConfig> pipeConfig = configService.queryPipeConfig(projectId);
+		List<AdmConfig> config = configService.queryCommonConfig(projectId);
+		List<AdmComponent> component = configService.queryComponent(projectId);
+		List<AdmContainerConfig> containerConfig = configService.queryContainerConfig(projectId);
+
+		HashMap<String, Object> data = new HashMap<>();
+		data.put("m2dTypes", m2dTypes);
+		data.put("infosConfig", infosConfig);
+		data.put("relConfig", relConfig);
+		data.put("pipeConfig", pipeConfig);
+		data.put("config", config);
+		data.put("component", component);
+		data.put("containerConfig", containerConfig);
+
+		return data;
+	}
+
+	@Override
+	public Map<String, Object> downloadFrameData(String groupCode, String projectId, String userId) {
+		//TODO 项目修改为从运维平台查询
+		QueryCriteria criteria = ServiceUtil.getQueryCriteria(objectMapper, AdmConst.OBJ_TYPE_PROJECT);
+		List<ObjectNode> prjList = ServiceUtil.call(() -> objectClient.query(groupCode, null, AdmConst.APP_ID, userId, criteria));
+		packInfos(prjList);
+
+		QueryCriteria criteria2 = ServiceUtil.getQueryCriteria(objectMapper, AdmConst.OBJ_TYPE_BUILDING, AdmConst.OBJ_TYPE_FLOOR);
+		List<ObjectNode> bdAndFl = ServiceUtil.call(() -> objectClient.query(groupCode, projectId, AdmConst.APP_ID, userId, criteria2));
+		packInfos(bdAndFl);
+
+		HashMap<String, Object> data = new HashMap<>();
+		data.put("projects", prjList);
+		data.put("buildingsAndFloors", bdAndFl);
+
+		return data;
+	}
+
+	private void packInfos(List<ObjectNode> dataList){
+		if(dataList != null) {
+			for(ObjectNode node : dataList) {
+				handle4Download(node);
+				DataExtrasUtil.packObjExtras(node);
+			}
+		}
+	}
+
+	/** 下载前处理数据结构 */
+	private void handle4Download(ObjectNode node){
+		JsonNode ol = node.get("outline");
+		if(ol != null){
+			try {
+				node.set("outline", objectMapper.readValue(ol.asText(), ArrayNode.class));
+			}catch (Exception e) {
+
+			}
+		}
+		JsonNode bl = node.get("bimLocation");
+		if(bl != null) {
+			try {
+				String[] arr = bl.asText().split(",");
+				ObjectNode ln = objectMapper.createObjectNode();
+				ln.put("x", Double.parseDouble(arr[0]));
+				ln.put("y", Double.parseDouble(arr[1]));
+				ln.put("z", Double.parseDouble(arr[2]));
+				node.set("location", ln);
+				node.remove("bimLocation");
+			}catch (Exception e) {
+
+			}
+		}
+	}
+
+	@Override
+	public BuildingData downloadBuildingData(String projectId, String buildingId, String uploadFlag, String lastDownloadTime) {
+		throw new RuntimeException("not supported");
+	}
+
+	@Override
+	public BuildingData downloadBuildingData(String groupCode, String projectId, String userId, String clientId, String buildingId, Long bdtpDownloadTs, Long admDownloadTs) {
+		String operator = getOperator(clientId, userId);
+
+//		//从bdtp下载对象(空间、竖井)
+//		QueryCriteria archCriteria = ServiceUtil.getQueryCriteria(objectMapper, AdmConst.OBJ_TYPE_SPACE, AdmConst.OBJ_TYPE_SHAFT);
+//		buildDownloadQueryCriteria(archCriteria, operator, bdtpDownloadTs);
+//		ObjectNode rt = archCriteria.getCriteria().putObject("relationTo");
+//		rt.put("graphCode", "ArchSubset");
+//		rt.put("objFrom", buildingId);
+//		List<ObjectNode> archList = ServiceUtil.queryAllPage(() -> objectClient.query(groupCode, projectId, AdmConst.APP_ID, userId, archCriteria), archCriteria, new Pagination(500));
+//		//系统、设备
+//		QueryCriteria eqCriteria = ServiceUtil.getQueryCriteria(objectMapper, AdmConst.OBJ_TYPE_SYSTEM, AdmConst.OBJ_TYPE_EQUIPMENT);
+//		buildDownloadQueryCriteria(eqCriteria, operator, bdtpDownloadTs);
+//		ObjectNode rf = eqCriteria.getCriteria().putObject("relationFrom");
+//		rf.put("graphCode", "MechInArch");
+//		rf.put("objTo", buildingId);
+//		List<ObjectNode> eqList = ServiceUtil.queryAllPage(() -> objectClient.query(groupCode, projectId, AdmConst.APP_ID, userId, eqCriteria), eqCriteria, new Pagination(500));
+//
+//		List<ObjectNode> objs = new ArrayList<>();
+//		if(archList != null)
+//			objs.addAll(archList);
+//		if(eqList != null)
+//			objs.addAll(eqList);
+
+		//从bdtp下载对象(空间、竖井、系统、设备、元空间)
+		QueryCriteria criteria = ServiceUtil.getQueryCriteria(objectMapper, AdmConst.OBJ_TYPE_SPACE, AdmConst.OBJ_TYPE_SHAFT, AdmConst.OBJ_TYPE_SYSTEM, AdmConst.OBJ_TYPE_EQUIPMENT, "ispace");
+		buildDownloadQueryCriteria(criteria, operator, bdtpDownloadTs);
+		criteria.getCriteria().put("buildingId", buildingId);
+
+		List<ObjectNode> objs = ServiceUtil.queryAllPage(() -> objectClient.query(groupCode, projectId, AdmConst.APP_ID, userId, criteria), criteria, new Pagination(500));
+		if(objs == null)
+			objs = new ArrayList<>(0);
+
+		packInfos(objs);
+		test4Ts(objs);
+
+		//关系数据按项目下载,不在建筑数据中处理
+
+		//管道数据,实验方案
+		List<AdmPipe> pipes = pipeMapper.selectList(buildDownloadQueryWrapper(new QueryWrapper<AdmPipe>(), projectId, buildingId, operator, admDownloadTs));
+
+		//任务相关数据查询
+		List<AdmJobSpace> jobSpace = jobSpaceMapper.selectList(buildDownloadQueryWrapper(new QueryWrapper<AdmJobSpace>(), projectId, buildingId, operator, admDownloadTs));
+		List<AdmProblemArch> problemArch = problemArchMapper.selectList(buildDownloadQueryWrapper(new QueryWrapper<AdmProblemArch>(), projectId, buildingId, operator, admDownloadTs));
+		List<AdmProblemEquip> problemEquip = problemEquipMapper.selectList(buildDownloadQueryWrapper(new QueryWrapper<AdmProblemEquip>(), projectId, buildingId, operator, admDownloadTs));
+		List<AdmFile> file = fileMapper.selectList(buildDownloadQueryWrapper(new QueryWrapper<AdmFile>(), projectId, buildingId, operator, admDownloadTs));
+		List<AdmQrCode> qrCode = qrCodeMapper.selectList(buildDownloadQueryWrapper(new QueryWrapper<AdmQrCode>(), projectId, buildingId, operator, admDownloadTs));
+		List<AdmServeArea> serveArea = serveAreaMapper.selectList(buildDownloadQueryWrapper(new QueryWrapper<AdmServeArea>(), projectId, buildingId, operator, admDownloadTs));
+
+		BuildingData data = new BuildingData();
+		data.setBuildingId(buildingId);
+
+		data.setObjects(objs);
+
+		data.setPipes(pipes);
+
+		data.setJobSpace(jobSpace);
+		data.setProblemArch(problemArch);
+		data.setProblemEquip(problemEquip);
+		data.setFile(file);
+		data.setQrCode(qrCode);
+		data.setServeArea(serveArea);
+
+		data.buildDownloadTs();
+		return data;
+	}
+
+	private String getOperator(String clientId, String userId){
+		return userId + ':' + clientId;
+	}
+
+	private <T> QueryWrapper<T> buildDownloadQueryWrapper(QueryWrapper<T> wrapper, String projectId, String buildingId, String operator, Long lastDownloadTime){
+		wrapper.eq("project_id", projectId).eq("building_id", buildingId);
+
+		if (lastDownloadTime != null && lastDownloadTime > 0) { //非初始化下载
+			wrapper.gt("ts", lastDownloadTime);
+
+			wrapper.and(
+					w -> w.isNotNull("modifier").ne("modifier", operator)
+							.or()
+							.isNull("modifier").ne("creator", operator)
+			);
+		}
+
+		return wrapper;
+	}
+
+	private void buildDownloadQueryCriteria(QueryCriteria criteria, String operator, Long lastDownloadTime){
+		if (lastDownloadTime != null && lastDownloadTime > 0) {
+			criteria.getCriteria().putObject("ts").put("$gt", lastDownloadTime);
+			criteria.getCriteria().putObject("modifier").put("$ne", operator); //TODO 暂时只能处理modifier
+		}
+	}
+
+	//TODO debug 接口未返回ts时,添加一个
+	private void test4Ts(List<ObjectNode> dataList){
+		long ts = System.currentTimeMillis();
+		for(ObjectNode data : dataList) {
+			if (data.get("ts") == null)
+				data.put("ts", ts);
+		}
+	}
+
+	@Override
+	public ProjectData downloadProjectData(String groupCode, String projectId, String userId, String clientId, Long bdtpDownloadTs, Long admDownloadTs) {
+		String operator = getOperator(clientId, userId);
+
+		QueryCriteria criteria = ServiceUtil.getQueryCriteria(objectMapper);
+		buildDownloadQueryCriteria(criteria, operator, bdtpDownloadTs);
+		criteria.getCriteria().put("createApp", AdmConst.CREATOR_APP); //TODO 临时逻辑,只下载app端创建的关系
+
+		List<ObjectNode> rels = ServiceUtil.queryAllPage(() -> rwdClient.queryRelation(groupCode, projectId, AdmConst.APP_ID, userId, criteria), criteria, new Pagination(500));
+		/*
+		//debug 关系数据量过大,测试下载1000条
+		criteria.setPage(1L);
+		criteria.setSize(1000L);
+		List<ObjectNode> rels = ServiceUtil.call(() -> rwdClient.queryRelation(groupCode, projectId, AdmConst.APP_ID, userId, criteria));
+		*/
+		if(rels == null)
+			rels = new ArrayList<>();
+
+		//单独下载元空间和空间的对应关系
+		QueryCriteria criteria2 = ServiceUtil.getQueryCriteria(objectMapper);
+		buildDownloadQueryCriteria(criteria2, operator, bdtpDownloadTs);
+		criteria2.getCriteria().put("graphCode", "MechInArch").put("relCode", "Sp2Si").put("relValue", "GeneralZone");
+		List<ObjectNode> spRels = ServiceUtil.queryAllPage(() -> rwdClient.queryRelation(groupCode, projectId, AdmConst.APP_ID, userId, criteria2), criteria2, new Pagination(500));
+		if(spRels != null)
+			rels.addAll(spRels);
+
+		test4Ts(rels);
+
+		ProjectData data = new ProjectData();
+		data.setRelations(rels);
+
+		data.buildDownloadTs();
+		return data;
+	}
+
+	@Override
+	public UploadRtn uploadData(UploadData uploadData, String groupCode, String projectId, String userId, String clientId) {
+		if(!uploadData.notEmpty())
+			return new UploadRtn(AdmConst.UPLOAD_FINISHED);
+
+		String operator = getOperator(clientId, userId);
+		String timestamp = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN);
+
+		UploadParams uploadParams = new UploadParams(groupCode, projectId, userId, uploadData.getUploadJobId(), operator, timestamp);
+
+		//检查上传任务状态
+		String status = checkUploadStatus(uploadParams);
+		if(status != null)
+			return new UploadRtn(status);
+
+
+		List<AdmUploadLog> logs = new ArrayList<>();
+
+		//TODO 分布式事务管理
+		try {
+			//上传bdtp数据
+			List<ObjectNode> relations = new ArrayList<>();
+
+			if (CollUtil.isNotEmpty(uploadData.getObjects())) {
+				D2mMessage d2mMessage = new D2mMessage("object", groupCode, projectId);
+				List<ObjectNode>[] objData = prepareBdtpData(uploadData.getObjects(), uploadParams, d2mMessage, logs);
+				uploadObjs(uploadParams, objData);
+
+				sendD2mMessage(d2mMessage, uploadParams);
+
+				autoRelations(objData[0], relations, uploadParams);
+			}
+
+			if(uploadData.getRelations() != null)
+				relations.addAll(uploadData.getRelations());
+			if (relations.size() > 0) {
+				List<ObjectNode>[] relData = prepareBdtpData(relations, uploadParams, null, logs);
+				uploadRels(uploadParams, relData);
+			}
+
+			//上传adm数据
+			uploadAdmData(uploadData, uploadParams, logs);
+		} catch (Exception e) {
+			markStatus(uploadData.getUploadJobId(), AdmConst.UPLOAD_ERROR);
+
+			if(e instanceof RuntimeException)
+				throw (RuntimeException)e;
+			throw new RuntimeException(e);
+		}
+
+		//标注上传任务状态
+		markStatus(uploadData.getUploadJobId(), AdmConst.UPLOAD_FINISHED);
+
+		//记录日志
+		logService.saveUploadLog(logs);
+
+		return new UploadRtn(AdmConst.UPLOAD_FINISHED);
+	}
+
+	private void autoRelations(List<ObjectNode> newObjs, List<ObjectNode> relations, UploadParams ps){
+		for(ObjectNode obj : newObjs) {
+			if (obj.get("objType") != null && AdmConst.OBJ_TYPE_EQUIPMENT.equals(obj.get("objType").asText())) {
+				String eqId = obj.get("id").asText();
+
+				if(obj.get("buildingId") != null) {
+					String bdId = obj.get("buildingId").asText();
+					relations.add(createRelation(eqId, bdId, "MechInArch", "Eq2Bd", ps.groupCode, ps.projectId));
+				}
+				if(obj.get("floorId") != null) {
+					String flId = obj.get("floorId").asText();
+					relations.add(createRelation(eqId, flId, "MechInArch", "Eq2Fl", ps.groupCode, ps.projectId));
+				}
+			}
+		}
+	}
+
+	private ObjectNode createRelation(String from, String to, String graphCode, String relCode, String groupCode, String projectId){
+		ObjectNode r = objectMapper.createObjectNode();
+		r.put("id", IdUtil.simpleUUID());
+		r.put("objFrom", from);
+		r.put("objTo", to);
+		r.put("graphCode", graphCode);
+		r.put("relCode", relCode);
+		r.put("groupCode", groupCode);
+		r.put("projectId", projectId);
+		r.put("valid", ValidEnum.TRUE.getType());
+		r.put("state", 0); //新增标识
+		return r;
+	}
+
+	private String checkUploadStatus(UploadParams uploadParams){
+		AdmUploadJob job = uploadJobMapper.selectOne(new QueryWrapper<AdmUploadJob>().eq("id", uploadParams.jobId));
+		if(job != null) {
+			if(!AdmConst.UPLOAD_ERROR.equals(job.getStatus()))
+				return job.getStatus();
+		} else {
+			job = new AdmUploadJob();
+			job.setId(uploadParams.jobId);
+			job.setProjectId(uploadParams.projectId);
+			job.setOperator(uploadParams.operator);
+			job.setStatus(AdmConst.UPLOAD_PROCESSING);
+			job.setStartTime(new Timestamp(System.currentTimeMillis()));
+			uploadJobMapper.insert(job);
+		}
+		return null;
+	}
+
+	private void markStatus(String uploadJobId, String status) {
+		AdmUploadJob job = new AdmUploadJob();
+		job.setId(uploadJobId);
+		job.setStatus(status);
+		job.setFinishTime(new Timestamp(System.currentTimeMillis()));
+		uploadJobMapper.updateById(job);
+	}
+
+	private void uploadObjs(UploadParams ps, List<ObjectNode>[] data) {
+		if(data[0].size() > 0)
+			ServiceUtil.call(() -> objectClient.create(ps.groupCode, ps.projectId, AdmConst.APP_ID, ps.userId, data[0]));
+		if (data[1].size() > 0)
+			ServiceUtil.call(() -> objectClient.update(ps.groupCode, ps.projectId, AdmConst.APP_ID, ps.userId, data[1]));
+	}
+
+	private void uploadRels(UploadParams ps, List<ObjectNode>[] data) {
+		if(data[0].size() > 0)
+			ServiceUtil.call(() -> relationClient.create(ps.groupCode, ps.projectId, AdmConst.APP_ID, ps.userId, data[0]));
+		if (data[1].size() > 0)
+			ServiceUtil.call(() -> relationClient.update(ps.groupCode, ps.projectId, AdmConst.APP_ID, ps.userId, data[1]));
+	}
+
+	private List<ObjectNode>[] prepareBdtpData(List<ObjectNode> list, UploadParams uploadParams, D2mMessage d2mMessage, List<AdmUploadLog> logs){
+		List<ObjectNode> updateList = new ArrayList<>();
+		Iterator<ObjectNode> iter = list.iterator();
+		while (iter.hasNext()) {
+			ObjectNode entity = iter.next();
+			DataExtrasUtil.unpackObjExtras(entity);
+			handle4Upload(entity);
+
+			AdmUploadLog log;
+			if (entity.get("state").asInt() == 1) {
+				updateList.add(entity);
+				iter.remove();
+
+				boolean remove = entity.get("valid").asInt() == ValidEnum.FALSE.getType();
+
+				//设备数据上传时向模型服务发同步消息
+				if(d2mMessage != null && needsD2m(entity)) {
+					if(remove)
+						d2mMessage.appendRemoveItem(entity);
+					else
+						d2mMessage.appendModifyItem(entity);
+				}
+
+				log = new AdmUploadLog(uploadParams.jobId, uploadParams.operator, remove ? AdmUploadLog.REMOVE : AdmUploadLog.MODIFY);
+				log.setData(entity, objectMapper);
+
+				entity.put("updateApp", AdmConst.CREATOR_APP);
+				entity.put("modifier", uploadParams.operator);
+				entity.put("modifiedTime", uploadParams.time);
+
+				//TODO 可能需要进行删除信息点操作
+
+			} else {
+				if(d2mMessage != null && needsD2m(entity))
+					d2mMessage.appendAddItem(entity);
+
+				log = new AdmUploadLog(uploadParams.jobId, uploadParams.operator, AdmUploadLog.ADD);
+				log.setData(entity, objectMapper);
+
+				entity.put("createApp", AdmConst.CREATOR_APP);
+				entity.put("creator", uploadParams.operator);
+				entity.put("creationTime", uploadParams.time);
+
+				entity.put("modifier", uploadParams.operator);
+				entity.put("modifiedTime", uploadParams.time);
+			}
+			logs.add(log);
+		}
+
+		return new List[] {list, updateList};
+	}
+
+	private boolean needsD2m(ObjectNode node){
+		return node != null && node.get("objType") != null && AdmConst.OBJ_TYPE_EQUIPMENT.equals(node.get("objType").asText());
+	}
+
+	@Transactional(rollbackFor = Exception.class)
+	public void uploadAdmData(UploadData uploadData, UploadParams uploadParams, List<AdmUploadLog> logs) {
+		if (CollUtil.isNotEmpty(uploadData.getPipes())) {
+			uploadAdmEntities(uploadData.getPipes(), uploadParams, pipeMapper, new D2mMessage("pipe", uploadParams.groupCode, uploadParams.projectId), logs, true);
+		}
+
+		if (CollUtil.isNotEmpty(uploadData.getJobSpace())) {
+			uploadAdmEntities(uploadData.getJobSpace(), uploadParams, jobSpaceMapper, null, logs, false);
+		}
+		if (CollUtil.isNotEmpty(uploadData.getProblemArch())) {
+			uploadAdmEntities(uploadData.getProblemArch(), uploadParams, problemArchMapper, null, logs, false);
+		}
+		if (CollUtil.isNotEmpty(uploadData.getProblemEquip())) {
+			uploadAdmEntities(uploadData.getProblemEquip(), uploadParams, problemEquipMapper, null, logs, false);
+		}
+		if (CollUtil.isNotEmpty(uploadData.getFile())) {
+			uploadAdmEntities(uploadData.getFile(), uploadParams, fileMapper, null, logs, false);
+		}
+		if (CollUtil.isNotEmpty(uploadData.getQrCode())) {
+			uploadAdmEntities(uploadData.getQrCode(), uploadParams, qrCodeMapper, null, logs, false);
+		}
+		if (CollUtil.isNotEmpty(uploadData.getServeArea())) {
+			uploadAdmEntities(uploadData.getServeArea(), uploadParams, serveAreaMapper, null, logs, false);
+		}
+	}
+
+	private <T extends BaseAdmDataEntity> void uploadAdmEntities(List<T> list, UploadParams ps, BaseMapper<T> mapper, D2mMessage d2mMessage, List<AdmUploadLog> logs, boolean merge) {
+		List<T> updateList = new ArrayList<>();
+		Iterator<T> iter = list.iterator();
+		while (iter.hasNext()) {
+			T entity = iter.next();
+
+			AdmUploadLog log;
+			if (entity.getState() == 1) {
+				updateList.add(entity);
+				iter.remove();
+
+				boolean remove = entity.getValid().intValue() == ValidEnum.FALSE.getType();
+
+				if(d2mMessage != null) {
+					if(remove)
+						d2mMessage.appendRemoveItem(entity);
+					else
+						d2mMessage.appendModifyItem(entity);
+				}
+
+				log = new AdmUploadLog(ps.jobId, ps.operator, remove ? AdmUploadLog.REMOVE : AdmUploadLog.MODIFY);
+
+				//任务空间不上传轮廓数据
+				if(entity instanceof AdmJobSpace)
+					((AdmJobSpace) entity).setOutline(null);
+			} else {
+				if(d2mMessage != null)
+					d2mMessage.appendAddItem(entity);
+
+				log = new AdmUploadLog(ps.jobId, ps.operator, AdmUploadLog.ADD);
+			}
+			log.setData(entity, objectMapper);
+			logs.add(log);
+
+			entity.setTs(null); //保存数据前,删除ts字段
+		}
+
+		//insert
+		if(list.size() > 0) {
+			for(T entity : list) {
+				entity.setCreator(ps.operator);
+				entity.setCreationTime(ps.time);
+				mapper.insert(entity);
+			}
+		}
+
+		//update
+		if (updateList.size() > 0) {
+			Map<String, T> dbObjsMap = null;
+			if(merge) {
+				ArrayList<String> updateIds = new ArrayList<>(updateList.size());
+				updateList.forEach(entity -> updateIds.add(entity.getId()));
+				List<T> dbList = mapper.selectBatchIds(updateIds);
+
+				dbObjsMap = new HashMap<>(dbList.size());
+				for(T dbObj : dbList) {
+					dbObjsMap.put(dbObj.getId(), dbObj);
+				}
+			}
+
+			for(T entity : updateList) {
+				if(merge)
+					entity = mergeEntity(entity, dbObjsMap.get(entity.getId()));
+
+				entity.setModifier(ps.operator);
+				entity.setModifiedTime(ps.time);
+				mapper.updateById(entity);
+			}
+		}
+
+		sendD2mMessage(d2mMessage, ps);
+	}
+
+	private <T extends BaseAdmDataEntity> T mergeEntity(T obj, T dbObj) {
+		if (dbObj != null) {
+			if(dbObj instanceof AdmPipe)
+				((AdmPipe)obj).setInfos(mergeInfos(((AdmPipe) obj).getInfos(), ((AdmPipe) dbObj).getInfos()));
+		}
+		return obj;
+	}
+
+	private ObjectNode mergeInfos(ObjectNode infos, ObjectNode dbInfos){
+		if (dbInfos != null) {
+			if(infos != null)
+				dbInfos.setAll(infos);
+			return dbInfos;
+		} else
+			return infos;
+	}
+
+	private void sendD2mMessage(D2mMessage d2mMessage, UploadParams ps){
+		if (d2mMessage != null && d2mMessage.isNotEmpty()) {
+//			if(d2mMessage.getAddItems() != null){
+//				for(Object o : d2mMessage.getAddItems()) {
+//					markM2dState(o);
+//				}
+//			}
+//			if(d2mMessage.getModifyItems() != null){
+//				for(Object o : d2mMessage.getModifyItems()) {
+//					markM2dState(o);
+//				}
+//			}
+//			if(d2mMessage.getRemoveItems() != null) {
+//				for(Object o : d2mMessage.getRemoveItems()) {
+//					markM2dState(o);
+//				}
+//			}
+			markM2dState(d2mMessage, ps);
+			syncModel.sendMessageToModel(d2mMessage);
+		}
+	}
+
+	/** 上传前处理数据结构 */
+	private void handle4Upload(ObjectNode node){
+		node.remove("ts"); //调用bdtp接口前,删除ts字段
+
+		//轮廓不上传
+		if(node.get("outline") != null)
+			node.remove("outline");
+
+		//location对象转为bimLocation
+		JsonNode l = node.get("location");
+		if(l != null) {
+			try {
+				if(l.get("x") != null)
+					node.put("bimLocation", StrUtil.join(",", l.get("x").asDouble(), l.get("y").asDouble(), l.get("z").asDouble()));
+				else if(l.get("X") != null)
+					node.put("bimLocation", StrUtil.join(",", l.get("X").asDouble(), l.get("Y").asDouble(), l.get("Z").asDouble()));
+				node.remove("location");
+			}catch (Exception e) {
+
+			}
+		}
+	}
+
+	private void markM2dState(D2mMessage d2mMessage, UploadParams ps){
+		AdmMessageP message = new AdmMessageP();
+		message.setId(d2mMessage.getId());
+		message.setProjectId(ps.projectId);
+		message.setTriggerType("upload");
+		message.setSender(ps.jobId);
+		message.setContent(d2mMessage);
+		message.setStatus(AdmConst.UPLOAD_PROCESSING);
+		message.setSendTime(new Timestamp(System.currentTimeMillis()));
+
+		messageMapper.insert(message);
+	}
+
+	private class UploadParams{
+
+		String groupCode;
+
+		String projectId;
+
+		String userId;
+
+		String jobId;
+
+		String operator;
+
+		String time;
+
+		public UploadParams(String groupCode, String projectId, String userId, String jobId, String operator, String time) {
+			this.groupCode = groupCode;
+			this.projectId = projectId;
+			this.userId = userId;
+			this.jobId = jobId;
+			this.operator = operator;
+			this.time = time;
+		}
+
+	}
+
+}

+ 498 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/impl/SyncAppImpl0.java

@@ -0,0 +1,498 @@
+package com.persagy.bdtp.adm.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.bdtp.adm.client.DicClient;
+import com.persagy.bdtp.adm.client.RwdClient;
+import com.persagy.bdtp.adm.common.AdmConst;
+import com.persagy.bdtp.adm.common.AdmResult;
+import com.persagy.bdtp.adm.dao.*;
+import com.persagy.bdtp.adm.entity.*;
+import com.persagy.bdtp.adm.entity.db.*;
+import com.persagy.bdtp.adm.entity.oldadm.OProject;
+import com.persagy.bdtp.adm.service.*;
+import com.persagy.dmp.basic.model.QueryCriteria;
+import com.persagy.dmp.common.constant.ResponseCode;
+import com.persagy.dmp.common.constant.ValidEnum;
+import com.persagy.dmp.common.exception.BusinessException;
+import com.persagy.dmp.common.model.response.CommonResult;
+import com.persagy.dmp.define.entity.RelationDefine;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.IOException;
+import java.util.*;
+import java.util.function.Supplier;
+
+@Service
+public class SyncAppImpl0 implements ISyncApp {
+
+	@Autowired
+	private IAdmObjectService objectService;
+
+	@Autowired
+	private IQueryFromOldAdm queryOldAdm;
+
+	@Autowired
+	private RwdClient rwdClient;
+
+	@Autowired
+	private DicClient dicClient;
+
+	@Autowired
+	private IConfigService configService;
+
+
+	@Autowired
+	private AdmObjectMapper admObjMapper;
+
+	@Autowired
+	private AdmRelationMapper relationMapper;
+
+	@Autowired
+	private AdmPipeMapper pipeMapper;
+
+	@Autowired
+	private AdmJobSpaceMapper jobSpaceMapper;
+
+	@Autowired
+	private AdmProblemArchMapper problemArchMapper;
+
+	@Autowired
+	private AdmProblemEquipMapper problemEquipMapper;
+
+	@Autowired
+	private AdmFileMapper fileMapper;
+
+	@Autowired
+	private AdmQrCodeMapper qrCodeMapper;
+
+	@Autowired
+	private AdmServeAreaMapper serveAreaMapper;
+
+	@Autowired
+	private ISyncModel syncModel;
+
+	@Autowired
+	private ObjectMapper objectMapper;
+
+	@Autowired
+	private IAdmLogService logService;
+
+	@Autowired
+	ResourceLoader resourceLoader;
+
+	@Override
+	public String getClientId(String userId) {
+		return IdUtil.fastSimpleUUID();
+	}
+
+	@Override
+	public Dict downloadDict(String groupCode, String projectId, String userId) {
+		//临时方案,腾讯云生产环境没有数据字典4.0,从本地文件加载
+		try{
+			Resource resource = resourceLoader.getResource("classpath:dict.json");
+			return objectMapper.readValue(resource.getInputStream(), Dict.class);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+
+		return queryDict(groupCode, projectId, userId, true, true);
+	}
+
+	@Override
+	public Map<String, Object> downloadConfig(String groupCode, String projectId, String userId) {
+		//配置数据查询
+		List<AdmM2dEquip> m2dTypes = configService.queryM2dEquip(projectId);
+		List<AdmInfosConfig> infosConfig = configService.queryInfosConfig(projectId);
+		List<AdmRelsConfig> relConfig = configService.queryRelsConfig(projectId);
+		List<AdmPipeConfig> pipeConfig = configService.queryPipeConfig(projectId);
+		List<AdmConfig> config = configService.queryCommonConfig(projectId);
+		List<AdmComponent> component = configService.queryComponent(projectId);
+		List<AdmContainerConfig> containerConfig = configService.queryContainerConfig(projectId);
+
+		HashMap<String, Object> data = new HashMap<>();
+		data.put("m2dTypes", m2dTypes);
+		data.put("infosConfig", serializeJsonProp(infosConfig));
+		data.put("relConfig", relConfig);
+		data.put("pipeConfig", pipeConfig);
+		data.put("config", serializeJsonProp(config));
+		data.put("component", component);
+		data.put("containerConfig", containerConfig);
+
+		return data;
+	}
+
+	@Override
+	public Dict queryDict(String groupCode, String projectId, String userId, boolean includeRel, boolean includeInfos){
+		boolean newDict = "JD".equalsIgnoreCase(groupCode);
+
+		//从知识库服务获取专业分类
+		QueryCriteria majorCriteria = ServiceUtil.getQueryCriteria(objectMapper);
+		majorCriteria.getCriteria().put("type", "major");
+		List<Map<String, Object>> majorList = ServiceUtil.call (() -> dicClient.dataQuery(groupCode, projectId, AdmConst.APP_ID, userId, majorCriteria));
+
+		//查询系统和设备定义
+		QueryCriteria criteria = ServiceUtil.getQueryCriteria(objectMapper, "system", "equipment");
+		List<TypeDef> typeList = ServiceUtil.queryAllPage(() -> rwdClient.queryObjectType(groupCode, projectId, AdmConst.APP_ID, userId, criteria), criteria, new Pagination(500));
+
+		//查询重命名设备类型
+		ObjectNode renameNode = !newDict ? configService.queryRenameEquipTypes(projectId) : null;
+
+		LinkedList<TypeDef> sysList = new LinkedList<>();
+		LinkedList<TypeDef> equipList = new LinkedList<>();
+		for(TypeDef def : typeList){
+			if(def.getObjType().equals("system"))
+				sysList.add(def);
+			else if(def.getObjType().equals("equipment")) {
+				if(!newDict) {
+					if (renameNode != null) { //设备类型重命名
+						JsonNode n = renameNode.get(def.getCode());
+						if(n != null)
+							def.setName(n.asText());
+					}
+				}
+				equipList.add(def);
+			}
+		}
+
+		//加载新增的自定义设备类
+//		try{
+//			Resource resource = resourceLoader.getResource("classpath:equip.json");
+//			List<TypeDef> types = objectMapper.readValue(resource.getInputStream(), new TypeReference<List<TypeDef>>(){});
+//			equipList.addAll(types);
+//		}catch (Exception e) {
+//
+//		}
+		if(!newDict) {
+			ArrayNode arr = configService.queryNewEquipTypes(projectId);
+			if(arr != null) {
+				try{
+					List<TypeDef> types = objectMapper.readValue(objectMapper.writeValueAsString(arr), new TypeReference<List<TypeDef>>(){});
+					equipList.addAll(types);
+				}catch (Exception e) {
+
+				}
+			}
+		}
+
+		Dict data = new Dict();
+		data.setMajor(majorList);
+		data.setSystem(sysList);
+		data.setEquipment(equipList);
+
+		//查询关系定义
+		if(includeRel) {
+			List<RelationDefine> relList = ServiceUtil.call(() -> rwdClient.queryRelDef(groupCode, projectId, AdmConst.APP_ID, userId, new QueryCriteria()));
+			data.setRelation(relList);
+		}
+		//查询信息点定义
+		if(includeInfos) {
+			QueryCriteria qc = new QueryCriteria();
+			qc.setCriteria(objectMapper.createObjectNode());
+			List<InfoDef> funcList = ServiceUtil.call(() -> rwdClient.queryFunc(groupCode, projectId, AdmConst.APP_ID, userId, qc));
+			data.setInfos(funcList);
+		}
+
+		return data;
+	}
+
+	@Override
+	public Map<String, Object> downloadFrameData(String groupCode, String projectId, String userId) {
+		List<OProject> prjList = null;
+		String token = queryOldAdm.login();
+		if(StrUtil.isNotBlank(token))
+			prjList = queryOldAdm.queryProject(token, groupCode, projectId);
+		else
+			throw new CallException(new AdmResult(ResponseCode.A0220.getCode(), "ADM platform: " + ResponseCode.A0220.getDesc()));
+
+		String[] prjIds = new String[prjList.size()];
+		for (int i = 0; i < prjIds.length; i++) {
+			prjIds[i] = prjList.get(i).getId();
+		}
+		List<AdmObject> bdAndFl = objectService.queryBdAndFl(prjIds);
+
+		HashMap<String, Object> data = new HashMap<>();
+		data.put("projects", prjList);
+		data.put("buildingsAndFloors", serializeJsonProp(bdAndFl));
+		return data;
+	}
+
+	@Override
+	public BuildingData downloadBuildingData(String projectId, String buildingId, String uploadFlag, String lastDownloadTime) {
+		List<AdmObject> bdData = admObjMapper.selectList(buildDownloadQueryWrapper(new QueryWrapper<AdmObject>(), projectId, buildingId, uploadFlag, lastDownloadTime));
+		List<AdmRelation> bdRel = relationMapper.selectList(buildDownloadQueryWrapper(new QueryWrapper<AdmRelation>(), projectId, buildingId, uploadFlag, lastDownloadTime));
+		List<AdmPipe> pipes = pipeMapper.selectList(buildDownloadQueryWrapper(new QueryWrapper<AdmPipe>(), projectId, buildingId, uploadFlag, lastDownloadTime));
+
+		//任务相关数据查询
+		List<AdmJobSpace> jobSpace = jobSpaceMapper.selectList(buildDownloadQueryWrapper(new QueryWrapper<AdmJobSpace>(), projectId, buildingId, uploadFlag, lastDownloadTime));
+		List<AdmProblemArch> problemArch = problemArchMapper.selectList(buildDownloadQueryWrapper(new QueryWrapper<AdmProblemArch>(), projectId, buildingId, uploadFlag, lastDownloadTime));
+		List<AdmProblemEquip> problemEquip = problemEquipMapper.selectList(buildDownloadQueryWrapper(new QueryWrapper<AdmProblemEquip>(), projectId, buildingId, uploadFlag, lastDownloadTime));
+		List<AdmFile> file = fileMapper.selectList(buildDownloadQueryWrapper(new QueryWrapper<AdmFile>(), projectId, buildingId, uploadFlag, lastDownloadTime));
+		List<AdmQrCode> qrCode = qrCodeMapper.selectList(buildDownloadQueryWrapper(new QueryWrapper<AdmQrCode>(), projectId, buildingId, uploadFlag, lastDownloadTime));
+		List<AdmServeArea> serveArea = serveAreaMapper.selectList(buildDownloadQueryWrapper(new QueryWrapper<AdmServeArea>(), projectId, buildingId, uploadFlag, lastDownloadTime));
+
+		BuildingData data = new BuildingData();
+		data.setBuildingId(buildingId);
+
+		data.setObjects(serializeJsonProp(bdData));
+		data.setRelations(bdRel);
+		data.setPipes(serializeJsonProp(pipes));
+
+		data.setJobSpace(serializeJsonProp(jobSpace));
+		data.setProblemArch(serializeJsonProp(problemArch));
+		data.setProblemEquip(problemEquip);
+		data.setFile(file);
+		data.setQrCode(serializeJsonProp(qrCode));
+		data.setServeArea(serveArea);
+		data.setTimestamp(DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN));
+
+		return data;
+	}
+
+	private <T> QueryWrapper<T> buildDownloadQueryWrapper(QueryWrapper<T> wrapper, String projectId, String buildingId, String uploadFlag, String lastDownloadTime){
+		wrapper.eq("project_id", projectId).eq("building_id", buildingId);
+		applyUploadFlag(wrapper, uploadFlag,lastDownloadTime);
+		return wrapper;
+	}
+
+	private void applyUploadFlag(QueryWrapper<?> wrapper, String uploadFlag, String lastDownloadTime){
+		if (StrUtil.isNotBlank(lastDownloadTime)) { //非初始化下载
+			if (StrUtil.isNotBlank(uploadFlag))
+				wrapper.and(w -> w.isNull("upload_flag").or().ne("upload_flag", uploadFlag));
+
+			wrapper.and(
+					w -> w.isNotNull("modified_time").gt("modified_time", lastDownloadTime)
+							.or()
+							.isNull("modified_time").gt("creation_time", lastDownloadTime)
+			);
+		}
+	}
+
+	@Override
+	public BuildingData downloadBuildingData(String groupCode, String projectId, String userId, String uploadFlag, String buildingId, Long bdtpDownloadTs, Long admDownloadTs) {
+		throw new RuntimeException("not supported");
+	}
+
+	@Override
+	public ProjectData downloadProjectData(String groupCode, String projectId, String userId, String uploadFlag, Long bdtpDownloadTs, Long admDownloadTs) {
+		throw new RuntimeException("not supported");
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public UploadRtn uploadData(UploadData uploadData, String groupCode, String projectId, String userId, String uploadFlag) {
+		UploadRtn rtn = new UploadRtn();
+		String timestamp = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN);
+
+		if (CollUtil.isNotEmpty(uploadData.getObjects())) {
+			List<AdmObject> dbObjs = admObjMapper.selectList(new QueryWrapper<AdmObject>().eq("building_id", uploadData.getBuildingId()).eq("valid", ValidEnum.TRUE.getType()));
+			List<AdmObject> expired = uploadAdmData(deserializeJsonProp(toEntities(uploadData.getObjects(), AdmObject.class)), dbObjs, uploadFlag, timestamp, admObjMapper, "object");
+			rtn.setExpiredObjectIds(buildExpiredIds(expired));
+		}
+		if (CollUtil.isNotEmpty(uploadData.getRelations())) {
+			List<AdmRelation> dbObjs = relationMapper.selectList(new QueryWrapper<AdmRelation>().eq("building_id", uploadData.getBuildingId()).eq("valid", ValidEnum.TRUE.getType()));
+			List<AdmRelation> expired = uploadAdmData(toEntities(uploadData.getRelations(), AdmRelation.class), dbObjs, uploadFlag, timestamp, relationMapper, "relation");
+			rtn.setExpiredRelationIds(buildExpiredIds(expired));
+		}
+
+		if (CollUtil.isNotEmpty(uploadData.getPipes())) {
+			List<AdmPipe> dbObjs = pipeMapper.selectList(new QueryWrapper<AdmPipe>().eq("building_id", uploadData.getBuildingId()).eq("valid", ValidEnum.TRUE.getType()));
+			List<AdmPipe> expired = uploadAdmData(deserializeJsonProp(uploadData.getPipes()), dbObjs, uploadFlag, timestamp, pipeMapper, "pipe");
+			rtn.setExpiredPipeIds(buildExpiredIds(expired));
+		}
+
+		if (CollUtil.isNotEmpty(uploadData.getJobSpace())) {
+			List<AdmJobSpace> dbObjs = jobSpaceMapper.selectList(new QueryWrapper<AdmJobSpace>().eq("building_id", uploadData.getBuildingId()).eq("valid", ValidEnum.TRUE.getType()));
+			List<AdmJobSpace> expired = uploadAdmData(deserializeJsonProp(uploadData.getJobSpace()), dbObjs, uploadFlag, timestamp, jobSpaceMapper, null);
+			rtn.setExpiredJobSpaceIds(buildExpiredIds(expired));
+		}
+		if (CollUtil.isNotEmpty(uploadData.getProblemArch())) {
+			List<AdmProblemArch> dbObjs = problemArchMapper.selectList(new QueryWrapper<AdmProblemArch>().eq("building_id", uploadData.getBuildingId()).eq("valid", ValidEnum.TRUE.getType()));
+			List<AdmProblemArch> expired = uploadAdmData(deserializeJsonProp(uploadData.getProblemArch()), dbObjs, uploadFlag, timestamp, problemArchMapper, null);
+			rtn.setExpiredProblemArchIds(buildExpiredIds(expired));
+		}
+		if (CollUtil.isNotEmpty(uploadData.getProblemEquip())) {
+			List<AdmProblemEquip> dbObjs = problemEquipMapper.selectList(new QueryWrapper<AdmProblemEquip>().eq("building_id", uploadData.getBuildingId()).eq("valid", ValidEnum.TRUE.getType()));
+			List<AdmProblemEquip> expired = uploadAdmData(uploadData.getProblemEquip(), dbObjs, uploadFlag, timestamp, problemEquipMapper, null);
+			rtn.setExpiredProblemEquipIds(buildExpiredIds(expired));
+		}
+		if (CollUtil.isNotEmpty(uploadData.getFile())) {
+			List<AdmFile> dbObjs = fileMapper.selectList(new QueryWrapper<AdmFile>().eq("building_id", uploadData.getBuildingId()).eq("valid", ValidEnum.TRUE.getType()));
+			List<AdmFile> expired = uploadAdmData(uploadData.getFile(), dbObjs, uploadFlag, timestamp, fileMapper, null);
+			rtn.setExpiredFileIds(buildExpiredIds(expired));
+		}
+		if (CollUtil.isNotEmpty(uploadData.getQrCode())) {
+			List<AdmQrCode> dbObjs = qrCodeMapper.selectList(new QueryWrapper<AdmQrCode>().eq("building_id", uploadData.getBuildingId()).eq("valid", ValidEnum.TRUE.getType()));
+			List<AdmQrCode> expired = uploadAdmData(deserializeJsonProp(uploadData.getQrCode()), dbObjs, uploadFlag, timestamp, qrCodeMapper, null);
+			rtn.setExpiredQrCodeIds(buildExpiredIds(expired));
+		}
+		if (CollUtil.isNotEmpty(uploadData.getServeArea())) {
+			List<AdmServeArea> dbObjs = serveAreaMapper.selectList(new QueryWrapper<AdmServeArea>().eq("building_id", uploadData.getBuildingId()).eq("valid", ValidEnum.TRUE.getType()));
+			List<AdmServeArea> expired = uploadAdmData(uploadData.getServeArea(), dbObjs, uploadFlag, timestamp, serveAreaMapper, null);
+			rtn.setExpiredServeAreaIds(buildExpiredIds(expired));
+		}
+
+		rtn.setTimestamp(timestamp);
+		rtn.setBuildingId(uploadData.getBuildingId());
+		return rtn;
+	}
+
+	private <T extends BaseAdmDataEntity> List<T> toEntities(List<ObjectNode> list, Class<T> cls){
+		List<T> entities = new ArrayList<>(list.size());
+		try {
+			for(ObjectNode node : list) {
+				entities.add(objectMapper.readValue(node.toString(), cls));
+			}
+		} catch (IOException e) {
+			throw new BusinessException(ResponseCode.A0427.getCode(), ResponseCode.A0427.getDesc());
+		}
+		return entities;
+	}
+
+	private <T extends BaseAdmDataEntity> List<T> uploadAdmData(List<T> objs, List<T> dbObjs, String uploadFlag, String timestamp, BaseMapper<T> mapper, String d2mType){
+		List<T> expired = new ArrayList<>();
+		HashMap<String, T> dbMap = new HashMap<>(dbObjs.size());
+		for(T dbObj : dbObjs) {
+			dbMap.put(dbObj.getId(), dbObj);
+		}
+
+		List<T> msgAdd = new ArrayList<>();
+		List<T> msgModify = new ArrayList<>();
+		List<T> msgRemove = new ArrayList<>();
+		for (T obj : objs) {
+			if(obj == null)
+				continue;
+
+			logService.saveUploadLog(new AdmUploadLog());
+
+			T dbObj = dbMap.get(obj.getId());
+			if (dbObj == null) {
+				if(obj.getValid().intValue() == ValidEnum.FALSE.getType())
+					continue;
+
+				obj.setCreationTime(timestamp);
+				obj.setCreator(AdmConst.CREATOR_APP);
+				//obj.setUploadFlag(uploadFlag);
+
+				if(d2mType != null)
+					setDeliveryDataProps((BaseDeliveryEntity) obj, null);
+
+				mapper.insert(obj);
+
+				if(d2mType != null)
+					msgAdd.add(obj);
+			} else {
+//				String dbTs;
+//				String ts;
+//				if(dbObj.getModifiedTime() != null){
+//					dbTs = dbObj.getModifiedTime();
+//					ts = obj.getModifiedTime();
+//				} else {
+//					dbTs = dbObj.getCreationTime();
+//					ts = obj.getCreationTime();
+//				}
+//				if (!dbTs.equals(ts)) {
+//					//TODO 时间戳不一致,离线数据无效,暂时跳过处理
+//					expired.add(obj);
+//				} else {
+					obj.setModifiedTime(timestamp);
+					obj.setModifier(AdmConst.CREATOR_APP);
+					//obj.setUploadFlag(uploadFlag);
+
+					if(d2mType != null)
+						setDeliveryDataProps((BaseDeliveryEntity) obj, null);
+
+					//合并信息点
+					if(dbObj instanceof AdmObject && obj instanceof AdmObject)
+						((AdmObject) obj).setInfos(mergeInfos(((AdmObject) obj).getInfos(), ((AdmObject) dbObj).getInfos()));
+					else if(dbObj instanceof AdmPipe && obj instanceof AdmPipe)
+						((AdmPipe) obj).setInfos(mergeInfos(((AdmPipe) obj).getInfos(), ((AdmPipe) dbObj).getInfos()));
+
+					mapper.updateById(obj);
+
+					if(d2mType != null) {
+						if(obj.getValid().intValue() == ValidEnum.FALSE.getType())
+							msgRemove.add(obj);
+						else
+							msgModify.add(obj);
+					}
+//				}
+			}
+		}
+
+		if(d2mType != null)
+			sendD2mMessage(d2mType, msgAdd, msgModify, msgRemove);
+
+		return expired;
+	}
+
+	private void setDeliveryDataProps(BaseDeliveryEntity obj, BaseDeliveryEntity dbObj){
+		obj.setD2mState(ValidEnum.FALSE.getType());
+		obj.setDeliveryState(ValidEnum.FALSE.getType());
+
+		if(dbObj != null) {
+			obj.setClientId(dbObj.getClientId());
+			obj.setClientDevice(dbObj.getClientDevice());
+		}
+	}
+
+	private ObjectNode mergeInfos(ObjectNode infos, ObjectNode dbInfos){
+		if(dbInfos != null) {
+			if(infos != null)
+				dbInfos.setAll(infos);
+			return dbInfos;
+		} else
+			return infos;
+	}
+
+	private void sendD2mMessage(String objectType, List msgAdd, List msgModify, List msgRemove){
+		D2mMessage message = new D2mMessage(objectType, "", "");
+		message.setAddItems(msgAdd);
+		message.setModifyItems(msgModify);
+		message.setRemoveItems(msgRemove);
+
+		if(message.isNotEmpty())
+			syncModel.sendMessageToModel(message);
+	}
+
+	private List<String> buildExpiredIds(List<? extends BaseAdmDataEntity> expired){
+		if(expired.size() > 0) {
+			List<String> ids = new ArrayList<>();
+			for(BaseAdmDataEntity entity : expired) {
+				ids.add(entity.getId());
+			}
+			return ids;
+		}
+		return null;
+	}
+
+	private <T extends BaseAdmEntity> List<T> serializeJsonProp(List<T> list){
+		//app端完善,不需要做tostr处理了
+//		for(BaseAdmEntity entity : list) {
+//			entity.serializeJsonProp();
+//		}
+		return list;
+	}
+
+	private <T extends BaseAdmEntity> List<T> deserializeJsonProp(List<T> list){
+		for(BaseAdmEntity entity : list) {
+			entity.deserializeJsonProp();
+		}
+		return list;
+	}
+
+}

+ 27 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/impl/SyncModelImpl.java

@@ -0,0 +1,27 @@
+package com.persagy.bdtp.adm.service.impl;
+
+import com.persagy.bdtp.adm.common.AdmMessageConst;
+import com.persagy.bdtp.adm.entity.D2mMessage;
+import com.persagy.bdtp.adm.service.ISyncModel;
+import com.persagy.bdtp.adm.util.AdmMessageHelper;
+import org.springframework.amqp.core.Message;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class SyncModelImpl implements ISyncModel {
+
+	@Autowired
+	private AdmMessageHelper messageHelper;
+
+	@Override
+	public void sendMessageToModel(D2mMessage message) {
+		messageHelper.sendMessage(message, AdmMessageConst.ADM_D2M_ROUTING, false);
+	}
+
+	@Override
+	public void handleModelMessage(String message, Message vo) {
+		//TODO 处理模型计算返回结果:标注状态, 增加对象
+	}
+
+}

+ 571 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/impl/SyncOldAdmImpl.java

@@ -0,0 +1,571 @@
+package com.persagy.bdtp.adm.service.impl;
+
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.ReflectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.bdtp.adm.client.OldAdmClient;
+import com.persagy.bdtp.adm.common.AdmConst;
+import com.persagy.bdtp.adm.common.AdmResult;
+import com.persagy.bdtp.adm.dao.AdmJobSpaceMapper;
+import com.persagy.bdtp.adm.dao.AdmObjectMapper;
+import com.persagy.bdtp.adm.entity.db.AdmJobSpace;
+import com.persagy.bdtp.adm.entity.db.AdmObject;
+import com.persagy.bdtp.adm.entity.oldadm.*;
+import com.persagy.bdtp.adm.service.CallException;
+import com.persagy.bdtp.adm.service.IAdmObjectService;
+import com.persagy.bdtp.adm.service.IQueryFromOldAdm;
+import com.persagy.bdtp.adm.service.ISyncOldAdm;
+import com.persagy.bdtp.adm.util.GeomUtil;
+import com.persagy.dmp.common.constant.ResponseCode;
+import com.persagy.dmp.common.constant.ValidEnum;
+import com.persagy.dmp.common.exception.BusinessException;
+import com.persagy.dmp.common.helper.SpringHelper;
+//import com.persagy.dmp.file.client.FileClientFacade;
+//import com.persagy.dmp.file.model.FileInfo;
+//import com.persagy.dmp.file.model.FileInfoCreator;
+//import com.persagy.dmp.storage.utils.FileStorageHelper;
+import feign.Response;
+import org.locationtech.jts.geom.Polygon;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+public class SyncOldAdmImpl implements ISyncOldAdm {
+
+	@Autowired
+	private IQueryFromOldAdm queryOldAdm;
+
+	@Autowired
+	private IAdmObjectService objectService;
+
+	@Autowired
+	private AdmObjectMapper objectMapper;
+
+	@Autowired
+	private AdmJobSpaceMapper jobSpaceMapper;
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public Map<String, Object> syncData(String groupCode, String projectId) {
+		String token = queryOldAdm.login();
+		if(StrUtil.isNotBlank(token)){
+			List<OBuilding> bdList = queryOldAdm.queryBdAnFl(token, groupCode, projectId);
+
+			List<OSpace> spList = queryOldAdm.querySpace(token, groupCode, projectId);
+			spList = spList.stream().filter(space -> GeomUtil.checkPolygon(space.getOutline())).collect(Collectors.toList());
+
+			List<OEquip> eqList  = queryOldAdm.queryEquip(token, groupCode, projectId);
+
+			List<AdmObject> bdObjs = new ArrayList<>(bdList.size());
+			List<AdmObject> flObjs = new ArrayList<>();
+			List<AdmObject> spObjs = new ArrayList<>(spList.size());
+			List<AdmObject> eqObjs = new ArrayList<>(eqList.size());
+
+			transEntities(bdObjs, bdList, (bdObj, oBd) -> {
+				setBdData(bdObj, (OBuilding) oBd);
+				if(((OBuilding) oBd).getFloor() != null)
+					transEntities(flObjs, ((OBuilding) oBd).getFloor(), (flObj, oFl) -> setFlData(flObj, (OFloor) oFl));
+			});
+
+			transEntities(spObjs, spList, (spObj, oSp) -> setSpData(spObj, (OSpace) oSp));
+			transEntities(eqObjs, eqList, (eqObj, oEq) -> setEqData(eqObj, (OEquip) oEq));
+
+			Map<String, String> floorIdMap = new HashMap<>();
+			List<AdmObject> dbBds = objectService.queryM2dByObjType(projectId, AdmConst.OBJ_TYPE_BUILDING);
+			List<AdmObject> dbFls = objectService.queryM2dByObjType(projectId, AdmConst.OBJ_TYPE_FLOOR);
+			List<AdmObject> dbSps = objectService.queryM2dByObjType(projectId, AdmConst.OBJ_TYPE_SPACE);
+			List<AdmObject> dbEqs = objectService.queryM2dByObjType(projectId, AdmConst.OBJ_TYPE_EQUIPMENT);
+
+			List<AdmObject>[] operations = new List[]{new ArrayList<>(), new ArrayList<>()};
+
+			syncObjs(bdObjs, dbBds, operations, 1, floorIdMap);
+			syncObjs(flObjs, dbFls, operations, 2, floorIdMap);
+			syncObjs(spObjs, dbSps, operations, 3, floorIdMap);
+			syncObjs(eqObjs, dbEqs, operations, 4, floorIdMap);
+
+			objectService.insert(operations[0]);
+			objectService.update(operations[1]);
+
+			/*uploadFloorMap(flObjs, groupCode, projectId);*/
+			HashMap<String, Object> rtn = new HashMap<>();
+			rtn.put(AdmConst.OBJ_TYPE_BUILDING, bdObjs.size());
+			rtn.put(AdmConst.OBJ_TYPE_FLOOR, flObjs.size());
+			rtn.put(AdmConst.OBJ_TYPE_SPACE, spObjs.size());
+			rtn.put(AdmConst.OBJ_TYPE_EQUIPMENT, eqObjs.size());
+
+			return rtn;
+		}
+		throw new CallException(new AdmResult(ResponseCode.A0220.getCode(), "ADM platform: " + ResponseCode.A0220.getDesc()));
+	}
+
+	//TODO 设备同步时,按正逆向规则过滤
+	private void syncObjs(List<AdmObject> objs, List<AdmObject> dbItems, List<AdmObject>[] operations, int objMark, Map<String, String> floorIdMap){
+		HashMap<String, AdmObject> dbMap = new HashMap<>();
+		for (AdmObject dbItem : dbItems){
+			dbMap.put(getFixedIdForSync(dbItem, objMark), dbItem);
+		}
+
+		String timestamp =  DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN);
+
+		for(AdmObject obj : objs) {
+			AdmObject dbItem = dbMap.remove(getFixedIdForSync(obj, objMark));
+			if(dbItem == null) {
+				obj.setCreator(AdmConst.CREATOR_SYNC);
+				obj.setModifiedTime(timestamp); //保留从老adm同步过来的createTime,设置updateTime
+				obj.setD2mState(ValidEnum.TRUE.getType());
+				obj.setDeliveryState(ValidEnum.FALSE.getType());
+
+				if(objMark == 3 || objMark == 4) { //新增空间|设备
+					if(floorIdMap.size() > 0){
+						String fixedFloorId = floorIdMap.get(obj.getFloorId());
+						if(fixedFloorId != null)
+							obj.setFloorId(fixedFloorId);
+					}
+				}
+
+				operations[0].add(obj); //add
+			} else {
+				AdmObject updateItem = mergeObj(obj, dbItem, timestamp, objMark);
+				if(updateItem != null)
+					operations[1].add(updateItem); //modify
+
+				if(objMark == 2 && !obj.getId().equals(dbItem.getId())) {
+					floorIdMap.put(obj.getId(), dbItem.getId());
+				}
+			}
+		}
+
+		if (dbMap.size() > 0) { //remove
+			for(AdmObject obj : dbMap.values()){
+				obj.setValid(ValidEnum.FALSE.getType());
+				obj.setModifiedTime(timestamp);
+				obj.setModifier(AdmConst.CREATOR_SYNC);
+				//obj.setUploadFlag(null);
+				operations[1].add(obj);
+			}
+		}
+	}
+
+	/**
+	 * 同步数据时固定的id,优先取bimId,没有bimId取数据id
+	 */
+	private String getFixedIdForSync(AdmObject obj, int objMark){
+		String bimId = null;
+		JsonNode node = obj.getInfo("bimId");
+		if(node != null)
+			bimId = node.asText();
+
+		if(StrUtil.isNotBlank(bimId))
+			return bimId;
+
+		if(objMark == 1) //建筑
+			return obj.getLocalId();
+		else if(objMark == 2) //楼层
+			return obj.getBuildingId() + ":" + obj.getLocalId();
+
+		return obj.getId();
+	}
+
+	private AdmObject mergeObj(AdmObject obj, AdmObject dbItem, String timestamp, int objMark){
+		if(objNotChange(obj, dbItem))
+			return null;
+
+		//合并属性和信息点
+//		if(objMark == 3) {//space
+//
+//		} else if(objMark == 4) {//equipment
+//
+//		}
+		if (obj.getInfos() != null) {
+			if (dbItem.getInfos() == null)
+				dbItem.setInfos(obj.getInfos());
+			else
+				dbItem.getInfos().setAll(obj.getInfos());
+		}
+
+		dbItem.setModifiedTime(timestamp);
+		dbItem.setModifier(AdmConst.CREATOR_SYNC);
+		//dbItem.setUploadFlag(null);
+		dbItem.setD2mState(ValidEnum.TRUE.getType());
+		dbItem.setDeliveryState(ValidEnum.FALSE.getType());
+
+		return dbItem;
+	}
+
+	private boolean objNotChange(AdmObject obj, AdmObject dbItem){
+		//TODO 数据无变化判断
+		return false;
+	}
+
+	private <T extends OBase> void transEntities(List<AdmObject> targetList, List<T> list, SetDataAction setDataAction){
+		if(list != null && list.size() > 0) {
+			for(T item : list) {
+				AdmObject obj = buildAdmObject(item);
+				setDataAction.setData(obj, item);
+				targetList.add(obj);
+			}
+		}
+	}
+
+	private AdmObject buildAdmObject(OBase base){
+		AdmObject obj = new AdmObject();
+		obj.setId(base.getId());
+		obj.setLocalId(base.getLocalId());
+		obj.setName(base.getName());
+		obj.setLocalName(base.getLocalName());
+		obj.setObjType(base.getObjectType());
+
+		if (base.getInfos() != null)
+			obj.setInfos(mapToNode(base.getInfos()));
+
+		if(base.getCreateTime() != null) //同步数据中没有createTime时,设置为当前时间
+			obj.setCreationTime(DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN));
+
+		obj.setValid(ValidEnum.TRUE.getType());
+
+		return obj;
+	}
+
+	private void setBdData(AdmObject obj, OBuilding bd){
+		obj.setProjectId(bd.getProjectId());
+		obj.setClassCode(bd.getObjectType());
+		//obj.setBuildingId(bd.getId());
+
+		if(bd.getDefaultQRCode() != null)
+			getInfos(obj).put("defaultQRCode", bd.getDefaultQRCode());
+		if(bd.getBuildQRCode() != null)
+			getInfos(obj).put("buildQRCode", bd.getBuildQRCode());
+	}
+
+	private void setFlData(AdmObject obj, OFloor fl){
+		obj.setProjectId(fl.getProjectId());
+		obj.setBuildingId(fl.getBuildingId());
+		//obj.setFloorId(fl.getId());
+		obj.setClassCode(fl.getObjectType());
+
+		setInfos(obj, fl, "projectId", "buildingId", "floorId");
+	}
+
+	private void setSpData(AdmObject obj, OSpace sp) {
+		obj.setProjectId(sp.getProjectId());
+		obj.setBuildingId(sp.getBuildingId());
+		obj.setFloorId(sp.getFloorId());
+		obj.setClassCode(sp.getClassCode());
+		obj.setObjType(AdmConst.OBJ_TYPE_SPACE);
+
+		setInfos(obj, sp, "projectId", "buildingId", "floorId", "classCode");
+	}
+
+	private void setEqData(AdmObject obj, OEquip eq) {
+		obj.setProjectId(eq.getProjectId());
+		obj.setBuildingId(eq.getBuildingId());
+		obj.setFloorId(eq.getFloorId());
+		obj.setClassCode(eq.getClassCode());
+
+		setInfos(obj, eq, "projectId", "buildingId", "floorId", "propertyId", "classCode");
+	}
+
+	private void setInfos(AdmObject obj, OBase oEntity, String... ignoreFields){
+		Field[] fields = oEntity.getClass().getDeclaredFields();
+		for (Field field : fields) {
+			if(ignoreFields.length == 0 || !ArrayUtil.contains(ignoreFields, field.getName())) {
+				Object val = ReflectUtil.getFieldValue(oEntity, field);
+				if(val != null) {
+					ObjectNode infos = getInfos(obj);
+					if(val instanceof String)
+						infos.put(field.getName(), (String)val);
+					else if(val instanceof Integer)
+						infos.put(field.getName(), (Integer)val);
+					else if(val instanceof Float)
+						infos.put(field.getName(), (Float)val);
+					else if(val instanceof Double)
+						infos.put(field.getName(), (Double)val);
+					else if(val instanceof List)
+						infos.putArray(field.getName()).addAll(listToNode((List)val));
+					else if(val instanceof Map)
+						infos.putObject(field.getName()).setAll(mapToNode((Map)val));
+				}
+			}
+		}
+	}
+
+	private ObjectNode getInfos(AdmObject obj) {
+		ObjectNode objectNode = obj.getInfos();
+		if(objectNode == null){
+			ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+			objectNode = objectMapper.createObjectNode();
+			obj.setInfos(objectNode);
+		}
+		return objectNode;
+	}
+
+	private ObjectNode mapToNode(Map<String, Object> map){
+		ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+		try {
+			String json = objectMapper.writeValueAsString(map);
+			return objectMapper.readValue(json, ObjectNode.class);
+		} catch (IOException e) {
+			throw new BusinessException(ResponseCode.A0427.getCode(), ResponseCode.A0427.getDesc());
+		}
+	}
+
+	private ArrayNode listToNode(List<Object> list){
+		ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+		try {
+			String json = objectMapper.writeValueAsString(list);
+			return objectMapper.readValue(json, ArrayNode.class);
+		} catch (IOException e) {
+			throw new BusinessException(ResponseCode.A0427.getCode(), ResponseCode.A0427.getDesc());
+		}
+	}
+
+	interface SetDataAction {
+		void setData(AdmObject obj, OBase oldAdmEntity);
+	}
+
+	/**
+	 * 创建/合并任务空间数据
+	 */
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public void handleJobSpace(String projectId){
+		QueryWrapper<AdmObject> queryWrapper = new QueryWrapper<>();
+		queryWrapper.eq("project_id", projectId).eq("obj_type", AdmConst.OBJ_TYPE_SPACE).eq("valid", ValidEnum.TRUE.getType()).orderByAsc("floor_id");
+		List<AdmObject> spaceList = objectMapper.selectList(queryWrapper);
+
+		QueryWrapper<AdmJobSpace> wrapper = new QueryWrapper<>();
+		wrapper.eq("project_id", projectId).eq("valid", ValidEnum.TRUE.getType());
+		List<AdmJobSpace> jobSpaceList = jobSpaceMapper.selectList(wrapper);
+
+		//空间按层分组,优先使用OtherZone,缺省GeneralZone
+		LinkedHashMap<String, List<AdmObject>> map = new LinkedHashMap<>();
+		String floorId = null;
+		List<AdmObject> generalList = null;
+		List<AdmObject> otherList = null;
+		for(AdmObject sp : spaceList){
+			if(floorId == null || !floorId.equals(sp.getFloorId())) {
+				if(floorId != null)
+					map.put(floorId, otherList.size() > 0 ? otherList : generalList);
+
+				floorId = sp.getFloorId();
+				generalList = new ArrayList<>();
+				otherList = new ArrayList<>();
+			}
+
+			String zone = sp.getClassCode();
+			if("GeneralZone".equals(zone))
+				generalList.add(sp);
+			else if("OtherZone".equals(zone))
+				otherList.add(sp);
+		}
+		if(floorId != null)
+			map.put(floorId, otherList.size() > 0 ? otherList : generalList);
+
+		List<AdmJobSpace> toCreate = new ArrayList<>();
+		List<AdmJobSpace> toModify = new ArrayList<>();
+
+		String time = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN);
+
+		//按楼层进行空间匹配操作
+		for (Map.Entry<String, List<AdmObject>> entry : map.entrySet()) {
+			floorId = entry.getKey();
+
+			HashMap<String, AdmJobSpace> jobMap = new HashMap<>();
+			for (int i = 0; i < jobSpaceList.size(); i++) {
+				AdmJobSpace jobSpace = jobSpaceList.get(i);
+				if(jobSpace.getFloorId().equals(floorId)){
+					jobMap.put(jobSpace.getSpaceId(), jobSpace);
+
+					jobSpaceList.remove(i);
+					i--;
+				}
+			}
+
+			List<AdmObject> sps = entry.getValue();
+			for(AdmObject sp : sps){
+				ArrayNode spOutline = (ArrayNode) sp.getInfo("outline");
+				AdmJobSpace job = jobMap.remove(sp.getId());
+				if(job != null) {
+					//id匹配,轮廓变化的空间,重置任务状态
+					if(!outlineMatch(job.getOutline(), spOutline)){
+						job.setArchState(AdmConst.JOB_STATE_PROCESSING);
+						job.setEquipState(AdmConst.JOB_STATE_PROCESSING);
+						job.setOutline(spOutline);
+						toModify.add(job);
+					} // else id和轮廓都匹配,不做处理
+				} else {
+					//id未匹配,轮廓完全一致的任务空间,重新设置spaceId
+					job = matchByOutline(jobMap, sp);
+					if(job != null) {
+						job.setSpaceId(sp.getId());
+						toModify.add(job);
+					}
+				}
+
+				if (job == null) {
+					job = new AdmJobSpace();
+					job.setId(IdUtil.fastSimpleUUID());
+					job.setSpaceId(sp.getId());
+					job.setOutline((ArrayNode) sp.getInfo("outline"));
+					job.setArchState(AdmConst.JOB_STATE_PROCESSING);
+					job.setEquipState(AdmConst.JOB_STATE_PROCESSING);
+					job.setProjectId(projectId);
+					job.setBuildingId(sp.getBuildingId());
+					job.setFloorId(sp.getFloorId());
+					job.setCreationTime(time);
+					job.setCreator(AdmConst.CREATOR_SYNC);
+					job.setValid(ValidEnum.TRUE.getType());
+
+					toCreate.add(job);
+				}
+			}
+
+			//楼层中未找到匹配关系的任务空间
+			for(AdmJobSpace job : jobMap.values()){
+				job.setValid(ValidEnum.FALSE.getType());
+				toModify.add(job);
+			}
+		}
+
+		//项目下未找到匹配关系的任务空间
+		for(AdmJobSpace job : jobSpaceList){
+			job.setValid(ValidEnum.FALSE.getType());
+			toModify.add(job);
+		}
+
+		for(AdmJobSpace job : toCreate) {
+			jobSpaceMapper.insert(job);
+		}
+		for(AdmJobSpace job : toModify) {
+			job.setModifiedTime(time);
+			job.setModifier(AdmConst.CREATOR_SYNC);
+			//job.setUploadFlag(null);
+			jobSpaceMapper.updateById(job);
+		}
+	}
+
+	private AdmJobSpace matchByOutline(HashMap<String, AdmJobSpace> jobMap, AdmObject space){
+		if(jobMap.size() == 0)
+			return null;
+
+		ArrayNode o1 = (ArrayNode) space.getInfo("outline");
+		if(!isValidOutline(o1))
+			return null;
+
+		Polygon[] ps = GeomUtil.getPolygon(o1);
+		Map.Entry<String, AdmJobSpace> target = null;
+		for(Map.Entry<String, AdmJobSpace> entry : jobMap.entrySet()){
+			ArrayNode o2 = entry.getValue().getOutline();
+			if(isValidOutline(o2) && polygonsMatch(ps, GeomUtil.getPolygon(o2))){
+				target = entry;
+				break;
+			}
+		}
+		if(target != null){
+			jobMap.remove(target.getKey());
+			return target.getValue();
+		}
+		return null;
+	}
+
+	/**
+	 * 判断空间轮廓是否变化
+	 * TODO 区分覆盖等情况
+	 */
+	private boolean outlineMatch(ArrayNode o1, ArrayNode o2){
+		return polygonsMatch(GeomUtil.getPolygon(o1), GeomUtil.getPolygon(o2));
+	}
+
+
+	/**
+	 * 轮廓匹配判断
+	 * TODO 暂不考虑顺序
+	 */
+	private boolean polygonsMatch(Polygon[] ps1, Polygon[] ps2){
+		if (ps1.length == ps2.length) {
+			for (int i = 0; i < ps2.length; i++) {
+				if (!ps1[i].equalsExact(ps2[i]))
+					return false;
+			}
+			return true;
+		}
+		return false;
+	}
+
+	private boolean isValidOutline(ArrayNode outline) {
+		if(outline != null && outline.size() > 0 && outline.get(0).isArray()) {
+			ArrayNode o1 = (ArrayNode) outline.get(0);
+			if (o1.size() > 0 && o1.get(0).isArray()) {
+				ArrayNode o2 = (ArrayNode) o1.get(0);
+				return o2.size() >= 3;
+			}
+		}
+		return false;
+	}
+
+	@Autowired
+	private OldAdmClient oldAdmClient;
+
+	/**
+	 *	把地图文件从image-service转存到文件服务
+	 */
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public void uploadFloorMap(String groupCode, String projectId) {
+		/* 不使用
+		List<AdmObject> floors = objectService.queryM2dByObjType(projectId, AdmConst.OBJ_TYPE_FLOOR);
+		List<AdmObject> modifiedFloors = new ArrayList<>();
+		for(AdmObject floor : floors) {
+			ObjectNode infos = floor.getInfos();
+			if(infos != null) {
+				JsonNode mapNode = infos.get("floorMap");
+				JsonNode mapIdNode = infos.get("floorMapId");
+				if(mapNode != null){
+					String map = mapNode.asText();
+					String mapId = mapIdNode != null ? mapIdNode.asText() : null;
+					if(mapId != null) {
+						FileInfo fileInfo = FileClientFacade.load(mapId);
+						if(fileInfo != null && fileInfo.getFileName().equals(map))
+							continue; //文件无变化
+
+						//删除之前的地图文件
+						FileStorageHelper.deleteFile(mapId);
+					}
+
+					try {
+						Response serviceResponse = oldAdmClient.getFloorMap(map, "revit");
+						Response.Body body = serviceResponse.body();
+
+						InputStream inputStream = body.asInputStream();
+						FileInfo fileInfo = FileInfoCreator.of(groupCode, projectId, AdmConst.APP_ID, map);
+						String fileId = FileStorageHelper.uploadFile(fileInfo, inputStream);
+
+						infos.put("floorMapId", fileId);
+						modifiedFloors.add(floor);
+					} catch (Exception e) {
+						e.printStackTrace();
+					}
+				}
+			}
+		}
+
+		objectService.update(modifiedFloors);
+		*/
+	}
+
+}

+ 264 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/service/impl/SyncSpaceImpl.java

@@ -0,0 +1,264 @@
+package com.persagy.bdtp.adm.service.impl;
+
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.fasterxml.jackson.databind.node.TextNode;
+import com.persagy.bdtp.adm.common.AdmConst;
+import com.persagy.bdtp.adm.dao.AdmJobSpaceMapper;
+import com.persagy.bdtp.adm.entity.Pagination;
+import com.persagy.bdtp.adm.entity.db.AdmJobSpace;
+import com.persagy.bdtp.adm.service.ISyncSpace;
+import com.persagy.bdtp.adm.service.ServiceUtil;
+import com.persagy.bdtp.adm.util.GeomUtil;
+import com.persagy.dmp.basic.model.QueryCriteria;
+import com.persagy.dmp.common.constant.ValidEnum;
+import com.persagy.dmp.digital.client.DigitalObjectClient;
+import org.locationtech.jts.geom.Polygon;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.IOException;
+import java.util.*;
+
+@Service
+public class SyncSpaceImpl implements ISyncSpace {
+
+	@Autowired
+	private ObjectMapper objectMapper;
+
+	@Autowired
+	private DigitalObjectClient objectClient;
+
+	@Autowired
+	private AdmJobSpaceMapper jobSpaceMapper;
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public Map<String, Object> sync(String groupCode, String projectId, String userId, String floorId, String zone) {
+		if(StrUtil.isBlank(floorId))
+			floorId = null;
+
+		//查询bdtp的空间数据
+		QueryCriteria criteria = ServiceUtil.getQueryCriteria(objectMapper, AdmConst.OBJ_TYPE_SPACE);
+		criteria.getCriteria().put("classCode", zone); //默认工作空间为物业分区
+		//按楼层查询
+		if (floorId != null) {
+			ObjectNode rt = criteria.getCriteria().putObject("relationTo");
+			rt.put("graphCode", "ArchSubset");
+			rt.put("relCode", "Fl2Sp");
+			rt.put("objFrom", floorId);
+		}
+		List<ObjectNode> spList = ServiceUtil.queryAllPage(() -> objectClient.query(groupCode, projectId, AdmConst.APP_ID, userId, criteria), criteria, new Pagination(500));
+
+		List<AdmJobSpace> toCreate = new ArrayList<>();
+		List<AdmJobSpace> toModify = new ArrayList<>();
+
+		if(floorId == null){
+			HashMap<String, List<ObjectNode>> floorMap = new HashMap<>();
+			for(ObjectNode sp : spList) {
+				JsonNode fId = sp.get("floorId");
+				if(fId != null) {
+					String flId = fId.asText();
+					List<ObjectNode> flSps = floorMap.get(flId);
+					if(flSps == null)
+						floorMap.put(flId, flSps = new ArrayList<>());
+					flSps.add(sp);
+				}
+			}
+
+			for (Map.Entry<String, List<ObjectNode>> entry : floorMap.entrySet()) {
+				syncByFloor(projectId, entry.getKey(), entry.getValue(), toCreate, toModify);
+			}
+		} else {
+			syncByFloor(projectId, floorId, spList, toCreate, toModify);
+		}
+
+		String time = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN);
+		for(AdmJobSpace job : toCreate) {
+			job.setCreationTime(time);
+			job.setCreator(AdmConst.CREATOR_SYNC);
+			jobSpaceMapper.insert(job);
+		}
+		for(AdmJobSpace job : toModify) {
+			job.setModifiedTime(time);
+			job.setModifier(AdmConst.CREATOR_SYNC);
+			job.setTs(null); //更新时清空ts字段
+			jobSpaceMapper.updateById(job);
+		}
+
+		HashMap<String, Object> rtn = new HashMap<>();
+		rtn.put("syncSpaces", toCreate.size() + toModify.size());
+		return rtn;
+	}
+
+	private void syncByFloor(String projectId, String floorId, List<ObjectNode> spList, List<AdmJobSpace> toCreate, List<AdmJobSpace> toModify){
+		//查询任务空间数据
+		QueryWrapper<AdmJobSpace> wrapper = new QueryWrapper<>();
+		wrapper.eq("project_id", projectId).eq("floor_id", floorId).eq("valid", ValidEnum.TRUE.getType());
+		List<AdmJobSpace> jobSpaceList = jobSpaceMapper.selectList(wrapper);
+
+		HashMap<String, AdmJobSpace> jobMap = new HashMap<>(jobSpaceList.size());
+		jobSpaceList.forEach(job -> jobMap.put(job.getSpaceId(), job));
+
+		//同步操作
+		for(ObjectNode sp : spList){
+			String spId = sp.get("id").asText();
+
+			ArrayNode spOutline = null;
+			Object o1 = sp.get("outline");
+			if(o1 instanceof TextNode) {
+				try {
+					spOutline = objectMapper.readValue(((TextNode) o1).asText().toLowerCase(), ArrayNode.class); //暂时toLowerCase()处理
+				} catch (IOException e) {
+
+				}
+			}
+
+			fixOutline(spOutline);
+			if(!GeomUtil.checkPolygon(spOutline))
+				continue;
+
+			AdmJobSpace job = jobMap.remove(spId);
+			if(job != null) { //id匹配
+				boolean change = false;
+
+				//轮廓变化的空间,重置任务状态
+				if(!outlineMatch(job.getOutline(), spOutline)){
+					job.setArchState(AdmConst.JOB_STATE_PROCESSING);
+					job.setEquipState(AdmConst.JOB_STATE_PROCESSING);
+					job.setOutline(spOutline);
+					change = true;
+				}
+
+				//重置空间id
+				if(!Objects.equals(spId, job.getSpaceId())) {
+					job.setSpaceId(spId);
+					change = true;
+				}
+
+				//轮廓和空间id都一致的,不需要做处理
+				if(change)
+					toModify.add(job);
+			} else { //id未匹配
+				job = matchByOutline(jobMap, spOutline);
+				if(job != null) { //轮廓完全一致的任务空间,重新设置spaceId
+					job.setSpaceId(spId);
+					toModify.add(job);
+				}
+			}
+
+			if (job == null) {
+				job = new AdmJobSpace();
+				job.setId(IdUtil.fastSimpleUUID());
+				job.setSpaceId(spId);
+				job.setOutline(spOutline);
+				job.setArchState(AdmConst.JOB_STATE_PROCESSING);
+				job.setEquipState(AdmConst.JOB_STATE_PROCESSING);
+				job.setProjectId(projectId);
+				job.setBuildingId(sp.get("buildingId").asText());
+				job.setFloorId(floorId != null ? floorId : sp.get("floorId").asText());
+				job.setValid(ValidEnum.TRUE.getType());
+
+				toCreate.add(job);
+			}
+		}
+
+		//未找到匹配关系的任务空间,删除
+		for(AdmJobSpace job : jobMap.values()){
+			job.setValid(ValidEnum.FALSE.getType());
+			toModify.add(job);
+		}
+	}
+
+	@Override
+	public Map<String, Object> sync(String groupCode, String projectId, String userId, String zone) {
+		return sync(groupCode, projectId, userId, null, zone);
+	}
+
+	private AdmJobSpace matchByOutline(HashMap<String, AdmJobSpace> jobMap, ArrayNode spOutline){
+		if(jobMap.size() == 0)
+			return null;
+
+		Polygon[] ps = GeomUtil.getPolygon(spOutline);
+		Map.Entry<String, AdmJobSpace> target = null;
+		for(Map.Entry<String, AdmJobSpace> entry : jobMap.entrySet()){
+			ArrayNode o2 = entry.getValue().getOutline();
+			if(polygonsMatch(ps, GeomUtil.getPolygon(o2))){
+				target = entry;
+				break;
+			}
+		}
+		if(target != null){
+			jobMap.remove(target.getKey());
+			return target.getValue();
+		}
+		return null;
+	}
+
+	/**
+	 * 判断空间轮廓是否变化
+	 * TODO 区分覆盖等情况
+	 */
+	private boolean outlineMatch(ArrayNode o1, ArrayNode o2){
+		return polygonsMatch(GeomUtil.getPolygon(o1), GeomUtil.getPolygon(o2));
+	}
+
+
+	/**
+	 * 轮廓匹配判断
+	 * TODO 暂不考虑顺序
+	 */
+	private boolean polygonsMatch(Polygon[] ps1, Polygon[] ps2){
+		if (ps1.length == ps2.length) {
+			for (int i = 0; i < ps2.length; i++) {
+				if (!ps1[i].equalsExact(ps2[i]))
+					return false;
+			}
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * 对轮廓线做闭合处理
+	 */
+	private void fixOutline(ArrayNode outline){
+		if (outline == null)
+			return;
+
+		for (int i = 0; i < outline.size(); i++) {
+			ArrayNode space = (ArrayNode) outline.get(i);
+			for (int n = 0; n < space.size(); n++) {
+				ArrayNode ring = (ArrayNode)space.get(n);
+				if(ring.size() > 2) {
+					JsonNode from = ring.get(0);
+					JsonNode to = ring.get(ring.size() - 1);
+					JsonNode x1,y1,x2,y2;
+					if(from != null && to != null){
+						x1 = from.get("x");
+						y1 = from.get("y");
+						x2 = to.get("x");
+						y2 = to.get("y");
+						if(x1 != null && y1 != null && x2 != null && y2 != null) {
+							if(x1.asDouble() != x2.asDouble() || y1.asDouble() != y2.asDouble()) {
+								//自动闭合
+								ObjectNode close = objectMapper.createObjectNode();
+								close.put("x", x1.asDouble()).put("y", y1.asDouble());
+								ring.add(close);
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+}

+ 0 - 0
adm-business/adm-server/src/main/java/com/persagy/bdtp/adm/util/AdmMessageHelper.java


Some files were not shown because too many files changed in this diff