소스 검색

Merge remote-tracking branch 'origin/develop'

欧阳劲驰 2 달 전
부모
커밋
7ad39fca8f
56개의 변경된 파일3741개의 추가작업 그리고 248개의 파일을 삭제
  1. 5 5
      sql.properties
  2. 21 0
      src/main/java/com/shkpr/service/alambizplugin/annotation/ExcelMapping.java
  3. 46 0
      src/main/java/com/shkpr/service/alambizplugin/apiparam/GisSurveyThirdImportParams.java
  4. 21 15
      src/main/java/com/shkpr/service/alambizplugin/bizservice/GisSurveyBizService.java
  5. 220 0
      src/main/java/com/shkpr/service/alambizplugin/bizservice/GisSurveyThirdImportBizService.java
  6. 27 0
      src/main/java/com/shkpr/service/alambizplugin/commproperties/GisSurveyThirdImportProperties.java
  7. 354 188
      src/main/java/com/shkpr/service/alambizplugin/commtools/ExcelUtils.java
  8. 260 0
      src/main/java/com/shkpr/service/alambizplugin/commtools/ExcelUtilsCopy.java
  9. 76 0
      src/main/java/com/shkpr/service/alambizplugin/commtools/GeomUtil.java
  10. 45 0
      src/main/java/com/shkpr/service/alambizplugin/commtools/PointCodeUtil.java
  11. 491 0
      src/main/java/com/shkpr/service/alambizplugin/components/GisSurveyThirdImporter.java
  12. 47 0
      src/main/java/com/shkpr/service/alambizplugin/components/checker/DuplicatePointsFinder.java
  13. 111 0
      src/main/java/com/shkpr/service/alambizplugin/components/checker/InvalidLinesFinder.java
  14. 234 0
      src/main/java/com/shkpr/service/alambizplugin/components/checker/InvalidPropertiesFinder.java
  15. 3 0
      src/main/java/com/shkpr/service/alambizplugin/constants/ApiURI.java
  16. 22 0
      src/main/java/com/shkpr/service/alambizplugin/constants/ExcelEnum.java
  17. 2 2
      src/main/java/com/shkpr/service/alambizplugin/constants/GisSurveyCheckStatusEnum.java
  18. 67 0
      src/main/java/com/shkpr/service/alambizplugin/constants/GisSurveyImportDefine.java
  19. 39 0
      src/main/java/com/shkpr/service/alambizplugin/constants/GisSurveyImportStatusEnum.java
  20. 4 0
      src/main/java/com/shkpr/service/alambizplugin/constants/ResponseCode.java
  21. 238 9
      src/main/java/com/shkpr/service/alambizplugin/controller/ApiGisSurveyController.java
  22. 3 0
      src/main/java/com/shkpr/service/alambizplugin/controllerfilter/third/ApiJWTGisSurveyBizFilter.java
  23. 27 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisMetadataLayerTemplateMapper.java
  24. 14 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisMetadataPropertyTemplateMapper.java
  25. 9 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisSurveyJobInfoMapper.java
  26. 8 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisSurveyLayerApplyMapper.java
  27. 38 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisSurveyLayerApplyThirdCopyMapper.java
  28. 9 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisSurveyProjectInfoMapper.java
  29. 19 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisSurveyPropertyValueMapper.java
  30. 30 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisSurveyPropertyValueThirdCopyMapper.java
  31. 39 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/services/GisMetadataLayerTemplateServiceImpl.java
  32. 88 8
      src/main/java/com/shkpr/service/alambizplugin/dbdao/services/GisSurveyLayerApplyServiceImpl.java
  33. 118 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/services/GisSurveyLayerApplyThirdCopyServiceImpl.java
  34. 22 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/services/intef/GisMetadataLayerTemplateService.java
  35. 12 4
      src/main/java/com/shkpr/service/alambizplugin/dbdao/services/intef/GisSurveyLayerApplyService.java
  36. 22 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/services/intef/GisSurveyLayerApplyThirdCopyService.java
  37. 77 0
      src/main/java/com/shkpr/service/alambizplugin/dto/GisMetadataLayerTemplate.java
  38. 111 0
      src/main/java/com/shkpr/service/alambizplugin/dto/GisMetadataPropertyTemplate.java
  39. 76 0
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyLayerApplyThirdCopy.java
  40. 51 0
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyPropertyValue.java
  41. 37 0
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyPropertyValueThirdCopy.java
  42. 1 1
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveySystemCheckResult.java
  43. 82 0
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyThirdImportElement.java
  44. 129 0
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyThirdImportResult.java
  45. 27 0
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyThirdImportResultDetail.java
  46. 30 0
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyThirdImportSubtask.java
  47. 23 6
      src/main/java/com/shkpr/service/alambizplugin/globalmgr/ScheduleTaskMgr.java
  48. 9 5
      src/main/resources/application.properties
  49. 93 0
      src/main/resources/mapper/GisMetadataLayerTemplateMapper.xml
  50. 5 0
      src/main/resources/mapper/GisMetadataPropertyTemplateMapper.xml
  51. 6 0
      src/main/resources/mapper/GisSurveyJobInfoMapper.xml
  52. 10 0
      src/main/resources/mapper/GisSurveyLayerApplyMapper.xml
  53. 111 0
      src/main/resources/mapper/GisSurveyLayerApplyThirdCopyMapper.xml
  54. 12 5
      src/main/resources/mapper/GisSurveyProjectInfoMapper.xml
  55. 11 0
      src/main/resources/mapper/GisSurveyPropertyValueMapper.xml
  56. 49 0
      src/main/resources/mapper/GisSurveyPropertyValueThirdCopyMapper.xml

+ 5 - 5
sql.properties

@@ -1,4 +1,4 @@
-spring.datasource.data.jdbc-url=jdbc:postgresql://140.246.183.164:5432/water_smart_develop_branch?useSSL=false&useAffectedRows=false&allowMultiQueries=true
+spring.datasource.data.jdbc-url=jdbc:postgresql://140.246.183.164:5432/water_smart_develop_branch?useSSL=false&useAffectedRows=false&allowMultiQueries=true&rewriteBatchedStatements=true
 spring.datasource.data.username=postgres
 spring.datasource.data.password=kpr.23417.postgres
 
@@ -15,9 +15,9 @@ spring.datasource.data.test-while-idle=true
 spring.datasource.data.max-lifetime=120000
 spring.datasource.data.idle-timeout=30000
 spring.datasource.data.connection-timeout=30000
-# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+# 锟斤拷锟矫硷拷锟斤拷锟矫才斤拷锟斤拷一锟轿硷拷猓�拷锟斤拷锟斤拷要锟截闭的匡拷锟斤拷锟斤拷锟接o拷锟斤拷位锟角猴拷锟斤拷
 spring.datasource.data.time-between-eviction-runs-millis=60000
-# 配置一个连接在池中最小生存的时间,单位是毫秒
+# ����һ�������ڳ�����С�����ʱ�䣬��λ�Ǻ���
 spring.datasource.data.minEvictableIdleTimeMillis=300000
 
 
@@ -37,7 +37,7 @@ spring.datasource.data2.test-while-idle=true
 spring.datasource.data2.max-lifetime=120000
 spring.datasource.data2.idle-timeout=30000
 spring.datasource.data2.connection-timeout=30000
-# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+# 锟斤拷锟矫硷拷锟斤拷锟矫才斤拷锟斤拷一锟轿硷拷猓�拷锟斤拷锟斤拷要锟截闭的匡拷锟斤拷锟斤拷锟接o拷锟斤拷位锟角猴拷锟斤拷
 spring.datasource.data2.time-between-eviction-runs-millis=60000
-# 配置一个连接在池中最小生存的时间,单位是毫秒
+# ����һ�������ڳ�����С�����ʱ�䣬��λ�Ǻ���
 spring.datasource.data2.minEvictableIdleTimeMillis=300000

+ 21 - 0
src/main/java/com/shkpr/service/alambizplugin/annotation/ExcelMapping.java

@@ -0,0 +1,21 @@
+package com.shkpr.service.alambizplugin.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * excel字段映射
+ *
+ * @author 欧阳劲驰
+ * @since 0.0.1
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface ExcelMapping {
+    /**
+     * @return excel表头
+     */
+    String value();
+}

+ 46 - 0
src/main/java/com/shkpr/service/alambizplugin/apiparam/GisSurveyThirdImportParams.java

@@ -0,0 +1,46 @@
+package com.shkpr.service.alambizplugin.apiparam;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+
+/**
+ * 第三方导入入参
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Getter
+@Setter
+@AllArgsConstructor
+@ToString
+public class GisSurveyThirdImportParams {
+    /**
+     * 文件列表
+     */
+    private final List<MultipartFile> files;
+    /**
+     * 操作人
+     */
+    private String operator;
+    /**
+     * 任务id
+     */
+    private String jobId;
+    /**
+     * 用水性质:supply/drain
+     */
+    private String nature;
+    /**
+     * 点线规则
+     */
+    private String codeRule;
+    /**
+     * 忽略失败
+     */
+    private Boolean ignoreFail;
+}

+ 21 - 15
src/main/java/com/shkpr/service/alambizplugin/bizservice/GisSurveyBizService.java

@@ -33,7 +33,7 @@ import java.util.stream.Collectors;
  * @since 1.0.0
  */
 @Component
