Browse Source

Merge remote-tracking branch 'origin/develop' into develop

lijie 3 years ago
parent
commit
ba51e41737
19 changed files with 2004 additions and 2 deletions
  1. 82 0
      src/main/java/com/persagy/proxy/migration/constant/MiGrationRelCode.java
  2. 55 0
      src/main/java/com/persagy/proxy/migration/constant/MigrationConstant.java
  3. 29 0
      src/main/java/com/persagy/proxy/migration/constant/MigrationObjType.java
  4. 46 0
      src/main/java/com/persagy/proxy/migration/constant/MigrationTable.java
  5. 32 0
      src/main/java/com/persagy/proxy/migration/constant/MigrationType.java
  6. 114 0
      src/main/java/com/persagy/proxy/migration/controller/DataMigrationController.java
  7. 50 0
      src/main/java/com/persagy/proxy/migration/handler/DataMigrationHandler.java
  8. 238 0
      src/main/java/com/persagy/proxy/migration/handler/DefineInfoMigration.java
  9. 243 0
      src/main/java/com/persagy/proxy/migration/handler/DefineTypeMigration.java
  10. 25 0
      src/main/java/com/persagy/proxy/migration/handler/IDataMigration.java
  11. 43 0
      src/main/java/com/persagy/proxy/migration/handler/IDataMigrationProcess.java
  12. 237 0
      src/main/java/com/persagy/proxy/migration/handler/ObjectDigitalMigration.java
  13. 235 0
      src/main/java/com/persagy/proxy/migration/handler/ObjectRelationMigration.java
  14. 57 0
      src/main/java/com/persagy/proxy/migration/model/DataMigrationExcel.java
  15. 60 0
      src/main/java/com/persagy/proxy/migration/model/DataMigrationResponse.java
  16. 18 0
      src/main/java/com/persagy/proxy/migration/model/MigrationInfo.java
  17. 329 0
      src/main/java/com/persagy/proxy/migration/service/Impl/MigrationAbstractServiceImpl.java
  18. 97 0
      src/main/java/com/persagy/proxy/migration/service/MigrationAbstractService.java
  19. 14 2
      src/main/java/com/persagy/proxy/object/controller/AdmEquipmentController.java

+ 82 - 0
src/main/java/com/persagy/proxy/migration/constant/MiGrationRelCode.java

@@ -0,0 +1,82 @@
+package com.persagy.proxy.migration.constant;
+
+/**
+ * 边类型编码
+ *
+ */
+public enum MiGrationRelCode {
+	
+	None("None"),Door("Door"),Window("Window"),DoorWindow("DoorWindow"),FFOpen("FFOpen"),FFClose("FFClose"),Natural("Natural"),OnewayMech("OnewayMech"),
+	MixMech("MixMech"),Connect("Connect"),Transparent("Transparent"),ExactCorrespond("ExactCorrespond"),InexactCorrespond("InexactCorrespond"),
+	Fill("Fill"),Backup("Backup"),Return("Return"),Fresh("Fresh"),Uncertain("Uncertain"),SupplyReturn("SupplyReturn"),Supply("Supply"),
+	Bypass("Bypass"),Discharge("Discharge"),Normal("Normal"),SyCtrl("SyCtrl"),EqCtrl("EqCtrl"),SyNormal("SyNormal"),SyBackup("SyBackup"),
+	EqNormal("EqNormal"),EqBackup("EqBackup"),
+	
+	Pj2Bd("Pj2Bd"),
+	Bd2Fl("Bd2Fl"),
+	Fl2Bd("Fl2Bd"),
+	Fl2Fl("Fl2Fl"),
+	Fl2Sh("Fl2Sh"),
+	Fl2Sp("Fl2Sp"),
+	Sh2Bd("Sh2Bd"),
+	Sh2Fl("Sh2Fl"),
+	Sh2Sh("Sh2Sh"),
+	Sh2Sp("Sh2Sp"),
+	Sp2Bd("Sp2Bd"),
+	Bd2Bd("Bd2Bd"),
+	Bd2Sh("Bd2Sh"),
+	Bd2Sp("Bd2Sp"),
+	Sp2Fl("Sp2Fl"),
+	Sp2Sh("Sp2Sh"),
+	Sp2Sp("Sp2Sp"),
+	Sy2Bd("Sy2Bd"),
+	Sy2Fl("Sy2Fl"),
+	Sy2Sh("Sy2Sh"),
+	Sy2Sp("Sy2Sp"),
+	Eq2Bd("Eq2Bd"),
+	Eq2Fl("Eq2Fl"),
+	Eq2Sh("Eq2Sh"),
+	Eq2Sp("Eq2Sp"),
+	Pj2Sy("Pj2Sy"),
+	Pj2Eq("Pj2Eq"),
+	Sy2Eq("Sy2Eq"),
+	Eq2Ec("Eq2Ec"),
+	Ss2Eq("Ss2Eq"),
+	Ss2Sy("Ss2Sy"),
+	Ss2Sp("Ss2Sp"),
+	Vv2Eq("Vv2Eq"),
+	Vv2Sy("Vv2Sy"),
+	Vv2Vv("Vv2Vv"),
+	Em2Bd("Em2Bd"),
+	Sub2Em("Sub2Em"),
+	SubTree("SubTree"),
+	Br2Eq("Br2Eq"),
+	Br2Sub("Br2Sub"),
+	Sch2Pj("Sch2Pj"),
+	Sch2Bd("Sch2Bd"),
+	Sch2Fl("Sch2Fl"),
+	Sch2Sp("Sch2Sp"),
+	Sch2Tn("Sch2Tn"),
+	Ms2Pj("Ms2Pj"),
+	Tn2Sp("Tn2Sp"),
+	Bl2Pj("Bl2Pj"),
+	Pe2Eq("Pe2Eq"),
+	Pe2Ec("Pe2Ec"),
+	Pe2Pj("Pe2Pj"),
+	Pe2Bd("Pe2Bd"),
+	Pe2Fl("Pe2Fl"),
+	Pe2Sh("Pe2Sh"),
+	Pe2Sp("Pe2Sp");
+
+	private String code;
+	public String getCode(){
+		return code;
+	}
+	MiGrationRelCode(String code){
+		this.code = code;	
+	}
+	@Override
+	public String toString() {
+		return this.code;
+	}
+}

+ 55 - 0
src/main/java/com/persagy/proxy/migration/constant/MigrationConstant.java

@@ -0,0 +1,55 @@
+package com.persagy.proxy.migration.constant;
+
+/**
+ * @author lvxianyun
+ * @title: MigrationConstant
+ * @projectName adm-middleware
+ * @date 2021/12/6 15:39
+ */
+public class MigrationConstant {
+
+    public final static int batchSubmitDataCount = 500;
+    /** 数据拼接 用于list->map 时key和value拼接 **/
+    public final static String SPLITER = "_";
+
+    /** 数据拼接 用于map的key和value拼接成一个串 **/
+    public final static String SPLITER_UNION = "@@";
+
+    /**   对象类型定义 接口 ***/
+    public final static String DEF_CLASS = "/dmp-rwd/rwd/def/class?";
+    public final static String DEF_CLASS_INSERT = "/dmp-rwd/rwd/def/class/createBatch?";
+    public final static String DEF_CLASS_DELETE = "/dmp-rwd/rwd/def/class/deleteBatch?";
+    public final static String DEF_CLASS_UPDATE = "/dmp-rwd/rwd/def/class/updateBatch?";
+
+    /**   信息点 接口 ***/
+    public final static String DEF_FUNCID = "/dmp-rwd/rwd/def/funcid?";
+    public final static String DEF_FUNCID_INSERT = "/dmp-rwd/rwd/def/funcid/createBatch?";
+    public final static String DEF_FUNCID_DELETE = "/dmp-rwd/rwd/def/funcid/deleteBatch?";
+    public final static String DEF_FUNCID_UPDATE = "/dmp-rwd/rwd/def/funcid/updateBatch?";
+
+    /**   图类型表 接口 需要提供批量 ***/
+    public final static String DEF_GRAPH = "/dmp-rwd/rwd/def/graph/query?";
+    public final static String DEF_GRAPH_INSERT = "/dmp-rwd/rwd/def/graph/create?";
+    public final static String DEF_GRAPH_DELETE = "/dmp-rwd/rwd/def/graph/delete?";
+    public final static String DEF_GRAPH_UPDATE = "/dmp-rwd/rwd/def/graph/update?";
+
+    /**   边类型表 接口  ***/
+    public final static String DEF_REL = "/dmp-rwd/rwd/def/rel/query?";
+    public final static String DEF_REL_INSERT = "/dmp-rwd/rwd/def/rel/create?";
+    public final static String DEF_REL_DELETE = "/dmp-rwd/rwd/def/rel/delete?";
+    public final static String DEF_REL_UPDATE = "/dmp-rwd/rwd/def/rel/update?";
+
+
+    /**   对象实例表 接口  ***/
+    public final static String DT_OBJECT = "/dmp-rwd/rwd/instance/object/query?";
+    public final static String DT_OBJECT_INSERT = "/dmp-rwd/rwd/instance/object/create?";
+    public final static String DT_OBJECT_DELETE = "/dmp-rwd/rwd/instance/object/delete?";
+    public final static String DT_OBJECT_UPDATE = "/dmp-rwd/rwd/instance/object/update?";
+
+
+    /**   关系实例表 接口  ***/
+    public final static String DT_RELATION = "/dmp-rwd/rwd/instance/relation/query?";
+    public final static String DT_RELATION_INSERT = "/dmp-rwd/rwd/instance/relation/create?";
+    public final static String DT_RELATION_DELETE = "/dmp-rwd/rwd/instance/relation/delete?";
+    public final static String DT_RELATION_UPDATE = "/dmp-rwd/rwd/instance/relation/update?";
+}

+ 29 - 0
src/main/java/com/persagy/proxy/migration/constant/MigrationObjType.java

@@ -0,0 +1,29 @@
+package com.persagy.proxy.migration.constant;
+
+/**
+ * @author lvxianyun
+ * @title: MigrationObjType
+ * @projectName adm-middleware
+ * @description: 
+ * @date 2021/12/9 21:04
+ */
+public enum MigrationObjType {
+
+     project("project") ,building("building") , floor("floor") ,component("component") , equipment("equipment") , shaft("shaft") , system("system") ,  /*ispace ,*/ space("space") ;
+
+     private String code;
+
+     public String getCode() {
+          return code;
+     }
+
+     MigrationObjType(String code) {
+          this.code = code;
+     }
+
+     @Override
+     public String toString() {
+          return this.code;
+     }
+
+}

+ 46 - 0
src/main/java/com/persagy/proxy/migration/constant/MigrationTable.java