-public class GisSurveyBizService {
+public class GisSurveySystemCheckBizService {
     /**
      * 任务缓存
      */
@@ -59,9 +59,9 @@ public class GisSurveyBizService {
     private final GisSurveyProjectInfoService projectInfoService;
     private final GisSurveyJobInfoService jobInfoService;
 
-    public GisSurveyBizService(GisSurveySystemCheckProperties systemCheckProperties, GisSurveySystemCheckResultManager systemCheckFileManager
+    public GisSurveySystemCheckBizService(GisSurveySystemCheckProperties systemCheckProperties, GisSurveySystemCheckResultManager systemCheckFileManager
             , GisSurveySystemChecker systemChecker, GisSurveyProjectInfoService projectInfoService, GisSurveyJobInfoService jobInfoService) {
-        mStrClassName = "GisSurveyBizService";
+        mStrClassName = "GisSurveySystemCheckBizService";
         mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
         this.systemCheckProperties = systemCheckProperties;
         this.systemCheckFileManager = systemCheckFileManager;
@@ -210,11 +210,8 @@ public class GisSurveyBizService {
         //获取已存在的任务
         ListenableFuture<GisSurveySystemCheckResult> previousFuture = TASK_CACHE.get(systemCheckId);
         //已结束判断,删除缓存
-        if (previousFuture != null && (previousFuture.isDone() || previousFuture.isCancelled())) {
-            TASK_CACHE.remove(systemCheckId);
-            SUBTASK_CACHE.remove(systemCheckId);
-            TIME_CACHE.remove(systemCheckId);
-        }
+        if (previousFuture != null && (previousFuture.isDone() || previousFuture.isCancelled()))
+            removeCache(systemCheckId);
         //异步执行系统检查任务
         ListenableFuture<GisSurveySystemCheckResult> checkFuture = systemChecker.systemCheckTask(params,
                 //缓存子任务句柄
@@ -231,25 +228,34 @@ public class GisSurveyBizService {
     /**
      * 停止任务
      *
-     * @param taskId 任务id
+     * @param systemCheckId 系统检查id
      * @return 关闭状态
      */
-    private Boolean stopTask(GisSurveySystemCheckId taskId) {
-        ListenableFuture<GisSurveySystemCheckResult> future = TASK_CACHE.get(taskId);
+    private Boolean stopTask(GisSurveySystemCheckId systemCheckId) {
+        ListenableFuture<GisSurveySystemCheckResult> future = TASK_CACHE.get(systemCheckId);
         //完成判断,完成删除缓存
         if (future.isCancelled() || future.isDone()) {
-            TASK_CACHE.remove(taskId);
-            TIME_CACHE.remove(taskId);
+            removeCache(systemCheckId);
             return true;
         }
         //尝试清除任务
         boolean cancel = future.cancel(true);
         //清除成功,删除缓存
         if (cancel) {
-            TASK_CACHE.remove(taskId);
-            TIME_CACHE.remove(taskId);
+            removeCache(systemCheckId);
             return true;
         }
         return false;
     }
+
+    /**
+     * 清除缓存
+     *
+     * @param systemCheckId 系统检查id
+     */
+    private void removeCache(GisSurveySystemCheckId systemCheckId) {
+        TASK_CACHE.remove(systemCheckId);
+        SUBTASK_CACHE.remove(systemCheckId);
+        TIME_CACHE.remove(systemCheckId);
+    }
 }

+ 220 - 0
src/main/java/com/shkpr/service/alambizplugin/bizservice/GisSurveyThirdImportBizService.java

@@ -0,0 +1,220 @@
+package com.shkpr.service.alambizplugin.bizservice;
+
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.alambizplugin.apiparam.GisSurveyThirdImportParams;
+import com.shkpr.service.alambizplugin.components.GisSurveyThirdImporter;
+import com.shkpr.service.alambizplugin.constants.GisSurveyImportStatusEnum;
+import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
+import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportResult;
+import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportSubtask;
+import org.springframework.stereotype.Component;
+import org.springframework.util.concurrent.ListenableFuture;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+
+/**
+ * 第三方导入管理service
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Component
+public class GisSurveyThirdImportBizService {
+    /**
+     * 任务缓存
+     */
+    private final static Map<String, ListenableFuture<GisSurveyThirdImportResult>> TASK_CACHE = new ConcurrentHashMap<>();
+    /**
+     * 子任务缓存
+     */
+    private final static Map<String, GisSurveyThirdImportSubtask> SUBTASK_CACHE = new ConcurrentHashMap<>();
+    /**
+     * 开始时间缓存
+     */
+    private final static Map<String, LocalDateTime> TIME_CACHE = new ConcurrentHashMap<>();
+    /**
+     * log
+     */
+    private final String mStrClassName;
+    private final String mBizType;
+
+    private final GisSurveyThirdImporter thirdImporter;
+
+
+    public GisSurveyThirdImportBizService(GisSurveyThirdImporter thirdImporter) {
+        mStrClassName = "GisSurveySystemCheckBizService";
+        mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
+        this.thirdImporter = thirdImporter;
+    }
+
+    /**
+     * 第三方导入
+     *
+     * @param params 第三方导入参数
+     * @return 导入状态
+     */
+    public GisSurveyThirdImportResult thirdImport(GisSurveyThirdImportParams params) {
+        //获取已存在的任务
+        ListenableFuture<GisSurveyThirdImportResult> previousFuture = TASK_CACHE.get(params.getJobId());
+
+        //判断完成
+        if (previousFuture != null && previousFuture.isDone()) {
+            try {
+                //获取结果
+                GisSurveyThirdImportResult thirdImportResult = previousFuture.get();
+                //如不忽略失败,且失败,则返回失败
+                if (!params.getIgnoreFail() && Objects.equals(thirdImportResult.getImportStatus(), GisSurveyImportStatusEnum.FAIL.getCode()))
+                    return thirdImportResult;
+                else if (Objects.equals(thirdImportResult.getImportStatus(), GisSurveyImportStatusEnum.SUCCESS.getCode()) ||
+                        Objects.equals(thirdImportResult.getImportStatus(), GisSurveyImportStatusEnum.DATA_ERROR.getCode())) {
+                    //如处理成功(导入成功或数据检查成功),返回成功,并清除缓存
+                    removeCache(params.getJobId());
+                    return thirdImportResult;
+                }
+            } catch (InterruptedException | ExecutionException e) {
+                //打印报错信息
+                LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
+                        , String.format("检查历史失败异常 任务id:%s msg:%s", params.getJobId(), e.getMessage())
+                );
+                return GisSurveyThirdImportResult.fail(params);
+            }
+        }
+
+        //系统检查子任务
+        GisSurveyThirdImportSubtask importSubtask = SUBTASK_CACHE.get(params.getJobId());
+        //进行中判断(未完成且未清除)
+        if (previousFuture != null && !previousFuture.isDone() && !previousFuture.isCancelled())
+            return GisSurveyThirdImportResult.inProgress(params, importSubtask, TIME_CACHE.get(params.getJobId()));
+
+        //获取文件流
+        List<InputStream> inputStreams = new ArrayList<>();
+        for (MultipartFile file : params.getFiles()) {
+            try {
+                inputStreams.add(file.getInputStream());
+            } catch (IOException e) {
+                return GisSurveyThirdImportResult.fail(params);
+            }
+        }
+        //启动检查任务
+        startTask(params, inputStreams);
+        //返回进行中
+        return GisSurveyThirdImportResult.inProgress(params, importSubtask, LocalDateTime.now());
+    }
+
+    /**
+     * 取消导入
+     *
+     * @param jobId 任务id
+     * @return 取消结果
+     */
+    public int cancelImport(String jobId) {
+        //如无缓存,则直接返回不存在
+        if (!TASK_CACHE.containsKey(jobId)) return GisSurveyImportStatusEnum.NOT_EXISTS.getCode();
+        //关闭检查任务
+        return stopTask(jobId) ? GisSurveyImportStatusEnum.SUCCESS.getCode() : GisSurveyImportStatusEnum.FAIL.getCode();
+    }
+
+    /**
+     * 过期任务
+     * <p>用于检查和使任务过期</p>
+     */
+    public void expireResult(Duration ttl) {
+        //获取超时的id
+        List<String> jobIds = TIME_CACHE.entrySet().stream()
+                .filter(entry ->
+                        Duration.between(entry.getValue(), LocalDateTime.now()).compareTo(ttl) > 0
+                )
+                .map(Map.Entry::getKey)
+                .collect(Collectors.toList());
+        //停止超时的任务并删除任务缓存
+        for (String jobid : jobIds) {
+            //如任务不存在,则删除时间缓存
+            if (!TASK_CACHE.containsKey(jobid)) TIME_CACHE.remove(jobid);
+            //停用缓存
+            if (stopTask(jobid)) TIME_CACHE.remove(jobid);
+            else {
+                //打印报错信息
+                LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
+                        , String.format(
+                                "过期任务停止失败 ttl:%s 任务id:%s"
+                                , ttl
+                                , jobid
+                        )
+                );
+            }
+        }
+    }
+
+    /**
+     * 启动任务
+     *
+     * @param params       导入参数
+     * @param inputStreams 文件输入流
+     */
+    private void startTask(GisSurveyThirdImportParams params, List<InputStream> inputStreams) {
+        String jobId = params.getJobId();
+        //获取已存在的任务
+        ListenableFuture<GisSurveyThirdImportResult> previousFuture = TASK_CACHE.get(jobId);
+        //已结束判断,删除缓存
+        if (previousFuture != null && (previousFuture.isDone() || previousFuture.isCancelled())) {
+            removeCache(params.getJobId());
+        }
+        //异步执行第三方导入查任务
+        ListenableFuture<GisSurveyThirdImportResult> checkFuture = thirdImporter.thirdImportTask(params, inputStreams,
+                //缓存子任务句柄
+                subtask -> SUBTASK_CACHE.put(jobId, subtask),
+                //删除子任务句柄
+                subtaskSystemCheckId -> SUBTASK_CACHE.remove(jobId)
+        );
+        //缓存任务句柄
+        TASK_CACHE.put(jobId, checkFuture);
+        //缓存时间
+        TIME_CACHE.put(jobId, LocalDateTime.now());
+    }
+
+    /**
+     * 停止任务
+     *
+     * @param jobId 任务id
+     * @return 关闭状态
+     */
+    private Boolean stopTask(String jobId) {
+        ListenableFuture<GisSurveyThirdImportResult> future = TASK_CACHE.get(jobId);
+        //完成判断,完成删除缓存
+        if (future.isCancelled() || future.isDone()) {
+            removeCache(jobId);
+            return true;
+        }
+        //尝试清除任务
+        boolean cancel = future.cancel(true);
+        //清除成功,删除缓存
+        if (cancel) {
+            removeCache(jobId);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 清除缓存
+     *
+     * @param jobId 任务id
+     */
+    private void removeCache(String jobId) {
+        TASK_CACHE.remove(jobId);
+        SUBTASK_CACHE.remove(jobId);
+        TIME_CACHE.remove(jobId);
+    }
+}

+ 27 - 0
src/main/java/com/shkpr/service/alambizplugin/commproperties/GisSurveyThirdImportProperties.java

@@ -0,0 +1,27 @@
+package com.shkpr.service.alambizplugin.commproperties;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+import java.time.Duration;
+
+/**
+ * 第三方导入属性
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Getter
+@Setter
+@ConfigurationProperties(prefix = "third-import")
+public class GisSurveyThirdImportProperties {
+    /**
+     * 系统检查任务超时时间
+     */
+    private Duration ttl;
+    /**
+     * 超时检查间隔(毫秒)
+     */
+    private Long ttlCheckInterval;
+}

+ 354 - 188
src/main/java/com/shkpr/service/alambizplugin/commtools/ExcelUtils.java

@@ -1,250 +1,344 @@
 package com.shkpr.service.alambizplugin.commtools;
 
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.alambizplugin.annotation.ExcelMapping;
+import com.shkpr.service.alambizplugin.constants.ExcelEnum;
+import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.*;
-import org.apache.poi.xssf.usermodel.*;
-import org.springframework.util.StringUtils;
-
-import java.io.*;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
+import org.apache.poi.xssf.usermodel.XSSFFont;
+import org.apache.poi.xssf.usermodel.XSSFRichTextString;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.text.DecimalFormat;
-import java.util.*;
-
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+/**
+ * excel工具类
+ *
+ * @author 欧阳劲驰
+ * @serial 1.0.0
+ */
 public class ExcelUtils {
-    public static class SheetObj{
-        private int index = 0; //sheet索引
-        private List<Map<String, Object>> rows2Col = new ArrayList<>();
-
-        public SheetObj() {
-        }
-
-        public SheetObj(int index, List<Map<String, Object>> rows2Col) {
-            this.index = index;
-            this.rows2Col = rows2Col;
-        }
-
-        public int getIndex() {
-            return index;
-        }
-
-        public void setIndex(int index) {
-            this.index = index;
-        }
-
-        public List<Map<String, Object>> getRows2Col() {
-            return rows2Col;
-        }
+    /**
+     * log
+     */
+    private static final String mStrClassName = "ExcelUtils";
+    private static final String mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
 
-        public void setRows2Col(List<Map<String, Object>> rows2Col) {
-            this.rows2Col = rows2Col;
+    /**
+     * 解析excel文件
+     *
+     * @param path         文件地址
+     * @param headerRowNum 表头行
+     * @param dataRowNum   数据行
+     * @return 数据(key : 页名, v : 数据)
+     */
+    public static Map<String, List<Map<String, String>>> parseExcelFile(String path, Integer headerRowNum, Integer dataRowNum) throws InterruptedException {
+        //excel枚举
+        ExcelEnum excelEnum = null;
+        //文件后缀
+        String ext = path.substring(path.lastIndexOf("."));
+        //根据后缀名指定枚举
+        if (".xls".equalsIgnoreCase(ext)) excelEnum = ExcelEnum.XLS;
+        else if (".xlsx".equalsIgnoreCase(ext)) excelEnum = ExcelEnum.XLS;
+        if (excelEnum == null) return null;
+        //解析文件
+        try {
+            return parseExcelFile(Files.newInputStream(Paths.get(path)), excelEnum, headerRowNum, dataRowNum);
+        } catch (IOException e) {
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
+                    , String.format("excel文件解释失败 msg:%s", e.getMessage())
+            );
+            return null;
         }
     }
 
-    public static List<SheetObj> parseExcelFile(String filePath){
-        List<SheetObj> arrRes = null;
-        if (StringUtils.isEmpty(filePath))
-            return arrRes;
-
-        Workbook wb = getExcelWorkObj(filePath);
-        if (wb == null)
-            return arrRes;
-
-        do {
-            int sheetsNum = wb.getNumberOfSheets();
-            if (sheetsNum <= 0)
-                break;
-            arrRes = new ArrayList<>();
-
-            for (int i = 0; i < sheetsNum; i++)
-                arrRes.add(new SheetObj(i, parseSheetObj(wb.getSheetAt(i))));
-        }while (false);
-
-        if (wb != null){
-            try {
-                wb.close();
-            }catch (Exception e){}
+    /**
+     * 解析excel文件
+     *
+     * @param inputStream  输入流
+     * @param excelEnum    excel类型
+     * @param headerRowNum 表头行
+     * @param dataRowNum   数据行
+     * @return 数据(key : 页名, v : 数据)
+     */
+    public static Map<String, List<Map<String, String>>> parseExcelFile(InputStream inputStream, ExcelEnum excelEnum
+            , Integer headerRowNum, Integer dataRowNum) throws InterruptedException {
+        if (inputStream == null || excelEnum == null || excelEnum == ExcelEnum.CSV) return null;
+        //读取输入流
+        try (Workbook workbook = excelEnum == ExcelEnum.XLSX ? new XSSFWorkbook(inputStream) : new HSSFWorkbook(inputStream)) {
+            if (workbook.getNumberOfSheets() <= 0) return null;
+            //结果
+            Map<String, List<Map<String, String>>> results = new HashMap<>(workbook.getNumberOfSheets());
+            //遍历页,并解析
+            for (Sheet sheet : workbook) results.put(sheet.getSheetName(), parseSheet(sheet, headerRowNum, dataRowNum));
+            return results;
+        } catch (IOException e) {
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
+                    , String.format("excel文件解释失败 msg:%s", e.getMessage())
+            );
+            return null;
         }
-        return arrRes;
     }
 
-    public static List<SheetObj> parseExcelFile(InputStream is, String ext){
-        List<SheetObj> arrRes = null;
-        Workbook wb = getExcelWorkObj(is, ext);
-        if (wb == null)
-            return arrRes;
-
-        do {
-            int sheetsNum = wb.getNumberOfSheets();
-            if (sheetsNum <= 0)
-                break;
-            arrRes = new ArrayList<>();
-
-            for (int i = 0; i < sheetsNum; i++)
-                arrRes.add(new SheetObj(i, parseSheetObj(wb.getSheetAt(i))));
-        }while (false);
-
-        if (wb != null){
-            try {
-                wb.close();
-            }catch (Exception e){}
+    /**
+     * 解析页
+     *
+     * @param sheet        页
+     * @param headerRowNum 表头行
+     * @param dataRowNum   数据行
+     * @return 数据
+     */
+    private static List<Map<String, String>> parseSheet(Sheet sheet, Integer headerRowNum, Integer dataRowNum) throws InterruptedException {
+        //数据集合
+        List<Map<String, String>> dataList = new ArrayList<>();
+        if (sheet == null) return dataList;
+        //行数
+        int rowsNum = sheet.getPhysicalNumberOfRows();
+        if (rowsNum <= 1) return dataList;
+        //页头行
+        Row rowHead = sheet.getRow(headerRowNum);
+        //字段映射
+        Map<Integer, String> fieldMap = new HashMap<>();
+        for (Cell cell : rowHead) {
+            //检查线程中断,并响应
+            if (Thread.interrupted()) throw new InterruptedException();
+            //获取值,如不为空,则存入索引关系
+            String cellValue = getCellValue(cell);
+            if (!StringUtils.isEmpty(cellValue)) {
+                fieldMap.put(cell.getColumnIndex(), cellValue);
+            }
         }
-        return arrRes;
-    }
-
-    private static Workbook getExcelWorkObj(InputStream is, String ext){
-        Workbook wb = null;
-        if (is != null && !StringUtils.isEmpty(ext)){
-            try {
-                if("xls".equalsIgnoreCase(ext)){
-                    wb = new HSSFWorkbook(is);
-                }else if("xlsx".equalsIgnoreCase(ext)){
-                    wb = new XSSFWorkbook(is);
-                }
-            } catch (FileNotFoundException e) {
-                e.printStackTrace();
-            } catch (IOException e) {
-                e.printStackTrace();
+        //遍历行
+        for (Row row : sheet) {
+            //检查线程中断,并响应
+            if (Thread.interrupted()) throw new InterruptedException();
+            //跳过非数据行
+            if (row == null || row.getRowNum() < dataRowNum) continue;
+            //跳过空行
+            if (IntStream.range(row.getFirstCellNum(), row.getLastCellNum())
+                    .mapToObj(row::getCell)
+                    .allMatch(cell -> cell == null || cell.getCellTypeEnum() == CellType.BLANK)) continue;
+            //数据
+            Map<String, String> data = new HashMap<>();
+            //遍历字段映射
+            for (Map.Entry<Integer, String> entry : fieldMap.entrySet()) {
+                //获取单元格
+                Cell cell = row.getCell(entry.getKey());
+                //设置值
+                data.put(entry.getValue(), getCellValue(cell));
             }
+            //添加数据
+            dataList.add(data);
         }
-        return wb;
+
+        return dataList;
     }
 
-    private static Workbook getExcelWorkObj(String filePath){
-        Workbook wb = null;
-        String ext = filePath.substring(filePath.lastIndexOf("."));
+    /**
+     * excel文件转数据集合
+     *
+     * @param path         文件地址
+     * @param clazz        数据类型
+     * @param headerRowNum 表头行
+     * @param dataRowNum   数据行
+     * @param <E>          数据泛形
+     * @return 数据集合
+     */
+    public static <E> Map<String, List<E>> parseExcelFile(String path, Class<E> clazz, Integer headerRowNum, Integer dataRowNum) {
+        //excel枚举
+        ExcelEnum excelEnum = null;
+        //文件后缀
+        String ext = path.substring(path.lastIndexOf("."));
+        //根据后缀名指定枚举
+        if (".xls".equalsIgnoreCase(ext)) excelEnum = ExcelEnum.XLS;
+        else if (".xlsx".equalsIgnoreCase(ext)) excelEnum = ExcelEnum.XLS;
+        if (excelEnum == null) return null;
+        //解析文件
         try {
-            InputStream is = new FileInputStream(filePath);
-            if(".xls".equalsIgnoreCase(ext)){
-                wb = new HSSFWorkbook(is);
-            }else if(".xlsx".equalsIgnoreCase(ext)){
-                wb = new XSSFWorkbook(is);
-            }
-        } catch (FileNotFoundException e) {
-            e.printStackTrace();
+            return parseExcelFile(Files.newInputStream(Paths.get(path)), clazz, excelEnum, headerRowNum, dataRowNum);
         } catch (IOException e) {
-            e.printStackTrace();
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
+                    , String.format("excel文件解释失败 msg:%s", e.getMessage())
+            );
+            return null;
         }
-        return wb;
     }
 
-    private static List<Map<String, Object>> parseSheetObj(Sheet sheet){
-        List<Map<String, Object>> rows2Col = new ArrayList<>();
-        if (sheet == null)
-            return rows2Col;
-
-        int rowsNum = sheet.getPhysicalNumberOfRows();
-        int colsNum = (rowsNum>0)?sheet.getRow(0).getPhysicalNumberOfCells():0;
-        if (rowsNum <= 1)
-            return rows2Col;
-
-        Row rowHead = sheet.getRow(0);
-        List<String> colsHeads = new ArrayList<>();
-        for (int j = 0; j < colsNum; j++){
-            Cell cell = (rowHead!=null)?rowHead.getCell(j):null;
-            String colHeadName = cell!=null?getCellValue(cell):String.format("col%d",j);
-            colsHeads.add(!StringUtils.isEmpty(colHeadName)?colHeadName:String.format("col%d",j));
-        }
-
-        for (int i = 1; i < rowsNum; i++){
-            Row row = sheet.getRow(i);
-            if (row == null)
-                continue;
-
-            Map<String, Object> oneRow2Cols = new HashMap<>();
-            for (int j = 0; j < colsNum; j++){
-                Cell cell = row.getCell(j);
-                oneRow2Cols.put(colsHeads.get(j), cell!=null?getCellValue(cell):"");
-            }
-            if (oneRow2Cols.size() > 0)
-                rows2Col.add(oneRow2Cols);
+    /**
+     * excel文件转数据集合
+     *
+     * @param inputStream  input流
+     * @param clazz        数据类型
+     * @param excelEnum    excel枚举
+     * @param headerRowNum 表头行
+     * @param dataRowNum   数据行
+     * @param <E>          数据泛形
+     * @return 数据集合
+     */
+    public static <E> Map<String, List<E>> parseExcelFile(InputStream inputStream, Class<E> clazz, ExcelEnum excelEnum
+            , Integer headerRowNum, Integer dataRowNum) {
+        if (inputStream == null || excelEnum == null || excelEnum == ExcelEnum.CSV) return null;
+        //读取表
+        try (Workbook workbook = excelEnum == ExcelEnum.XLSX ? new XSSFWorkbook(inputStream) : new HSSFWorkbook(inputStream)) {
+            if (workbook.getNumberOfSheets() <= 0) return null;
+            //结果
+            Map<String, List<E>> results = new HashMap<>(workbook.getNumberOfSheets());
+            //遍历页,并解析
+            for (Sheet sheet : workbook)
+                results.put(sheet.getSheetName(), parseSheet(sheet, clazz, headerRowNum, dataRowNum));
+            return results;
+        } catch (IOException e) {
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
+                    , String.format("excel文件解释失败 msg:%s", e.getMessage())
+            );
+            return null;
         }
-        return rows2Col;
     }
 
-    private static String getCellValue(Cell cell) {
-        String result = "";
-        if (cell == null)
-            return result;
-
+    /**
+     * 解析页
+     *
+     * @param sheet        页
+     * @param clazz        类型
+     * @param headerRowNum 表头行
+     * @param dataRowNum   数据行
+     * @param <E>          数据泛形
+     * @return 数据
+     */
+    private static <E> List<E> parseSheet(Sheet sheet, Class<E> clazz, Integer headerRowNum, Integer dataRowNum) {
         try {
-            switch (cell.getCellTypeEnum()){
-                case NUMERIC:{
-                    if (DateUtil.isCellDateFormatted(cell)){
-                        result = TimeTool.convertDateObj2DateStr(cell.getDateCellValue(), cell.getCellStyle().getDataFormatString());
-                    }else if(String.valueOf(cell.getNumericCellValue()).contains(".")){
-                        DecimalFormat df = new DecimalFormat("#.####");
-                        result = df.format(cell.getNumericCellValue());
-                    }else
-                        result = String.valueOf(cell.getNumericCellValue());;
-                }
-                break;
-                case STRING:{
-                    result = cell.getRichStringCellValue().toString();
-                }
-                break;
-                case BOOLEAN:{
-                    result = String.valueOf(cell.getBooleanCellValue());
-                }
-                break;
-                case FORMULA:{
-                    result = String.valueOf(cell.getNumericCellValue());
+            //数据集合
+            List<E> dataList = new ArrayList<>();
+            if (sheet == null) return dataList;
+            //行数
+            int rowsNum = sheet.getPhysicalNumberOfRows();
+            if (rowsNum <= 1) return dataList;
+            //页头行
+            Row headerRow = sheet.getRow(headerRowNum);
+            //字段映射
+            Map<Integer, Field> fieldMap = Arrays.stream(clazz.getDeclaredFields())
+                    //过滤需要导出的字段
+                    .filter(f -> f.isAnnotationPresent(ExcelMapping.class))
+                    //设置字段公开
+                    .peek(f -> f.setAccessible(true))
+                    .collect(Collectors.toMap(
+                            f -> {
+                                //获取excel映射值
+                                String excelMappingValue = f.getAnnotation(ExcelMapping.class).value();
+                                //获取对应的索引
+                                return IntStream.range(0, headerRow.getLastCellNum())
+                                        //过滤相同的值
+                                        .filter(index -> headerRow.getCell(index).getStringCellValue().equals(excelMappingValue))
+                                        .findFirst().orElse(-1);
+                            }, Function.identity()
+                    ));
+            //遍历行
+            for (Row row : sheet) {
+                //跳过第非数据
+                if (row == null || row.getRowNum() < dataRowNum) continue;
+                //跳过空行
+                if (IntStream.range(row.getFirstCellNum(), row.getLastCellNum())
+                        .mapToObj(row::getCell)
+                        .allMatch(cell -> cell == null || cell.getCellTypeEnum() == CellType.BLANK)) continue;
+                //实列化数据
+                E data = clazz.getDeclaredConstructor().newInstance();
+                //遍历字段映射
+                for (Map.Entry<Integer, Field> fieldEntry : fieldMap.entrySet()) {
+                    //跳过未找到的字段
+                    if (fieldEntry.getKey() == -1) continue;
+                    //获取单元格
+                    Cell cell = row.getCell(fieldEntry.getKey());
+                    //设置值
+                    setObjValue(data, fieldEntry.getValue(), getCellValue(cell));
                 }
-                break;
-                default:{
-                    result = "";
-                }
-                break;
+                //添加数据
+                dataList.add(data);
             }
-        }catch (Exception e){}
-        return result==null?"":result.trim();
+            return dataList;
+        } catch (NoSuchMethodException | InvocationTargetException | InstantiationException |
+                 IllegalAccessException e) {
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
+                    , String.format("excel页解释失败 msg:%s", e.getMessage())
+            );
+            return null;
+        }
     }
 
+
     /**
-     *
      * @param rowsWithColsData
      * @param outputStream
      */
-    public static void writeExcel(List<List<Object>> rowsWithColsData, OutputStream outputStream, boolean hasHeader){
+    public static void writeExcel(List<List<Object>> rowsWithColsData, OutputStream outputStream, boolean hasHeader) {
         if (rowsWithColsData == null || rowsWithColsData.size() <= 0 || outputStream == null)
             return;
         XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
         XSSFSheet xssfSheet = xssfWorkbook.createSheet("sheet1");
 
         XSSFCellStyle colHeaderStyle = null;
-        if (hasHeader){
+        if (hasHeader) {
             colHeaderStyle = xssfWorkbook.createCellStyle();
             XSSFFont colHeaderFont = xssfWorkbook.createFont();
             colHeaderFont.setBold(true);
             colHeaderStyle.setFont(colHeaderFont);
         }
 
-        for (int i=0,j=rowsWithColsData.size();i<j;i++){
+        for (int i = 0, j = rowsWithColsData.size(); i < j; i++) {
             XSSFRow xssfRow = xssfSheet.createRow(i);
             List<Object> columnData = rowsWithColsData.get(i);
             if (columnData == null)
                 continue;
 
-            for (int m=0,n=columnData.size();m<n;m++){
+            for (int m = 0, n = columnData.size(); m < n; m++) {
                 XSSFCell xssfCell = xssfRow.createCell(m);
                 Object col = columnData.get(m);
                 if (i == 0 && colHeaderStyle != null)
                     xssfCell.setCellStyle(colHeaderStyle);
 
-                if (col == null){
+                if (col == null) {
                     xssfCell.setCellValue("");
-                }else {
-                    if (col instanceof String){
-                        xssfCell.setCellValue(new XSSFRichTextString((String)col));
-                    }else if (col instanceof Date){
-                        xssfCell.setCellValue((Date)col);
-                    }else if (col instanceof Boolean){
-                        xssfCell.setCellValue((Boolean)col);
-                    }else if (col instanceof Double){
-                        xssfCell.setCellValue((Double)col);
-                    }else
+                } else {
+                    if (col instanceof String) {
+                        xssfCell.setCellValue(new XSSFRichTextString((String) col));
+                    } else if (col instanceof Date) {
+                        xssfCell.setCellValue((Date) col);
+                    } else if (col instanceof Boolean) {
+                        xssfCell.setCellValue((Boolean) col);
+                    } else if (col instanceof Double) {
+                        xssfCell.setCellValue((Double) col);
+                    } else
                         xssfCell.setCellValue(new XSSFRichTextString(String.valueOf(col)));
                 }
 
-                if (i != 0 && i == j-1)
+                if (i != 0 && i == j - 1)
                     xssfSheet.autoSizeColumn(m);
             }
         }
@@ -253,8 +347,80 @@ public class ExcelUtils {
             xssfWorkbook.write(outputStream);
             outputStream.flush();
             outputStream.close();
-        }catch (IOException e) {
+        } catch (IOException e) {
             e.printStackTrace();
         }
     }
+
+    /**
+     * 获取单元格值
+     *
+     * @param cell 单元格
+     * @return 值
+     */
+    private static String getCellValue(Cell cell) {
+        if (cell == null) return null;
+        //值
+        String value = null;
+        try {
+            switch (cell.getCellTypeEnum()) {
+                case NUMERIC: {
+                    if (DateUtil.isCellDateFormatted(cell)) {
+                        value = TimeTool.convertDateObj2DateStr(cell.getDateCellValue(), cell.getCellStyle().getDataFormatString());
+                    } else if (String.valueOf(cell.getNumericCellValue()).contains(".")) {
+                        DecimalFormat df = new DecimalFormat("#.####");
+                        value = df.format(cell.getNumericCellValue());
+                    } else
+                        value = String.valueOf(cell.getNumericCellValue());
+                }
+                break;
+                case STRING:
+                    value = cell.getRichStringCellValue().toString();
+                    break;
+                case BOOLEAN:
+                    value = String.valueOf(cell.getBooleanCellValue());
+                    break;
+                case FORMULA:
+                    value = String.valueOf(cell.getNumericCellValue());
+                    break;
+                default:
+                    break;
+            }
+        } catch (Exception ignored) {
+        }
+        return value == null ? "" : value.trim();
+    }
+
+    /**
+     * 设置数据值
+     *
+     * @param data  数据
+     * @param field 字段
+     * @param value 值
+     * @param <E>   数据泛形
+     * @throws IllegalAccessException 非法访问异常
+     */
+    private static <E> void setObjValue(E data, Field field, Object value) throws IllegalAccessException {
+        //值判断空
+        if (value != null) {
+            //判断数据类型是否相同,如相同直接设置值,如不同,则转换值
+            if (field.getType().isAssignableFrom(value.getClass())) {
+                //设置值
+                field.set(data, value);
+            } else {
+                //如值为double类型
+                if (value instanceof Double) {
+                    //对double类型兼容的类型处理
+                    if (field.getType() == short.class || field.getType() == Short.class)
+                        field.set(data, ((Double) value).shortValue());
+                    else if (field.getType() == int.class || field.getType() == Integer.class)
+                        field.set(data, ((Double) value).intValue());
+                    else if (field.getType() == long.class || field.getType() == Long.class)
+                        field.set(data, ((Double) value).longValue());
+                    else if (field.getType() == float.class || field.getType() == Float.class)
+                        field.set(data, ((Double) value).floatValue());
+                }
+            }
+        }
+    }
 }

+ 260 - 0
src/main/java/com/shkpr/service/alambizplugin/commtools/ExcelUtilsCopy.java

@@ -0,0 +1,260 @@
+package com.shkpr.service.alambizplugin.commtools;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.*;
+import org.springframework.util.StringUtils;
+
+import java.io.*;
+import java.text.DecimalFormat;
+import java.util.*;
+
+public class ExcelUtilsCopy {
+    public static class SheetObj{
+        private int index = 0; //sheet索引
+        private List<Map<String, Object>> rows2Col = new ArrayList<>();
+
+        public SheetObj() {
+        }
+
+        public SheetObj(int index, List<Map<String, Object>> rows2Col) {
+            this.index = index;
+            this.rows2Col = rows2Col;
+        }
+
+        public int getIndex() {
+            return index;
+        }
+
+        public void setIndex(int index) {
+            this.index = index;
+        }
+
+        public List<Map<String, Object>> getRows2Col() {
+            return rows2Col;
+        }
+
+        public void setRows2Col(List<Map<String, Object>> rows2Col) {
+            this.rows2Col = rows2Col;
+        }
+    }
+
+    public static List<SheetObj> parseExcelFile(String filePath){
+        List<SheetObj> arrRes = null;
+        if (StringUtils.isEmpty(filePath))
+            return arrRes;
+
+        Workbook wb = getExcelWorkObj(filePath);
+        if (wb == null)
+            return arrRes;
+
+        do {
+            int sheetsNum = wb.getNumberOfSheets();
+            if (sheetsNum <= 0)
+                break;
+            arrRes = new ArrayList<>();
+
+            for (int i = 0; i < sheetsNum; i++)
+                arrRes.add(new SheetObj(i, parseSheetObj(wb.getSheetAt(i))));
+        }while (false);
+
+        if (wb != null){
+            try {
+                wb.close();
+            }catch (Exception e){}
+        }
+        return arrRes;
+    }
+
+    public static List<SheetObj> parseExcelFile(InputStream is, String ext){
+        List<SheetObj> arrRes = null;
+        Workbook wb = getExcelWorkObj(is, ext);
+        if (wb == null)
+            return arrRes;
+
+        do {
+            int sheetsNum = wb.getNumberOfSheets();
+            if (sheetsNum <= 0)
+                break;
+            arrRes = new ArrayList<>();
+
+            for (int i = 0; i < sheetsNum; i++)
+                arrRes.add(new SheetObj(i, parseSheetObj(wb.getSheetAt(i))));
+        }while (false);
+
+        if (wb != null){
+            try {
+                wb.close();
+            }catch (Exception e){}
+        }
+        return arrRes;
+    }
+
+    private static Workbook getExcelWorkObj(InputStream is, String ext){
+        Workbook wb = null;
+        if (is != null && !StringUtils.isEmpty(ext)){
+            try {
+                if("xls".equalsIgnoreCase(ext)){
+                    wb = new HSSFWorkbook(is);
+                }else if("xlsx".equalsIgnoreCase(ext)){
+                    wb = new XSSFWorkbook(is);
+                }
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return wb;
+    }
+
+    private static Workbook getExcelWorkObj(String filePath){
+        Workbook wb = null;
+        String ext = filePath.substring(filePath.lastIndexOf("."));
+        try {
+            InputStream is = new FileInputStream(filePath);
+            if(".xls".equalsIgnoreCase(ext)){
+                wb = new HSSFWorkbook(is);
+            }else if(".xlsx".equalsIgnoreCase(ext)){
+                wb = new XSSFWorkbook(is);
+            }
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return wb;
+    }
+
+    private static List<Map<String, Object>> parseSheetObj(Sheet sheet){
+        List<Map<String, Object>> rows2Col = new ArrayList<>();
+        if (sheet == null)
+            return rows2Col;
+
+        int rowsNum = sheet.getPhysicalNumberOfRows();
+        int colsNum = (rowsNum>0)?sheet.getRow(0).getPhysicalNumberOfCells():0;
+        if (rowsNum <= 1)
+            return rows2Col;
+
+        Row rowHead = sheet.getRow(0);
+        List<String> colsHeads = new ArrayList<>();
+        for (int j = 0; j < colsNum; j++){
+            Cell cell = (rowHead!=null)?rowHead.getCell(j):null;
+            String colHeadName = cell!=null?getCellValue(cell):String.format("col%d",j);
+            colsHeads.add(!StringUtils.isEmpty(colHeadName)?colHeadName:String.format("col%d",j));
+        }
+
+        for (int i = 1; i < rowsNum; i++){
+            Row row = sheet.getRow(i);
+            if (row == null)
+                continue;
+
+            Map<String, Object> oneRow2Cols = new HashMap<>();
+            for (int j = 0; j < colsNum; j++){
+                Cell cell = row.getCell(j);
+                oneRow2Cols.put(colsHeads.get(j), cell!=null?getCellValue(cell):"");
+            }
+            if (oneRow2Cols.size() > 0)
+                rows2Col.add(oneRow2Cols);
+        }
+        return rows2Col;
+    }
+
+    private static String getCellValue(Cell cell) {
+        String result = "";
+        if (cell == null)
+            return result;
+
+        try {
+            switch (cell.getCellTypeEnum()){
+                case NUMERIC:{
+                    if (DateUtil.isCellDateFormatted(cell)){
+                        result = TimeTool.convertDateObj2DateStr(cell.getDateCellValue(), cell.getCellStyle().getDataFormatString());
+                    }else if(String.valueOf(cell.getNumericCellValue()).contains(".")){
+                        DecimalFormat df = new DecimalFormat("#.####");
+                        result = df.format(cell.getNumericCellValue());
+                    }else
+                        result = String.valueOf(cell.getNumericCellValue());;
+                }
+                break;
+                case STRING:{
+                    result = cell.getRichStringCellValue().toString();
+                }
+                break;
+                case BOOLEAN:{
+                    result = String.valueOf(cell.getBooleanCellValue());
+                }
+                break;
+                case FORMULA:{
+                    result = String.valueOf(cell.getNumericCellValue());
+                }
+                break;
+                default:{
+                    result = "";
+                }
+                break;
+            }
+        }catch (Exception e){}
+        return result==null?"":result.trim();
+    }
+
+    /**
+     *
+     * @param rowsWithColsData
+     * @param outputStream
+     */
+    public static void writeExcel(List<List<Object>> rowsWithColsData, OutputStream outputStream, boolean hasHeader){
+        if (rowsWithColsData == null || rowsWithColsData.size() <= 0 || outputStream == null)
+            return;
+        XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
+        XSSFSheet xssfSheet = xssfWorkbook.createSheet("sheet1");
+
+        XSSFCellStyle colHeaderStyle = null;
+        if (hasHeader){
+            colHeaderStyle = xssfWorkbook.createCellStyle();
+            XSSFFont colHeaderFont = xssfWorkbook.createFont();
+            colHeaderFont.setBold(true);
+            colHeaderStyle.setFont(colHeaderFont);
+        }
+
+        for (int i=0,j=rowsWithColsData.size();i<j;i++){
+            XSSFRow xssfRow = xssfSheet.createRow(i);
+            List<Object> columnData = rowsWithColsData.get(i);
+            if (columnData == null)
+                continue;
+
+            for (int m=0,n=columnData.size();m<n;m++){
+                XSSFCell xssfCell = xssfRow.createCell(m);
+                Object col = columnData.get(m);
+                if (i == 0 && colHeaderStyle != null)
+                    xssfCell.setCellStyle(colHeaderStyle);
+
+                if (col == null){
+                    xssfCell.setCellValue("");
+                }else {
+                    if (col instanceof String){
+                        xssfCell.setCellValue(new XSSFRichTextString((String)col));
+                    }else if (col instanceof Date){
+                        xssfCell.setCellValue((Date)col);
+                    }else if (col instanceof Boolean){
+                        xssfCell.setCellValue((Boolean)col);
+                    }else if (col instanceof Double){
+                        xssfCell.setCellValue((Double)col);
+                    }else
+                        xssfCell.setCellValue(new XSSFRichTextString(String.valueOf(col)));
+                }
+
+                if (i != 0 && i == j-1)
+                    xssfSheet.autoSizeColumn(m);
+            }
+        }
+
+        try {
+            xssfWorkbook.write(outputStream);
+            outputStream.flush();
+            outputStream.close();
+        }catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 76 - 0
src/main/java/com/shkpr/service/alambizplugin/commtools/GeomUtil.java

@@ -0,0 +1,76 @@
+package com.shkpr.service.alambizplugin.commtools;
+
+import org.locationtech.jts.geom.GeometryFactory;
+import org.locationtech.jts.geom.Point;
+import org.locationtech.jts.geom.PrecisionModel;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+/**
+ * 地理工具类
+ *
+ * @author 欧阳劲驰
+ * @since JDK1.8
+ */
+public class GeomUtil {
+    /**
+     * geom工厂
+     */
+    private static final GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), 4490);
+    /**
+     * 地球半径
+     */
+    private static final int EARTH_RADIUS = 6378137;
+
+    /**
+     * 将米转换为度
+     *
+     * @param degrees 度
+     * @return 对应的米
+     */
+    public static double convertDegreesToMeters(double degrees) {
+        return degrees * (Math.PI / 180) * EARTH_RADIUS;
+    }
+
+
+    /**
+     * 将米转换为度
+     *
+     * @param meters 米
+     * @return 对应的度
+     */
+    public static double convertMetersToDegrees(double meters) {
+        return meters / (Math.PI / 180 * EARTH_RADIUS);
+    }
+
+    /**
+     * 经纬度的度转十进制
+     * <p>如RMC(NMEA0183)协议报文:</p>
+     * <blockquote><pre>$GNRMC,072905.00,A,3640.46260,N,11707.54950,E,000.0,000.0,050119,OK*24</pre></blockquote>
+     * <p>则表示为:{@code [36.67438,117.12583]}</p>
+     *
+     * @param degrees      度
+     * @param minutesIndex 分索引,如 {@code  ddmm.mmmmm} 则为2
+     * @return 十进制表示
+     */
+    public static double convertDegreesToDecimal(String degrees, int minutesIndex) {
+        return Integer.parseInt(degrees.substring(0, minutesIndex)) +
+                //分除60保留8位
+                BigDecimal.valueOf(Float.parseFloat(degrees.substring(minutesIndex)))
+                        .divide(BigDecimal.valueOf(60), 8, RoundingMode.HALF_UP)
+                        .doubleValue();
+    }
+
+    /**
+     * 判断点1是否在点2距离范围内
+     *
+     * @param point1   点1
+     * @param point2   点2
+     * @param distance 距离(米)
+     * @return 判断状态
+     */
+    public static Boolean isWithinDistance(Point point1, Point point2, double distance) {
+        return point1.isWithinDistance(point2, convertMetersToDegrees(distance));
+    }
+}

+ 45 - 0
src/main/java/com/shkpr/service/alambizplugin/commtools/PointCodeUtil.java

@@ -0,0 +1,45 @@
+package com.shkpr.service.alambizplugin.commtools;
+
+import org.apache.commons.codec.digest.DigestUtils;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.UUID;
+
+/**
+ * 点code工具
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+public class PointCodeUtil {
+    /**
+     * 时间格式化规则
+     */
+    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyMMddHHmmss");
+    /**
+     * 前缀
+     */
+    private static final String PREFIX = "GSX";
+    /**
+     * 截取范围
+     */
+    private static final int[] RANGE = {9, 21};
+
+    /**
+     * 生成code
+     *
+     * @return code
+     */
+    public static String generateCode() {
+        //生成时间字符串
+        String timeStr = LocalDateTime.now().format(FORMATTER);
+        //生成UUID
+        String uuid = UUID.randomUUID().toString();
+        //转为md5,并截取10-21,并转大写
+        String md5Hash = DigestUtils.md5Hex(uuid);
+        String md5Str = md5Hash.substring(RANGE[0], RANGE[1]).toUpperCase();
+        // 拼接结果
+        return PREFIX + timeStr + md5Str;
+    }
+}

+ 491 - 0
src/main/java/com/shkpr/service/alambizplugin/components/GisSurveyThirdImporter.java

@@ -0,0 +1,491 @@
+package com.shkpr.service.alambizplugin.components;
+
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.alambizplugin.apiparam.GisSurveyThirdImportParams;
+import com.shkpr.service.alambizplugin.commtools.ExcelUtils;
+import com.shkpr.service.alambizplugin.commtools.PointCodeUtil;
+import com.shkpr.service.alambizplugin.components.checker.DuplicatePointsFinder;
+import com.shkpr.service.alambizplugin.components.checker.InvalidLinesFinder;
+import com.shkpr.service.alambizplugin.components.checker.InvalidPropertiesFinder;
+import com.shkpr.service.alambizplugin.constants.ExcelEnum;
+import com.shkpr.service.alambizplugin.constants.GisMetadataDefine;
+import com.shkpr.service.alambizplugin.constants.GisSurveyCheckStatusEnum;
+import com.shkpr.service.alambizplugin.constants.GisSurveyImportDefine;
+import com.shkpr.service.alambizplugin.constants.GisSurveyImportStatusEnum;
+import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
+import com.shkpr.service.alambizplugin.dbdao.services.intef.GisMetadataLayerTemplateService;
+import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveyLayerApplyThirdCopyService;
+import com.shkpr.service.alambizplugin.dto.GisMetadataLayerTemplate;
+import com.shkpr.service.alambizplugin.dto.GisMetadataPropertyTemplate;
+import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyThirdCopy;
+import com.shkpr.service.alambizplugin.dto.GisSurveyPropertyValueThirdCopy;
+import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportElement;
+import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportResult;
+import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportResultDetail;
+import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportSubtask;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.AsyncResult;
+import org.springframework.stereotype.Component;
+import org.springframework.util.concurrent.ListenableFuture;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ExecutionException;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+
+/**
+ * 第三方导入执行器
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Component
+public class GisSurveyThirdImporter {
+    /**
+     * log
+     */
+    private final String mStrClassName;
+    private final String mBizType;
+    private final GisMetadataLayerTemplateService layerTemplateService;
+    private final GisSurveyLayerApplyThirdCopyService gisSurveyLayerApplyThirdCopyService;
+    private final DuplicatePointsFinder duplicatePointsFinder;
+    private final InvalidLinesFinder invalidLinesFinder;
+    private final InvalidPropertiesFinder invalidPropertiesFinder;
+
+    public GisSurveyThirdImporter(GisMetadataLayerTemplateService layerTemplateService, GisSurveyLayerApplyThirdCopyService gisSurveyLayerApplyThirdCopyService
+            , DuplicatePointsFinder duplicatePointsFinder, InvalidLinesFinder invalidLinesFinder, InvalidPropertiesFinder invalidPropertiesFinder) {
+        mStrClassName = "GisSurveyThirdImporter";
+        mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
+        this.layerTemplateService = layerTemplateService;
+        this.gisSurveyLayerApplyThirdCopyService = gisSurveyLayerApplyThirdCopyService;
+        this.duplicatePointsFinder = duplicatePointsFinder;
+        this.invalidLinesFinder = invalidLinesFinder;
+        this.invalidPropertiesFinder = invalidPropertiesFinder;
+    }
+
+    /**
+     * 第三方导入任务
+     *
+     * @param params              系统检查参数
+     * @param inputStreams        文件输入流
+     * @param onStartSubtask      启动子任务
+     * @param onDeprecatedSubtask 弃用子任务(完成数据收集/取消)
+     * @return 系统检查返回
+     */
+    @Async
+    public ListenableFuture<GisSurveyThirdImportResult> thirdImportTask(GisSurveyThirdImportParams params, List<InputStream> inputStreams
+            , Consumer<GisSurveyThirdImportSubtask> onStartSubtask, Consumer<String> onDeprecatedSubtask) {
+        //构建返回
+        GisSurveyThirdImportResult result = GisSurveyThirdImportResult.fail(params);
+        //无效属性任务
+        ListenableFuture<GisSurveyThirdImportResultDetail<Map<String, List<GisSurveyThirdImportElement>>>> invalidPropertiesFuture = null;
+        //重复点号任务
+        ListenableFuture<GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>> duplicatePointsFuture = null;
+        //无效线任务
+        ListenableFuture<GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>> invalidLinesFuture = null;
+        //点集合
+        List<Map<String, String>> points = new ArrayList<>();
+        //线集合
+        List<Map<String, String>> lines = new ArrayList<>();
+        try {
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                    , String.format(
+                            "开始执行第三方导入;任务id: %s"
+                            , params.getJobId()
+                    )
+            );
+
+            //解析excel
+            parseExcel(inputStreams, points, lines);
+
+            //提取图层名
+            List<String> pointLayerNames = getLayerNames(points, GisSurveyImportDefine.POINT.LAYER);
+            List<String> lineLayerNames = getLayerNames(lines, GisSurveyImportDefine.LINE.LAYER);
+            //图层模版
+            List<GisMetadataLayerTemplate> pointLayerTemplates = layerTemplateService.findByNatureAndNameIn(params.getNature(), pointLayerNames);
+            List<GisMetadataLayerTemplate> lineLayerTemplates = layerTemplateService.findByNatureAndNameIn(params.getNature(), lineLayerNames);
+
+            //无效属性检查
+            invalidPropertiesFuture = invalidPropertiesFinder.findInvalidProperties(points, lines, pointLayerTemplates, lineLayerTemplates);
+            //重复点检查
+            duplicatePointsFuture = duplicatePointsFinder.findDuplicatePoints(points);
+            //无效线检查
+            invalidLinesFuture = invalidLinesFinder.finderInvalidLines(points, lines);
+
+            //返回子任务
+            onStartSubtask.accept(
+                    new GisSurveyThirdImportSubtask(invalidPropertiesFuture, duplicatePointsFuture, invalidLinesFuture)
+            );
+
+            //等待结果
+            GisSurveyThirdImportResultDetail<Map<String, List<GisSurveyThirdImportElement>>> invalidPropertiesResult = invalidPropertiesFuture.get();
+            //存入无效属性结果
+            result.setInvalidLayersResult(untarInvalidProperties(invalidPropertiesResult, GisSurveyImportDefine.RESULT.INVALID_LAYERS));
+            result.setMissingRequirementsResult(untarInvalidProperties(invalidPropertiesResult, GisSurveyImportDefine.RESULT.MISSING_REQUIREMENTS));
+            result.setInvalidTypesResult(untarInvalidProperties(invalidPropertiesResult, GisSurveyImportDefine.RESULT.INVALID_TYPES));
+            result.setOutRangesResult(untarInvalidProperties(invalidPropertiesResult, GisSurveyImportDefine.RESULT.OUT_RANGES));
+            //存入重复点结果
+            result.setDuplicatePointsResult(duplicatePointsFuture.get());
+            //存入无效线结果
+            result.setInvalidLinesResult(invalidLinesFuture.get());
+
+            //结果未通过
+            if (!checkResult(result)) {
+                result.setImportStatus(GisSurveyImportStatusEnum.DATA_ERROR.getCode());
+                result.setCompleteTime(LocalDateTime.now());
+                LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                        , String.format(
+                                "第三方导入结果未通过;任务id: %s, 用时(毫秒):%d",
+                                params.getJobId(),
+                                Duration.between(result.getRequestTime(), result.getCompleteTime()).toMillis()
+                        )
+                );
+                //弃用子任务
+                onDeprecatedSubtask.accept(params.getJobId());
+                return new AsyncResult<>(result);
+            }
+
+            //解码点线数据
+            List<GisSurveyLayerApplyThirdCopy> layerApplyList = decodeDataToLayerApply(points, lines, pointLayerTemplates, lineLayerTemplates, params);
+            //批量写入
+            Boolean saved = gisSurveyLayerApplyThirdCopyService.saveAll(params.getJobId(), layerApplyList);
+            if (!saved) {
+                result.setCompleteTime(LocalDateTime.now());
+                LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                        , String.format(
+                                "第三方导入入库失败;任务id: %s, 用时(毫秒):%d",
+                                params.getJobId(),
+                                Duration.between(result.getRequestTime(), LocalDateTime.now()).toMillis()
+                        )
+                );
+                //弃用子任务
+                onDeprecatedSubtask.accept(params.getJobId());
+                return new AsyncResult<>(result);
+            }
+
+            //完成任务
+            result.setImportStatus(GisSurveyImportStatusEnum.SUCCESS.getCode());
+            result.setCompleteTime(LocalDateTime.now());
+            result.setPreviewData(layerApplyList);
+
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                    , String.format(
+                            "结束执行第三方导入;任务id: %s, 用时(毫秒):%d",
+                            params.getJobId(),
+                            Duration.between(result.getRequestTime(), result.getCompleteTime()).toMillis()
+                    )
+            );
+            //弃用子任务
+            onDeprecatedSubtask.accept(params.getJobId());
+            return new AsyncResult<>(result);
+        } catch (InterruptedException | ExecutionException | IOException | RuntimeException e) {
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
+                    , String.format(
+                            "监测到中断或执行异常,开始清除子任务 任务id:%s error:%s",
+                            params.getJobId(),
+                            e
+                    )
+            );
+
+            //清除子任务
+            if (invalidPropertiesFuture != null) invalidPropertiesFuture.cancel(true);
+            if (duplicatePointsFuture != null) duplicatePointsFuture.cancel(true);
+            if (invalidLinesFuture != null) invalidLinesFuture.cancel(true);
+
+            //失败信息
+            result.setImportStatus(GisSurveyCheckStatusEnum.FAIL.getCode());
+            result.setCompleteTime(LocalDateTime.now());
+
+            //弃用子任务
+            onDeprecatedSubtask.accept(params.getJobId());
+            return new AsyncResult<>(result);
+        }
+    }
+
+    /**
+     * 解析excel
+     *
+     * @param inputStreams 输入流
+     * @param points       点集合
+     * @param lines        线集合
+     * @throws IOException io异常
+     */
+    private void parseExcel(List<InputStream> inputStreams, List<Map<String, String>> points, List<Map<String, String>> lines) throws IOException, InterruptedException {
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始执行解析excel   ======>");
+        long begin = System.currentTimeMillis();
+
+        //解析文件
+        for (InputStream inputStream : inputStreams) {
+            //检查线程中断,并响应
+            if (Thread.interrupted()) throw new InterruptedException();
+            //解析excel
+            Map<String, List<Map<String, String>>> excelData = ExcelUtils.parseExcelFile(inputStream,
+                    ExcelEnum.XLSX, 0, 2);
+            //填入集合
+            if (excelData != null && excelData.containsKey(GisMetadataDefine.TYPE_KINE.POINT))
+                points.addAll(excelData.get(GisMetadataDefine.TYPE_KINE.POINT));
+            if (excelData != null && excelData.containsKey(GisMetadataDefine.TYPE_KINE.LINE))
+                lines.addAll(excelData.get(GisMetadataDefine.TYPE_KINE.LINE));
+            //释放流
+            inputStream.close();
+        }
+
+        long end = System.currentTimeMillis();
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                , String.format(
+                        "结束执行执行解析excel,用时(毫秒):%d"
+                        , (end - begin)
+                )
+        );
+    }
+
+    /**
+     * 获取图层名称
+     *
+     * @param datas    数据
+     * @param layerKey 图层的key
+     * @return 图层名称集合
+     */
+    private List<String> getLayerNames(List<Map<String, String>> datas, String layerKey) {
+        //去重图层
+        return datas.parallelStream()
+                .filter(data -> data.get(layerKey) != null)
+                .map(data -> data.get(layerKey))
+                .distinct()
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * 解包无效属性
+     *
+     * @param invalidPropertiesResult 无效属性结果
+     * @param resultKey               结果key
+     * @return 具体结果
+     */
+    private GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>> untarInvalidProperties(
+            GisSurveyThirdImportResultDetail<Map<String, List<GisSurveyThirdImportElement>>> invalidPropertiesResult
+            , String resultKey) {
+        //获取结果
+        List<GisSurveyThirdImportElement> importElements = invalidPropertiesResult.getResults().get(resultKey);
+
+        return new GisSurveyThirdImportResultDetail<>(true, importElements);
+    }
+
+    /**
+     * 检查结果
+     *
+     * @param result 结果
+     * @return 结果通过状态
+     */
+    private Boolean checkResult(GisSurveyThirdImportResult result) {
+        List<GisSurveyThirdImportElement> invalidLayers = result.getInvalidLayersResult().getResults();
+        List<GisSurveyThirdImportElement> missingRequirements = result.getMissingRequirementsResult().getResults();
+        List<GisSurveyThirdImportElement> invalidTypesResult = result.getInvalidTypesResult().getResults();
+        List<GisSurveyThirdImportElement> outRanges = result.getOutRangesResult().getResults();
+        List<GisSurveyThirdImportElement> duplicatePoints = result.getDuplicatePointsResult().getResults();
+        List<GisSurveyThirdImportElement> invalidLines = result.getInvalidLinesResult().getResults();
+        //检查是否都为空
+        return CollectionUtils.isEmpty(invalidLayers) && CollectionUtils.isEmpty(missingRequirements) &&
+                CollectionUtils.isEmpty(invalidTypesResult) && CollectionUtils.isEmpty(outRanges) &&
+                CollectionUtils.isEmpty(duplicatePoints) && CollectionUtils.isEmpty(invalidLines);
+    }
+
+    /**
+     * 解码数据到采集元素对象
+     * <p>从Map转为 {@code GisSurveyLayerApplyThirdCopy}</p>
+     *
+     * @param points              点数据
+     * @param lines               线数据
+     * @param pointLayerTemplates 点图层模版
+     * @param lineLayerTemplates  线图层模版
+     * @param params              导入参数
+     * @return 格式化后数据
+     */
+    private List<GisSurveyLayerApplyThirdCopy> decodeDataToLayerApply(List<Map<String, String>> points, List<Map<String, String>> lines
+            , List<GisMetadataLayerTemplate> pointLayerTemplates, List<GisMetadataLayerTemplate> lineLayerTemplates, GisSurveyThirdImportParams params) {
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "导入结果通过,开始解码点线数据   ======>");
+        long begin = System.currentTimeMillis();
+
+        //按模版名分组,便于快速找到模版
+        Map<String, GisMetadataLayerTemplate> poineTemplateMap = pointLayerTemplates.stream()
+                .collect(Collectors.toMap(
+                        GisMetadataLayerTemplate::getName, it -> it,
+                        (it1, it2) -> it1
+                ));
+        Map<String, GisMetadataLayerTemplate> lineTemplateMap = lineLayerTemplates.stream()
+                .collect(Collectors.toMap(
+                        GisMetadataLayerTemplate::getName, it -> it,
+                        (it1, it2) -> it1
+                ));
+
+        //采集元素象集合
+        List<GisSurveyLayerApplyThirdCopy> result = new ArrayList<>();
+        //点号映射,用于线写入上下游节点
+        Map<String, String> pointNoMapping = new HashMap<>();
+        //格式化点
+        for (Map<String, String> point : points) {
+            //获取模版
+            GisMetadataLayerTemplate layerTemplate = poineTemplateMap.get(point.get(GisSurveyImportDefine.POINT.LAYER));
+            //解码点对象
+            GisSurveyLayerApplyThirdCopy layerApply = decodePointToLayerApply(point, layerTemplate, params);
+            //存入点号
+            pointNoMapping.put(layerApply.getNo(), layerApply.getCode());
+
+            result.add(layerApply);
+        }
+        //格式化线
+        for (Map<String, String> line : lines) {
+            //获取模版
+            GisMetadataLayerTemplate layerTemplate = lineTemplateMap.get(line.get(GisSurveyImportDefine.LINE.LAYER));
+            //解码对象
+            GisSurveyLayerApplyThirdCopy layerApply = decodeLineToLayerApply(line, layerTemplate, params, pointNoMapping);
+
+            result.add(layerApply);
+        }
+
+        long end = System.currentTimeMillis();
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                , String.format(
+                        "结束执行解码点线数据,用时(毫秒):%d"
+                        , (end - begin)
+                )
+        );
+        return result;
+    }
+
+    /**
+     * 解码点数据到采集元素对象
+     *
+     * @param point         点数据
+     * @param layerTemplate 图层模版
+     * @param params        导入参数
+     * @return 采集元素拷贝对象
+     */
+    private GisSurveyLayerApplyThirdCopy decodePointToLayerApply(Map<String, String> point, GisMetadataLayerTemplate layerTemplate, GisSurveyThirdImportParams params) {
+        GisSurveyLayerApplyThirdCopy layerApply = new GisSurveyLayerApplyThirdCopy();
+        //必填项
+        layerApply.setJobId(params.getJobId());
+        layerApply.setCode(PointCodeUtil.generateCode());
+        layerApply.setLayer(layerTemplate.getKey());
+        layerApply.setKind(GisMetadataDefine.TYPE_KINE.POINT);
+        //解析坐标
+        double[] coordinate = {Double.parseDouble(point.get(GisSurveyImportDefine.POINT.LNG)),
+                Double.parseDouble(point.get(GisSurveyImportDefine.POINT.LAT))};
+        layerApply.setGis(Arrays.toString(coordinate));
+        //默认值
+        layerApply.setApply(GisSurveyImportDefine.DEFAULT_VALUE.APPLY);
+        layerApply.setSource(GisSurveyImportDefine.DEFAULT_VALUE.SOURCE);
+        //高程和埋深
+        String elevationStr = point.get(GisSurveyImportDefine.POINT.ELEVATION);
+        if (NumberUtils.isParsable(elevationStr))
+            layerApply.setElevation(Double.parseDouble(elevationStr));
+        String depthStr = point.get(GisSurveyImportDefine.POINT.DEPTH);
+        if (NumberUtils.isParsable(depthStr))
+            layerApply.setDepth(Double.parseDouble(depthStr));
+        //点号
+        layerApply.setNo(point.get(GisSurveyImportDefine.POINT.NO));
+        //遍历属性模版
+        List<GisSurveyPropertyValueThirdCopy> propertyValueList = new ArrayList<>();
+        for (GisMetadataPropertyTemplate propertyTemplate : layerTemplate.getPropertyTemplates()) {
+            //解析属性
+            GisSurveyPropertyValueThirdCopy propertyValue = decodeDataToPropertyValue(point, layerApply
+                    , propertyTemplate, params, GisSurveyImportDefine.LayerType.POINT);
+            if (propertyValue != null) propertyValueList.add(propertyValue);
+        }
+        layerApply.setPropertyValueList(propertyValueList);
+
+        return layerApply;
+    }
+
+    /**
+     * 解码线数据到采集元素对象
+     *
+     * @param line           线数据
+     * @param layerTemplate  图层模版
+     * @param params         导入参数
+     * @param pointNoMapping 点号映射
+     * @return 采集元素拷贝对象
+     */
+    private GisSurveyLayerApplyThirdCopy decodeLineToLayerApply(Map<String, String> line, GisMetadataLayerTemplate layerTemplate, GisSurveyThirdImportParams params, Map<String, String> pointNoMapping) {
+        GisSurveyLayerApplyThirdCopy layerApply = new GisSurveyLayerApplyThirdCopy();
+        //必填项
+        layerApply.setJobId(params.getJobId());
+        layerApply.setCode(PointCodeUtil.generateCode());
+        layerApply.setLayer(layerTemplate.getKey());
+        layerApply.setKind(GisMetadataDefine.TYPE_KINE.LINE);
+        //默认值
+        layerApply.setApply(GisSurveyImportDefine.DEFAULT_VALUE.APPLY);
+        layerApply.setSource(GisSurveyImportDefine.DEFAULT_VALUE.SOURCE);
+        //上下游节点
+        layerApply.setUpNode(pointNoMapping.get(line.get(GisSurveyImportDefine.LINE.UP_NO)));
+        layerApply.setDownNode(pointNoMapping.get(line.get(GisSurveyImportDefine.LINE.DOWN_NO)));
+        //遍历属性模版
+        List<GisSurveyPropertyValueThirdCopy> propertyValueList = new ArrayList<>();
+        for (GisMetadataPropertyTemplate propertyTemplate : layerTemplate.getPropertyTemplates()) {
+            //解析属性
+            GisSurveyPropertyValueThirdCopy propertyValue = decodeDataToPropertyValue(line, layerApply, propertyTemplate, params, GisSurveyImportDefine.LayerType.LINE);
+            if (propertyValue != null) propertyValueList.add(propertyValue);
+        }
+        layerApply.setPropertyValueList(propertyValueList);
+
+        return layerApply;
+    }
+
+    /**
+     * 解码数据到属性值对象
+     *
+     * @param data             数据
+     * @param layerApply       采集元素
+     * @param propertyTemplate 属性模版
+     * @param params           导出参数
+     * @param layerType        图层类型
+     * @return 属性值对象
+     */
+    private GisSurveyPropertyValueThirdCopy decodeDataToPropertyValue(Map<String, String> data, GisSurveyLayerApplyThirdCopy layerApply
+            , GisMetadataPropertyTemplate propertyTemplate, GisSurveyThirdImportParams params, GisSurveyImportDefine.LayerType layerType) {
+        //点号直接返回点号属性
+        if (Objects.equals(GisSurveyImportDefine.TEMPLATE.CODE, propertyTemplate.getKey()))
+            return new GisSurveyPropertyValueThirdCopy(params.getJobId(), layerApply.getCode()
+                    , propertyTemplate.getKey(), layerApply.getCode());
+        //根据图层类型和模版映射,获取表头
+        String templateName = propertyTemplate.getName();
+        if (layerType == GisSurveyImportDefine.LayerType.POINT)
+            switch (propertyTemplate.getKey()) {
+                case GisSurveyImportDefine.TEMPLATE.LNG:
+                    templateName = GisSurveyImportDefine.POINT.LNG;
+                    break;
+                case GisSurveyImportDefine.TEMPLATE.LAT:
+                    templateName = GisSurveyImportDefine.POINT.LAT;
+                    break;
+            }
+        if (layerType == GisSurveyImportDefine.LayerType.LINE)
+            switch (propertyTemplate.getKey()) {
+                case GisSurveyImportDefine.TEMPLATE.UP_NODE:
+                    templateName = GisSurveyImportDefine.LINE.UP_NO;
+                    break;
+                case GisSurveyImportDefine.TEMPLATE.DOWN_NODE:
+                    templateName = GisSurveyImportDefine.LINE.DOWN_NO;
+                    break;
+            }
+        //获取值
+        String value = data.get(templateName);
+        if (StringUtils.isNotBlank(value)) return new GisSurveyPropertyValueThirdCopy(params.getJobId()
+                , layerApply.getCode(), propertyTemplate.getKey(), value);
+
+        return null;
+    }
+}

+ 47 - 0
src/main/java/com/shkpr/service/alambizplugin/components/checker/DuplicatePointsFinder.java

@@ -4,12 +4,16 @@ import com.global.base.log.LogLevelFlag;
 import com.global.base.log.LogPrintMgr;
 import com.shkpr.service.alambizplugin.commtools.BeanUtil;
 import com.shkpr.service.alambizplugin.components.GisSurveySystemCheckResultManager;
+import com.shkpr.service.alambizplugin.constants.GisMetadataDefine;
+import com.shkpr.service.alambizplugin.constants.GisSurveyImportDefine;
 import com.shkpr.service.alambizplugin.constants.GisSurveySystemCheckResultPath;
 import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
 import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyPoint;
 import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckElement;
 import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckId;
 import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckResultDetail;
+import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportElement;
+import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportResultDetail;
 import com.shkpr.service.alambizplugin.dto.TypeDefine;
 import org.apache.commons.lang3.StringUtils;
 import org.locationtech.jts.geom.Coordinate;
@@ -26,6 +30,9 @@ import java.util.stream.Collectors;
 
 /**
  * 重复点寻找器
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
  */
 @Component
 public class DuplicatePointsFinder {
@@ -56,6 +63,46 @@ public class DuplicatePointsFinder {
 
     /**
      * 寻找重复点
+     * <p>根据 <strong>code</strong> 匹配</p>
+     *
+     * @param points 点集合
+     * @return 重复点
+     */
+    @Async
+    public ListenableFuture<GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>> findDuplicatePoints(List<Map<String, String>> points) throws InterruptedException {
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始执行寻找重复点   ======>");
+        long begin = System.currentTimeMillis();
+
+        //根据code度分组
+        Map<String, List<Map<String, String>>> keyToPoints = points.parallelStream()
+                //过滤类型为字符串
+                .filter(point ->
+                        point.get(GisSurveyImportDefine.POINT.NO) != null)
+                .collect(Collectors.groupingBy(point ->
+                                point.get(GisSurveyImportDefine.POINT.NO),
+                        Collectors.toList())
+                );
+        //响应中断
+        if (Thread.interrupted()) throw new InterruptedException();
+        //并行流寻找重复点号
+        List<GisSurveyThirdImportElement> groupElements = keyToPoints.entrySet().parallelStream()
+                //过滤组内大于1
+                .filter(group -> group.getValue().size() > 1)
+                .map(entry -> new GisSurveyThirdImportElement(GisMetadataDefine.TYPE_KINE.POINT, entry.getKey()))
+                .collect(Collectors.toList());
+
+        long end = System.currentTimeMillis();
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                , String.format(
+                        "结束执行寻找重复点,用时(毫秒):%d"
+                        , (end - begin)
+                )
+        );
+        return new AsyncResult<>(new GisSurveyThirdImportResultDetail<>(true, groupElements));
+    }
+
+    /**
+     * 寻找重复点
      * <p>根据 <strong>精度</strong> 强匹配</p>
      *
      * @param points      点集合

+ 111 - 0
src/main/java/com/shkpr/service/alambizplugin/components/checker/InvalidLinesFinder.java

@@ -0,0 +1,111 @@
+package com.shkpr.service.alambizplugin.components.checker;
+
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.google.common.collect.Lists;
+import com.shkpr.service.alambizplugin.constants.GisSurveyImportDefine;
+import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
+import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportElement;
+import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportResultDetail;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.AsyncResult;
+import org.springframework.stereotype.Component;
+import org.springframework.util.concurrent.ListenableFuture;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static com.shkpr.service.alambizplugin.constants.GisSurveyImportDefine.LINE.DOWN_NO;
+import static com.shkpr.service.alambizplugin.constants.GisSurveyImportDefine.LINE.UP_NO;
+
+/**
+ * 无效线查找器
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Component
+public class InvalidLinesFinder {
+    /**
+     * log
+     */
+    private final String mStrClassName;
+    private final String mBizType;
+
+    public InvalidLinesFinder() {
+        mStrClassName = "InvalidLinesFinder";
+        mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
+    }
+
+    /**
+     * 寻找无效线
+     *
+     * @param points 点集合
+     * @param lines  线集合
+     * @return 线分组
+     */
+    @Async
+    public ListenableFuture<GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>> finderInvalidLines(List<Map<String, String>> points
+            , List<Map<String, String>> lines) throws InterruptedException {
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始执行寻找无效线   ======>");
+        long begin = System.currentTimeMillis();
+
+        //如点为空,则全是无效线
+        if (points.isEmpty()) {
+            long end = System.currentTimeMillis();
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                    , String.format(
+                            "结束执行寻找无效线,用时(毫秒):%d"
+                            , (end - begin)
+                    )
+            );
+            return new AsyncResult<>(new GisSurveyThirdImportResultDetail<>(true,
+                    lines.stream()
+                            //转code字符串
+                            .map(line -> GisSurveyThirdImportElement.create(line, GisSurveyImportDefine.LayerType.LINE))
+                            .collect(Collectors.toList())
+            ));
+        }
+        //如线为空,则无无效线
+        if (lines.isEmpty()) {
+            long end = System.currentTimeMillis();
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                    , String.format(
+                            "结束执行寻找无效线,用时(毫秒):%d"
+                            , (end - begin)
+                    )
+            );
+            return new AsyncResult<>(new GisSurveyThirdImportResultDetail<>(
+                    true, Lists.newArrayList()
+            ));
+        }
+
+        //点号集合
+        Set<String> nos = points.parallelStream()
+                .map(it -> it.get(GisSurveyImportDefine.POINT.NO))
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+        //收集无效线
+        List<GisSurveyThirdImportElement> results = new ArrayList<>();
+        for (Map<String, String> line : lines) {
+            //响应中断
+            if (Thread.interrupted()) throw new InterruptedException();
+            //不包含上节点或下节点,则收集
+            if (!nos.contains(line.get(UP_NO)) || !nos.contains(line.get(DOWN_NO)))
+                results.add(GisSurveyThirdImportElement.create(line, GisSurveyImportDefine.LayerType.LINE));
+        }
+
+        long end = System.currentTimeMillis();
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                , String.format(
+                        "结束执行寻找无效线,用时(毫秒):%d"
+                        , (end - begin)
+                )
+        );
+        return new AsyncResult<>(new GisSurveyThirdImportResultDetail<>(true, results));
+    }
+}

+ 234 - 0
src/main/java/com/shkpr/service/alambizplugin/components/checker/InvalidPropertiesFinder.java

@@ -0,0 +1,234 @@
+package com.shkpr.service.alambizplugin.components.checker;
+
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.alambizplugin.commtools.GeomUtil;
+import com.shkpr.service.alambizplugin.constants.GisSurveyImportDefine;
+import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
+import com.shkpr.service.alambizplugin.dto.GisMetadataLayerTemplate;
+import com.shkpr.service.alambizplugin.dto.GisMetadataPropertyTemplate;
+import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportElement;
+import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportResultDetail;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.AsyncResult;
+import org.springframework.stereotype.Component;
+import org.springframework.util.concurrent.ListenableFuture;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * 无效属性查找器
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Component
+public class InvalidPropertiesFinder {
+    /**
+     * 中国经纬度范围
+     */
+    private static final Double MIN_LAT = GeomUtil.convertDegreesToDecimal("351", 1);
+    private static final Double MAX_LAT = GeomUtil.convertDegreesToDecimal("5333", 2);
+    private static final Double MIN_LNG = GeomUtil.convertDegreesToDecimal("7333", 2);
+    private static final Double MAX_LNG = GeomUtil.convertDegreesToDecimal("13505", 3);
+    /**
+     * log
+     */
+    private final String mStrClassName;
+    private final String mBizType;
+
+    public InvalidPropertiesFinder() {
+        mStrClassName = "InvalidPropertiesFinder";
+        mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
+    }
+
+    /**
+     * 寻找无效属性
+     *
+     * @param points              点集合
+     * @param lines               线集合
+     * @param pointLayerTemplates 点图层模版集合
+     * @param lineLayerTemplates  线图层模版集合
+     * @return 重复点
+     */
+    @Async
+    public ListenableFuture<GisSurveyThirdImportResultDetail<Map<String, List<GisSurveyThirdImportElement>>>> findInvalidProperties(
+            List<Map<String, String>> points, List<Map<String, String>> lines, List<GisMetadataLayerTemplate> pointLayerTemplates
+            , List<GisMetadataLayerTemplate> lineLayerTemplates) throws InterruptedException {
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始执行寻找无效属性   ======>");
+        long begin = System.currentTimeMillis();
+
+        //无效图层结果
+        List<GisSurveyThirdImportElement> invalidLayersResult = new ArrayList<>();
+        //缺失必填结果
+        List<GisSurveyThirdImportElement> missingRequirementsResult = new ArrayList<>();
+        //无效类型结果
+        List<GisSurveyThirdImportElement> invalidTypesResult = new ArrayList<>();
+        //超出范围结果
+        List<GisSurveyThirdImportElement> outRangesResult = new ArrayList<>();
+        //检查点属性
+        for (Map<String, String> point : points) {
+            //响应中断
+            if (Thread.interrupted()) throw new InterruptedException();
+            //点号
+            String no = point.get(GisSurveyImportDefine.POINT.NO);
+            //如点号缺失直接返回必填不存在
+            if (StringUtils.isBlank(no)) {
+                missingRequirementsResult.add(GisSurveyThirdImportElement.create(point
+                        , GisSurveyImportDefine.POINT.NO
+                        , GisSurveyImportDefine.LayerType.POINT
+                ));
+                continue;
+            }
+            //过滤图层
+            GisMetadataLayerTemplate layerTemplate = pointLayerTemplates.stream()
+                    .filter(template -> Objects.equals(point.get(GisSurveyImportDefine.POINT.LAYER), template.getName()))
+                    .findFirst().orElse(null);
+            //图层不存在则加入无效图层结果
+            if (layerTemplate == null)
+                invalidLayersResult.add(GisSurveyThirdImportElement.create(point, GisSurveyImportDefine.LayerType.POINT));
+            else
+                //图层存在则检查图层
+                checkLayer(point, layerTemplate, missingRequirementsResult, invalidTypesResult, GisSurveyImportDefine.LayerType.POINT);
+            //检查坐标超出范围
+            if (checkOutRanges(point))
+                outRangesResult.add(GisSurveyThirdImportElement.create(point, GisSurveyImportDefine.LayerType.POINT));
+        }
+        //检查线属性
+        for (Map<String, String> line : lines) {
+            //响应中断
+            if (Thread.interrupted()) throw new InterruptedException();
+            //上下游点号
+            String upNo = line.get(GisSurveyImportDefine.LINE.UP_NO);
+            String downNo = line.get(GisSurveyImportDefine.LINE.DOWN_NO);
+            //如点号缺失直接返回必填不存在
+            if (StringUtils.isBlank(upNo)) {
+                missingRequirementsResult.add(GisSurveyThirdImportElement.create(line
+                        , GisSurveyImportDefine.LINE.UP_NO
+                        , GisSurveyImportDefine.LayerType.LINE
+                ));
+                continue;
+            }
+            if (StringUtils.isBlank(downNo)) {
+                missingRequirementsResult.add(GisSurveyThirdImportElement.create(line
+                        , GisSurveyImportDefine.LINE.DOWN_NO
+                        , GisSurveyImportDefine.LayerType.LINE
+                ));
+                continue;
+            }
+            //过滤图层
+            GisMetadataLayerTemplate layerTemplate = lineLayerTemplates.stream()
+                    .filter(template -> Objects.equals(template.getName(), line.get(GisSurveyImportDefine.LINE.LAYER)))
+                    .findFirst().orElse(null);
+            //图层不存在则加入无效图层结果
+            if (layerTemplate == null)
+                invalidLayersResult.add(GisSurveyThirdImportElement.create(line, GisSurveyImportDefine.LayerType.LINE));
+            else
+                //图层存在则检查图层
+                checkLayer(line, layerTemplate, missingRequirementsResult, invalidTypesResult, GisSurveyImportDefine.LayerType.LINE);
+        }
+
+        long end = System.currentTimeMillis();
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                , String.format(
+                        "结束执行寻找无效属性,用时(毫秒):%d"
+                        , (end - begin)
+                )
+        );
+
+        //构建结果
+        Map<String, List<GisSurveyThirdImportElement>> result = new HashMap<>();
+        result.put(GisSurveyImportDefine.RESULT.INVALID_LAYERS, invalidLayersResult);
+        result.put(GisSurveyImportDefine.RESULT.MISSING_REQUIREMENTS, missingRequirementsResult);
+        result.put(GisSurveyImportDefine.RESULT.INVALID_TYPES, invalidTypesResult);
+        result.put(GisSurveyImportDefine.RESULT.OUT_RANGES, outRangesResult);
+        return new AsyncResult<>(new GisSurveyThirdImportResultDetail<>(true, result));
+    }
+
+    /**
+     * 检查超出范围
+     *
+     * @param point 点
+     * @return 超出范围昨状态
+     */
+    public Boolean checkOutRanges(Map<String, String> point) {
+        //获取经纬度字段
+        String latStr = point.get(GisSurveyImportDefine.POINT.LAT);
+        String lngStr = point.get(GisSurveyImportDefine.POINT.LNG);
+        //检查是否字符串
+        if (latStr == null || lngStr == null) return true;
+        //检查是否可解析
+        if (!NumberUtils.isParsable(latStr) || !NumberUtils.isParsable(lngStr)) return true;
+        //解析
+        double lat = Double.parseDouble(latStr);
+        double lng = Double.parseDouble(lngStr);
+        //判断是否在范围
+        return MIN_LAT >= lat || lat >= MAX_LAT || MIN_LNG >= lng || lng >= MAX_LNG;
+    }
+
+    /**
+     * 检查图层
+     *
+     * @param data                      数据
+     * @param layerTemplate             图层模版
+     * @param missingRequirementsResult 缺少必填结果
+     * @param invalidTypesResult        无效类型结果
+     * @param layerType                 图层类型
+     */
+    public void checkLayer(Map<String, String> data, GisMetadataLayerTemplate layerTemplate
+            , List<GisSurveyThirdImportElement> missingRequirementsResult
+            , List<GisSurveyThirdImportElement> invalidTypesResult, GisSurveyImportDefine.LayerType layerType) {
+        //遍历图层属性模版
+        for (GisMetadataPropertyTemplate propertyTemplate : layerTemplate.getPropertyTemplates()) {
+            //排除非必填
+            if (propertyTemplate.getRequired() != 1)
+                continue;
+            //排除code
+            if (Objects.equals(GisSurveyImportDefine.TEMPLATE.CODE, propertyTemplate.getKey()))
+                continue;
+            //模版名称
+            String templateName = propertyTemplate.getName();
+            //点类型模版表头映射
+            if (layerType == GisSurveyImportDefine.LayerType.POINT)
+                switch (propertyTemplate.getKey()) {
+                    case GisSurveyImportDefine.TEMPLATE.LNG:
+                        templateName = GisSurveyImportDefine.POINT.LNG;
+                        break;
+                    case GisSurveyImportDefine.TEMPLATE.LAT:
+                        templateName = GisSurveyImportDefine.POINT.LAT;
+                        break;
+                }
+            if (layerType == GisSurveyImportDefine.LayerType.LINE)
+                switch (propertyTemplate.getKey()) {
+                    case GisSurveyImportDefine.TEMPLATE.UP_NODE:
+                        templateName = GisSurveyImportDefine.LINE.UP_NO;
+                        break;
+                    case GisSurveyImportDefine.TEMPLATE.DOWN_NODE:
+                        templateName = GisSurveyImportDefine.LINE.DOWN_NO;
+                        break;
+                }
+            //必填不存在则存入缺少必填
+            if (!data.containsKey(templateName))
+                missingRequirementsResult.add(GisSurveyThirdImportElement.create(data,
+                        templateName,
+                        layerType
+                ));
+            else if ((propertyTemplate.getType().equals("float") || propertyTemplate.getType().equals("int"))
+                    && !NumberUtils.isParsable(data.get(templateName)))
+                //存在且类型为数字则判断数字类型
+                invalidTypesResult.add(GisSurveyThirdImportElement.create(data,
+                        data.get(templateName),
+                        layerType
+                ));
+        }
+
+    }
+
+
+}

+ 3 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/ApiURI.java

@@ -27,6 +27,9 @@ public class ApiURI {
     public static final String URI_XXX_SYS_CHECK = "sys-check";
     public static final String URI_XXX_SYS_CHECK_CANCEL = "sys-check-cancel";
     public static final String URI_XXX_SYS_CHECK_RESULTS = "sys-check-results";
+    public static final String URI_XXX_THIRD_IMPORT= "third-import";
+    public static final String URI_XXX_THIRD_IMPORT_CANCEL= "third-import-cancel";
+    public static final String URI_XXX_THIRD_IMPORT_COMMIT= "third-import-commit";
 
     public static final String URI_ACCESS_TOKEN_CHECK = "/kpr-plugin/apply/access-token-check";
     public static final String URI_FILE_BUSI_XXX = "/files/**";

+ 22 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/ExcelEnum.java

@@ -0,0 +1,22 @@
+package com.shkpr.service.alambizplugin.constants;
+
+/**
+ * excel枚举
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+public enum ExcelEnum {
+    /**
+     * csv
+     */
+    CSV,
+    /**
+     * xls
+     */
+    XLS,
+    /**
+     * xlsx
+     */
+    XLSX
+}

+ 2 - 2
src/main/java/com/shkpr/service/alambizplugin/constants/GisSurveyCheckStatusEnum.java

@@ -4,7 +4,7 @@ import lombok.AllArgsConstructor;
 import lombok.Getter;
 
 /**
- * 系统检查状态枚举
+ * 系统检查状态枚举
  *
  * @author 欧阳劲驰
  * @serial 1.0.0
@@ -25,7 +25,7 @@ public enum GisSurveyCheckStatusEnum {
      */
     FAIL(2),
     /**
-     * 存在
+     * 存在
      */
     NOT_EXISTS(3);
     /**

+ 67 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/GisSurveyImportDefine.java

@@ -0,0 +1,67 @@
+package com.shkpr.service.alambizplugin.constants;
+
+/**
+ * 第三方导入字典
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+public interface GisSurveyImportDefine {
+    /**
+     * 图层 枚举
+     */
+    enum LayerType {
+        POINT,
+        LINE
+    }
+
+    /**
+     * 点文件映射
+     */
+    interface POINT {
+        String NO = "点号";
+        String LAYER = "点类型";
+        String LNG = "X坐标/经度";
+        String LAT = "Y坐标/纬度";
+        String ELEVATION = "地面高程";
+        String DEPTH = "埋深";
+    }
+
+    /**
+     * 线文件映射
+     */
+    interface LINE {
+        String UP_NO = "起点号";
+        String DOWN_NO = "终点号";
+        String LAYER = "线类型";
+    }
+
+    /**
+     * 数据库模版映射
+     */
+    interface TEMPLATE {
+        String CODE = "code";
+        String LNG = "lng";
+        String LAT = "lat";
+        String UP_NODE = "up_node";
+        String DOWN_NODE = "down_node";
+    }
+
+    /**
+     * 入库默认值
+     */
+    interface DEFAULT_VALUE {
+        String APPLY = "add";
+        Short SOURCE = (short) (0xff);
+    }
+
+    /**
+     * 结果key
+     */
+    interface RESULT {
+        String INVALID_LAYERS = "invalidLayersResult";
+        String MISSING_REQUIREMENTS = "missingRequirementsResult";
+        String INVALID_TYPES = "invalidTypesResult";
+        String OUT_RANGES = "outRangesResult";
+    }
+}

+ 39 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/GisSurveyImportStatusEnum.java

@@ -0,0 +1,39 @@
+package com.shkpr.service.alambizplugin.constants;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 第三方导入状态枚举
+ *
+ * @author 欧阳劲驰
+ * @serial 1.0.0
+ */
+@AllArgsConstructor
+@Getter
+public enum GisSurveyImportStatusEnum {
+    /**
+     * 进行中
+     */
+    IN_PROGRESS(0),
+    /**
+     * 成功
+     */
+    SUCCESS(1),
+    /**
+     * 失败
+     */
+    FAIL(2),
+    /**
+     * 不存在
+     */
+    NOT_EXISTS(3),
+    /**
+     * 数据错误
+     */
+    DATA_ERROR(4);
+    /**
+     * code
+     */
+    private final Integer code;
+}

+ 4 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/ResponseCode.java

@@ -100,6 +100,10 @@ public enum ResponseCode {
     RESULT_SYSTEM_CHECK_CANCEL_FAILED(40002, "System check cancel failed."),
     RESULT_SYSTEM_CHECK_RESULT_NOT_FOUND(40003, "System check result not found."),
 
+    RESULT_THIRD_IMPORT_FAILED(40010, "Third import failed."),
+    RESULT_THIRD_IMPORT_NOT_FOUND(40011, "Third import not found."),
+    RESULT_THIRD_IMPORT_CANCEL_FAILED(40012, "Third import cancel failed."),
+
     BUSINESS_SYNC_FUN_FAILED(65529,"The Synch operation failed."),
     BUSINESS_DB_REQ_FAILED(65530,"The DB operation failed."),
     BUSINESS_API_ABOLISH(65531,"The Api has been abolished."),

+ 238 - 9
src/main/java/com/shkpr/service/alambizplugin/controller/ApiGisSurveyController.java

@@ -3,26 +3,37 @@ package com.shkpr.service.alambizplugin.controller;
 import com.global.base.log.LogLevelFlag;
 import com.global.base.log.LogPrintMgr;
 import com.shkpr.service.alambizplugin.apiparam.GisSurveyCheckParams;
-import com.shkpr.service.alambizplugin.bizservice.GisSurveyBizService;
+import com.shkpr.service.alambizplugin.apiparam.GisSurveyThirdImportParams;
+import com.shkpr.service.alambizplugin.bizservice.GisSurveySystemCheckBizService;
+import com.shkpr.service.alambizplugin.bizservice.GisSurveyThirdImportBizService;
 import com.shkpr.service.alambizplugin.commtools.CommTool;
 import com.shkpr.service.alambizplugin.constants.ApiURI;
 import com.shkpr.service.alambizplugin.constants.GisSurveyCheckStatusEnum;
+import com.shkpr.service.alambizplugin.constants.GisSurveyImportStatusEnum;
 import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
 import com.shkpr.service.alambizplugin.constants.ResponseCode;
 import com.shkpr.service.alambizplugin.controllerfilter.TokenAuthenticationService;
 import com.shkpr.service.alambizplugin.controllervalid.CommonParamValidSK;
+import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveyLayerApplyService;
 import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckResult;
+import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportResult;
 import com.shkpr.service.alambizplugin.dto.ResponseRes;
 import com.shkpr.service.alambizplugin.exception.SelfException;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.validation.BindingResult;
 import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestHeader;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletRequest;
+import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -34,16 +45,25 @@ public class ApiGisSurveyController {
     private final String mBizType;
     //计数器
     private final AtomicInteger mSeqSysCheckReq;
-    private final AtomicInteger mSeqSysCheckDelReq;
+    private final AtomicInteger mSeqSysCheckCancelReq;
+    private final AtomicInteger mSeqThirdImportReq;
+    private final AtomicInteger mSeqThirdImportCancelReq;
 
-    private final GisSurveyBizService gisSurveyBizService;
+    private final GisSurveySystemCheckBizService systemCheckBizService;
+    private final GisSurveyThirdImportBizService thirdImportBizService;
+    private final GisSurveyLayerApplyService layerApplyService;
 
-    public ApiGisSurveyController(GisSurveyBizService gisSurveyBizService) {
+    public ApiGisSurveyController(GisSurveySystemCheckBizService systemCheckBizService
+            , GisSurveyThirdImportBizService thirdImportBizService, GisSurveyLayerApplyService layerApplyService) {
         mStrClassName = "ApiGisSurveyController";
         mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
         mSeqSysCheckReq = new AtomicInteger(0);
-        mSeqSysCheckDelReq = new AtomicInteger(0);
-        this.gisSurveyBizService = gisSurveyBizService;
+        mSeqSysCheckCancelReq = new AtomicInteger(0);
+        mSeqThirdImportReq = new AtomicInteger(0);
+        mSeqThirdImportCancelReq = new AtomicInteger(0);
+        this.systemCheckBizService = systemCheckBizService;
+        this.thirdImportBizService = thirdImportBizService;
+        this.layerApplyService = layerApplyService;
     }
 
     /**
@@ -89,7 +109,7 @@ public class ApiGisSurveyController {
         resResult.setResmsg(ResponseCode.RESULT_SYSTEM_CHECK_FAILED.toStrMsg());
 
         //执行系统检查
-        GisSurveySystemCheckResult result = gisSurveyBizService.sysCheckFun(oJsonParam);
+        GisSurveySystemCheckResult result = systemCheckBizService.sysCheckFun(oJsonParam);
 
         //执行成功
         if (result != null && !Objects.equals(result.getCheckStatus(), GisSurveyCheckStatusEnum.FAIL.getCode())) {
@@ -150,7 +170,7 @@ public class ApiGisSurveyController {
         }
         //begin
         long llReqBefore = System.currentTimeMillis();
-        String strRunSeq = String.format("%d-%d", llReqBefore, mSeqSysCheckDelReq.incrementAndGet());
+        String strRunSeq = String.format("%d-%d", llReqBefore, mSeqSysCheckCancelReq.incrementAndGet());
         LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, strUserId
                 , String.format("%s:%s seq:{%s} param:%s begin====>"
                         , strPlatform
@@ -162,7 +182,7 @@ public class ApiGisSurveyController {
         resResult.setRescode(ResponseCode.RESULT_SYSTEM_CHECK_CANCEL_FAILED.toStrCode());
         resResult.setResmsg(ResponseCode.RESULT_SYSTEM_CHECK_CANCEL_FAILED.toStrMsg());
         //清除检查
-        GisSurveySystemCheckResult cancelCheck = gisSurveyBizService.cancelCheck(oJsonParam);
+        GisSurveySystemCheckResult cancelCheck = systemCheckBizService.cancelCheck(oJsonParam);
         //成功
         if (Objects.equals(cancelCheck.getCheckStatus(), GisSurveyCheckStatusEnum.SUCCESS.getCode())) {
             resResult.setRescode(ResponseCode.RESULT_NORMAL.toStrCode());
@@ -185,4 +205,213 @@ public class ApiGisSurveyController {
                         , resResult.getTimestamp() - llReqBefore));
         return resResult;
     }
+
+
+    /**
+     * 执行第三方导入
+     *
+     * @param request       request
+     * @param strClientType 客户端类型
+     * @param strUserAgent  用户信息
+     * @param files         文件列表
+     * @param operator      操作人
+     * @param jobId         任务id
+     * @param nature        用水性质,supply/drain
+     * @param codeRule      点号规则
+     * @param ignoreFail    是否忽略失败
+     * @return 第三方导入结果
+     */
+    @PostMapping(value = ApiURI.URI_XXX_THIRD_IMPORT)
+    public ResponseRes<GisSurveyThirdImportResult> thirdImport(HttpServletRequest request
+            , @RequestHeader(value = ApiURI.HEADER_CLIENT_TYPE, required = false) String strClientType
+            , @RequestHeader(value = ApiURI.HEADER_USER_AGENT, required = false) String strUserAgent
+            , @RequestParam(value = "files", required = false) List<MultipartFile> files
+            , @RequestParam(value = "operator", required = false) String operator
+            , @RequestParam(value = "jobId", required = false) String jobId
+            , @RequestParam(value = "nature", required = false) String nature
+            , @RequestParam(value = "codeRule", required = false) String codeRule
+            , @RequestParam(value = "ignoreFail", required = false, defaultValue = "false") String ignoreFail) throws SelfException {
+        //入参校验
+        final String URI_PATH = request.getRequestURI();
+        final String strPlatform = CommTool.getPlatformByAgent(strClientType, strUserAgent);
+        final String strUserId = (String) request.getAttribute(TokenAuthenticationService.HEADER_USERID);
+        if (StringUtils.isAnyBlank(operator, jobId, nature) || CollectionUtils.isEmpty(files)) {
+            throw new SelfException(ResponseCode.STATUS_ERROR_PARAM_FORMAT.toStrCode()
+                    , String.format(ApiURI.EXCEPTION_FORMAT
+                    , strPlatform
+                    , URI_PATH
+                    , ResponseCode.STATUS_ERROR_PARAM_FORMAT.toStrMsg()));
+        }
+        //构建入参数
+        GisSurveyThirdImportParams params = new GisSurveyThirdImportParams(files, operator, jobId, nature, codeRule, Boolean.parseBoolean(ignoreFail));
+        //begin
+        long llReqBefore = System.currentTimeMillis();
+        String strRunSeq = String.format("%d-%d", llReqBefore, mSeqThirdImportReq.incrementAndGet());
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, strUserId
+                , String.format("%s:%s seq:{%s} param:%s begin====>"
+                        , strPlatform
+                        , URI_PATH
+                        , strRunSeq
+                        , params));
+        //构建result
+        ResponseRes<GisSurveyThirdImportResult> resResult = new ResponseRes<>();
+        resResult.setRescode(ResponseCode.RESULT_THIRD_IMPORT_FAILED.toStrCode());
+        resResult.setResmsg(ResponseCode.RESULT_THIRD_IMPORT_FAILED.toStrMsg());
+
+        //执行第三方导入
+        GisSurveyThirdImportResult result = thirdImportBizService.thirdImport(params);
+
+        //执行成功
+        if (result != null && !Objects.equals(result.getImportStatus(), GisSurveyImportStatusEnum.FAIL.getCode())) {
+            resResult.setRescode(ResponseCode.RESULT_NORMAL.toStrCode());
+            resResult.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg());
+            resResult.setResdata(result);
+        }
+        //执行失败
+        if (result != null && Objects.equals(result.getImportStatus(), GisSurveyImportStatusEnum.FAIL.getCode())) {
+            resResult.setResdata(result);
+        }
+        //结果为空
+        if (result == null) {
+            resResult.setRescode(ResponseCode.RESULT_THIRD_IMPORT_NOT_FOUND.toStrCode());
+            resResult.setResmsg(ResponseCode.RESULT_THIRD_IMPORT_NOT_FOUND.toStrMsg());
+        }
+
+        //end
+        resResult.setTimestamp(System.currentTimeMillis());
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, strUserId
+                , String.format("%s:%s seq:{%s} rescode:{%s} resmsg:{%s} time:{%d ms} end<===="
+                        , strPlatform
+                        , URI_PATH
+                        , strRunSeq
+                        , resResult.getRescode()
+                        , resResult.getResmsg()
+                        , resResult.getTimestamp() - llReqBefore));
+        return resResult;
+    }
+
+    /**
+     * 清除第三方导入
+     *
+     * @param request       request
+     * @param strClientType 客户端类型
+     * @param strUserAgent  用户信息
+     * @param jobId         任务id
+     * @return 清除状态
+     * @throws SelfException selfException
+     */
+    @GetMapping(value = ApiURI.URI_XXX_THIRD_IMPORT_CANCEL)
+    public ResponseRes<?> cancelImport(HttpServletRequest request
+            , @RequestHeader(value = ApiURI.HEADER_CLIENT_TYPE, required = false) String strClientType
+            , @RequestHeader(value = ApiURI.HEADER_USER_AGENT, required = false) String strUserAgent
+            , @RequestParam("jobId") String jobId) throws Exception {
+        //入参校验
+        final String URI_PATH = request.getRequestURI();
+        final String strPlatform = CommTool.getPlatformByAgent(strClientType, strUserAgent);
+        final String strUserId = (String) request.getAttribute(TokenAuthenticationService.HEADER_USERID);
+        if (StringUtils.isBlank(jobId)) {
+            throw new SelfException(ResponseCode.STATUS_ERROR_PARAM_FORMAT.toStrCode()
+                    , String.format(ApiURI.EXCEPTION_FORMAT
+                    , strPlatform
+                    , URI_PATH
+                    , ResponseCode.STATUS_ERROR_PARAM_FORMAT.toStrMsg()));
+        }
+        //begin
+        long llReqBefore = System.currentTimeMillis();
+        String strRunSeq = String.format("%d-%d", llReqBefore, mSeqThirdImportCancelReq.incrementAndGet());
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, strUserId
+                , String.format("%s:%s seq:{%s} param:%s begin====>"
+                        , strPlatform
+                        , URI_PATH
+                        , strRunSeq
+                        , jobId));
+        //构建result
+        ResponseRes<Boolean> resResult = new ResponseRes<>();
+        resResult.setRescode(ResponseCode.RESULT_THIRD_IMPORT_CANCEL_FAILED.toStrCode());
+        resResult.setResmsg(ResponseCode.RESULT_THIRD_IMPORT_CANCEL_FAILED.toStrMsg());
+        //清除导入
+        Integer cancelCheck = thirdImportBizService.cancelImport(jobId);
+        //成功
+        if (Objects.equals(cancelCheck, GisSurveyCheckStatusEnum.SUCCESS.getCode())) {
+            resResult.setRescode(ResponseCode.RESULT_NORMAL.toStrCode());
+            resResult.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg());
+        }
+        //不存在
+        else if (Objects.equals(cancelCheck, GisSurveyCheckStatusEnum.NOT_EXISTS.getCode())) {
+            resResult.setRescode(ResponseCode.RESULT_THIRD_IMPORT_NOT_FOUND.toStrCode());
+            resResult.setResmsg(ResponseCode.RESULT_THIRD_IMPORT_NOT_FOUND.toStrMsg());
+        }
+        //end
+        resResult.setTimestamp(System.currentTimeMillis());
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, strUserId
+                , String.format("%s:%s seq:{%s} rescode:{%s} resmsg:{%s} time:{%d ms} end<===="
+                        , strPlatform
+                        , URI_PATH
+                        , strRunSeq
+                        , resResult.getRescode()
+                        , resResult.getResmsg()
+                        , resResult.getTimestamp() - llReqBefore));
+        return resResult;
+    }
+
+    /**
+     * 提交第三方导入
+     *
+     * @param request       request
+     * @param strClientType 客户端类型
+     * @param strUserAgent  用户信息
+     * @param jobId         任务id
+     * @return 清除状态
+     * @throws SelfException selfException
+     */
+    @GetMapping(value = ApiURI.URI_XXX_THIRD_IMPORT_COMMIT)
+    public ResponseRes<?> commitImport(HttpServletRequest request
+            , @RequestHeader(value = ApiURI.HEADER_CLIENT_TYPE, required = false) String strClientType
+            , @RequestHeader(value = ApiURI.HEADER_USER_AGENT, required = false) String strUserAgent
+            , @RequestParam("jobId") String jobId) throws Exception {
+        //入参校验
+        final String URI_PATH = request.getRequestURI();
+        final String strPlatform = CommTool.getPlatformByAgent(strClientType, strUserAgent);
+        final String strUserId = (String) request.getAttribute(TokenAuthenticationService.HEADER_USERID);
+        if (StringUtils.isBlank(jobId)) {
+            throw new SelfException(ResponseCode.STATUS_ERROR_PARAM_FORMAT.toStrCode()
+                    , String.format(ApiURI.EXCEPTION_FORMAT
+                    , strPlatform
+                    , URI_PATH
+                    , ResponseCode.STATUS_ERROR_PARAM_FORMAT.toStrMsg()));
+        }
+        //begin
+        long llReqBefore = System.currentTimeMillis();
+        String strRunSeq = String.format("%d-%d", llReqBefore, mSeqThirdImportCancelReq.incrementAndGet());
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, strUserId
+                , String.format("%s:%s seq:{%s} param:%s begin====>"
+                        , strPlatform
+                        , URI_PATH
+                        , strRunSeq
+                        , jobId));
+        //构建result
+        ResponseRes<Boolean> resResult = new ResponseRes<>();
+        resResult.setRescode(ResponseCode.RESULT_THIRD_IMPORT_FAILED.toStrCode());
+        resResult.setResmsg(ResponseCode.RESULT_THIRD_IMPORT_FAILED.toStrMsg());
+
+        //提交导入
+        Boolean commitStatus = layerApplyService.mergeCopy(jobId);
+        //成功
+        if (Objects.equals(commitStatus, Boolean.TRUE)) {
+            resResult.setRescode(ResponseCode.RESULT_NORMAL.toStrCode());
+            resResult.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg());
+        }
+
+        //end
+        resResult.setTimestamp(System.currentTimeMillis());
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, strUserId
+                , String.format("%s:%s seq:{%s} rescode:{%s} resmsg:{%s} time:{%d ms} end<===="
+                        , strPlatform
+                        , URI_PATH
+                        , strRunSeq
+                        , resResult.getRescode()
+                        , resResult.getResmsg()
+                        , resResult.getTimestamp() - llReqBefore));
+        return resResult;
+    }
 }

+ 3 - 0
src/main/java/com/shkpr/service/alambizplugin/controllerfilter/third/ApiJWTGisSurveyBizFilter.java

@@ -22,6 +22,9 @@ public class ApiJWTGisSurveyBizFilter extends JWTAuthenticationFilter {
         msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_GIS_SURVEY_H, ApiURI.URI_XXX_SYS_CHECK), "POST");
         msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_GIS_SURVEY_H, ApiURI.URI_XXX_SYS_CHECK_CANCEL), "POST");
         msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_GIS_SURVEY_H, ApiURI.URI_XXX_SYS_CHECK_RESULTS), "GET");
+        msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_GIS_SURVEY_H, ApiURI.URI_XXX_THIRD_IMPORT), "POST");
+        msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_GIS_SURVEY_H, ApiURI.URI_XXX_THIRD_IMPORT_CANCEL), "GET");
+        msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_GIS_SURVEY_H, ApiURI.URI_XXX_THIRD_IMPORT_COMMIT), "GET");
     }
 
     public ApiJWTGisSurveyBizFilter(String url, AuthenticationManager authenticationManager){

+ 27 - 0
src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisMetadataLayerTemplateMapper.java

@@ -0,0 +1,27 @@
+package com.shkpr.service.alambizplugin.dbdao.mapper;
+
+import com.shkpr.service.alambizplugin.dto.GisMetadataLayerTemplate;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * gis元数据图层定义模板mapper
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Mapper
+public interface GisMetadataLayerTemplateMapper {
+
+    /**
+     * 根据用水类别和图层名集合查询
+     *
+     * @param nature 用水类别
+     * @param names  图层名集合
+     * @return 图层定义模版
+     */
+    List<GisMetadataLayerTemplate> findByNatureAndNameIn(@Param("nature") String nature, @Param("names") List<String> names);
+
+}

+ 14 - 0
src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisMetadataPropertyTemplateMapper.java

@@ -0,0 +1,14 @@
+package com.shkpr.service.alambizplugin.dbdao.mapper;
+
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * gis元数据图层属性定义模板mapper
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Mapper
+public interface GisMetadataPropertyTemplateMapper {
+
+}

+ 9 - 0
src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisSurveyJobInfoMapper.java

@@ -20,4 +20,13 @@ public interface GisSurveyJobInfoMapper {
      * @return 刷新时间
      */
     LocalDateTime findRefreshTimeByUid(@Param("uid") String uid);
+
+    /**
+     * 根据uid更新刷新时间
+     *
+     * @param uid       uid
+     * @param timestamp 时间戳
+     * @return 刷新时间
+     */
+    int updateRefreshTimeByUid(@Param("uid") String uid, @Param("timestamp") Long timestamp);
 }

+ 8 - 0
src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisSurveyLayerApplyMapper.java

@@ -45,4 +45,12 @@ public interface GisSurveyLayerApplyMapper {
      * @return 线集合
      */
     Cursor<GisSurveyLayerApplyLine> findAddLineByJobId(@Param("jobId") String jobId);
+
+    /**
+     * 根据任务id合并副表
+     *
+     * @param jobId 任务id
+     * @return 合并数量
+     */
+    int mergeCopyByJobId(@Param("jobId") String jobId);
 }

+ 38 - 0
src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisSurveyLayerApplyThirdCopyMapper.java

@@ -0,0 +1,38 @@
+package com.shkpr.service.alambizplugin.dbdao.mapper;
+
+import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyThirdCopy;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 采集元素第三方导入副本mapper
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Mapper
+public interface GisSurveyLayerApplyThirdCopyMapper {
+    /**
+     * 保存
+     *
+     * @param record 对象
+     * @return 保存数量
+     */
+    int save(GisSurveyLayerApplyThirdCopy record);
+
+    /**
+     * 根据任务Id删除
+     *
+     * @param jobId jobId
+     * @return 删除数量
+     */
+    int deleteByJobId(@Param("jobId") String jobId);
+
+    /**
+     * 根据任务Id获取总数
+     *
+     * @param jobId 任务id
+     * @return 总数
+     */
+    int countByJobId(@Param("jobId") String jobId);
+}

+ 9 - 0
src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisSurveyProjectInfoMapper.java

@@ -20,4 +20,13 @@ public interface GisSurveyProjectInfoMapper {
      * @return 刷新时间
      */
     LocalDateTime findRefreshTimeByUid(@Param("uid") String uid);
+
+    /**
+     * 根据任务id更新刷新时间
+     *
+     * @param jobId     任务id
+     * @param timestamp 时间戳
+     * @return 刷新时间
+     */
+    int updateRefreshTimeByUid(@Param("jobId") String jobId, @Param("timestamp") Long timestamp);
 }

+ 19 - 0
src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisSurveyPropertyValueMapper.java

@@ -0,0 +1,19 @@
+package com.shkpr.service.alambizplugin.dbdao.mapper;
+
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 采集元素属性取值mapper
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+public interface GisSurveyPropertyValueMapper {
+    /**
+     * 根据任务id合并副表
+     *
+     * @param jobId 任务id
+     * @return 合并数量
+     */
+    int mergeCopyByJobId(@Param("jobId") String jobId);
+}

+ 30 - 0
src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisSurveyPropertyValueThirdCopyMapper.java

@@ -0,0 +1,30 @@
+package com.shkpr.service.alambizplugin.dbdao.mapper;
+
+import com.shkpr.service.alambizplugin.dto.GisSurveyPropertyValueThirdCopy;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 采集元素属性第三方导入副本表
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Mapper
+public interface GisSurveyPropertyValueThirdCopyMapper {
+    /**
+     * 保存
+     *
+     * @param record 对象
+     * @return 保存数量
+     */
+    int save(GisSurveyPropertyValueThirdCopy record);
+
+    /**
+     * 根据jobId删除
+     *
+     * @param jobId jobId
+     * @return 删除数量
+     */
+    int deleteByJobId(@Param("jobId") String jobId);
+}

+ 39 - 0
src/main/java/com/shkpr/service/alambizplugin/dbdao/services/GisMetadataLayerTemplateServiceImpl.java

@@ -0,0 +1,39 @@
+package com.shkpr.service.alambizplugin.dbdao.services;
+
+import com.shkpr.service.alambizplugin.dbdao.mapper.GisMetadataLayerTemplateMapper;
+import com.shkpr.service.alambizplugin.dbdao.services.intef.GisMetadataLayerTemplateService;
+import com.shkpr.service.alambizplugin.dto.GisMetadataLayerTemplate;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * gis元数据图层定义模板service实现
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Service
+public class GisMetadataLayerTemplateServiceImpl implements GisMetadataLayerTemplateService {
+    final
+    GisMetadataLayerTemplateMapper layerTemplateMapper;
+
+    public GisMetadataLayerTemplateServiceImpl(GisMetadataLayerTemplateMapper layerTemplateMapper) {
+        this.layerTemplateMapper = layerTemplateMapper;
+    }
+
+    /**
+     * 根据用水类别和图层名集合查询
+     *
+     * @param nature 用水类别
+     * @param names  图层名集合
+     * @return 图层定义模版
+     */
+    @Override
+    public List<GisMetadataLayerTemplate> findByNatureAndNameIn(String nature, List<String> names) {
+        if (CollectionUtils.isEmpty(names)) return Collections.emptyList();
+        return layerTemplateMapper.findByNatureAndNameIn(nature, names);
+    }
+}

+ 88 - 8
src/main/java/com/shkpr/service/alambizplugin/dbdao/services/GisSurveyLayerApplyServiceImpl.java

@@ -3,11 +3,18 @@ package com.shkpr.service.alambizplugin.dbdao.services;
 import com.global.base.log.LogLevelFlag;
 import com.global.base.log.LogPrintMgr;
 import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
+import com.shkpr.service.alambizplugin.dbdao.mapper.GisSurveyJobInfoMapper;
 import com.shkpr.service.alambizplugin.dbdao.mapper.GisSurveyLayerApplyMapper;
+import com.shkpr.service.alambizplugin.dbdao.mapper.GisSurveyLayerApplyThirdCopyMapper;
+import com.shkpr.service.alambizplugin.dbdao.mapper.GisSurveyProjectInfoMapper;
+import com.shkpr.service.alambizplugin.dbdao.mapper.GisSurveyPropertyValueMapper;
 import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveyLayerApplyService;
 import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyLine;
 import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyPoint;
 import org.apache.ibatis.cursor.Cursor;
+import org.apache.ibatis.session.SqlSession;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -23,18 +30,21 @@ import java.util.List;
  */
 @Service
 public class GisSurveyLayerApplyServiceImpl implements GisSurveyLayerApplyService {
-    final
-    GisSurveyLayerApplyMapper gisSurveyLayerApplyMapper;
     /**
      * log
      */
     private final String mStrClassName;
     private final String mBizType;
 
-    public GisSurveyLayerApplyServiceImpl(GisSurveyLayerApplyMapper gisSurveyLayerApplyMapper) {
+    private final SqlSessionFactory sqlSessionFactory;
+    private final GisSurveyLayerApplyMapper layerApplyMapper;
+
+    public GisSurveyLayerApplyServiceImpl(@Qualifier("mainSqlSessionFactory") SqlSessionFactory sqlSessionFactory
+            , GisSurveyLayerApplyMapper layerApplyMapper) {
         mStrClassName = "GisSurveyLayerApplyServiceImpl";
         mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
-        this.gisSurveyLayerApplyMapper = gisSurveyLayerApplyMapper;
+        this.sqlSessionFactory = sqlSessionFactory;
+        this.layerApplyMapper = layerApplyMapper;
     }
 
 
@@ -56,7 +66,7 @@ public class GisSurveyLayerApplyServiceImpl implements GisSurveyLayerApplyServic
         );
         long begin = System.currentTimeMillis();
         //获取游标
-        try (Cursor<GisSurveyLayerApplyPoint> cursor = gisSurveyLayerApplyMapper.findAddPointByProjId(projId)) {
+        try (Cursor<GisSurveyLayerApplyPoint> cursor = layerApplyMapper.findAddPointByProjId(projId)) {
             //迭代游标
             for (GisSurveyLayerApplyPoint point : cursor) {
                 //检查线程中断,并响应
@@ -103,7 +113,7 @@ public class GisSurveyLayerApplyServiceImpl implements GisSurveyLayerApplyServic
         );
         long begin = System.currentTimeMillis();
         //获取游标
-        try (Cursor<GisSurveyLayerApplyLine> cursor = gisSurveyLayerApplyMapper.findAddLineByProjId(projId)) {
+        try (Cursor<GisSurveyLayerApplyLine> cursor = layerApplyMapper.findAddLineByProjId(projId)) {
             //迭代游标
             for (GisSurveyLayerApplyLine point : cursor) {
                 //检查线程中断,并响应
@@ -150,7 +160,7 @@ public class GisSurveyLayerApplyServiceImpl implements GisSurveyLayerApplyServic
         );
         long begin = System.currentTimeMillis();
         //获取游标
-        try (Cursor<GisSurveyLayerApplyPoint> cursor = gisSurveyLayerApplyMapper.findAddPointByJobId(jobId)) {
+        try (Cursor<GisSurveyLayerApplyPoint> cursor = layerApplyMapper.findAddPointByJobId(jobId)) {
             //迭代游标
             for (GisSurveyLayerApplyPoint gisSurveyLayerApplyPoint : cursor) {
                 //检查线程中断,并响应
@@ -197,7 +207,7 @@ public class GisSurveyLayerApplyServiceImpl implements GisSurveyLayerApplyServic
         );
         long begin = System.currentTimeMillis();
         //获取游标
-        try (Cursor<GisSurveyLayerApplyLine> cursor = gisSurveyLayerApplyMapper.findAddLineByJobId(jobId)) {
+        try (Cursor<GisSurveyLayerApplyLine> cursor = layerApplyMapper.findAddLineByJobId(jobId)) {
             //迭代游标
             for (GisSurveyLayerApplyLine line : cursor) {
                 //检查线程中断,并响应
@@ -225,4 +235,74 @@ public class GisSurveyLayerApplyServiceImpl implements GisSurveyLayerApplyServic
         }
         return lines;
     }
+
+    /**
+     * 合并副表
+     *
+     * @param jobId 任务id
+     * @return 合并结果
+     */
+    public Boolean mergeCopy(String jobId) {
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                , String.format(
+                        "开始合并副表,开启session和事务 任务ID:%s"
+                        , jobId
+                )
+        );
+        long begin = System.currentTimeMillis();
+        //开启session
+        try (SqlSession session = sqlSessionFactory.openSession(false)) {
+            try {
+                //获取需要的mapper
+                GisSurveyLayerApplyMapper layerApplyMapper = session.getMapper(GisSurveyLayerApplyMapper.class);
+                GisSurveyLayerApplyThirdCopyMapper layerApplyThirdCopyMapper = session.getMapper(GisSurveyLayerApplyThirdCopyMapper.class);
+                GisSurveyPropertyValueMapper propertyValueMapper = session.getMapper(GisSurveyPropertyValueMapper.class);
+                GisSurveyProjectInfoMapper projectInfoMapper = session.getMapper(GisSurveyProjectInfoMapper.class);
+                GisSurveyJobInfoMapper jobInfoMapper = session.getMapper(GisSurveyJobInfoMapper.class);
+
+                //需要合并的数量
+                int mergeCount = layerApplyThirdCopyMapper.countByJobId(jobId);
+
+                //合并属性
+                propertyValueMapper.mergeCopyByJobId(jobId);
+                //合并元素
+                int layerApply = layerApplyMapper.mergeCopyByJobId(jobId);
+
+                //检查合并数量
+                if (mergeCount != layerApply) {
+                    session.rollback();
+                    return false;
+                }
+
+                //更新刷新时间
+                long timestamp = System.currentTimeMillis();
+                System.out.println(timestamp);
+                projectInfoMapper.updateRefreshTimeByUid(jobId, timestamp);
+                jobInfoMapper.updateRefreshTimeByUid(jobId, timestamp);
+
+                long end = System.currentTimeMillis();
+                LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                        , String.format(
+                                "合并副表成功,提交事务 任务ID:%s 用时(毫秒):%d"
+                                , jobId
+                                , (end - begin)
+                        )
+                );
+                //提交
+                session.commit();
+                return true;
+            } catch (Exception e) {
+                LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
+                        , String.format(
+                                "合并副表失败 开始回滚操作 任务id:%s error:%s"
+                                , jobId
+                                , e
+                        )
+                );
+
+                session.rollback();
+                return false;
+            }
+        }
+    }
 }

+ 118 - 0
src/main/java/com/shkpr/service/alambizplugin/dbdao/services/GisSurveyLayerApplyThirdCopyServiceImpl.java

@@ -0,0 +1,118 @@
+package com.shkpr.service.alambizplugin.dbdao.services;
+
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
+import com.shkpr.service.alambizplugin.dbdao.mapper.GisSurveyLayerApplyThirdCopyMapper;
+import com.shkpr.service.alambizplugin.dbdao.mapper.GisSurveyPropertyValueThirdCopyMapper;
+import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveyLayerApplyThirdCopyService;
+import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyThirdCopy;
+import com.shkpr.service.alambizplugin.dto.GisSurveyPropertyValueThirdCopy;
+import org.apache.ibatis.session.ExecutorType;
+import org.apache.ibatis.session.SqlSession;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 采集元素第三方导入副本Service实现
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Service
+public class GisSurveyLayerApplyThirdCopyServiceImpl implements GisSurveyLayerApplyThirdCopyService {
+    /**
+     * log
+     */
+    private final String mStrClassName;
+    private final String mBizType;
+    private final SqlSessionFactory mainSqlSessionFactory;
+
+    public GisSurveyLayerApplyThirdCopyServiceImpl(@Qualifier("mainSqlSessionFactory") SqlSessionFactory mainSqlSessionFactory) {
+        this.mainSqlSessionFactory = mainSqlSessionFactory;
+        mStrClassName = "GisSurveyThirdImporter";
+        mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
+    }
+
+    /**
+     * 批量保存
+     *
+     * @param jobId          任务id
+     * @param layerApplyList 数据集合
+     * @return 保存状态
+     */
+    @Override
+    public Boolean saveAll(String jobId, List<GisSurveyLayerApplyThirdCopy> layerApplyList) throws InterruptedException {
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                , String.format(
+                        "开始批量写入元素和图形,开启批处理 任务ID:%s"
+                        , jobId
+                )
+        );
+        long begin = System.currentTimeMillis();
+        //开启批处理
+        try (SqlSession sqlSession = mainSqlSessionFactory.openSession(ExecutorType.BATCH, false)) {
+            try {
+                //从session获取mapper
+                GisSurveyLayerApplyThirdCopyMapper layerApplyThirdCopyMapper = sqlSession.getMapper(GisSurveyLayerApplyThirdCopyMapper.class);
+                GisSurveyPropertyValueThirdCopyMapper propertyValueThirdCopyMapper = sqlSession.getMapper(GisSurveyPropertyValueThirdCopyMapper.class);
+
+                //删除原本job
+                layerApplyThirdCopyMapper.deleteByJobId(jobId);
+                propertyValueThirdCopyMapper.deleteByJobId(jobId);
+
+                //批量插入图层
+                for (GisSurveyLayerApplyThirdCopy layerApply : layerApplyList) {
+                    //检查线程中断,并响应
+                    if (Thread.interrupted()) throw new InterruptedException();
+                    //插入元素
+                    layerApplyThirdCopyMapper.save(layerApply);
+                }
+
+                //提取属性集合
+                List<GisSurveyPropertyValueThirdCopy> propertyValueList = layerApplyList.parallelStream()
+                        .flatMap(it -> it.getPropertyValueList().stream())
+                        .collect(Collectors.toList());
+                //批量插入属性
+                for (GisSurveyPropertyValueThirdCopy gisSurveyPropertyValueThirdCopy : propertyValueList) {
+                    //检查线程中断,并响应
+                    if (Thread.interrupted()) throw new InterruptedException();
+                    propertyValueThirdCopyMapper.save(gisSurveyPropertyValueThirdCopy);
+                }
+
+                //提交(此处会发送sql至数据库)
+                sqlSession.commit();
+
+                long end = System.currentTimeMillis();
+                LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                        , String.format(
+                                "结束批量写入元素和图形,提交并关闭批处理 任务ID:%s 用时(毫秒):%d"
+                                , jobId
+                                , (end - begin)
+                        )
+                );
+                return true;
+            } catch (Exception e) {
+                //回滚
+                sqlSession.rollback();
+
+                LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
+                        , String.format(
+                                "批量写入元素和图形失败,回滚操作 任务ID:%s error:%s"
+                                , jobId
+                                , e
+                        )
+                );
+
+                //传递中断异常
+                if (e instanceof InterruptedException) throw new InterruptedException();
+
+                return false;
+            }
+        }
+    }
+}

+ 22 - 0
src/main/java/com/shkpr/service/alambizplugin/dbdao/services/intef/GisMetadataLayerTemplateService.java

@@ -0,0 +1,22 @@
+package com.shkpr.service.alambizplugin.dbdao.services.intef;
+
+import com.shkpr.service.alambizplugin.dto.GisMetadataLayerTemplate;
+
+import java.util.List;
+
+/**
+ * gis元数据图层定义模板service实现
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+public interface GisMetadataLayerTemplateService {
+    /**
+     * 根据用水类别和图层名集合查询
+     *
+     * @param nature 用水类别
+     * @param names  图层名集合
+     * @return 图层定义模版
+     */
+    List<GisMetadataLayerTemplate> findByNatureAndNameIn(String nature, List<String> names);
+}

+ 12 - 4
src/main/java/com/shkpr/service/alambizplugin/dbdao/services/intef/GisSurveyLayerApplyService.java

@@ -18,7 +18,7 @@ public interface GisSurveyLayerApplyService {
      * @param projId 项目id
      * @return 点集合
      */
-    List<GisSurveyLayerApplyPoint> findAddPointByProjId(String projId)throws InterruptedException;
+    List<GisSurveyLayerApplyPoint> findAddPointByProjId(String projId) throws InterruptedException;
 
     /**
      * 根据项目id查询新增线
@@ -26,7 +26,7 @@ public interface GisSurveyLayerApplyService {
      * @param projId 项目id
      * @return 线集合
      */
-    List<GisSurveyLayerApplyLine> findAddLineByProjId(String projId)throws InterruptedException;
+    List<GisSurveyLayerApplyLine> findAddLineByProjId(String projId) throws InterruptedException;
 
     /**
      * 根据任务id查询新增点
@@ -34,7 +34,7 @@ public interface GisSurveyLayerApplyService {
      * @param jobId 任务id
      * @return 点集合
      */
-    List<GisSurveyLayerApplyPoint> findAddPointByJobId(String jobId)throws InterruptedException;
+    List<GisSurveyLayerApplyPoint> findAddPointByJobId(String jobId) throws InterruptedException;
 
     /**
      * 根据任务id查询新增线
@@ -42,5 +42,13 @@ public interface GisSurveyLayerApplyService {
      * @param jobId 任务id
      * @return 线集合
      */
-    List<GisSurveyLayerApplyLine> findAddLineByJobId(String jobId)throws InterruptedException;
+    List<GisSurveyLayerApplyLine> findAddLineByJobId(String jobId) throws InterruptedException;
+
+    /**
+     * 合并副表
+     *
+     * @param jobId 任务id
+     * @return 合并结果
+     */
+    Boolean mergeCopy(String jobId);
 }

+ 22 - 0
src/main/java/com/shkpr/service/alambizplugin/dbdao/services/intef/GisSurveyLayerApplyThirdCopyService.java

@@ -0,0 +1,22 @@
+package com.shkpr.service.alambizplugin.dbdao.services.intef;
+
+import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyThirdCopy;
+
+import java.util.List;
+
+/**
+ * 采集元素第三方导入副本Service实现
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+public interface GisSurveyLayerApplyThirdCopyService {
+    /**
+     * 批量保存
+     *
+     * @param jobId          任务id
+     * @param layerApplyList 数据集合
+     * @return 保存状态
+     */
+    Boolean saveAll(String jobId, List<GisSurveyLayerApplyThirdCopy> layerApplyList) throws InterruptedException;
+}