@@ -0,0 +1,46 @@
+package com.persagy.proxy.migration.constant;
+
+/**
+ * @author lvxianyun
+ * @title: MigrationTable
+ * @projectName adm-middleware
+ * @date 2021/12/2 12:24
+ */
+public enum MigrationTable {
+    DTDEFINETYPE("dt_define_type","对象类型定义"),
+    DTDEFINEINFO("dt_define_info","信息点定义表"),
+    DTOBJECT("dt_object","对象实例"),
+    DTRALATION("dt_relation","关系实例表"),
+    //DTDEFINEGRAPH("dt_define_graph","图类型表"),
+    //DTDEFINEREL("dt_define_rel","边类型表"),
+    //DTDEFINEINFOCOLLECT("dt_define_info_collect","采集信息点配置表"),
+    //DTEQUIPCLASSREL("dt_equip_class_rel","项目设备类边关系表")
+    ;
+
+    private String code;
+    private String desc;
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    MigrationTable(String code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    @Override
+    public String toString() {
+        return this.code + "_" + this.desc;
+    }
+
+    public static void main(String[] args) {
+        for (MigrationTable key : MigrationTable.values()) {
+            System.out.println(key.code + "-----------");
+        }
+    }
+}

+ 32 - 0
src/main/java/com/persagy/proxy/migration/constant/MigrationType.java

@@ -0,0 +1,32 @@
+package com.persagy.proxy.migration.constant;
+
+/**
+ * @author lvxianyun
+ * @title: MigrationType
+ * @projectName adm-middleware
+ * @description: 数据迁移类型 insert delete update
+ * @date 2021/12/3 19:54
+ */
+public enum MigrationType {
+    INSERT("insert","新增"),UPDATE("update","更新"),DELETE("delete","删除"),QUERY("query","查询");
+    private String code;
+    private String desc;
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    MigrationType(String code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    @Override
+    public String toString() {
+        return this.code + "_" + this.desc;
+    }
+}

+ 114 - 0
src/main/java/com/persagy/proxy/migration/controller/DataMigrationController.java

@@ -0,0 +1,114 @@
+package com.persagy.proxy.migration.controller;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.ExcelWriter;
+import com.alibaba.excel.write.metadata.WriteSheet;
+import com.persagy.dmp.common.constant.ResponseCode;
+import com.persagy.dmp.common.exception.BusinessException;
+import com.persagy.proxy.adm.request.AdmQueryCriteria;
+import com.persagy.proxy.adm.request.AdmResponse;
+import com.persagy.proxy.adm.utils.AdmContextUtil;
+import com.persagy.proxy.common.entity.InstanceUrlParam;
+import com.persagy.proxy.migration.handler.DataMigrationHandler;
+import com.persagy.proxy.migration.model.DataMigrationExcel;
+import com.persagy.proxy.migration.model.MigrationInfo;
+import com.persagy.proxy.object.model.AdmProject;
+import com.persagy.proxy.object.service.IAdmProjectService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletResponse;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author lvxianyun
+ * @title: adm 交付的数据同步到现场,TODO 需要提供中台的连接,可以使用接口传,也可以配置在项目中
+ * @projectName adm-middleware
+ * @description: 该方式会覆盖被同步方数据(以adm交付为主)
+ * @date 2021/12/1 16:07
+ */
+@Slf4j
+@RestController
+@RequestMapping("/data/migration")
+@RequiredArgsConstructor
+public class DataMigrationController {
+    private final DataMigrationHandler dataMigrationHandler;
+    private final IAdmProjectService projectService;
+
+    /**
+     *
+     * @param response
+     * @migrationInfo :
+     *  targetUrl  现场中台调用的url, eg:http://develop.persagy.com/dmp-rwd
+     *  targetGroupCode 现场集团编码
+     *  targetProjectId 现场项目id
+     */
+    @GetMapping
+    public void migrate(HttpServletResponse response, @RequestBody MigrationInfo migrationInfo) {
+        //调用服务迁移数据,返回处理结果excel
+        try {
+            InstanceUrlParam context = AdmContextUtil.toDmpContext();
+            context.setGroupCode(migrationInfo.getTargetGroupCode());
+
+            response.setContentType("application/vnd.ms-excel");
+            String encode = StandardCharsets.UTF_8.name();
+            response.setCharacterEncoding(encode);
+            if(migrationInfo == null || StrUtil.isBlank(migrationInfo.getTargetUrl())){
+                throw new BusinessException(ResponseCode.A0402.getCode(), ResponseCode.A0402.getDesc());
+            }
+            if(StrUtil.isBlank(migrationInfo.getTargetGroupCode())){
+                migrationInfo.setTargetGroupCode(context.getGroupCode());
+            }
+            if(StrUtil.isBlank(migrationInfo.getTargetProjectId())){
+                migrationInfo.setTargetProjectId(context.getProjectId());
+            }
+
+            Map<String,List<DataMigrationExcel>> results = dataMigrationHandler.handle(context, migrationInfo);
+
+            AdmQueryCriteria projectRequest = new AdmQueryCriteria();
+            projectRequest.setName(AdmProject.OBJ_TYPE);
+            projectRequest.setFilters("id = '" + context.getProjectId() + "';");
+            AdmResponse responsePro = projectService.doQuery(AdmContextUtil.toDmpContext(), projectRequest, AdmProject.class);
+
+            if (CollUtil.isEmpty(responsePro.getContent())) {
+                throw new BusinessException(ResponseCode.A0402.getCode(), ResponseCode.A0402.getDesc());
+            } else {
+                AdmProject admProject = (AdmProject) responsePro.getContent().get(0);
+                // 防止中文乱码
+                String fileName = admProject.getLocalName() + "_数据迁移";
+
+                fileName = URLEncoder.encode(fileName, encode);
+
+                response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
+                //每个迁移的表写成一个sheet
+                if(CollUtil.isNotEmpty(results)){
+                    int sheetNo = 0;
+                    ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), DataMigrationExcel.class).build();
+                    try {
+                        for (String sheet : results.keySet()) {
+                            WriteSheet writeSheet = EasyExcel.writerSheet(sheetNo, sheet).build();
+                            excelWriter.write(results.get(sheet), writeSheet);
+                            sheetNo++;
+                        }
+                    } finally {
+                        if (excelWriter != null) {
+                            excelWriter.finish();
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            log.error("数据迁移失败",e);
+        }
+    }
+
+}

+ 50 - 0
src/main/java/com/persagy/proxy/migration/handler/DataMigrationHandler.java

@@ -0,0 +1,50 @@
+package com.persagy.proxy.migration.handler;
+
+import cn.hutool.core.collection.CollUtil;
+import com.persagy.proxy.common.entity.InstanceUrlParam;
+import com.persagy.proxy.migration.constant.MigrationTable;
+import com.persagy.proxy.migration.model.DataMigrationExcel;
+import com.persagy.proxy.migration.model.MigrationInfo;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author lvxianyun
+ * @title: DataMigrationHandler
+ * @projectName adm-middleware
+ * @date 2021/12/3 11:14
+ */
+@Component
+public class DataMigrationHandler {
+
+    private static Map<String, IDataMigration> migrationMap = new HashMap<>(16);
+
+    public Map<String, List<DataMigrationExcel>> handle(InstanceUrlParam context, MigrationInfo migrationInfo){
+        Map<String,List<DataMigrationExcel>> results = new HashMap<>(16);
+        if(CollUtil.isNotEmpty(migrationMap)){
+            for (MigrationTable migrationTable : MigrationTable.values()){
+                if(!migrationMap.containsKey(migrationTable.getCode())){
+                    continue;
+                }
+                results.put(migrationTable.getCode(), migrationMap.get(migrationTable.getCode()).migrate(context, migrationInfo));
+            }
+        }
+        return results;
+    }
+
+    public void addMap(String tableName, IDataMigration iDataMigration){
+        migrationMap.put(tableName, iDataMigration);
+    }
+
+    @PostConstruct
+    private void initHandleService(){
+        addMap(MigrationTable.DTDEFINETYPE.getCode(), DefineTypeMigration.getInstance());
+        addMap(MigrationTable.DTDEFINEINFO.getCode(), DefineInfoMigration.getInstance());
+        addMap(MigrationTable.DTOBJECT.getCode(), ObjectDigitalMigration.getInstance());
+        addMap(MigrationTable.DTRALATION.getCode(), ObjectRelationMigration.getInstance());
+    }
+}

+ 238 - 0
src/main/java/com/persagy/proxy/migration/handler/DefineInfoMigration.java

@@ -0,0 +1,238 @@
+package com.persagy.proxy.migration.handler;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.dmp.basic.model.QueryCriteria;
+import com.persagy.dmp.basic.utils.JsonNodeUtils;
+import com.persagy.dmp.common.constant.ResponseCode;
+import com.persagy.dmp.common.model.entity.BaseEntity;
+import com.persagy.dmp.define.client.DigitalObjectInfoFacade;
+import com.persagy.dmp.define.entity.ObjectInfoDefine;
+import com.persagy.proxy.common.entity.InstanceUrlParam;
+import com.persagy.proxy.migration.constant.MigrationConstant;
+import com.persagy.proxy.migration.constant.MigrationType;
+import com.persagy.proxy.migration.model.DataMigrationExcel;
+import com.persagy.proxy.migration.model.DataMigrationResponse;
+import com.persagy.proxy.migration.model.MigrationInfo;
+import com.persagy.proxy.migration.service.Impl.MigrationAbstractServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @author lvxianyun
+ * @title: DefineInfoMigration
+ * @projectName adm-middleware
+ * @description:  迁移adm交付的数据到现场,覆盖现场数据,提供增加、删除、修改 记录放入excel; DefineInfo 数据迁移 adm -> target project
+ * @date 2021/12/8 17:28
+ */
+@Slf4j
+public class DefineInfoMigration extends MigrationAbstractServiceImpl<ObjectInfoDefine> implements IDataMigration, IDataMigrationProcess<ObjectInfoDefine> {
+    
+    private static DefineInfoMigration instance;
+
+    private DefineInfoMigration() {}
+
+    // 静态方法返回该实例
+    public static DefineInfoMigration getInstance() {
+        if(instance == null) {
+            synchronized (DefineInfoMigration.class) {
+                if (instance == null) {
+                    instance = new DefineInfoMigration();
+                }
+            }
+        }
+        return instance;
+    }
+
+
+    /**
+     * 数据迁移
+     *
+     * @param context
+     * @param migrationInfo
+     * @return
+     */
+    @Override
+    public List<DataMigrationExcel> migrate(InstanceUrlParam context, MigrationInfo migrationInfo) {
+        log.info("######################### DefineInfo 同步开始 #########################");
+        long start = System.currentTimeMillis();
+        List<DataMigrationExcel> dataMigrationExcels = new ArrayList<>();
+
+        QueryCriteria queryCriteria = new QueryCriteria();
+        ObjectNode criteria = JsonNodeFactory.instance.objectNode();
+        criteria.put("valid", 1);
+
+        ObjectNode groupCode =  JsonNodeFactory.instance.objectNode();
+        groupCode.put("$ne", "0");
+
+        ObjectNode projectId =  JsonNodeFactory.instance.objectNode();
+        projectId.put("$ne", "0");
+
+        ObjectNode andOr = JsonNodeFactory.instance.objectNode();
+        andOr.putPOJO("groupCode", projectId);
+        andOr.putPOJO("projectId", groupCode);
+
+        criteria.putPOJO("$andOr", andOr);
+
+        queryCriteria.setCriteria(criteria);
+        queryCriteria.setSize(-1L);
+        List<ObjectInfoDefine> admDefineList = getAdmData(context, queryCriteria);
+        String queryUrl = requestUrl(context, migrationInfo, MigrationType.QUERY.getCode());
+        List<ObjectInfoDefine> projectDefineList = getProjectData(queryCriteria, ObjectInfoDefine.class, queryUrl);
+
+        if(CollUtil.isEmpty(admDefineList)){
+            log.error(" ######################### DefineInfo adm已交付需要同步的数据:"+ ResponseCode.C0320.getDesc() +" 同步结束 #########################");
+            return dataMigrationExcels;
+        }
+        String insertUrl = requestUrl(context, migrationInfo, MigrationType.INSERT.getCode());
+        if(CollUtil.isEmpty(projectDefineList)){
+            log.info("######################### DefineInfo 批量插入数据 #########################");
+            DataMigrationResponse response = insertBatch(admDefineList, ObjectInfoDefine.class, insertUrl);
+            dataMigrationExcels.addAll(processData(response, MigrationType.INSERT.getDesc()));
+            return dataMigrationExcels;
+        }
+        List<ObjectNode> objectNodeListPro = JsonNodeUtils.toListNode(projectDefineList, null, null);
+        Map<String,Object> projectDefineMap = toEntityMap(objectNodeListPro, ObjectInfoDefine.class);
+        List<ObjectNode> objectNodeListAdm = JsonNodeUtils.toListNode(admDefineList, null, null);
+        Map<String,Object> admDefineMap = toEntityMap(objectNodeListAdm, ObjectInfoDefine.class);
+
+
+        //差集 新增
+        log.info("######################### DefineInfo 批量插入数据 #########################");
+        Map<String,Object> subtractFromDel = doSubtractAdd(admDefineMap, projectDefineMap);
+        if(!CollUtil.isEmpty(subtractFromDel)){
+            List<ObjectInfoDefine> insertData = toList(subtractFromDel, admDefineList);
+            dataMigrationExcels.addAll(processData(insertBatch(insertData, ObjectInfoDefine.class, insertUrl), MigrationType.INSERT.getDesc()));
+        }
+
+        //差集 删除
+        log.info("######################### DefineInfo 批量处理删除数据 #########################");
+        Map<String,Object> subtractFromDelete = doSubtractDel(admDefineMap, projectDefineMap);
+        if(!CollUtil.isEmpty(subtractFromDelete)){
+            List<String> deleteIds = subtractFromDelete.entrySet().stream().map(en -> en.getKey()).collect(Collectors.toList());
+            String delUrl = requestUrl(context, migrationInfo, MigrationType.DELETE.getCode());
+            DataMigrationResponse response = deleteBatch(deleteIds, ObjectInfoDefine.class, delUrl);
+            dataMigrationExcels.addAll(processData(response, MigrationType.DELETE.getDesc()));
+        }
+
+        //交集更新
+        log.info("######################### DefineInfo 批量处理更新数据 #########################");
+        Map<String,Object> intersectionUpdateFrom = doIntersectionGetFrom(admDefineMap, projectDefineMap);
+        Map<String,Object> intersectionUpdateTo = doIntersectionGetTo(admDefineMap, projectDefineMap);
+
+        if(!CollUtil.isEmpty(intersectionUpdateFrom) && !CollUtil.isEmpty(intersectionUpdateTo)){
+            Map<String, Object> compareData = compareData(intersectionUpdateFrom, intersectionUpdateTo);
+            if(CollUtil.isNotEmpty(compareData) && compareData.size() > 0){
+                List<ObjectInfoDefine> updateData = toList(compareData, admDefineList);
+                String updateUrl = requestUrl(context, migrationInfo, MigrationType.UPDATE.getCode());
+                dataMigrationExcels.addAll(processData(updateBatch(updateData, ObjectInfoDefine.class, updateUrl), MigrationType.UPDATE.getCode()));
+            }
+        }
+        long end = System.currentTimeMillis();
+        log.info("######################### DefineInfo 数据迁移已结束 时间:"+(end-start)+" #########################");
+
+        return dataMigrationExcels;
+    }
+
+    /**
+     * 获取adm交付的数据,默认获取有效数据
+     *
+     * @param context
+     * @return
+     */
+    @Override
+    public List<ObjectInfoDefine> getAdmData(InstanceUrlParam context, QueryCriteria queryCriteria) {
+        log.info("######################### DefineInfo 获取adm交付数据 #########################");
+        List<ObjectInfoDefine> infos = DigitalObjectInfoFacade.query(context.getGroupCode(),context.getProjectId(),context.getUserId(),context.getUserId(),queryCriteria);
+        return infos;
+    }
+
+    /**
+     * 根据map转为需要处理的对象集合
+     * 使用 MigrationConstant.spliter 作为拼接符
+     * @param fromMap
+     * @param fromList
+     * @return
+     */
+
+    public List<ObjectInfoDefine> toList(Map<String, Object> fromMap, List<ObjectInfoDefine> fromList) {
+        if(CollUtil.isEmpty(fromMap) || CollUtil.isEmpty(fromList)){
+            return null;
+        }
+        List<ObjectInfoDefine> results = new ArrayList<>(fromMap.size());
+        Map<String, ObjectInfoDefine> objectInfoDefineMap = CollUtil.fieldValueMap(fromList, BaseEntity.PROP_ID);
+        for(String key : fromMap.keySet()){
+            results.add(objectInfoDefineMap.get(key));
+        }
+        return results;
+    }
+
+    /**
+     * 拼接访问链接
+     *
+     * @param context
+     * @param migrationInfo
+     * @param type
+     * @return
+     */
+    @Override
+    public String requestUrl(InstanceUrlParam context, MigrationInfo migrationInfo, String type) {
+        if(StrUtil.isBlank(migrationInfo.getTargetUrl())){
+            return null;
+        }
+        StringBuilder url = new StringBuilder(migrationInfo.getTargetUrl());
+        if(type.equals(MigrationType.QUERY.getCode())) {
+            url.append(MigrationConstant.DEF_FUNCID);
+        }else if(type.equals(MigrationType.INSERT.getCode())){
+            url.append(MigrationConstant.DEF_FUNCID_INSERT);
+        }else if(type.equals(MigrationType.UPDATE.getCode())){
+            url.append(MigrationConstant.DEF_FUNCID_UPDATE);
+        }else{
+            url.append(MigrationConstant.DEF_FUNCID_DELETE);
+        }
+        return commonUrl(context, url.toString(), migrationInfo);
+    }
+
+    /**
+     * 将目标集合处理成excel格式的集合  使用与insert/delete
+     *
+     * @param dataMigrationResponse
+     * @return
+     */
+    @Override
+    public List<DataMigrationExcel> processData(DataMigrationResponse dataMigrationResponse, String type) {
+        if(CollUtil.isEmpty(dataMigrationResponse.getData()) && CollUtil.isEmpty(dataMigrationResponse.getErrorMsg())){
+            return Collections.emptyList();
+        }
+        List<DataMigrationExcel> dataMigrationExcels = new ArrayList<>();
+        if(CollUtil.isNotEmpty(dataMigrationResponse.getData())){
+            for(Object obj : dataMigrationResponse.getData()){
+                if(!type.equals(MigrationType.DELETE.getCode())){
+                    ObjectInfoDefine define = (ObjectInfoDefine) obj;
+                    DataMigrationExcel excel = new DataMigrationExcel();
+                    excel.setId(define.getId());
+                    excel.setCode(define.getCode());
+                    excel.setName(define.getName());
+                    excel.setType(type);
+                    dataMigrationExcels.add(excel);
+                }else{
+                    DataMigrationExcel excel = new DataMigrationExcel();
+                    excel.setId(obj.toString());
+                    excel.setType(type);
+                    dataMigrationExcels.add(excel);
+                }
+            }
+        }
+        if(CollUtil.isNotEmpty(dataMigrationResponse.getErrorMsg())){
+            dataMigrationExcels.addAll(addErrorInfo(dataMigrationResponse.getErrorMsg()));
+        }
+        return dataMigrationExcels;
+    }
+}

+ 243 - 0
src/main/java/com/persagy/proxy/migration/handler/DefineTypeMigration.java

@@ -0,0 +1,243 @@
+package com.persagy.proxy.migration.handler;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.dmp.basic.model.QueryCriteria;
+import com.persagy.dmp.basic.utils.JsonNodeUtils;
+import com.persagy.dmp.common.constant.ResponseCode;
+import com.persagy.dmp.common.model.entity.BaseEntity;
+import com.persagy.dmp.define.client.DigitalDefineFacade;
+import com.persagy.dmp.define.entity.ObjectTypeDefine;
+import com.persagy.proxy.common.entity.InstanceUrlParam;
+import com.persagy.proxy.migration.constant.MigrationConstant;
+import com.persagy.proxy.migration.constant.MigrationType;
+import com.persagy.proxy.migration.model.DataMigrationExcel;
+import com.persagy.proxy.migration.model.DataMigrationResponse;
+import com.persagy.proxy.migration.model.MigrationInfo;
+import com.persagy.proxy.migration.service.Impl.MigrationAbstractServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @author lvxianyun
+ * @projectName adm-middleware
+ * @description: 迁移adm交付的数据到现场,覆盖现场数据,提供增加、删除、修改 记录放入excel; DefineType 数据迁移 adm -> target project
+ * @date 2021/12/1 19:38
+ */
+@Slf4j
+public class DefineTypeMigration extends MigrationAbstractServiceImpl<ObjectTypeDefine> implements IDataMigration, IDataMigrationProcess<ObjectTypeDefine> {
+
+    private static DefineTypeMigration instance;
+
+    private DefineTypeMigration() {}
+
+    // 静态方法返回该实例
+    public static DefineTypeMigration getInstance() {
+        if(instance == null) {
+            synchronized (DefineTypeMigration.class) {
+                if (instance == null) {
+                    instance = new DefineTypeMigration();
+                }
+            }
+        }
+        return instance;
+    }
+
+
+    /**
+     * 数据迁移
+     *
+     * @param context
+     * @param migrationInfo
+     * @return
+     */
+    @Override
+    public List<DataMigrationExcel> migrate(InstanceUrlParam context, MigrationInfo migrationInfo) {
+        log.info("######################### DefineType 同步开始 #########################");
+        long start = System.currentTimeMillis();
+        List<DataMigrationExcel> dataMigrationExcels = new ArrayList<>();
+
+        QueryCriteria queryCriteria = new QueryCriteria();
+        ObjectNode criteria = JsonNodeFactory.instance.objectNode();
+        criteria.put("valid", 1);
+        ObjectNode groupCode =  JsonNodeFactory.instance.objectNode();
+        groupCode.put("$ne", "0");
+
+        ObjectNode projectId =  JsonNodeFactory.instance.objectNode();
+        projectId.put("$ne", "0");
+
+        ObjectNode andOr = JsonNodeFactory.instance.objectNode();
+        andOr.putPOJO("groupCode", projectId);
+        andOr.putPOJO("projectId", groupCode);
+
+        criteria.putPOJO("$andOr", andOr);
+
+        queryCriteria.setCriteria(criteria);
+        queryCriteria.setSize(-1L);
+
+        List<ObjectTypeDefine> admDefineList = getAdmData(context, queryCriteria);
+        String queryUrl = requestUrl(context, migrationInfo, MigrationType.QUERY.getCode());
+        List<ObjectTypeDefine> projectDefineList = getProjectData(queryCriteria, ObjectTypeDefine.class, queryUrl);
+        List<ObjectNode> objectNodeList = JsonNodeUtils.toListNode(projectDefineList, null, null);
+        if(CollUtil.isEmpty(admDefineList)){
+            log.error(" ######################### DefineType adm已交付需要同步的数据:"+ ResponseCode.C0320.getDesc() +" 同步结束 #########################");
+            return dataMigrationExcels;
+        }
+
+        String insertUrl = requestUrl(context, migrationInfo, MigrationType.INSERT.getCode());
+        if(CollUtil.isEmpty(objectNodeList)){
+            log.info("######################### DefineType 批量插入数据 #########################");
+            DataMigrationResponse dataMigrationResponse = insertBatch(admDefineList, ObjectTypeDefine.class, insertUrl);
+            dataMigrationExcels.addAll(processData(dataMigrationResponse, MigrationType.INSERT.getDesc()));
+
+            return dataMigrationExcels;
+        }
+        List<ObjectNode> objectNodeListPro = JsonNodeUtils.toListNode(objectNodeList, null, null);
+        Map<String,Object> projectDefineMap = toEntityMap(objectNodeListPro, ObjectTypeDefine.class);
+        List<ObjectNode> objectNodeListAdm = JsonNodeUtils.toListNode(admDefineList, null, null);
+        Map<String,Object> admDefineMap = toEntityMap(objectNodeListAdm, ObjectTypeDefine.class);
+
+        //差集 新增
+        log.info("######################### DefineType 批量处理新增数据 #########################");
+        Map<String,Object> doSubtractFromInsert = doSubtractAdd(admDefineMap, projectDefineMap);
+        if(!CollUtil.isEmpty(doSubtractFromInsert)){
+            List<ObjectTypeDefine> insertData = toList(doSubtractFromInsert, admDefineList);
+            DataMigrationResponse dataMigrationResponse = insertBatch(insertData, ObjectTypeDefine.class, insertUrl);
+            dataMigrationExcels.addAll(processData(dataMigrationResponse, MigrationType.INSERT.getDesc()));
+        }
+
+        //差集 删除
+        log.info("######################### DefineType 批量处理删除数据 #########################");
+        Map<String,Object> doSubtractFromDelete = doSubtractDel(admDefineMap, projectDefineMap);
+        if(!CollUtil.isEmpty(doSubtractFromDelete)){
+            List<String> deleteIds = doSubtractFromDelete.entrySet().stream().map(en -> en.getKey()).collect(Collectors.toList());
+            List<ObjectTypeDefine> deleteData = toList(doSubtractFromDelete, projectDefineList);
+
+            String delUrl = requestUrl(context, migrationInfo, MigrationType.DELETE.getCode());
+            DataMigrationResponse dataMigrationResponse = deleteBatch(deleteIds, ObjectTypeDefine.class, delUrl);
+            dataMigrationExcels.addAll(processData(dataMigrationResponse, MigrationType.DELETE.getDesc()));
+        }
+
+        //交集更新
+        log.info("######################### DefineType 批量处理更新数据 #########################");
+        Map<String,Object> intersectionUpdateFrom = doIntersectionGetFrom(admDefineMap, projectDefineMap);
+        Map<String,Object> intersectionUpdateTo = doIntersectionGetTo(admDefineMap, projectDefineMap);
+
+        if(!CollUtil.isEmpty(intersectionUpdateFrom) && !CollUtil.isEmpty(intersectionUpdateTo)){
+            Map<String, Object> compareData = compareData(intersectionUpdateFrom, intersectionUpdateTo);
+            if(CollUtil.isNotEmpty(compareData) && compareData.size() > 0){
+                List<ObjectTypeDefine> updateData = toList(compareData, admDefineList);
+                String updateUrl = requestUrl(context, migrationInfo, MigrationType.UPDATE.getCode());
+                DataMigrationResponse dataMigrationResponse = updateBatch(updateData, ObjectTypeDefine.class, updateUrl);
+                dataMigrationExcels.addAll(processData(dataMigrationResponse, MigrationType.UPDATE.getDesc()));
+            }
+        }
+        long end = System.currentTimeMillis();
+        log.info("######################### DefineType 数据迁移已结束 时间:"+(end-start)+" #########################");
+        return dataMigrationExcels;
+    }
+
+    /**
+     * 获取adm交付的数据,默认获取有效数据
+     *
+     * @param context
+     * @return
+     */
+    @Override
+    public List<ObjectTypeDefine> getAdmData(InstanceUrlParam context, QueryCriteria queryCriteria) {
+        log.info("######################### DefineType 获取adm交付数据 #########################");
+        List<ObjectTypeDefine> types = DigitalDefineFacade.queryObjectType(context.getGroupCode(),context.getProjectId(),context.getUserId(),context.getUserId(),queryCriteria);
+        return types;
+    }
+
+    /**
+     * 根据map转为需要处理的对象集合
+     * 使用 MigrationConstant.spliter 作为拼接符
+     * @param fromMap
+     * @param fromList
+     * @return
+     */
+
+    public List<ObjectTypeDefine> toList(Map<String, Object> fromMap, List<ObjectTypeDefine> fromList) {
+        if(CollUtil.isEmpty(fromMap) || CollUtil.isEmpty(fromList)){
+            return null;
+        }
+        List<ObjectTypeDefine> results = new ArrayList<>(fromMap.size());
+        Map<String, ObjectTypeDefine> objectTypeDefineMap = CollUtil.fieldValueMap(fromList, BaseEntity.PROP_ID);
+        for(String key : fromMap.keySet()){
+            results.add(objectTypeDefineMap.get(StrUtil.trim(key)));
+        }
+        return results;
+    }
+
+
+    /**
+     * 拼接访问链接
+     *
+     * @param context
+     * @param migrationInfo
+     * @param type
+     * @return
+     */
+    @Override
+    public String requestUrl(InstanceUrlParam context, MigrationInfo migrationInfo, String type) {
+        if(StrUtil.isBlank(migrationInfo.getTargetUrl())){
+            return null;
+        }
+        StringBuilder url = new StringBuilder(migrationInfo.getTargetUrl());
+        if(type.equals(MigrationType.QUERY.getCode())) {
+            url.append(MigrationConstant.DEF_CLASS);
+        }else if(type.equals(MigrationType.INSERT.getCode())){
+            url.append(MigrationConstant.DEF_CLASS_INSERT);
+        }else if(type.equals(MigrationType.UPDATE.getCode())){
+            url.append(MigrationConstant.DEF_CLASS_UPDATE);
+        }else{
+            url.append(MigrationConstant.DEF_CLASS_DELETE);
+        }
+        return commonUrl(context, url.toString(), migrationInfo);
+    }
+
+    /**
+     * 将目标集合处理成excel格式的集合  使用与insert/delete
+     *
+     * @param dataMigrationResponse
+     * @return
+     */
+    @Override
+    public List<DataMigrationExcel> processData(DataMigrationResponse dataMigrationResponse, String type) {
+        if(CollUtil.isEmpty(dataMigrationResponse.getData()) && CollUtil.isEmpty(dataMigrationResponse.getErrorMsg())){
+            return Collections.emptyList();
+        }
+        List<DataMigrationExcel> dataMigrationExcels = new ArrayList<>();
+        if(CollUtil.isNotEmpty(dataMigrationResponse.getData())){
+            for(Object obj : dataMigrationResponse.getData()){
+                if(!type.equals(MigrationType.DELETE.getCode())){
+                    ObjectTypeDefine objectTypeDefine = (ObjectTypeDefine) obj;
+                    DataMigrationExcel excel = new DataMigrationExcel();
+                    excel.setId(objectTypeDefine.getId());
+                    excel.setCode(objectTypeDefine.getCode());
+                    excel.setName(objectTypeDefine.getName());
+                    excel.setType(type);
+                    dataMigrationExcels.add(excel);
+                }else{
+                    DataMigrationExcel excel = new DataMigrationExcel();
+                    excel.setId(obj.toString());
+                    excel.setType(type);
+                    dataMigrationExcels.add(excel);
+                }
+            }
+        }
+        if(CollUtil.isNotEmpty(dataMigrationResponse.getErrorMsg())){
+            dataMigrationExcels.addAll(addErrorInfo(dataMigrationResponse.getErrorMsg()));
+        }
+        return dataMigrationExcels;
+    }
+
+}

+ 25 - 0
src/main/java/com/persagy/proxy/migration/handler/IDataMigration.java

@@ -0,0 +1,25 @@
+package com.persagy.proxy.migration.handler;
+
+import com.persagy.proxy.common.entity.InstanceUrlParam;
+import com.persagy.proxy.migration.model.DataMigrationExcel;
+import com.persagy.proxy.migration.model.MigrationInfo;
+
+import java.util.List;
+
+/**
+ * @author lvxianyun
+ * @title: DataMigrationService
+ * @projectName adm-middleware
+ * @description: 处理需要迁移的数据
+ * @date 2021/12/1 18:09
+ */
+public interface IDataMigration{
+
+    /**
+     * 数据迁移
+     * @param context
+     * @return
+     */
+    List<DataMigrationExcel> migrate(InstanceUrlParam context, MigrationInfo migrationInfo);
+
+}

+ 43 - 0
src/main/java/com/persagy/proxy/migration/handler/IDataMigrationProcess.java

@@ -0,0 +1,43 @@
+package com.persagy.proxy.migration.handler;
+
+import com.persagy.dmp.basic.model.QueryCriteria;
+import com.persagy.proxy.common.entity.InstanceUrlParam;
+import com.persagy.proxy.migration.model.DataMigrationExcel;
+import com.persagy.proxy.migration.model.DataMigrationResponse;
+import com.persagy.proxy.migration.model.MigrationInfo;
+
+import java.util.List;
+
+/**
+ * @author lvxianyun
+ * @title: DefineTypeMigrationService
+ * @projectName adm-middleware
+ * @description:
+ * @date 2021/12/8 10:45
+ */
+public interface IDataMigrationProcess<T> {
+    /**
+     * 获取adm交付的数据,默认获取有效数据
+     * @param context
+     * @return
+     */
+    List getAdmData(InstanceUrlParam context, QueryCriteria queryCriteria);
+
+    /**
+     * 拼接访问链接
+     * @param context
+     * @param migrationInfo
+     * @param type
+     * @return
+     */
+    String requestUrl(InstanceUrlParam context, MigrationInfo migrationInfo, String type);
+
+    /**
+     * 将目标集合处理成excel格式的集合  使用与insert/delete
+     * @param dataMigrationResponse
+     * @param type insert/delete
+     * @return
+     */
+    List<DataMigrationExcel> processData(DataMigrationResponse dataMigrationResponse, String type);
+
+}

+ 237 - 0
src/main/java/com/persagy/proxy/migration/handler/ObjectDigitalMigration.java

@@ -0,0 +1,237 @@
+package com.persagy.proxy.migration.handler;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.dmp.basic.model.QueryCriteria;
+import com.persagy.dmp.basic.utils.JsonNodeUtils;
+import com.persagy.dmp.common.constant.ResponseCode;
+import com.persagy.dmp.digital.client.DigitalObjectFacade;
+import com.persagy.dmp.digital.entity.ObjectDigital;
+import com.persagy.proxy.common.entity.InstanceUrlParam;
+import com.persagy.proxy.migration.constant.MigrationConstant;
+import com.persagy.proxy.migration.constant.MigrationType;
+import com.persagy.proxy.migration.model.DataMigrationExcel;
+import com.persagy.proxy.migration.model.DataMigrationResponse;
+import com.persagy.proxy.migration.model.MigrationInfo;
+import com.persagy.proxy.migration.service.Impl.MigrationAbstractServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author lvxianyun
+ * @title: ObjectMigration
+ * @projectName adm-middleware
+ * @description: 迁移adm交付的数据到现场,覆盖现场数据,提供增加、删除、修改 记录放入excel; dt_object 数据迁移 adm -> target project
+ * @date 2021/12/8 19:53
+ */
+@Slf4j
+public class ObjectDigitalMigration extends MigrationAbstractServiceImpl<ObjectDigital> implements IDataMigration, IDataMigrationProcess<ObjectDigital> {
+
+   private static ObjectDigitalMigration instance;
+
+    private ObjectDigitalMigration() {}
+
+    // 静态方法返回该实例
+    public static ObjectDigitalMigration getInstance() {
+        if(instance == null) {
+            synchronized (ObjectDigitalMigration.class) {
+                if (instance == null) {
+                    instance = new ObjectDigitalMigration();
+                }
+            }
+        }
+        return instance;
+    }
+
+    /**
+     * 数据迁移
+     *
+     * @param context
+     * @param migrationInfo
+     * @return
+     */
+    @Override
+    public List<DataMigrationExcel> migrate(InstanceUrlParam context, MigrationInfo migrationInfo) {
+        log.info("######################### dt_object 同步开始 #########################");
+        long start = System.currentTimeMillis();
+        List<DataMigrationExcel> dataMigrationExcels = new ArrayList<>();
+
+        //for(MigrationObjType objType : MigrationObjType.values()){
+            //log.info("######################### dt_object "+objType.getCode()+"同步开始 #########################");
+            QueryCriteria queryCriteria = new QueryCriteria();
+            queryCriteria.setSize(-1L);
+            ObjectNode criteria = JsonNodeFactory.instance.objectNode();
+            criteria.put("valid", 1);
+            criteria.put("objType", "equipment");
+            //criteria.put("objType", objType.getCode());
+            queryCriteria.setCriteria(criteria);
+            dataMigrationExcels.addAll(startMigrate(context,migrationInfo,queryCriteria));
+            //log.info("######################### dt_object "+objType.getCode()+"同步结束 #########################");
+        //}
+        long end = System.currentTimeMillis();
+        log.info("######################### dt_object 数据迁移已结束 时间:"+(end-start)+" #########################");
+        return dataMigrationExcels;
+    }
+
+    private List<DataMigrationExcel> startMigrate(InstanceUrlParam context, MigrationInfo migrationInfo, QueryCriteria queryCriteria) {
+        List<DataMigrationExcel> dataMigrationExcels = new ArrayList<>();
+        List<ObjectNode> admData = getAdmData(context,queryCriteria);
+
+        String queryUrl = requestUrl(context, migrationInfo, MigrationType.QUERY.getCode());
+        List<ObjectDigital> projectData = getProjectData(queryCriteria, ObjectDigital.class, queryUrl);
+        List<ObjectNode> objectNodeList = JsonNodeUtils.toListNode(projectData, null, null);
+
+        if(CollUtil.isEmpty(admData)){
+            log.error(" ######################### dt_object adm已交付:"+ ResponseCode.C0320.getDesc() +" 同步结束 #########################");
+            return Collections.emptyList();
+        }
+
+        String insertUrl = requestUrl(context, migrationInfo, MigrationType.INSERT.getCode());
+        if(CollUtil.isEmpty(objectNodeList)){
+            DataMigrationResponse dataMigrationResponse = insertBatch(admData, ObjectDigital.class, insertUrl);
+            dataMigrationExcels.addAll(processData(dataMigrationResponse, MigrationType.INSERT.getDesc()));
+            return dataMigrationExcels;
+        }
+        Map<String,Object> projectMap = toEntityMap(objectNodeList, ObjectDigital.class);
+        Map<String,Object> admMap = toEntityMap(admData, ObjectDigital.class);
+        //差集 新增
+        Map<String,Object> doSubtractFromInsert = doSubtractAdd(admMap, projectMap);
+        if(!CollUtil.isEmpty(doSubtractFromInsert)){
+            List<ObjectNode> insertData = toList(doSubtractFromInsert, admData);
+            DataMigrationResponse dataMigrationResponse = insertBatch(insertData, ObjectDigital.class, insertUrl);
+            dataMigrationExcels.addAll(processData(dataMigrationResponse, MigrationType.INSERT.getDesc()));
+        }
+
+        //差集 删除
+        Map<String,Object> doSubtractFromDelete = doSubtractDel(admMap, projectMap);
+        if(!CollUtil.isEmpty(doSubtractFromDelete)){
+            List<String> deleteIds = doSubtractFromDelete.entrySet().stream().map(en -> en.getKey()).collect(Collectors.toList());
+            String delUrl = requestUrl(context, migrationInfo, MigrationType.DELETE.getCode());
+            DataMigrationResponse dataMigrationResponse = deleteBatch(deleteIds, ObjectDigital.class, delUrl);
+            dataMigrationExcels.addAll(processData(dataMigrationResponse, MigrationType.DELETE.getDesc()));
+        }
+
+        //交集更新
+        Map<String,Object> intersectionUpdateFrom = doIntersectionGetFrom(admMap, projectMap);
+        Map<String,Object> intersectionUpdateTo = doIntersectionGetTo(admMap, projectMap);
+
+        if(!CollUtil.isEmpty(intersectionUpdateFrom) && !CollUtil.isEmpty(intersectionUpdateTo)){
+            Map<String, Object> compareData = compareData(intersectionUpdateFrom, intersectionUpdateTo);
+            if(CollUtil.isNotEmpty(compareData) && compareData.size() > 0){
+                List<ObjectNode> updateData = toList(compareData, admData);
+                String updateUrl = requestUrl(context, migrationInfo, MigrationType.UPDATE.getCode());
+                DataMigrationResponse dataMigrationResponse = updateBatch(updateData, ObjectDigital.class, updateUrl);
+                dataMigrationExcels.addAll(processData(dataMigrationResponse, MigrationType.UPDATE.getDesc()));
+            }
+        }
+
+        return dataMigrationExcels;
+    }
+
+    /**
+     * 获取adm交付的数据,默认获取有效数据
+     *
+     * @param context
+     * @return
+     */
+    @Override
+    public List<ObjectNode> getAdmData(InstanceUrlParam context, QueryCriteria queryCriteria) {
+        List<ObjectNode> digitalList = DigitalObjectFacade.query(context.getGroupCode(),context.getProjectId(),context.getUserId(),context.getUserId(),queryCriteria);
+        if(CollUtil.isEmpty(digitalList)){
+            return Collections.emptyList();
+        }
+        return digitalList;
+    }
+
+    /**
+     * 根据map转为需要处理的对象集合
+     * 使用 MigrationConstant.spliter 作为拼接符
+     * @param fromMap
+     * @param fromList
+     * @return
+     */
+    public List<ObjectNode> toList(Map<String, Object> fromMap, List<ObjectNode> fromList) {
+        if(CollUtil.isEmpty(fromMap) || CollUtil.isEmpty(fromList)){
+            return null;
+        }
+        List<ObjectNode> results = new ArrayList<>(fromMap.size());
+
+        Map<String, ObjectNode> objectDigitalMap =  new HashMap<>(fromList.size());
+        for(ObjectNode node :  fromList){
+            if(!node.get("id").isTextual()){
+                continue;
+            }
+            objectDigitalMap.put(node.get("id").asText(), node);
+        }
+
+        for(String key : fromMap.keySet()){
+            results.add(objectDigitalMap.get(key));
+        }
+        return results;
+    }
+
+    /**
+     * 拼接访问链接
+     *
+     * @param context
+     * @param migrationInfo
+     * @param type
+     * @return
+     */
+    @Override
+    public String requestUrl(InstanceUrlParam context, MigrationInfo migrationInfo, String type) {
+        if(StrUtil.isBlank(migrationInfo.getTargetUrl())){
+            return null;
+        }
+        StringBuilder url = new StringBuilder(migrationInfo.getTargetUrl());
+        if(type.equals(MigrationType.QUERY.getCode())) {
+            url.append(MigrationConstant.DT_OBJECT);
+        }else if(type.equals(MigrationType.INSERT.getCode())){
+            url.append(MigrationConstant.DT_OBJECT_INSERT);
+        }else if(type.equals(MigrationType.UPDATE.getCode())){
+            url.append(MigrationConstant.DT_OBJECT_UPDATE);
+        }else{
+            url.append(MigrationConstant.DT_OBJECT_DELETE);
+        }
+        return commonUrl(context, url.toString(), migrationInfo);
+    }
+
+    /**
+     * 将目标集合处理成excel格式的集合  使用与insert/delete
+     *
+     * @param dataMigrationResponse
+     * @return
+     */
+    @Override
+    public List<DataMigrationExcel> processData(DataMigrationResponse dataMigrationResponse, String type) {
+        if(CollUtil.isEmpty(dataMigrationResponse.getData()) && CollUtil.isEmpty(dataMigrationResponse.getErrorMsg())){
+            return Collections.emptyList();
+        }
+        List<DataMigrationExcel> dataMigrationExcels = new ArrayList<>();
+        if(CollUtil.isNotEmpty(dataMigrationResponse.getData())){
+            for(Object obj : dataMigrationResponse.getData()){
+                if(!type.equals(MigrationType.DELETE.getCode())){
+                    ObjectDigital digital = (ObjectDigital) obj;
+                    DataMigrationExcel excel = new DataMigrationExcel();
+                    excel.setId(digital.getId());
+                    excel.setName(digital.getName());
+                    excel.setType(type);
+                    dataMigrationExcels.add(excel);
+                }else{
+                    DataMigrationExcel excel = new DataMigrationExcel();
+                    excel.setId(obj.toString());
+                    excel.setType(type);
+                    dataMigrationExcels.add(excel);
+                }
+            }
+        }
+        if(CollUtil.isNotEmpty(dataMigrationResponse.getErrorMsg())){
+            dataMigrationExcels.addAll(addErrorInfo(dataMigrationResponse.getErrorMsg()));
+        }
+        return dataMigrationExcels;
+    }
+}

+ 235 - 0
src/main/java/com/persagy/proxy/migration/handler/ObjectRelationMigration.java

@@ -0,0 +1,235 @@
+package com.persagy.proxy.migration.handler;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.dmp.basic.model.QueryCriteria;
+import com.persagy.dmp.basic.utils.JsonNodeUtils;
+import com.persagy.dmp.common.constant.ResponseCode;
+import com.persagy.dmp.common.model.entity.BaseEntity;
+import com.persagy.dmp.digital.client.DigitalRelationFacade;
+import com.persagy.dmp.digital.entity.ObjectRelation;
+import com.persagy.proxy.common.entity.InstanceUrlParam;
+import com.persagy.proxy.migration.constant.MiGrationRelCode;
+import com.persagy.proxy.migration.constant.MigrationConstant;
+import com.persagy.proxy.migration.constant.MigrationType;
+import com.persagy.proxy.migration.model.DataMigrationExcel;
+import com.persagy.proxy.migration.model.DataMigrationResponse;
+import com.persagy.proxy.migration.model.MigrationInfo;
+import com.persagy.proxy.migration.service.Impl.MigrationAbstractServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @author lvxianyun
+ * @title: RelationMigration
+ * @projectName adm-middleware
+ * @description: 迁移adm交付的数据到现场,覆盖现场数据,提供增加、删除、修改 记录放入excel; dt_relation 数据迁移 adm -> target project
+ * @date 2021/12/8 19:51
+ */
+@Slf4j
+public class ObjectRelationMigration extends MigrationAbstractServiceImpl<ObjectRelation> implements IDataMigration, IDataMigrationProcess<ObjectRelation> {
+
+    private static ObjectRelationMigration instance;
+
+    private ObjectRelationMigration() {}
+
+    // 静态方法返回该实例
+    public static ObjectRelationMigration getInstance() {
+        if(instance == null) {
+            synchronized (ObjectRelationMigration.class) {
+                if (instance == null) {
+                    instance = new ObjectRelationMigration();
+                }
+            }
+        }
+        return instance;
+    }
+
+    /**
+     * 数据迁移
+     *
+     * @param context
+     * @param migrationInfo
+     * @return
+     */
+    @Override
+    public List<DataMigrationExcel> migrate(InstanceUrlParam context, MigrationInfo migrationInfo) {
+        log.info("######################### dt_relation 同步开始 #########################");
+        long start = System.currentTimeMillis();
+        List<DataMigrationExcel> dataMigrationExcels = new ArrayList<>();
+
+        for (MiGrationRelCode miGrationRelCode: MiGrationRelCode.values()){
+            log.info("######################### dt_relation "+miGrationRelCode.getCode()+"同步开始 #########################");
+
+            QueryCriteria queryCriteria = new QueryCriteria();
+            ObjectNode criteria = JsonNodeFactory.instance.objectNode();
+            criteria.put("valid", 1);
+            criteria.put("relCode", miGrationRelCode.getCode());
+            dataMigrationExcels.addAll(startMigrate(context, migrationInfo, queryCriteria));
+
+            log.info("######################### dt_relation "+miGrationRelCode.getCode()+"同步结束 #########################");
+        }
+        long end = System.currentTimeMillis();
+        log.info("######################### dt_relation 同步结束 "+(end-start)+"#########################");
+        return dataMigrationExcels;
+    }
+
+    private List<DataMigrationExcel> startMigrate(InstanceUrlParam context, MigrationInfo migrationInfo, QueryCriteria queryCriteria){
+        List<DataMigrationExcel> dataMigrationExcels = new ArrayList<>();
+        List<ObjectRelation> admRelations = getAdmData(context, queryCriteria);
+
+        String queryUrl = requestUrl(context, migrationInfo, MigrationType.QUERY.getCode());
+        List<ObjectRelation> projectRelations = getProjectData(queryCriteria, ObjectRelation.class, queryUrl);
+        if(CollUtil.isEmpty(admRelations)){
+            log.error(" ######################### dt_relation adm已交付:"+ ResponseCode.C0320.getDesc() +" 同步结束 #########################");
+            return dataMigrationExcels;
+        }
+
+        String insertUrl = requestUrl(context, migrationInfo, MigrationType.INSERT.getCode());
+        if(CollUtil.isEmpty(projectRelations)){
+            DataMigrationResponse dataMigrationResponse = insertBatch(admRelations, ObjectRelation.class, insertUrl);
+            dataMigrationExcels.addAll(processData(dataMigrationResponse, MigrationType.INSERT.getDesc()));
+            return dataMigrationExcels;
+        }
+        List<ObjectNode> objectNodeListPro = JsonNodeUtils.toListNode(projectRelations, null, null);
+        Map<String,Object> projectDefineMap = toEntityMap(objectNodeListPro, ObjectRelation.class);
+        List<ObjectNode> objectNodeListAdm = JsonNodeUtils.toListNode(admRelations, null, null);
+        Map<String,Object> admDefineMap = toEntityMap(objectNodeListAdm, ObjectRelation.class);
+
+        //差集 新增
+        Map<String,Object> doSubtractFromInsert = doSubtractAdd(admDefineMap, projectDefineMap);
+        if(!CollUtil.isEmpty(doSubtractFromInsert)){
+            List<ObjectRelation> insertData = toList(doSubtractFromInsert, admRelations);
+            DataMigrationResponse dataMigrationResponse = insertBatch(insertData, ObjectRelation.class, insertUrl);
+            dataMigrationExcels.addAll(processData(dataMigrationResponse, MigrationType.INSERT.getDesc()));
+        }
+
+        //差集 删除
+        Map<String,Object> doSubtractFromDelete = doSubtractDel(admDefineMap, projectDefineMap);
+        if(!CollUtil.isEmpty(doSubtractFromDelete)){
+            List<String> deleteIds = doSubtractFromDelete.entrySet().stream().map(en -> en.getKey()).collect(Collectors.toList());
+            String delUrl = requestUrl(context, migrationInfo, MigrationType.DELETE.getCode());
+            DataMigrationResponse dataMigrationResponse = deleteBatch(deleteIds, ObjectRelation.class, delUrl);
+            dataMigrationExcels.addAll(processData(dataMigrationResponse, MigrationType.DELETE.getDesc()));
+        }
+
+        //交集更新
+        Map<String,Object> intersectionUpdateFrom = doIntersectionGetFrom(admDefineMap, projectDefineMap);
+        Map<String,Object> intersectionUpdateTo = doIntersectionGetTo(admDefineMap, projectDefineMap);
+
+        if(!CollUtil.isEmpty(intersectionUpdateFrom) && !CollUtil.isEmpty(intersectionUpdateTo)){
+            Map<String, Object> compareData = compareData(intersectionUpdateFrom, intersectionUpdateTo);
+            if(CollUtil.isNotEmpty(compareData) && compareData.size() > 0){
+                List<ObjectRelation> updateData = toList(compareData, admRelations);
+                String updateUrl = requestUrl(context, migrationInfo, MigrationType.UPDATE.getCode());
+                DataMigrationResponse dataMigrationResponse = updateBatch(updateData, ObjectRelation.class, updateUrl);
+                dataMigrationExcels.addAll(processData(dataMigrationResponse, MigrationType.UPDATE.getDesc()));
+            }
+        }
+        return dataMigrationExcels;
+    }
+
+
+
+
+    /**
+     * 获取adm交付的数据,默认获取有效数据
+     *
+     * @param context
+     * @return
+     */
+    @Override
+    public List<ObjectRelation> getAdmData(InstanceUrlParam context, QueryCriteria queryCriteria) {
+        List<ObjectRelation> relations = DigitalRelationFacade.query(context.getGroupCode(),context.getProjectId(),context.getUserId(),context.getUserId(),queryCriteria);
+        return relations;
+    }
+
+    /**
+     * 根据map转为需要处理的对象集合
+     * 使用 MigrationConstant.spliter 作为拼接符
+     * @param fromMap
+     * @param fromList
+     * @return
+     */
+    public List<ObjectRelation> toList(Map<String, Object> fromMap, List<ObjectRelation> fromList) {
+        if(CollUtil.isEmpty(fromMap) || CollUtil.isEmpty(fromList)){
+            return null;
+        }
+        List<ObjectRelation> results = new ArrayList<>(fromMap.size());
+        Map<String, ObjectRelation> objectRelationMap = CollUtil.fieldValueMap(fromList, BaseEntity.PROP_ID);
+        for(String key : fromMap.keySet()){
+            results.add(objectRelationMap.get(key));
+        }
+        return results;
+    }
+
+    /**
+     * 拼接访问链接
+     *
+     * @param context
+     * @param migrationInfo
+     * @param type
+     * @return
+     */
+    @Override
+    public String requestUrl(InstanceUrlParam context, MigrationInfo migrationInfo, String type) {
+        if(StrUtil.isBlank(migrationInfo.getTargetUrl())){
+            return null;
+        }
+        StringBuilder uRL = new StringBuilder(migrationInfo.getTargetUrl());
+        if(type.equals(MigrationType.QUERY.getCode())) {
+            uRL.append(MigrationConstant.DT_RELATION);
+        }else if(type.equals(MigrationType.INSERT.getCode())){
+            uRL.append(MigrationConstant.DT_RELATION_INSERT);
+        }else if(type.equals(MigrationType.UPDATE.getCode())){
+            uRL.append(MigrationConstant.DT_RELATION_UPDATE);
+        }else{
+            uRL.append(MigrationConstant.DT_RELATION_DELETE);
+        }
+        return commonUrl(context, uRL.toString(), migrationInfo);
+    }
+
+
+    /**
+     * 将目标集合处理成excel格式的集合  使用与insert/delete
+     *
+     * @param dataMigrationResponse
+     * @return
+     */
+    @Override
+    public List<DataMigrationExcel> processData(DataMigrationResponse dataMigrationResponse, String type) {
+        if(CollUtil.isEmpty(dataMigrationResponse.getData()) && CollUtil.isEmpty(dataMigrationResponse.getErrorMsg())){
+            return Collections.emptyList();
+        }
+        List<DataMigrationExcel> dataMigrationExcels = new ArrayList<>();
+        if(CollUtil.isNotEmpty(dataMigrationResponse.getData())){
+            for(Object obj : dataMigrationResponse.getData()){
+                if(!type.equals(MigrationType.DELETE.getCode())){
+                    ObjectRelation define = (ObjectRelation) obj;
+                    DataMigrationExcel excel = new DataMigrationExcel();
+                    excel.setId(define.getId());
+                    excel.setCode(define.getRelCode());
+                    excel.setCode1(define.getGraphCode());
+                    excel.setType(type);
+                    dataMigrationExcels.add(excel);
+                }else{
+                    DataMigrationExcel excel = new DataMigrationExcel();
+                    excel.setId(obj.toString());
+                    excel.setType(type);
+                    dataMigrationExcels.add(excel);
+                }
+            }
+        }
+        if(CollUtil.isNotEmpty(dataMigrationResponse.getErrorMsg())){
+            dataMigrationExcels.addAll(addErrorInfo(dataMigrationResponse.getErrorMsg()));
+        }
+        return dataMigrationExcels;
+    }
+}

+ 57 - 0
src/main/java/com/persagy/proxy/migration/model/DataMigrationExcel.java

@@ -0,0 +1,57 @@
+package com.persagy.proxy.migration.model;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ColumnWidth;
+import com.alibaba.excel.annotation.write.style.HeadFontStyle;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.poi.ss.usermodel.Font;
+
+/**
+ * @author lvxianyun
+ * @title: DataMigrationExcel
+ * @projectName adm-middleware
+ * @description: adm数据同步到现场返回结果
+ * @date 2021/11/23 18:27
+ */
+@Getter
+@Setter
+@HeadFontStyle(color = Font.COLOR_NORMAL)
+public class DataMigrationExcel {
+
+    @ColumnWidth(20)
+    @ExcelProperty(value = "id", index=0)
+    private String id;
+
+    @ColumnWidth(20)
+    @ExcelProperty(value = "名称", index=1)
+    private String name;
+
+    @ColumnWidth(20)
+    @ExcelProperty(value = "code", index=2)
+    private String code;
+
+    @ColumnWidth(20)
+    @ExcelProperty(value = "code1", index=3)
+    private String code1;
+
+    @ColumnWidth(20)
+    @ExcelProperty(value = "类型(增加/删除/修改)", index=4)
+    private String type;
+
+    @ColumnWidth(20)
+    @ExcelProperty(value = "源(云端/现场)", index=5)
+    private String directional = "adm-to-project";
+
+    @ColumnWidth(30)
+    @ExcelProperty(value = "from(adm)", index=6)
+    private String source;
+
+    @ColumnWidth(30)
+    @ExcelProperty(value = "to(project)", index=7)
+    private String targetProject;
+
+    @ColumnWidth(50)
+    @ExcelProperty(value = "备注", index=8)
+    private String mark;
+}

+ 60 - 0
src/main/java/com/persagy/proxy/migration/model/DataMigrationResponse.java

@@ -0,0 +1,60 @@
+package com.persagy.proxy.migration.model;
+
+import cn.hutool.core.collection.CollUtil;
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author lvxianyun
+ * @title: DataMigrationResponse
+ * @projectName adm-middleware
+ * @date 2021/12/15 17:09
+ */
+@Data
+@Builder
+public class DataMigrationResponse {
+
+    public final static String SUCCESS = "success";
+    public final static String FAILURE = "failure";
+    /** 结果 */
+    private String result;
+
+    List<?> data;
+    List<String> errorMsg;
+
+    public void addData(List list){
+        if(data == null){
+            data = new ArrayList<>();
+        }
+        if(CollUtil.isNotEmpty(list)){
+            data.addAll(list);
+        }
+    }
+
+    public void addError(List<String> error){
+        if(errorMsg == null){
+            result = FAILURE;
+            errorMsg = new ArrayList<>();
+        }
+        if(CollUtil.isNotEmpty(error)){
+            errorMsg.addAll(error);
+        }
+    }
+
+
+    public static DataMigrationResponse success(List<?> data) {
+        return new DataMigrationResponse(SUCCESS,CollUtil.isEmpty(data) ? new ArrayList<>(1): data,null);
+    }
+
+    public static DataMigrationResponse success() {
+        return new DataMigrationResponse(SUCCESS,null,null);
+    }
+
+    public static DataMigrationResponse error(String errorMsg) {
+        return new DataMigrationResponse(FAILURE,null, Arrays.asList(errorMsg));
+    }
+}

+ 18 - 0
src/main/java/com/persagy/proxy/migration/model/MigrationInfo.java

@@ -0,0 +1,18 @@
+package com.persagy.proxy.migration.model;
+
+import lombok.Builder;
+import lombok.Data;
+
+/**
+ * @author lvxianyun
+ * @title: MigrationInfo 数据迁移参数
+ * @projectName adm-middleware
+ * @date 2021/12/3 17:18
+ */
+@Data
+@Builder
+public class MigrationInfo {
+    private String targetUrl;
+    private String targetGroupCode;
+    private String targetProjectId;
+}

+ 329 - 0
src/main/java/com/persagy/proxy/migration/service/Impl/MigrationAbstractServiceImpl.java

@@ -0,0 +1,329 @@
+package com.persagy.proxy.migration.service.Impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpException;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONUtil;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.Sets;
+import com.persagy.dmp.basic.model.QueryCriteria;
+import com.persagy.dmp.basic.utils.JsonNodeUtils;
+import com.persagy.dmp.common.constant.ResponseCode;
+import com.persagy.dmp.common.model.entity.AuditableEntity;
+import com.persagy.dmp.common.model.entity.BaseEntity;
+import com.persagy.dmp.common.model.response.CommonResult;
+import com.persagy.dmp.common.utils.JsonHelper;
+import com.persagy.proxy.common.entity.DmpResult;
+import com.persagy.proxy.common.entity.InstanceUrlParam;
+import com.persagy.proxy.migration.constant.MigrationConstant;
+import com.persagy.proxy.migration.model.DataMigrationExcel;
+import com.persagy.proxy.migration.model.DataMigrationResponse;
+import com.persagy.proxy.migration.model.MigrationInfo;
+import com.persagy.proxy.migration.service.MigrationAbstractService;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author lvxianyun
+ * @title: MigrationAbstractServiceImpl
+ * @projectName adm-middleware
+ * @description: 提供基础的数据操作方法 using guava
+ * @date 2021/12/3 10:56
+ */
+@Slf4j
+public class MigrationAbstractServiceImpl<T> implements MigrationAbstractService<T> {
+
+    /**
+     * adm交付数据(A) ∩ 现场数据(B)
+     * (A∩B) A
+     * 需要进一步对比的数据
+     *
+     * @param from
+     * @param to
+     */
+    @Override
+    public Map<String, Object> doIntersectionGetFrom(Map<String, Object> from, Map<String, Object> to) {
+        Sets.SetView<String> intersection = Sets.intersection(from.keySet(), to.keySet());
+        if(CollUtil.isEmpty(intersection)){
+            return null;
+        }
+        return getValueForMapByKeys(intersection, from);
+    }
+
+    /**
+     * adm交付数据(A) ∩ 现场数据(B)
+     * (A∩B) B
+     * 需要进一步对比的数据
+     *
+     * @param from
+     * @param to
+     */
+    @Override
+    public Map<String, Object> doIntersectionGetTo(Map<String, Object> from, Map<String, Object> to) {
+        Sets.SetView<String> intersection = Sets.intersection(from.keySet(), to.keySet());
+        if(CollUtil.isEmpty(intersection)){
+            return null;
+        }
+        return getValueForMapByKeys(intersection, to);
+    }
+
+    /**
+     * adm交付数据(From) 与 现场数据(to) 差集  返回adm数据
+     * (From - to)
+     * 新增
+     *
+     * @param from
+     * @param to
+     */
+    @Override
+    public Map<String, Object> doSubtractAdd(Map<String, Object> from, Map<String, Object> to) {
+        Sets.SetView<String> diffA = Sets.difference(from.keySet(), to.keySet());
+        return getValueForMapByKeys(diffA, from);
+    }
+
+    /**
+     * adm交付数据(From) 与 现场数据(to ) 差集  现场数据
+     * (to - From )
+     * 删除
+     *
+     * @param from
+     * @param to
+     */
+    @Override
+    public Map<String, Object> doSubtractDel(Map<String, Object> from, Map<String, Object> to) {
+        Sets.SetView<String> diffB = Sets.difference(to.keySet(), from.keySet());
+        return getValueForMapByKeys(diffB, to);
+    }
+
+    /**
+     * 拼接sql
+     *
+     * @param context
+     * @param migrationInfo
+     * @param urlStart
+     * @return
+     */
+    @Override
+    public String commonUrl(InstanceUrlParam context, String urlStart, MigrationInfo migrationInfo) {
+        if(StrUtil.isEmpty(urlStart) || StrUtil.isBlank(urlStart)){
+            return null;
+        }
+        StringBuffer url = new StringBuffer(urlStart);
+        url.append("groupCode=").append(migrationInfo.getTargetGroupCode());
+        url.append("&projectId=").append(migrationInfo.getTargetProjectId());
+        if(StrUtil.isNotEmpty(context.getUserId())){
+            url.append("&userId=").append(context.getUserId());
+        }
+        if(StrUtil.isNotEmpty(context.getAppId())) {
+            url.append("&appId=").append(context.getAppId());
+        }
+        return url.toString();
+    }
+
+    /**
+     * 向项目侧提交迁移数据
+     *
+     * @param url
+     * @param requestBody
+     */
+    @Override
+    public String commitDataByHttp(String url, String requestBody) {
+        try{
+            return HttpUtil.post(url, requestBody, 5000);
+        }catch (HttpException e){
+           log.error(ResponseCode.C0001.getDesc()+",url:"+ url);
+           return null;
+        }
+    }
+
+    /**
+     * 将list根据自定义规则转为map  id为key,
+     * 使用 MigrationConstant.spliter 作为拼接符
+     *
+     * @param list
+     * @return
+     */
+    @Override
+    public Map<String, Object> toEntityMap(List<ObjectNode> list, Class<T> clazz) {
+        if(CollUtil.isEmpty(list)){
+            return null;
+        }
+        Map<String, Field> fieldMap = JsonNodeUtils.getFieldMap(clazz);
+        Set<String> fields = fieldMap.keySet();
+        Map<String, Object> map = new HashMap<>(list.size());
+        for(ObjectNode objectNode : list){
+            String key = objectNode.get("id").toString();
+            StringBuffer value = new StringBuffer();
+            for(String fieldKey : fields){
+                if(fieldKey.equals(AuditableEntity.DO_PROP_CREATIONTIME)
+                        || fieldKey.equals(AuditableEntity.PROP_CREATOR)
+                        || fieldKey.equals(AuditableEntity.DO_PROP_MODIFIEDTIME)
+                        || fieldKey.equals(AuditableEntity.PROP_MODIFIER)
+                        || fieldKey.equals(BaseEntity.PROP_TS)){
+                    continue;
+                }
+                value.append(objectNode.get(fieldKey) == null ? "" : objectNode.get(fieldKey)).append(MigrationConstant.SPLITER);
+            }
+            map.put(key.replaceAll("\"",""), value.toString().replaceAll("\"",""));
+        }
+        return map;
+    }
+
+
+    /**
+     * 获取项目现场交付的数据,默认全部
+     *
+     * @param queryCriteria
+     * @param clazz
+     * @return
+     */
+    @Override
+    public List getProjectData(QueryCriteria queryCriteria, Class<T> clazz, String url) {
+        return processProjectData(null, queryCriteria, clazz, url).getData();
+    }
+
+    @Override
+    public DataMigrationResponse updateBatch(List vos, Class<T> clazz, String url) {
+        return saveOrUpdateCommProcess(vos, clazz, url);
+    }
+
+    @Override
+    public DataMigrationResponse insertBatch(List vos,  Class<T> clazz, String url) {
+       return saveOrUpdateCommProcess(vos, clazz, url);
+    }
+
+    /**
+     * 批量更新,分批次更新,大于500条,每500条提交一次
+     * @param vos
+     * @param clazz
+     * @param url
+     * @return
+     */
+    private DataMigrationResponse saveOrUpdateCommProcess(List vos,  Class<T> clazz, String url){
+        DataMigrationResponse dataMigrationResponse = DataMigrationResponse.success();
+        if(vos.size() <= MigrationConstant.batchSubmitDataCount){
+            DataMigrationResponse temp = processProjectData(vos,null, clazz, url);
+            if(CollUtil.isNotEmpty(temp.getData())){
+                dataMigrationResponse.addData(temp.getData());
+            }
+        }else{
+            int count= vos.size() / MigrationConstant.batchSubmitDataCount;
+            for(int k = 0; k< count + 1 ;k++){
+                int end = (k+1)  * MigrationConstant.batchSubmitDataCount - 1;
+                if(end > vos.size()){
+                    end = vos.size();
+                }
+                List admDataSub = vos.subList(k * MigrationConstant.batchSubmitDataCount, end);
+                DataMigrationResponse responseTemp = processProjectData(admDataSub,null, clazz, url);
+                if(CollUtil.isNotEmpty(responseTemp.getData())){
+                    dataMigrationResponse.addData(responseTemp.getData());
+                }
+                if(CollUtil.isNotEmpty(responseTemp.getErrorMsg())){
+                    dataMigrationResponse.addError(responseTemp.getErrorMsg());
+                }
+            }
+        }
+        return dataMigrationResponse;
+    }
+
+
+    @Override
+    public DataMigrationResponse deleteBatch(List<String> ids, Class<T> clazz, String url) {
+        String response = null;
+        try {
+            response = commitDataByHttp(url, JsonHelper.toJsonStr(ids));
+        } catch (IOException e) {
+            log.error(e.getMessage());
+            return DataMigrationResponse.error(e.getMessage());
+        }
+        CommonResult<List> commonResult = JSONUtil.toBean(response, CommonResult.class);
+        if(commonResult.getResult().equals(DmpResult.SUCCESS)){
+            return DataMigrationResponse.success(ids);
+        }else {
+            log.error(commonResult.getMessage());
+            return DataMigrationResponse.error(commonResult.getResult());
+        }
+    }
+
+    /**
+     * 对比需要更新的数据
+     *
+     * @param from
+     * @param to
+     */
+    @Override
+    public Map<String, Object> compareData(Map<String, Object> from, Map<String, Object> to) {
+        if(CollUtil.isEmpty(from) || CollUtil.isEmpty(to)){
+            return null;
+        }
+        Set<String> formSets = from.entrySet().stream().map(en -> String.join(MigrationConstant.SPLITER_UNION,en.getKey(),en.getValue().toString())).collect(Collectors.toSet());
+        Set<String> toSets = to.entrySet().stream().map(en -> String.join(MigrationConstant.SPLITER_UNION,en.getKey(),en.getValue().toString())).collect(Collectors.toSet());
+
+        Sets.SetView<String> difference = Sets.difference(formSets, toSets);
+        if(CollUtil.isEmpty(difference)){
+            return null;
+        }
+        Set<String> diff = difference.stream().map(entity -> StrUtil.subBefore(entity, MigrationConstant.SPLITER_UNION, true)).collect(Collectors.toSet());
+        Map<String, Object> results = getValueForMapByKeys(diff, from);
+        return results;
+    }
+
+    @Override
+    public List<DataMigrationExcel> addErrorInfo(List<String> errorMsg) {
+        if(CollUtil.isEmpty(errorMsg)){
+            return Collections.emptyList();
+        }
+        List<DataMigrationExcel> dataMigrationExcels = new ArrayList<>(errorMsg.size());
+        for(String msg : errorMsg){
+            DataMigrationExcel dataMigrationExcelError = new DataMigrationExcel();
+            dataMigrationExcelError.setId("error");
+            dataMigrationExcelError.setMark(msg);
+            dataMigrationExcels.add(dataMigrationExcelError);
+        }
+        return dataMigrationExcels;
+    }
+
+    private DataMigrationResponse processProjectData(List vos, QueryCriteria queryCriteria, Class<T> clazz, String url){
+        //处理rwd 请求返回超时
+        String body = null;
+        try {
+            if(CollUtil.isEmpty(vos) && queryCriteria != null){
+                body = JsonHelper.toJsonStr(queryCriteria);
+            }else{
+                body = JsonHelper.toJsonStr(vos);
+            }
+
+        } catch (IOException e) {
+            log.error(ResponseCode.C0001.toString());
+            return DataMigrationResponse.error(ResponseCode.C0001.toString());
+        }
+        String response = commitDataByHttp(url, body);
+        CommonResult<List> commonResult = JSONUtil.toBean(response, CommonResult.class);
+        if(commonResult.getResult().equals(DmpResult.SUCCESS)){
+            ArrayNode arrayNode = JsonNodeUtils.toArrayNode(commonResult.getData(), null, null);
+            if(arrayNode == null){
+                return DataMigrationResponse.success();
+            }
+            return DataMigrationResponse.success(JsonNodeUtils.toEntity(arrayNode, clazz, null));
+        }else {
+            log.error(commonResult.getMessage());
+            return DataMigrationResponse.error(commonResult.getMessage());
+        }
+    }
+
+    @Override
+    public Map<String, Object> getValueForMapByKeys(Set<String> sets, Map<String, Object> map){
+        if(CollUtil.isEmpty(sets) || CollUtil.isEmpty(map)){
+            return  null;
+        }
+        Map<String, Object> targetsMap = new HashMap<>(sets.size());
+        sets.forEach(key -> targetsMap.put(key, map.get(key)));
+        return targetsMap;
+    }
+}

+ 97 - 0
src/main/java/com/persagy/proxy/migration/service/MigrationAbstractService.java

@@ -0,0 +1,97 @@
+package com.persagy.proxy.migration.service;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.dmp.basic.model.QueryCriteria;
+import com.persagy.proxy.common.entity.InstanceUrlParam;
+import com.persagy.proxy.migration.model.DataMigrationExcel;
+import com.persagy.proxy.migration.model.DataMigrationResponse;
+import com.persagy.proxy.migration.model.MigrationInfo;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author lvxianyun
+ * @title: MigrationAbstractService
+ * @projectName adm-middleware
+ * @description: 提供基础的数据操作方法
+ * @date 2021/12/3 10:42
+ */
+public interface MigrationAbstractService<T> {
+
+    /**
+     * adm交付数据(A) ∩ 现场数据(B)
+     * (A∩B) A
+     *  需要进一步对比的数据
+     */
+    Map<String,Object> doIntersectionGetFrom(Map<String,Object> from, Map<String,Object> to);
+
+    /**
+     * adm交付数据(A) ∩ 现场数据(B)
+     * (A∩B) B
+     *  需要进一步对比的数据
+     */
+    Map<String,Object> doIntersectionGetTo(Map<String,Object> from, Map<String,Object> to);
+
+    /**
+     * adm交付数据(A) 与 现场数据(B) 差集  返回adm数据
+     * (A-B)
+     * 新增
+     */
+    Map<String,Object> doSubtractAdd(Map<String,Object> from, Map<String,Object> to);
+
+    /**
+     * 现场数据(B) 与 adm交付数据(A) 差集  现场数据
+     * (B-A)
+     * 删除
+     */
+    Map<String,Object> doSubtractDel(Map<String,Object> from, Map<String,Object> to);
+
+    /**
+     *
+     * @param sets
+     * @param map
+     * @return
+     */
+    Map<String, Object> getValueForMapByKeys(Set<String> sets, Map<String, Object> map);
+    /**
+     * 拼接公共链接
+     * @param context
+     * @param urlStart
+     * @return
+     */
+    String commonUrl(InstanceUrlParam context, String urlStart, MigrationInfo migrationInfo);
+    /**
+     * 向项目侧提交迁移数据
+     * @param url
+     * @param requestBody
+     */
+    String commitDataByHttp(String url, String requestBody);
+
+    /**
+     * 将list根据自定义规则转为map  id为key的第一个串
+     * 使用 MigrationConstant.spliter 作为拼接符
+     * @param list
+     * @return
+     */
+    Map<String,Object> toEntityMap(List<ObjectNode> list, Class<T> clazz);
+    /**
+     * 获取项目现场交付的数据,默认全部
+     * @return
+     */
+    List<T> getProjectData(QueryCriteria queryCriteria, Class<T> clazz, String url);
+    DataMigrationResponse updateBatch(List vos, Class<T> clazz, String url);
+    DataMigrationResponse insertBatch(List vos, Class<T> clazz, String url);
+    DataMigrationResponse deleteBatch(List<String> ids, Class<T> clazz, String url);
+
+    /**
+     * 对比需要更新的数据
+     * @param from
+     * @param to
+     */
+    Map<String, Object> compareData(Map<String,Object> from, Map<String,Object> to);
+
+    List<DataMigrationExcel> addErrorInfo(List<String> errorMsg);
+
+}

+ 14 - 2
src/main/java/com/persagy/proxy/object/controller/AdmEquipmentController.java

@@ -15,6 +15,8 @@ import cn.hutool.poi.excel.WorkbookUtil;
 import cn.hutool.poi.excel.cell.CellUtil;
 import cn.hutool.poi.excel.editors.TrimEditor;
 import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.ExcelWriter;
+import com.alibaba.excel.write.metadata.WriteSheet;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.persagy.dmp.basic.dto.RequestData;
 import com.persagy.dmp.basic.model.QueryCriteria;
@@ -270,8 +272,18 @@ public class AdmEquipmentController {
 				List<EquipmentPointExcel> equipmentPointExcels = dealEquipmentPoint(admProject.getGroupCode(),admProject.getId(),type, false, null);
 				int count = equipmentPointExcels.size();
 				if(count > 100000){
-					EasyExcel.write(response.getOutputStream(), EquipmentPointExcel.class).sheet("sheet1").doWrite(equipmentPointExcels.subList(0,100000));
-					EasyExcel.write(response.getOutputStream(), EquipmentPointExcel.class).sheet("sheet2").doWrite(equipmentPointExcels.subList(100000,count+1));
+					ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), EquipmentPointExcel.class).build();
+					try {
+						WriteSheet writeSheet = EasyExcel.writerSheet(0, "sheet1").build();
+						excelWriter.write(equipmentPointExcels.subList(0,100000), writeSheet);
+
+						WriteSheet writeSheet2 = EasyExcel.writerSheet(1, "sheet2").build();
+						excelWriter.write(equipmentPointExcels.subList(100000,count), writeSheet2);
+					} finally {
+						if (excelWriter != null) {
+							excelWriter.finish();
+						}
+					}
 				}else{
 					EasyExcel.write(response.getOutputStream(), EquipmentPointExcel.class).sheet("sheet1").doWrite(equipmentPointExcels);
 				}