+ 77 - 0
src/main/java/com/shkpr/service/alambizplugin/dto/GisMetadataLayerTemplate.java

@@ -0,0 +1,77 @@
+package com.shkpr.service.alambizplugin.dto;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * gis元数据图层定义模板
+ */
+@Data
+public class GisMetadataLayerTemplate {
+    /**
+     * 主键
+     */
+    private Long id;
+
+    /**
+     * 用水类别
+     */
+    private String nature;
+
+    /**
+     * 图层标识符key
+     */
+    private String key;
+
+    /**
+     * 图层所属种类
+     */
+    private String kind;
+
+    /**
+     * 图层名称
+     */
+    private String name;
+
+    /**
+     * 相关图标
+     */
+    private String icon;
+
+    /**
+     * 相关图标颜色
+     */
+    private String color;
+
+    /**
+     * 状态:0--禁用;1--启用
+     */
+    private Short status;
+
+    /**
+     * 相关描述
+     */
+    private String remark;
+
+    /**
+     * 创建者
+     */
+    private String creator;
+
+    private String param1;
+
+    private String param2;
+
+    private LocalDateTime createTime;
+
+    private LocalDateTime updateTime;
+
+    private Short ordering;
+
+    /**
+     * 属性模版集合
+     */
+    private List<GisMetadataPropertyTemplate> propertyTemplates;
+}

+ 111 - 0
src/main/java/com/shkpr/service/alambizplugin/dto/GisMetadataPropertyTemplate.java

@@ -0,0 +1,111 @@
+package com.shkpr.service.alambizplugin.dto;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * gis元数据图层属性定义模板
+ */
+@Data
+public class GisMetadataPropertyTemplate {
+    /**
+     * 主键
+     */
+    private Long id;
+
+    /**
+     * 用水性质:supply/drain
+     */
+    private String nature;
+
+    /**
+     * 图层标识符key
+     */
+    private String layer;
+
+    /**
+     * 属性标识符key
+     */
+    private String key;
+
+    /**
+     * 属性名称
+     */
+    private String name;
+
+    /**
+     * 取值类型:string/float/int
+     */
+    private String type;
+
+    /**
+     * 取值范围列表
+     */
+    private String ranges;
+
+    /**
+     * 控件输入类型
+     */
+    private String widget;
+
+    /**
+     * 默认取值
+     */
+    private String defaults;
+
+    /**
+     * 是否必填:0--非必填;1--必填
+     */
+    private Short required;
+
+    /**
+     * 显示顺序
+     */
+    private Short ordering;
+
+    /**
+     * 数据来源
+     */
+    private String source;
+
+    /**
+     * 取值单位
+     */
+    private String unit;
+
+    /**
+     * 是否可编辑:0--不可编辑;1--可编辑
+     */
+    private Short editable;
+
+    /**
+     * 浮点数精度位数
+     */
+    private Short precisions;
+
+    /**
+     * 状态:0--禁用(隐藏);1--启用(正常)
+     */
+    private Short status;
+
+    /**
+     * 相关描述
+     */
+    private String remark;
+
+    /**
+     * 创建人
+     */
+    private String creator;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+}

+ 76 - 0
src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyLayerApplyThirdCopy.java

@@ -0,0 +1,76 @@
+package com.shkpr.service.alambizplugin.dto;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 采集元素第三方导入副本表
+ */
+@Data
+public class GisSurveyLayerApplyThirdCopy {
+    /**
+     * 所属任务的唯一ID
+     */
+    private String jobId;
+
+    /**
+     * 元素唯一编码
+     */
+    private String code;
+
+    /**
+     * 元素类型标识符
+     */
+    private String layer;
+
+    /**
+     * 元素分类:point--点;line--线;face--面
+     */
+    private String kind;
+
+    /**
+     * 坐标值
+     */
+    private String gis;
+
+    /**
+     * 固定操作标记为:add
+     */
+    private String apply;
+
+    /**
+     * 固定数据来源为:255
+     */
+    private Short source;
+
+    /**
+     * 线的起点唯一编码
+     */
+    private String upNode;
+
+    /**
+     * 线的终点唯一编码
+     */
+    private String downNode;
+
+    /**
+     * 点的高程
+     */
+    private Double elevation;
+
+    /**
+     * 点的埋深
+     */
+    private Double depth;
+
+    /**
+     * 点的序号
+     */
+    private String no;
+
+    /**
+     * 属性值
+     */
+    private List<GisSurveyPropertyValueThirdCopy> propertyValueList;
+}

+ 51 - 0
src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyPropertyValue.java

@@ -0,0 +1,51 @@
+package com.shkpr.service.alambizplugin.dto;
+
+import lombok.Data;
+
+/**
+ * 采集元素属性取值表
+ */
+@Data
+public class GisSurveyPropertyValue {
+    /**
+    * 所属任务的唯一ID
+    */
+    private String jobId;
+
+    /**
+    * 所属元素的唯一编码
+    */
+    private String code;
+
+    /**
+    * 属性唯一标识符
+    */
+    private String property;
+
+    private Long id;
+
+    /**
+    * 取值
+    */
+    private String value;
+
+    /**
+    * 审核结果:-1--待审核;0--未通过;1--已通过
+    */
+    private Short pass;
+
+    /**
+    * 最近审核备注说明
+    */
+    private String checkNote;
+
+    /**
+    * 最近审核修改数据:{"before":"xxx","after":"yyy"}
+    */
+    private String checkData;
+
+    /**
+    * 最近审核修改标记:0--未修改;1--已修改
+    */
+    private Short checkEdit;
+}

+ 37 - 0
src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyPropertyValueThirdCopy.java

@@ -0,0 +1,37 @@
+package com.shkpr.service.alambizplugin.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+/**
+ * 采集元素属性第三方导入副本表
+ */
+@Getter
+@Setter
+@ToString
+@AllArgsConstructor
+@NoArgsConstructor
+public class GisSurveyPropertyValueThirdCopy {
+    /**
+     * 所属任务的唯一ID
+     */
+    private String jobId;
+
+    /**
+     * 所属元素的唯一编码
+     */
+    private String code;
+
+    /**
+     * 属性唯一标识符
+     */
+    private String property;
+
+    /**
+     * 取值
+     */
+    private String value;
+}

+ 1 - 1
src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveySystemCheckResult.java

@@ -18,7 +18,7 @@ import java.time.LocalDateTime;
 @Data
 public class GisSurveySystemCheckResult {
     /**
-     * 检查状态:0:进行中,1:成功,2:失败,3:不存在,4:中断
+     * 检查状态:0:进行中,1:成功,2:失败,3:不存在
      */
     private Integer checkStatus;
     /**

+ 82 - 0
src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyThirdImportElement.java

@@ -0,0 +1,82 @@
+package com.shkpr.service.alambizplugin.dto;
+
+import com.shkpr.service.alambizplugin.constants.GisMetadataDefine;
+import com.shkpr.service.alambizplugin.constants.GisSurveyImportDefine;
+import lombok.Data;
+
+import java.util.Map;
+
+/**
+ * 第三方导入元素dto
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Data
+public class GisSurveyThirdImportElement {
+    /**
+     * 点号
+     */
+    private String no;
+    /**
+     * 上游点号
+     */
+    private String upNO;
+    /**
+     * 下游点号
+     */
+    private String downNO;
+    /**
+     * 元素分类:point--点;line--线;face--面
+     */
+    private String kind;
+    /**
+     * 图层名称
+     */
+    private String layerName;
+    /**
+     * 属性名称
+     */
+    private String propertyName;
+
+    public GisSurveyThirdImportElement(String kind, String no) {
+        this.kind = kind;
+        this.no = no;
+    }
+
+    public GisSurveyThirdImportElement(String kind, String no, String layerName, String propertyName) {
+        this.kind = kind;
+        this.no = no;
+        this.layerName = layerName;
+        this.propertyName = propertyName;
+    }
+
+    public GisSurveyThirdImportElement(String kind, String upNO, String downNO, String layerName, String propertyName) {
+        this.kind = kind;
+        this.upNO = upNO;
+        this.downNO = downNO;
+        this.layerName = layerName;
+        this.propertyName = propertyName;
+    }
+
+    public static GisSurveyThirdImportElement create(Map<String, String> data, GisSurveyImportDefine.LayerType layerType) {
+        return create(data, null, layerType);
+    }
+
+    public static GisSurveyThirdImportElement create(Map<String, String> data, String propertyName
+            , GisSurveyImportDefine.LayerType layerType) {
+        //点号
+        String no = data.get(GisSurveyImportDefine.POINT.NO);
+        String upNo = data.get(GisSurveyImportDefine.LINE.UP_NO);
+        String Down = data.get(GisSurveyImportDefine.LINE.DOWN_NO);
+        //根据类型创建
+        if (layerType == GisSurveyImportDefine.LayerType.POINT) {
+            return new GisSurveyThirdImportElement(GisMetadataDefine.TYPE_KINE.POINT, no
+                    , data.get(GisSurveyImportDefine.POINT.LAYER), propertyName);
+        } else if (layerType == GisSurveyImportDefine.LayerType.LINE) {
+            return new GisSurveyThirdImportElement(GisMetadataDefine.TYPE_KINE.LINE, upNo, Down
+                    , data.get(GisSurveyImportDefine.LINE.LAYER), propertyName);
+        }
+        return null;
+    }
+}

+ 129 - 0
src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyThirdImportResult.java

@@ -0,0 +1,129 @@
+package com.shkpr.service.alambizplugin.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.shkpr.service.alambizplugin.apiparam.GisSurveyThirdImportParams;
+import com.shkpr.service.alambizplugin.constants.GisSurveyImportStatusEnum;
+import lombok.Data;
+import org.springframework.beans.BeanUtils;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * 第三方导入返回dto
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Data
+public class GisSurveyThirdImportResult {
+    /**
+     * 导入状态:0:进行中,1:成功,2:失败,3:不存在
+     */
+    private Integer importStatus;
+
+    /**
+     * 任务id
+     */
+    private String jobId;
+    /**
+     * 当前操作人id
+     */
+    private String operator;
+    /**
+     * 请求导入时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh_CN", timezone = "Asia/Shanghai")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime requestTime;
+    /**
+     * 完成导入时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh_CN", timezone = "Asia/Shanghai")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime completeTime;
+
+    /**
+     * 无效图层结果
+     */
+    private GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>> invalidLayersResult = new GisSurveyThirdImportResultDetail<>();
+
+    /**
+     * 缺失必填结果
+     */
+    private GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>> missingRequirementsResult = new GisSurveyThirdImportResultDetail<>();
+
+    /**
+     * 无效类型结果
+     */
+    private GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>> invalidTypesResult = new GisSurveyThirdImportResultDetail<>();
+
+    /**
+     * 超出范围结果
+     */
+    private GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>> outRangesResult = new GisSurveyThirdImportResultDetail<>();
+
+    /**
+     * 重复点号结果
+     */
+    private GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>> duplicatePointsResult = new GisSurveyThirdImportResultDetail<>();
+
+    /**
+     * 无效线结果
+     */
+    private GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>> invalidLinesResult = new GisSurveyThirdImportResultDetail<>();
+
+    /**
+     * 预览数据
+     */
+    private List<GisSurveyLayerApplyThirdCopy> previewData;
+
+    /**
+     * 进行中
+     */
+    public static GisSurveyThirdImportResult inProgress(GisSurveyThirdImportParams params, GisSurveyThirdImportSubtask subtask, LocalDateTime requestTime) {
+        GisSurveyThirdImportResult result = new GisSurveyThirdImportResult();
+        BeanUtils.copyProperties(params, result);
+
+        //设置子任务状态
+        if (subtask != null) {
+            if (subtask.getInvalidPropertiesFuture() != null) {
+                result.getInvalidLayersResult().setDone(subtask.getInvalidPropertiesFuture().isDone());
+                result.getMissingRequirementsResult().setDone(subtask.getInvalidPropertiesFuture().isDone());
+                result.getInvalidTypesResult().setDone(subtask.getInvalidPropertiesFuture().isDone());
+                result.getOutRangesResult().setDone(subtask.getInvalidPropertiesFuture().isDone());
+            }
+            if (subtask.getDuplicatePointsFuture() != null)
+                result.getDuplicatePointsResult().setDone(subtask.getDuplicatePointsFuture().isDone());
+            if (subtask.getInvalidLinesFuture() != null)
+                result.getInvalidLinesResult().setDone(subtask.getInvalidLinesFuture().isDone());
+        }
+
+        result.setImportStatus(GisSurveyImportStatusEnum.IN_PROGRESS.getCode());
+        result.setRequestTime(requestTime);
+        return result;
+    }
+
+    /**
+     * 成功
+     */
+    public static GisSurveyThirdImportResult success(GisSurveyThirdImportParams params) {
+        GisSurveyThirdImportResult result = new GisSurveyThirdImportResult();
+        BeanUtils.copyProperties(params, result);
+        result.setImportStatus(GisSurveyImportStatusEnum.SUCCESS.getCode());
+        result.setRequestTime(LocalDateTime.now());
+        return result;
+    }
+
+    /**
+     * 失败
+     */
+    public static GisSurveyThirdImportResult fail(GisSurveyThirdImportParams params) {
+        GisSurveyThirdImportResult result = new GisSurveyThirdImportResult();
+        BeanUtils.copyProperties(params, result);
+        result.setImportStatus(GisSurveyImportStatusEnum.FAIL.getCode());
+        result.setRequestTime(LocalDateTime.now());
+        return result;
+    }
+}

+ 27 - 0
src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyThirdImportResultDetail.java

@@ -0,0 +1,27 @@
+package com.shkpr.service.alambizplugin.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * 第三方导入结果详情
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class GisSurveyThirdImportResultDetail<T> {
+    /**
+     * 完成状态
+     */
+    private Boolean done;
+    /**
+     * 结果
+     */
+    private T results;
+}

+ 30 - 0
src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyThirdImportSubtask.java

@@ -0,0 +1,30 @@
+package com.shkpr.service.alambizplugin.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.util.concurrent.ListenableFuture;
+
+/**
+ * 第三方导入子任务
+ *
+ * @author 欧阳劲驰
+ * @since 0.0.1
+ */
+@Getter
+@Setter
+@AllArgsConstructor
+public class GisSurveyThirdImportSubtask {
+    /**
+     * 无效属性任务
+     */
+    private ListenableFuture<? extends GisSurveyThirdImportResultDetail<?>> invalidPropertiesFuture;
+    /**
+     * 重复点号任务
+     */
+    private ListenableFuture<? extends GisSurveyThirdImportResultDetail<?>> duplicatePointsFuture;
+    /**
+     * 无效线任务
+     */
+    private ListenableFuture<? extends GisSurveyThirdImportResultDetail<?>> invalidLinesFuture;
+}

+ 23 - 6
src/main/java/com/shkpr/service/alambizplugin/globalmgr/ScheduleTaskMgr.java

@@ -3,8 +3,10 @@ package com.shkpr.service.alambizplugin.globalmgr;
 import com.global.base.log.LogLevelFlag;
 import com.global.base.log.LogPrintMgr;
 import com.global.base.thread.ThreadPoolProxy;
-import com.shkpr.service.alambizplugin.bizservice.GisSurveyBizService;
+import com.shkpr.service.alambizplugin.bizservice.GisSurveySystemCheckBizService;
+import com.shkpr.service.alambizplugin.bizservice.GisSurveyThirdImportBizService;
 import com.shkpr.service.alambizplugin.commproperties.GisSurveySystemCheckProperties;
+import com.shkpr.service.alambizplugin.commproperties.GisSurveyThirdImportProperties;
 import com.shkpr.service.alambizplugin.commtools.TimeTool;
 import com.shkpr.service.alambizplugin.components.GisDynamicDataSource;
 import com.shkpr.service.alambizplugin.components.locks.AlarmOrderLockMgr;
@@ -22,17 +24,22 @@ import java.util.Map;
 import java.util.Set;
 
 @Component
-@EnableConfigurationProperties(GisSurveySystemCheckProperties.class)
+@EnableConfigurationProperties({GisSurveySystemCheckProperties.class,GisSurveyThirdImportProperties.class})
 public class ScheduleTaskMgr {
     private final String mStrClassName;
     private final GisSurveySystemCheckProperties systemCheckProperties;
-    private final GisSurveyBizService gisSurveyBizService;
+    private final GisSurveyThirdImportProperties thirdImportProperties;
+    private final GisSurveySystemCheckBizService systemCheckBizService;
+    private final GisSurveyThirdImportBizService thirdImportBizService;
 
 
-    public ScheduleTaskMgr(GisSurveySystemCheckProperties systemCheckProperties, GisSurveyBizService gisSurveyBizService) {
+    public ScheduleTaskMgr(GisSurveySystemCheckProperties systemCheckProperties,GisSurveyThirdImportProperties thirdImportProperties
+            , GisSurveySystemCheckBizService systemCheckBizService,GisSurveyThirdImportBizService thirdImportBizService) {
         mStrClassName = this.getClass().getSimpleName();
         this.systemCheckProperties = systemCheckProperties;
-        this.gisSurveyBizService = gisSurveyBizService;
+        this.thirdImportProperties = thirdImportProperties;
+        this.systemCheckBizService = systemCheckBizService;
+        this.thirdImportBizService = thirdImportBizService;
     }
 
     @PostConstruct
@@ -52,7 +59,17 @@ public class ScheduleTaskMgr {
     public void sysCheckTasksTtl() {
         LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue(), mStrClassName
                 , String.format("开始执行系统检查超时任务 ttl:%s ======>", systemCheckProperties.getTtl()));
-        if (systemCheckProperties.getTtl() != null) gisSurveyBizService.expireResult(systemCheckProperties.getTtl());
+        if (systemCheckProperties.getTtl() != null) systemCheckBizService.expireResult(systemCheckProperties.getTtl());
+    }
+
+    /**
+     * 第三方导入超时任务
+     */
+    @Scheduled(fixedRateString = "${third-import.ttl-check-interval}")
+    public void thirdImportTasksTtl() {
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue(), mStrClassName
+                , String.format("开始执行第三方导入超时任务 ttl:%s ======>", thirdImportProperties.getTtl()));
+        if (thirdImportProperties.getTtl() != null) thirdImportBizService.expireResult(thirdImportProperties.getTtl());
     }
 
     @Scheduled(cron = "${cron.refresh.timer.clock}")

+ 9 - 5
src/main/resources/application.properties

@@ -140,14 +140,18 @@ des.proxy.fdfs=http://116.63.130.83:9999
 
 #=============系统检查========================
 #超时时间
-system-check.ttl= 24h
+system-check.ttl=24h
 #检查周期(毫秒)
-system-check.ttl-check-interval= 60000
+system-check.ttl-check-interval=60000
 #资源路径
-system-check.resource-path= /home/kprCloud/alam_dma_kpr_plugin/sys-check-results/
+system-check.resource-path=/home/kprCloud/alam_dma_kpr_plugin/sys-check-results/
 #结果滞后时间
-system-check.result-lag-duration= 30m
-
+system-check.result-lag-duration=30m
+#=============第三方导入========================
+#超时时间
+third-import.ttl=24h
+#检查周期(毫秒)
+third-import.ttl-check-interval=60000
 
 
 

+ 93 - 0
src/main/resources/mapper/GisMetadataLayerTemplateMapper.xml

@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.shkpr.service.alambizplugin.dbdao.mapper.GisMetadataLayerTemplateMapper">
+    <resultMap id="BaseResultMap" type="com.shkpr.service.alambizplugin.dto.GisMetadataLayerTemplate">
+        <!--@Table k3_gis_metadata_layer_template-->
+        <id column="nature" jdbcType="VARCHAR" property="nature"/>
+        <id column="key" jdbcType="VARCHAR" property="key"/>
+        <result column="id" jdbcType="BIGINT" property="id"/>
+        <result column="kind" jdbcType="VARCHAR" property="kind"/>
+        <result column="name" jdbcType="VARCHAR" property="name"/>
+        <result column="icon" jdbcType="VARCHAR" property="icon"/>
+        <result column="color" jdbcType="VARCHAR" property="color"/>
+        <result column="status" jdbcType="SMALLINT" property="status"/>
+        <result column="remark" jdbcType="VARCHAR" property="remark"/>
+        <result column="creator" jdbcType="VARCHAR" property="creator"/>
+        <result column="param1" jdbcType="VARCHAR" property="param1"/>
+        <result column="param2" jdbcType="VARCHAR" property="param2"/>
+        <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
+        <result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
+        <result column="ordering" jdbcType="SMALLINT" property="ordering"/>
+        <collection property="propertyTemplates"
+                    ofType="com.shkpr.service.alambizplugin.dto.GisMetadataPropertyTemplate">
+            <id column="property_nature" jdbcType="VARCHAR" property="nature"/>
+            <id column="property_layer" jdbcType="VARCHAR" property="layer"/>
+            <id column="property_key" jdbcType="VARCHAR" property="key"/>
+            <result column="property_id" jdbcType="BIGINT" property="id"/>
+            <result column="property_name" jdbcType="VARCHAR" property="name"/>
+            <result column="property_type" jdbcType="VARCHAR" property="type"/>
+            <result column="property_ranges" jdbcType="VARCHAR" property="ranges"/>
+            <result column="property_widget" jdbcType="VARCHAR" property="widget"/>
+            <result column="property_defaults" jdbcType="VARCHAR" property="defaults"/>
+            <result column="property_required" jdbcType="SMALLINT" property="required"/>
+            <result column="property_ordering" jdbcType="SMALLINT" property="ordering"/>
+            <result column="property_source" jdbcType="VARCHAR" property="source"/>
+            <result column="property_unit" jdbcType="VARCHAR" property="unit"/>
+            <result column="property_editable" jdbcType="SMALLINT" property="editable"/>
+            <result column="property_precisions" jdbcType="SMALLINT" property="precisions"/>
+            <result column="property_status" jdbcType="SMALLINT" property="status"/>
+            <result column="property_remark" jdbcType="VARCHAR" property="remark"/>
+            <result column="property_creator" jdbcType="VARCHAR" property="creator"/>
+            <result column="property_create_time" jdbcType="TIMESTAMP" property="createTime"/>
+            <result column="property_update_time" jdbcType="TIMESTAMP" property="updateTime"/>
+        </collection>
+    </resultMap>
+
+    <select id="findByNatureAndNameIn" resultMap="BaseResultMap">
+        select mlt.id,
+        mlt.nature,
+        mlt.kind,
+        mlt.key,
+        mlt.name,
+        mlt.icon,
+        mlt.color,
+        mlt.status,
+        mlt.remark,
+        mlt.creator,
+        mlt.param1,
+        mlt.param2,
+        mlt.create_time,
+        mlt.update_time,
+        mlt.ordering,
+        mpt.id as property_id,
+        mpt.nature as property_nature,
+        mpt.layer as property_layer,
+        mpt.key as property_key,
+        mpt.name as property_name,
+        mpt.type as property_type,
+        mpt.ranges as property_ranges,
+        mpt.widget as property_widget,
+        mpt.defaults as property_defaults,
+        mpt.required as property_required,
+        mpt.ordering as property_ordering,
+        mpt.source as property_source,
+        mpt.unit as property_unit,
+        mpt.editable as property_editable,
+        mpt.precisions as property_precisions,
+        mpt.status as property_status,
+        mpt.remark as property_remark,
+        mpt.creator as property_creator,
+        mpt.create_time as property_create_time,
+        mpt.update_time as property_update_time
+        from k3_gis_metadata_layer_template mlt
+        left join k3_gis_metadata_property_template mpt
+        on mlt.nature = mpt.nature and mlt.key = mpt.layer and mpt.status = 1
+        where mlt.nature = #{nature,jdbcType=VARCHAR}
+        and mlt.status = 1
+        and mlt.name in
+        <foreach item="item" index="index" collection="names"
+                 open="(" separator="," close=")">
+            #{item,jdbcType=VARCHAR}
+        </foreach>
+    </select>
+</mapper>

+ 5 - 0
src/main/resources/mapper/GisMetadataPropertyTemplateMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.shkpr.service.alambizplugin.dbdao.mapper.GisMetadataPropertyTemplateMapper">
+
+</mapper>

+ 6 - 0
src/main/resources/mapper/GisSurveyJobInfoMapper.xml

@@ -6,4 +6,10 @@
         from k3_gis_survey_job_info
         where uid = #{uid,jdbcType=VARCHAR};
     </select>
+
+    <update id="updateRefreshTimeByUid">
+        update k3_gis_survey_job_info
+        set refresh_time = #{timestamp,jdbcType=BIGINT}
+        where uid = #{uid,jdbcType=VARCHAR};
+    </update>
 </mapper>

+ 10 - 0
src/main/resources/mapper/GisSurveyLayerApplyMapper.xml

@@ -75,4 +75,14 @@
         where jo.uid = #{jobId,jdbcType=VARCHAR}
         and la.kind = 'line';
     </select>
+
+    <insert id="mergeCopyByJobId">
+        insert into k3_gis_survey_layer_apply(code, job_id, layer, kind, gis, apply, source, up_node,
+        down_node,elevation,depth,no)
+        select code, job_id, layer, kind, gis, apply, source, up_node,
+        down_node,elevation,depth,no
+        from k3_gis_survey_layer_apply_third_copy
+        where job_id = #{jobId,jdbcType=VARCHAR}
+        order by job_id, code
+    </insert>
 </mapper>

+ 111 - 0
src/main/resources/mapper/GisSurveyLayerApplyThirdCopyMapper.xml

@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.shkpr.service.alambizplugin.dbdao.mapper.GisSurveyLayerApplyThirdCopyMapper">
+    <resultMap id="BaseResultMap" type="com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyThirdCopy">
+        <!--@Table k3_gis_survey_layer_apply_third_copy-->
+        <id column="job_id" jdbcType="VARCHAR" property="jobId"/>
+        <id column="code" jdbcType="VARCHAR" property="code"/>
+        <result column="layer" jdbcType="VARCHAR" property="layer"/>
+        <result column="kind" jdbcType="VARCHAR" property="kind"/>
+        <result column="gis" jdbcType="VARCHAR" property="gis"/>
+        <result column="apply" jdbcType="VARCHAR" property="apply"/>
+        <result column="source" jdbcType="SMALLINT" property="source"/>
+        <result column="up_node" jdbcType="VARCHAR" property="upNode"/>
+        <result column="down_node" jdbcType="VARCHAR" property="downNode"/>
+        <result column="elevation" jdbcType="DOUBLE" property="elevation"/>
+        <result column="depth" jdbcType="DOUBLE" property="depth"/>
+        <result column="no" jdbcType="VARCHAR" property="no"/>
+    </resultMap>
+
+    <insert id="save">
+        INSERT INTO k3_gis_survey_layer_apply_third_copy
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="jobId != null">
+                job_id,
+            </if>
+            <if test="code != null">
+                code,
+            </if>
+            <if test="layer != null">
+                layer,
+            </if>
+            <if test="kind != null">
+                kind,
+            </if>
+            <if test="gis != null">
+                gis,
+            </if>
+            <if test="apply != null">
+                apply,
+            </if>
+            <if test="source != null">
+                "source",
+            </if>
+            <if test="upNode != null">
+                up_node,
+            </if>
+            <if test="downNode != null">
+                down_node,
+            </if>
+            <if test="elevation != null">
+                elevation,
+            </if>
+            <if test="depth != null">
+                "depth",
+            </if>
+            <if test="no != null">
+                "no"
+            </if>
+        </trim>
+        VALUES
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="jobId != null">
+                #{jobId,jdbcType=VARCHAR},
+            </if>
+            <if test="code != null">
+                #{code,jdbcType=VARCHAR},
+            </if>
+            <if test="layer != null">
+                #{layer,jdbcType=VARCHAR},
+            </if>
+            <if test="kind != null">
+                #{kind,jdbcType=VARCHAR},
+            </if>
+            <if test="gis != null">
+                #{gis,jdbcType=VARCHAR},
+            </if>
+            <if test="apply != null">
+                #{apply,jdbcType=VARCHAR},
+            </if>
+            <if test="source != null">
+                #{source,jdbcType=SMALLINT},
+            </if>
+            <if test="upNode != null">
+                #{upNode,jdbcType=VARCHAR},
+            </if>
+            <if test="downNode != null">
+                #{downNode,jdbcType=VARCHAR},
+            </if>
+            <if test="elevation != null">
+                #{elevation,jdbcType=DOUBLE},
+            </if>
+            <if test="depth != null">
+                #{depth,jdbcType=DOUBLE},
+            </if>
+            <if test="no != null">
+                #{no,jdbcType=VARCHAR}
+            </if>
+        </trim>
+    </insert>
+
+    <delete id="deleteByJobId">
+        delete from k3_gis_survey_layer_apply_third_copy
+        where job_id=#{jobId,jdbcType=VARCHAR}
+    </delete>
+
+    <select id="countByJobId" resultType="java.lang.Integer">
+        select count(1)
+        from k3_gis_survey_layer_apply_third_copy
+        where job_id=#{jobId,jdbcType=VARCHAR}
+    </select>
+</mapper>

+ 12 - 5
src/main/resources/mapper/GisSurveyProjectInfoMapper.xml

@@ -1,9 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.shkpr.service.alambizplugin.dbdao.mapper.GisSurveyProjectInfoMapper">
-  <select id="findRefreshTimeByUid" resultType="java.time.LocalDateTime">
-    select to_timestamp(refresh_time / 1000.0) AT TIME ZONE 'PRC'
-    from k3_gis_survey_project_info
-    where uid = #{uid,jdbcType=VARCHAR};
-  </select>
+    <select id="findRefreshTimeByUid" resultType="java.time.LocalDateTime">
+        select to_timestamp(refresh_time / 1000.0) AT TIME ZONE 'PRC'
+        from k3_gis_survey_project_info
+        where uid = #{uid,jdbcType=VARCHAR};
+    </select>
+
+    <update id="updateRefreshTimeByUid">
+        update k3_gis_survey_project_info pi
+        set refresh_time =#{timestamp,jdbcType=BIGINT}
+        where exists (select 1 from k3_gis_survey_job_info ji where ji.uid=#{jobId,jdbcType=VARCHAR} )
+        and pi.uid = (select proj_id from k3_gis_survey_job_info ji where ji.uid=#{jobId,jdbcType=VARCHAR} limit 1)
+    </update>
 </mapper>

+ 11 - 0
src/main/resources/mapper/GisSurveyPropertyValueMapper.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.shkpr.service.alambizplugin.dbdao.mapper.GisSurveyPropertyValueMapper">
+    <insert id="mergeCopyByJobId">
+        insert into k3_gis_survey_property_value (property, code, job_id, value)
+        select property, code, job_id, value
+        from k3_gis_survey_property_value_third_copy
+        where job_id = #{jobId,jdbcType=VARCHAR}
+        order by job_id, code, property;
+    </insert>
+</mapper>

+ 49 - 0
src/main/resources/mapper/GisSurveyPropertyValueThirdCopyMapper.xml

@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.shkpr.service.alambizplugin.dbdao.mapper.GisSurveyPropertyValueThirdCopyMapper">
+    <resultMap id="BaseResultMap" type="com.shkpr.service.alambizplugin.dto.GisSurveyPropertyValueThirdCopy">
+        <!--@Table k3_gis_survey_property_value_third_copy-->
+        <id column="job_id" jdbcType="VARCHAR" property="jobId"/>
+        <id column="code" jdbcType="VARCHAR" property="code"/>
+        <id column="property" jdbcType="VARCHAR" property="property"/>
+        <result column="value" jdbcType="VARCHAR" property="value"/>
+    </resultMap>
+
+    <insert id="save">
+        INSERT INTO k3_gis_survey_property_value_third_copy
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="jobId != null">
+                job_id,
+            </if>
+            <if test="code != null">
+                code,
+            </if>
+            <if test="property != null">
+                property,
+            </if>
+            <if test="value != null">
+                "value"
+            </if>
+        </trim>
+        VALUES
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="jobId != null">
+                #{jobId,jdbcType=VARCHAR},
+            </if>
+            <if test="code != null">
+                #{code,jdbcType=VARCHAR},
+            </if>
+            <if test="property != null">
+                #{property,jdbcType=VARCHAR},
+            </if>
+            <if test="value != null">
+                #{value,jdbcType=VARCHAR}
+            </if>
+        </trim>
+    </insert>
+
+    <delete id="deleteByJobId">
+        delete from k3_gis_survey_property_value_third_copy
+        where job_id=#{jobId,jdbcType=VARCHAR}
+    </delete>
+</mapper>