20 Commits 810188b923 ... 2d9ebf8f98

Auteur SHA1 Bericht Datum
  aozzl 2d9ebf8f98 修改无效线提示 3 weken geleden
  aozzl 585bfea0da 无效线增肌并行流处理 3 weken geleden
  aozzl 7a35409544 修改excel解析,兼容公式类型 4 weken geleden
  欧阳劲驰 43011de082 线对象改为多线对象,第三方导入加入gis写入处理 1 maand geleden
  欧阳劲驰 d3df6ce151 修改第三方导入,图层无效时不检查坐标,无效图层去重 1 maand geleden
  欧阳劲驰 2bbd1fd787 无效线检查加入线gis包含点gis判断 1 maand geleden
  欧阳劲驰 ff61202486 孤立线检查加入线gis包含点gis判断 1 maand geleden
  欧阳劲驰 c6bb8c0d00 系统检查增加修改的元素 1 maand geleden
  欧阳劲驰 c9b6bcca1f 修改原因描述 1 maand geleden
  欧阳劲驰 bc1c04de33 第三方导入excel结果增加原因 1 maand geleden
  欧阳劲驰 ddcebc15e1 第三方导入excel结果增加原因 1 maand geleden
  欧阳劲驰 757a0d800c 第三方导入excel结果增加约束范围 1 maand geleden
  欧阳劲驰 333292ac45 修改第三方导入key 1 maand geleden
  欧阳劲驰 d692e65ca8 第三方导入增加excel结果 1 maand geleden
  欧阳劲驰 e9d9b7db64 增加第三方导入提交查询接口 1 maand geleden
  欧阳劲驰 2e952adb5b 修复属性表导出失败的问题 1 maand geleden
  欧阳劲驰 0f870507fe 优化导出内存,避免内存耗尽GC失能 1 maand geleden
  欧阳劲驰 d9073cf160 优化导出内存,避免内存耗尽GC失能 1 maand geleden
  欧阳劲驰 371763d518 提交导入改为异步处理,文件上传大小改为200MB 1 maand geleden
  欧阳劲驰 a837bc726c shapefile导出按图层名称分组 1 maand geleden
40 gewijzigde bestanden met toevoegingen van 1668 en 733 verwijderingen
  1. 1 1
      pom.xml
  2. 1 6
      src/main/java/com/shkpr/service/alambizplugin/apiparam/GisSurveyThirdImportParams.java
  3. 195 48
      src/main/java/com/shkpr/service/alambizplugin/bizservice/GisSurveyThirdImportBizService.java
  4. 5 0
      src/main/java/com/shkpr/service/alambizplugin/commproperties/AsyncTaskProperties.java
  5. 16 10
      src/main/java/com/shkpr/service/alambizplugin/commtools/ExcelUtils.java
  6. 182 0
      src/main/java/com/shkpr/service/alambizplugin/commtools/GeomUtil.java
  7. 76 8
      src/main/java/com/shkpr/service/alambizplugin/commtools/ShapeUtils.java
  8. 8 0
      src/main/java/com/shkpr/service/alambizplugin/components/AsyncResultManager.java
  9. 10 2
      src/main/java/com/shkpr/service/alambizplugin/components/GisSurveySystemChecker.java
  10. 42 11
      src/main/java/com/shkpr/service/alambizplugin/components/GisSurveyThirdExporter.java
  11. 150 72
      src/main/java/com/shkpr/service/alambizplugin/components/GisSurveyThirdImporter.java
  12. 2 2
      src/main/java/com/shkpr/service/alambizplugin/components/checker/CrossLinesFinder.java
  13. 64 10
      src/main/java/com/shkpr/service/alambizplugin/components/checker/DuplicatePointsFinder.java
  14. 104 48
      src/main/java/com/shkpr/service/alambizplugin/components/checker/InvalidLinesFinder.java
  15. 154 32
      src/main/java/com/shkpr/service/alambizplugin/components/checker/InvalidPropertiesFinder.java
  16. 39 19
      src/main/java/com/shkpr/service/alambizplugin/components/checker/IsolatedPointsFinder.java
  17. 10 10
      src/main/java/com/shkpr/service/alambizplugin/components/checker/OverlapLinesFinder.java
  18. 1 0
      src/main/java/com/shkpr/service/alambizplugin/constants/ApiURI.java
  19. 5 1
      src/main/java/com/shkpr/service/alambizplugin/constants/CommAsyncStatusEnum.java
  20. 42 7
      src/main/java/com/shkpr/service/alambizplugin/constants/GisSurveyExcelDefine.java
  21. 0 39
      src/main/java/com/shkpr/service/alambizplugin/constants/GisSurveyImportStatusEnum.java
  22. 42 0
      src/main/java/com/shkpr/service/alambizplugin/constants/GisSurveyThirdImportKeys.java
  23. 134 0
      src/main/java/com/shkpr/service/alambizplugin/constants/GisSurveyThirdImportResultHead.java
  24. 122 28
      src/main/java/com/shkpr/service/alambizplugin/controller/ApiGisSurveyController.java
  25. 1 0
      src/main/java/com/shkpr/service/alambizplugin/controllerfilter/third/ApiJWTGisSurveyBizFilter.java
  26. 8 8
      src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisSurveyLayerApplyMapper.java
  27. 0 107
      src/main/java/com/shkpr/service/alambizplugin/dbdao/pgtype/GeomLineStringTypeHandlePg.java
  28. 109 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/pgtype/GeomMultiLineStringTypeHandlePg.java
  29. 40 20
      src/main/java/com/shkpr/service/alambizplugin/dbdao/pgtype/GeomPointTypeHandlePg.java
  30. 54 54
      src/main/java/com/shkpr/service/alambizplugin/dbdao/pgtype/GeomTypeHandlePg.java
  31. 4 4
      src/main/java/com/shkpr/service/alambizplugin/dbdao/services/GisSurveyLayerApplyServiceImpl.java
  32. 2 3
      src/main/java/com/shkpr/service/alambizplugin/dto/CommAsyncResult.java
  33. 2 2
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyLayerApplyLine.java
  34. 17 7
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyThirdImportElement.java
  35. 0 131
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyThirdImportResult.java
  36. 8 0
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyThirdImportResultDetail.java
  37. 0 30
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyThirdImportSubtask.java
  38. 4 0
      src/main/resources/application.properties
  39. 12 12
      src/main/resources/mapper/GisSurveyLayerApplyMapper.xml
  40. 2 1
      src/main/resources/mapper/GisSurveyLayerApplyThirdCopyMapper.xml

+ 1 - 1
pom.xml

@@ -23,7 +23,7 @@
         <fasterxml.version>2.9.5</fasterxml.version><!-- 2.8.11.2 -->
         <fastercore.version>2.9.5</fastercore.version>
         <fasterannot.version>2.9.5</fasterannot.version>
-        <geotools.version>28.6</geotools.version>
+        <geotools.version>28.6.1</geotools.version>
     </properties>
 
     <!--工具包jar版本不一致,解决方案,以下配置促使本应用工程中的相应jar强制使用规定版本-->

+ 1 - 6
src/main/java/com/shkpr/service/alambizplugin/apiparam/GisSurveyThirdImportParams.java

@@ -47,13 +47,8 @@ public class GisSurveyThirdImportParams {
      * 是否检查约束
      */
     private Boolean checkConstraint;
-    /**
-     * 忽略失败
-     */
-    private Boolean ignoreFail;
 
-    public GisSurveyThirdImportParams(String jobId, Boolean ignoreFail) {
+    public GisSurveyThirdImportParams(String jobId) {
         this.jobId = jobId;
-        this.ignoreFail = ignoreFail;
     }
 }

+ 195 - 48
src/main/java/com/shkpr/service/alambizplugin/bizservice/GisSurveyThirdImportBizService.java

@@ -5,11 +5,13 @@ import com.global.base.log.LogPrintMgr;
 import com.shkpr.service.alambizplugin.apiparam.GisSurveyThirdImportParams;
 import com.shkpr.service.alambizplugin.commproperties.AsyncTaskProperties;
 import com.shkpr.service.alambizplugin.components.GisSurveyThirdImporter;
-import com.shkpr.service.alambizplugin.constants.GisSurveyImportStatusEnum;
+import com.shkpr.service.alambizplugin.constants.CommAsyncStatusEnum;
+import com.shkpr.service.alambizplugin.constants.GisSurveyThirdImportKeys;
 import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
 import com.shkpr.service.alambizplugin.dto.CommAsyncCache;
-import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportResult;
-import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportSubtask;
+import com.shkpr.service.alambizplugin.dto.CommAsyncResult;
+import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportElement;
+import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportResultDetail;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
 import org.springframework.stereotype.Component;
@@ -21,6 +23,7 @@ import java.io.InputStream;
 import java.time.Instant;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -36,17 +39,32 @@ import java.util.concurrent.ExecutionException;
 @Component
 public class GisSurveyThirdImportBizService {
     /**
-     * 任务缓存
+     * 导入任务缓存
      */
-    private final static Map<String, ListenableFuture<GisSurveyThirdImportResult>> TASK_CACHE = new ConcurrentHashMap<>();
+    private final static Map<String, ListenableFuture<CommAsyncResult<Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>>>>>
+            IMPORT_TASK_CACHE = new ConcurrentHashMap<>();
+    /**
+     * 提交任务缓存
+     */
+    private final static Map<String, ListenableFuture<CommAsyncResult<Boolean>>> COMMIT_TASK_CACHE = new ConcurrentHashMap<>();
     /**
      * 子任务缓存
      */
-    private final static Map<String, GisSurveyThirdImportSubtask> SUBTASK_CACHE = new ConcurrentHashMap<>();
+    private final static Map<String, Map<String, ListenableFuture<?>>> SUBTASK_CACHE = new ConcurrentHashMap<>();
     /**
      * 开始时间缓存
      */
     private final static Map<String, CommAsyncCache> INFO_CACHE = new ConcurrentHashMap<>();
+
+    /**
+     * 导入前缀
+     */
+    private final static String IMPORT_PREFIX = "import-";
+    /**
+     * 提交前缀
+     */
+    private final static String COMMIT_PREFIX = "commit-";
+
     /**
      * log
      */
@@ -74,9 +92,11 @@ public class GisSurveyThirdImportBizService {
      * @param params 第三方导入参数
      * @return 导入状态
      */
-    public GisSurveyThirdImportResult thirdImport(GisSurveyThirdImportParams params) {
+    public CommAsyncResult<Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>>> thirdImport(
+            GisSurveyThirdImportParams params) {
         //获取结果
-        GisSurveyThirdImportResult result = getResult(params);
+        CommAsyncResult<Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>>>
+                result = getImportResult(params);
         if (result != null) return result;
 
         //获取文件流
@@ -85,63 +105,154 @@ public class GisSurveyThirdImportBizService {
             try {
                 inputStreams.add(file.getInputStream());
             } catch (IOException e) {
-                return GisSurveyThirdImportResult.fail(params);
+                return CommAsyncResult.fail(params.getJobId());
             }
         }
         //启动检查任务
-        startTask(params, inputStreams);
+        startImport(params, inputStreams);
         //返回进行中
-        return GisSurveyThirdImportResult.inProgress(params, SUBTASK_CACHE.get(params.getJobId()),
+        return CommAsyncResult.inProgress(params.getJobId(),
                 LocalDateTime.now(),
                 params.getOperator()
         );
     }
 
     /**
-     * 获取结果
+     * 提交导入
+     *
+     * @param jobId    任务id
+     * @param operator 操作人
+     * @return 提交状态
+     */
+    public CommAsyncResult<Boolean> commitImport(String jobId, String operator) {
+        //获取结果
+        CommAsyncResult<Boolean> result = getCommitResult(jobId);
+        if (result != null) return result;
+
+        //启动提交任务
+        startCommit(jobId, operator);
+        //返回进行中
+        return CommAsyncResult.inProgress(jobId,
+                LocalDateTime.now(),
+                operator
+        );
+    }
+
+
+    /**
+     * 获取导入结果
      *
      * @param params 第三方导入参数
      * @return 导入结果
      */
-    public GisSurveyThirdImportResult getResult(GisSurveyThirdImportParams params) {
+    public CommAsyncResult<Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>>> getImportResult(GisSurveyThirdImportParams params) {
         //获取已存在的任务
-        ListenableFuture<GisSurveyThirdImportResult> previousFuture = TASK_CACHE.get(params.getJobId());
+        ListenableFuture<CommAsyncResult<Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>>>>
+                previousFuture = IMPORT_TASK_CACHE.get(IMPORT_PREFIX + 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());
+                CommAsyncResult<Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>>>
+                        thirdImportResult = previousFuture.get();
+                //如处理成功/失败,返回结果,并清除缓存
+                if (Objects.equals(thirdImportResult.getStatus(), CommAsyncStatusEnum.FAIL.getCode()) ||
+                        Objects.equals(thirdImportResult.getStatus(), CommAsyncStatusEnum.SUCCESS.getCode()) ||
+                        Objects.equals(thirdImportResult.getStatus(), CommAsyncStatusEnum.RESULT_ERROR.getCode())) {
+                    removeCache(IMPORT_PREFIX + 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())
+                        , String.format("检查历史异常 任务id:%s msg:%s", params.getJobId(), e.getMessage())
                 );
-                return GisSurveyThirdImportResult.fail(params);
+                return CommAsyncResult.fail(params.getJobId());
             }
         }
 
         //进行中判断(未完成且未清除)
         if (previousFuture != null && !previousFuture.isDone() && !previousFuture.isCancelled()) {
-            CommAsyncCache asyncCache = INFO_CACHE.get(params.getJobId());
+            CommAsyncCache asyncCache = INFO_CACHE.get(IMPORT_PREFIX + params.getJobId());
+            if (asyncCache != null) {
+                //构建结果
+                CommAsyncResult<Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>>>
+                        result = CommAsyncResult.inProgress(params.getJobId(),
+                        asyncCache.getStartTime(), asyncCache.getOperator());
+                //数据
+                Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>> data = new HashMap<>();
+                //获取子任务
+                Map<String, ListenableFuture<?>> subtask = SUBTASK_CACHE.get(IMPORT_PREFIX + params.getJobId());
+                //无效属性任务
+                ListenableFuture<?> invalidPropertiesFuture = subtask.get(GisSurveyThirdImportKeys.INVALID_PROPERTIES);
+                if (invalidPropertiesFuture != null) {
+                    data.put(GisSurveyThirdImportKeys.INVALID_LAYERS, new GisSurveyThirdImportResultDetail<>(invalidPropertiesFuture.isDone()));
+                    data.put(GisSurveyThirdImportKeys.MISSING_REQUIREMENTS, new GisSurveyThirdImportResultDetail<>(invalidPropertiesFuture.isDone()));
+                    data.put(GisSurveyThirdImportKeys.INVALID_TYPES, new GisSurveyThirdImportResultDetail<>(invalidPropertiesFuture.isDone()));
+                    data.put(GisSurveyThirdImportKeys.OUT_RANGES, new GisSurveyThirdImportResultDetail<>(invalidPropertiesFuture.isDone()));
+                    data.put(GisSurveyThirdImportKeys.OUT_CONSTRAINT, new GisSurveyThirdImportResultDetail<>(invalidPropertiesFuture.isDone()));
+                }
+                //重复点任务
+                ListenableFuture<?> duplicatePointsFuture = subtask.get(GisSurveyThirdImportKeys.DUPLICATE_POINTS);
+                if (duplicatePointsFuture != null)
+                    data.put(GisSurveyThirdImportKeys.DUPLICATE_POINTS, new GisSurveyThirdImportResultDetail<>(duplicatePointsFuture.isDone()));
+                //无效线任务
+                ListenableFuture<?> invalidLinesFuture = subtask.get(GisSurveyThirdImportKeys.INVALID_LINES);
+                if (invalidLinesFuture != null)
+                    data.put(GisSurveyThirdImportKeys.INVALID_LINES, new GisSurveyThirdImportResultDetail<>(invalidLinesFuture.isDone()));
+
+                result.setData(data);
+                return result;
+
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * 获取提交结果
+     *
+     * @param jobId 任务id
+     * @return 提交结果
+     */
+    public CommAsyncResult<Boolean> getCommitResult(String jobId) {
+        //获取已存在的任务
+        ListenableFuture<CommAsyncResult<Boolean>> previousFuture = COMMIT_TASK_CACHE.get(COMMIT_PREFIX + jobId);
+        //判断完成
+        if (previousFuture != null && previousFuture.isDone()) {
+            try {
+                //获取结果
+                CommAsyncResult<Boolean> commitResult = previousFuture.get();
+                //如处理成功/失败,返回结果,并清除缓存
+                if (Objects.equals(commitResult.getStatus(), CommAsyncStatusEnum.FAIL.getCode()) ||
+                        Objects.equals(commitResult.getStatus(), CommAsyncStatusEnum.SUCCESS.getCode())) {
+                    removeCache(COMMIT_PREFIX + jobId);
+                    return commitResult;
+                }
+            } catch (InterruptedException | ExecutionException e) {
+                //打印报错信息
+                LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
+                        , String.format("检查历史异常 任务id:%s msg:%s", jobId, e.getMessage())
+                );
+                return CommAsyncResult.fail(jobId);
+            }
+        }
+
+        //进行中判断(未完成且未清除)
+        if (previousFuture != null && !previousFuture.isDone() && !previousFuture.isCancelled()) {
+            CommAsyncCache asyncCache = INFO_CACHE.get(COMMIT_PREFIX + jobId);
             if (asyncCache != null)
-                return GisSurveyThirdImportResult.inProgress(params,
-                        SUBTASK_CACHE.get(params.getJobId()),
-                        asyncCache.getStartTime(), asyncCache.getOperator()
+                return CommAsyncResult.inProgress(jobId,
+                        asyncCache.getStartTime(),
+                        asyncCache.getOperator()
                 );
         }
 
         return null;
     }
 
+
     /**
      * 取消导入
      *
@@ -150,10 +261,11 @@ public class GisSurveyThirdImportBizService {
      */
     public int cancelImport(String jobId) {
         //如无缓存,则直接返回不存在
-        if (!TASK_CACHE.containsKey(jobId)) return GisSurveyImportStatusEnum.NOT_EXISTS.getCode();
+        if (!IMPORT_TASK_CACHE.containsKey(IMPORT_PREFIX + jobId))
+            return CommAsyncStatusEnum.NOT_EXISTS.getCode();
         //关闭检查任务
-        if (stopTask(TASK_CACHE.get(jobId))) {
-            removeCache(jobId);
+        if (stopTask(IMPORT_TASK_CACHE.get(IMPORT_PREFIX + jobId))) {
+            removeCache(IMPORT_PREFIX + jobId);
 
             LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
                     , String.format(
@@ -161,35 +273,37 @@ public class GisSurveyThirdImportBizService {
                             , jobId
                     )
             );
-            return GisSurveyImportStatusEnum.SUCCESS.getCode();
+            return CommAsyncStatusEnum.SUCCESS.getCode();
         }
-        return GisSurveyImportStatusEnum.FAIL.getCode();
+        return CommAsyncStatusEnum.FAIL.getCode();
     }
 
     /**
-     * 启动任务
+     * 启动导入
      *
      * @param params       导入参数
      * @param inputStreams 文件输入流
      */
-    private void startTask(GisSurveyThirdImportParams params, List<InputStream> inputStreams) {
+    private void startImport(GisSurveyThirdImportParams params, List<InputStream> inputStreams) {
         String jobId = params.getJobId();
         //获取已存在的任务
-        ListenableFuture<GisSurveyThirdImportResult> previousFuture = TASK_CACHE.get(jobId);
+        ListenableFuture<CommAsyncResult<Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>>>>
+                previousFuture = IMPORT_TASK_CACHE.get(IMPORT_PREFIX + jobId);
         //已结束判断,删除缓存
         if (previousFuture != null && (previousFuture.isDone() || previousFuture.isCancelled()))
-            removeCache(params.getJobId());
+            removeCache(IMPORT_PREFIX + params.getJobId());
         //异步执行第三方导入查任务
-        ListenableFuture<GisSurveyThirdImportResult> future = thirdImporter.thirdImportTask(params, inputStreams,
+        ListenableFuture<CommAsyncResult<Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>>>>
+                future = thirdImporter.thirdImportTask(params, inputStreams,
                 //缓存子任务句柄
-                subtask -> SUBTASK_CACHE.put(jobId, subtask),
+                subtask -> SUBTASK_CACHE.put(IMPORT_PREFIX + jobId, subtask),
                 //删除子任务句柄
-                subtaskSystemCheckId -> SUBTASK_CACHE.remove(jobId)
+                subtaskSystemCheckId -> SUBTASK_CACHE.remove(IMPORT_PREFIX + jobId)
         );
         //任务超时
         taskScheduler.schedule(() -> {
             if (!future.isCancelled() && !future.isDone() && stopTask(future)) {
-                removeCache(jobId);
+                removeCache(IMPORT_PREFIX + jobId);
                 LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
                         , String.format(
                                 "第三方导入超时,成功停止任务;任务id: %s"
@@ -199,9 +313,41 @@ public class GisSurveyThirdImportBizService {
             }
         }, Instant.now().plusMillis(asyncTaskProperties.getThirdImportTimeout().toMillis()));
         //缓存任务句柄
-        TASK_CACHE.put(jobId, future);
+        IMPORT_TASK_CACHE.put(IMPORT_PREFIX + jobId, future);
         //缓存时间
-        INFO_CACHE.put(jobId, new CommAsyncCache(LocalDateTime.now(), params.getOperator()));
+        INFO_CACHE.put(IMPORT_PREFIX + jobId, new CommAsyncCache(LocalDateTime.now(), params.getOperator()));
+    }
+
+    /**
+     * 启动提交
+     *
+     * @param jobId    任务id
+     * @param operator 操作人
+     */
+    private void startCommit(String jobId, String operator) {
+        //获取已存在的任务
+        ListenableFuture<CommAsyncResult<Boolean>> previousFuture = COMMIT_TASK_CACHE.get(COMMIT_PREFIX + jobId);
+        //已结束判断,删除缓存
+        if (previousFuture != null && (previousFuture.isDone() || previousFuture.isCancelled()))
+            removeCache(COMMIT_PREFIX + jobId);
+        //异步执行第三方导入查任务
+        ListenableFuture<CommAsyncResult<Boolean>> future = thirdImporter.commitImportTask(jobId, operator);
+        //任务超时
+        taskScheduler.schedule(() -> {
+            if (!future.isCancelled() && !future.isDone() && stopTask(future)) {
+                removeCache(COMMIT_PREFIX + jobId);
+                LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                        , String.format(
+                                "提交导入超时,成功停止任务;任务id: %s"
+                                , jobId
+                        )
+                );
+            }
+        }, Instant.now().plusMillis(asyncTaskProperties.getCommitImportTimeout().toMillis()));
+        //缓存任务句柄
+        COMMIT_TASK_CACHE.put(COMMIT_PREFIX + jobId, future);
+        //缓存时间
+        INFO_CACHE.put(COMMIT_PREFIX + jobId, new CommAsyncCache(LocalDateTime.now(), operator));
     }
 
     /**
@@ -220,11 +366,12 @@ public class GisSurveyThirdImportBizService {
     /**
      * 清除缓存
      *
-     * @param jobId 任务id
+     * @param key 缓存key
      */
-    private void removeCache(String jobId) {
-        TASK_CACHE.remove(jobId);
-        SUBTASK_CACHE.remove(jobId);
-        INFO_CACHE.remove(jobId);
+    private void removeCache(String key) {
+        IMPORT_TASK_CACHE.remove(key);
+        COMMIT_TASK_CACHE.remove(key);
+        SUBTASK_CACHE.remove(key);
+        INFO_CACHE.remove(key);
     }
 }

+ 5 - 0
src/main/java/com/shkpr/service/alambizplugin/commproperties/AsyncTaskProperties.java

@@ -33,6 +33,11 @@ public class AsyncTaskProperties {
     private Duration thirdImportTimeout;
 
     /**
+     * 第三方导入超时时间
+     */
+    private Duration commitImportTimeout;
+
+    /**
      * 第三方导出超时时间
      */
     private Duration thirdExportTimeout;

+ 16 - 10
src/main/java/com/shkpr/service/alambizplugin/commtools/ExcelUtils.java

@@ -9,6 +9,7 @@ import org.apache.commons.collections4.map.CaseInsensitiveMap;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 
 import java.io.IOException;
@@ -302,7 +303,7 @@ public class ExcelUtils {
     public static void writeFile(Map<String, Map<String, String>> headers, Map<String, List<Map<String, Object>>> datas
             , OutputStream outputStream, ExcelEnum excelEnum, Integer headerRowNum, Integer dataRowNum) {
         //创建表
-        try (Workbook workbook = excelEnum == ExcelEnum.XLSX ? new XSSFWorkbook() : new HSSFWorkbook()) {
+        try (Workbook workbook = excelEnum == ExcelEnum.XLSX ? new SXSSFWorkbook() : new HSSFWorkbook()) {
             //表头样式
             CellStyle headerStyle = workbook.createCellStyle();
             headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
@@ -323,6 +324,8 @@ public class ExcelUtils {
             }
             //写入文件
             workbook.write(outputStream);
+            //清理临时文件
+            if (workbook instanceof SXSSFWorkbook) ((SXSSFWorkbook) workbook).dispose();
         } catch (IOException e) {
             LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
                     , String.format("excel文件写入失败 msg:%s", e.getMessage())
@@ -406,11 +409,6 @@ public class ExcelUtils {
                 setCellValue(cell, item.get(headerKey));
             }
         }
-        //设置自动宽度
-        for (int i = 0; i < header.size(); i++) {
-            sheet.autoSizeColumn(i, true);
-            sheet.setColumnWidth(i, sheet.getColumnWidth(i) * 12 / 10);
-        }
     }
 
     /**
@@ -440,13 +438,21 @@ public class ExcelUtils {
                 case BOOLEAN:
                     value = String.valueOf(cell.getBooleanCellValue());
                     break;
-                case FORMULA:
-                    value = String.valueOf(cell.getNumericCellValue());
-                    break;
+                case FORMULA: {
+                    //根据结果类型设置值
+                    CellType cellType = cell.getCachedFormulaResultTypeEnum();
+                    if (cellType == CellType.NUMERIC) value = String.valueOf(cell.getNumericCellValue());
+                    else if (cellType == CellType.STRING) value = cell.getRichStringCellValue().toString();
+                    else value = cell.getCellFormula();
+                }
+                break;
                 default:
                     break;
             }
-        } catch (Exception ignored) {
+        } catch (Exception e) {
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
+                    , String.format("excel单元格解释失败 error:%s", e)
+            );
         }
         return value == null ? "" : value.trim();
     }

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

@@ -3,17 +3,29 @@ package com.shkpr.service.alambizplugin.commtools;
 import com.global.base.log.LogLevelFlag;
 import com.global.base.log.LogPrintMgr;
 import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
+import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyLine;
+import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyPoint;
+import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckDefine;
+import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckDeviation;
 import org.geotools.referencing.CRS;
 import org.geotools.referencing.GeodeticCalculator;
 import org.locationtech.jts.geom.Coordinate;
 import org.locationtech.jts.geom.Envelope;
+import org.locationtech.jts.geom.Geometry;
 import org.locationtech.jts.geom.GeometryFactory;
+import org.locationtech.jts.geom.LineString;
+import org.locationtech.jts.geom.MultiLineString;
 import org.locationtech.jts.geom.Polygon;
 import org.locationtech.jts.util.GeometricShapeFactory;
+import org.locationtech.jts.util.NumberUtil;
 import org.opengis.referencing.FactoryException;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.operation.TransformException;
 
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
 /**
  * 地理工具类
  *
@@ -35,6 +47,176 @@ public class GeomUtil {
      */
     private final static GeometricShapeFactory shapeFactory = new GeometricShapeFactory(geometryFactory);
 
+
+    /**
+     * 获取公差
+     *
+     * @param define   系统检查定义
+     * @param property 属性
+     * @return 公差
+     */
+    public static double getTolerance(GisSurveySystemCheckDefine define, String property) {
+        //偏差集合
+        List<GisSurveySystemCheckDeviation> deviations = define != null ? define.getDeviation() : Collections.emptyList();
+        //匹配属性
+        return deviations.stream()
+                .filter(deviation -> Objects.equals(property, deviation.getProperty()))
+                .map(GisSurveySystemCheckDeviation::getTolerance)
+                .findFirst().orElse(0d);
+    }
+
+    /**
+     * 计算包含
+     *
+     * @param line         线
+     * @param point        点
+     * @param lngTolerance 经度公差
+     * @param latTolerance 纬度公差
+     * @return 包含关系
+     */
+    public static Boolean calcContain(GisSurveyLayerApplyLine line, GisSurveyLayerApplyPoint point, double lngTolerance, double latTolerance) {
+        //上节点判断
+        if (Objects.equals(point.getCode(), line.getUpNode())) {
+            //线坐标
+            Coordinate lineCcoordinate = line.getGis().getCoordinates()[0];
+            //点坐标
+            Coordinate pointCoordinate = point.getGis().getCoordinate();
+            //比较x和y
+            return NumberUtil.equalsWithTolerance(lineCcoordinate.x, pointCoordinate.x, lngTolerance) &&
+                    NumberUtil.equalsWithTolerance(lineCcoordinate.y, pointCoordinate.y, latTolerance);
+
+        }
+        //下节点判断
+        if (Objects.equals(point.getCode(), line.getDownNode())) {
+            //线坐标
+            Coordinate lineCcoordinate = line.getGis().getCoordinates()[line.getGis().getCoordinates().length - 1];
+            //点坐标
+            Coordinate pointCoordinate = point.getGis().getCoordinate();
+            //比较x和y
+            return NumberUtil.equalsWithTolerance(lineCcoordinate.x, pointCoordinate.x, lngTolerance) &&
+                    NumberUtil.equalsWithTolerance(lineCcoordinate.y, pointCoordinate.y, latTolerance);
+        }
+        return false;
+    }
+
+    /**
+     * 计算长度
+     *
+     * @param coordinate1 坐标1
+     * @param coordinate2 坐标2
+     * @return 长度
+     */
+    public static double calcLength(Coordinate coordinate1, Coordinate coordinate2) {
+        double x1 = coordinate1.getX();
+        double y1 = coordinate1.getY();
+        double x2 = coordinate2.getX();
+        double y2 = coordinate2.getY();
+        //计算差
+        double dx = Math.abs(x1 - x2);
+        double dy = Math.abs(y1 - y2);
+        //计算长
+        return Math.sqrt(dx * dx + dy * dy);
+    }
+
+    /**
+     * 转数组
+     *
+     * @param coordinate 坐标
+     * @return 坐标数组
+     */
+    public static double[] toArray(Coordinate coordinate) {
+        return new double[]{coordinate.getX(), coordinate.getY()};
+    }
+
+    /**
+     * 转数组
+     *
+     * @param lineString 线
+     * @return 坐标数组
+     */
+    public static double[][] toArray(LineString lineString) {
+        //获取geom的坐标
+        Coordinate[] coords = lineString.getCoordinates();
+        if (coords == null || coords.length == 0) return new double[0][2];
+        //构建坐标数组
+        double[][] result = new double[coords.length][2];
+        //存入坐标
+        for (int j = 0; j < coords.length; j++) {
+            result[j][0] = coords[j].getX();
+            result[j][1] = coords[j].getY();
+        }
+        return result;
+    }
+
+    /**
+     * 转数组
+     *
+     * @param multiLineString 线集合
+     * @return 坐标数组
+     */
+    public static double[][][] toArray(MultiLineString multiLineString) {
+        //geom长度
+        int geomLength = multiLineString.getNumGeometries();
+        //结果
+        double[][][] result = new double[geomLength][][];
+        //遍历geom
+        for (int i = 0; i < geomLength; i++) {
+            //获取geom
+            Geometry geom = multiLineString.getGeometryN(i);
+            if (geom instanceof LineString) result[i] = toArray((LineString) geom);
+            else result[i] = new double[0][];
+        }
+        return result;
+    }
+
+    /**
+     * 从数组转换
+     *
+     * @param array 数组
+     * @return 坐标
+     */
+    public static Coordinate ofArray(double[] array) {
+        if (array == null || array.length < 2) return null;
+        return new Coordinate(array[0], array[1]);
+    }
+
+    /**
+     * 从数组转换
+     *
+     * @param array 数组
+     * @return 线
+     */
+    public static LineString ofArray(double[][] array) {
+        if (array == null || array.length == 0) return geometryFactory.createLineString();
+        //遍历数组并构建坐标集合
+        Coordinate[] coordinates = new Coordinate[array.length];
+        for (int j = 0; j < array.length; j++) {
+            //坐标判断
+            if (array[j].length < 2) throw new IllegalArgumentException("坐标点必须包含 [x, y]");
+            //转坐标
+            coordinates[j] = ofArray(array[j]);
+        }
+        return geometryFactory.createLineString(coordinates);
+    }
+
+    /**
+     * 从数组转换
+     *
+     * @param array 数组
+     * @return 多线
+     */
+    public static MultiLineString ofArray(double[][][] array) {
+        if (array == null || array.length == 0) return geometryFactory.createMultiLineString();
+        //遍历数组并构建线集合
+        LineString[] lineStrings = new LineString[array.length];
+        for (int i = 0; i < array.length; i++) {
+            //转线
+            lineStrings[i] = ofArray(array[i]);
+        }
+        return geometryFactory.createMultiLineString(lineStrings);
+    }
+
+
     /**
      * 创建圆
      *

+ 76 - 8
src/main/java/com/shkpr/service/alambizplugin/commtools/ShapeUtils.java

@@ -1,6 +1,10 @@
 package com.shkpr.service.alambizplugin.commtools;
 
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.alambizplugin.constants.GisMetadataDefine;
 import com.shkpr.service.alambizplugin.constants.GisSurveyExcelDefine;
+import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
 import org.geotools.data.Transaction;
 import org.geotools.data.collection.ListFeatureCollection;
 import org.geotools.data.shapefile.ShapefileDataStore;
@@ -10,12 +14,14 @@ import org.geotools.feature.simple.SimpleFeatureBuilder;
 import org.opengis.feature.simple.SimpleFeatureType;
 
 import java.io.IOException;
-import java.io.Serializable;
+import java.nio.charset.Charset;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * ShapeFile工具
@@ -24,8 +30,19 @@ import java.util.Map;
  * @since 1.0.0
  */
 public class ShapeUtils {
-    //缓存库工厂
+    /**
+     * log
+     */
+    private static final String mStrClassName = "ShapeUtils";
+    private static final String mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
+    /**
+     * 缓存库工厂
+     */
     private static final ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
+    /**
+     * 编码
+     */
+    private static final Charset charset = Charset.forName("GB18030");
 
     /**
      * 输出shape文件
@@ -38,8 +55,33 @@ public class ShapeUtils {
         for (Map.Entry<SimpleFeatureType, List<Map<String, Object>>> entry : datas.entrySet()) {
             final SimpleFeatureType KEY = entry.getKey();
             List<Map<String, Object>> value = entry.getValue();
-
-            writeShape(KEY, value, Paths.get(directoryPath + "/" + KEY.getTypeName() + ".shp"));
+            //点类型处理
+            if (Objects.equals(GisMetadataDefine.TYPE_KINE.POINT, KEY.getTypeName())) {
+                //按图层名称分组
+                Map<Object, List<Map<String, Object>>> group = value.stream()
+                        .collect(Collectors.groupingBy(it ->
+                                it.get(GisSurveyExcelDefine.FILE.POINT_LAYER))
+                        );
+                //按组导出
+                for (Map.Entry<Object, List<Map<String, Object>>> groupEntry : group.entrySet()) {
+                    writeShape(KEY, groupEntry.getValue(),
+                            Paths.get(directoryPath + "/" + groupEntry.getKey() + ".shp")
+                    );
+                }
+            }
+            //线类型处理
+            if (Objects.equals(GisMetadataDefine.TYPE_KINE.LINE, KEY.getTypeName())) {
+                //按图层名称分组
+                Map<Object, List<Map<String, Object>>> group = value.stream()
+                        .collect(Collectors.groupingBy(it ->
+                                it.get(GisSurveyExcelDefine.FILE.LINE_LAYER)
+                        ));
+                //按组导出
+                for (Map.Entry<Object, List<Map<String, Object>>> mapEntry : group.entrySet()) {
+                    writeShape(KEY, mapEntry.getValue(),
+                            Paths.get(directoryPath + "/" + mapEntry.getKey() + ".shp"));
+                }
+            }
         }
     }
 
@@ -51,11 +93,17 @@ public class ShapeUtils {
      * @throws IOException io异常
      */
     public static void writeShape(final SimpleFeatureType TYPE, List<Map<String, Object>> data, Path filePath) throws IOException {
-        //特征构建
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                , String.format(
+                        "开始构建特征,类型:%s========>"
+                        , TYPE.getTypeName()
+                )
+        );
+        //根据类型创建特征构建器
         final SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
         //特征集合
         ListFeatureCollection collection = new ListFeatureCollection(TYPE);
-        //遍历数据
+        //遍历数据,构建特征集合
         data.forEach(it -> {
             //设置geom
             featureBuilder.set(GisSurveyExcelDefine.FILE.THE_GEOM, it.get(GisSurveyExcelDefine.FILE.THE_GEOM));
@@ -65,14 +113,24 @@ public class ShapeUtils {
             });
             collection.add(featureBuilder.buildFeature(null));
         });
+        //释放数据
+        data.clear();
 
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                , String.format(
+                        "开启shapefile缓存库,开始写入,类型:%s========>"
+                        , TYPE.getTypeName()
+                )
+        );
         //从文件构建数据缓存库
-        Map<String, Serializable> params = new HashMap<>();
+        Map<String, Object> params = new HashMap<>();
         params.put(ShapefileDataStoreFactory.URLP.key, filePath.toUri().toURL());
         params.put(ShapefileDataStoreFactory.CREATE_SPATIAL_INDEX.key, Boolean.TRUE);
-        params.put(ShapefileDataStoreFactory.DBFCHARSET.key, "GB18030");
+        params.put(ShapefileDataStoreFactory.MEMORY_MAPPED.key, Boolean.TRUE);
 
         ShapefileDataStore dataStore = (ShapefileDataStore) dataStoreFactory.createDataStore(params);
+        dataStore.setTryCPGFile(true);
+        dataStore.setCharset(charset);
         dataStore.createSchema(TYPE);
 
         //启动事务
@@ -85,5 +143,15 @@ public class ShapeUtils {
             //写入特征集合
             featureStore.addFeatures(collection);
         }
+
+        //释放资源
+        collection.clear();
+        dataStore.dispose();
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                , String.format(
+                        "释放shapefile缓存库,结束写入,类型:%s========>"
+                        , TYPE.getTypeName()
+                )
+        );
     }
 }

+ 8 - 0
src/main/java/com/shkpr/service/alambizplugin/components/AsyncResultManager.java

@@ -305,6 +305,14 @@ public class AsyncResultManager {
             Path tempDirectory = Files.createTempDirectory(tempFileProperties.getResourcePath(), flag);
             //导出到shape
             ShapeUtils.writeShape(data, tempDirectory);
+
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                    , String.format(
+                            "开始执行压缩文件,结果标识:%s,文件名:%s"
+                            , flag
+                            , fileName
+                    )
+            );
             //压缩文件夹
             Path zipPath = CompressorUtils.archivalZip(tempDirectory);
             //移动文件

+ 10 - 2
src/main/java/com/shkpr/service/alambizplugin/components/GisSurveySystemChecker.java

@@ -151,6 +151,14 @@ public class GisSurveySystemChecker {
 
             //查询经纬度类型定义
             List<TypeDefine> typeDefines = typeDefineService.findLatLng();
+            //孤立点定义
+            GisSurveySystemCheckDefine isolatedPointsDefine = systemCheckDefines.stream().
+                    filter(it -> Objects.equals(GisSurveySystemCheckKeys.ISOLATED_POINTS, it.getKey()))
+                    .findFirst().orElse(null);
+            //无效线定义
+            GisSurveySystemCheckDefine invalidLinesDefine = systemCheckDefines.stream().
+                    filter(it -> Objects.equals(GisSurveySystemCheckKeys.INVALID_LINES, it.getKey()))
+                    .findFirst().orElse(null);
             //重复点定义
             GisSurveySystemCheckDefine duplicatePointsDefine = systemCheckDefines.stream().
                     filter(it -> Objects.equals(GisSurveySystemCheckKeys.DUPLICATE_POINTS, it.getKey()))
@@ -168,14 +176,14 @@ public class GisSurveySystemChecker {
             //孤立点检查
             if (points != null && lines != null) {
                 if (params.getStartSubitemKeys().contains(GisSurveySystemCheckKeys.ISOLATED_POINTS)) {
-                    isolatedPointsFuture = isolatedPointsFinder.findIsolatedPoints(points, lines, systemCheckId);
+                    isolatedPointsFuture = isolatedPointsFinder.findIsolatedPoints(points, lines, isolatedPointsDefine, systemCheckId);
                     subtask.put(GisSurveySystemCheckKeys.ISOLATED_POINTS, isolatedPointsFuture);
                 }
             }
             //无效线检查
             if (points != null && lines != null) {
                 if (params.getStartSubitemKeys().contains(GisSurveySystemCheckKeys.INVALID_LINES)) {
-                    invalidLinesFuture = invalidLinesFinder.finderInvalidLines(points, lines, systemCheckId);
+                    invalidLinesFuture = invalidLinesFinder.finderInvalidLines(points, lines, invalidLinesDefine, systemCheckId);
                     subtask.put(GisSurveySystemCheckKeys.INVALID_LINES, invalidLinesFuture);
                 }
             }

+ 42 - 11
src/main/java/com/shkpr/service/alambizplugin/components/GisSurveyThirdExporter.java

@@ -38,6 +38,7 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.time.Duration;
 import java.time.LocalDateTime;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -45,6 +46,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -114,13 +116,24 @@ public class GisSurveyThirdExporter {
             //处理坐标系
             if (!Objects.equals(targetCRSCode, CommCRSDefine.CGCS2000)) transformGeom(targetCRSCode, points, lines);
 
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                    , String.format("开始构建模版查询条件;任务id: %s", jobId)
+            );
             //获取图层key
-            List<String> pointLayer = getLayerKeys(points);
-            List<String> lineLayer = getLayerKeys(lines);
+            Set<String> pointLayer = getLayerKeys(points);
+            Set<String> lineLayer = getLayerKeys(lines);
+
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                    , String.format("开始查询模版;任务id: %s", jobId)
+            );
             //查询点图层模版
-            List<GisMetadataLayerTemplate> pointLayerTemplates = layerTemplateService.findByKeyIn(pointLayer);
+            List<GisMetadataLayerTemplate> pointLayerTemplates = layerTemplateService.findByKeyIn(new ArrayList<>(pointLayer));
             //查询线图层模版
-            List<GisMetadataLayerTemplate> lineLayerTemplates = layerTemplateService.findByKeyIn(lineLayer);
+            List<GisMetadataLayerTemplate> lineLayerTemplates = layerTemplateService.findByKeyIn(new ArrayList<>(lineLayer));
+
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                    , String.format("查询模版完毕,开始导出;任务id: %s", jobId)
+            );
 
             //结果flag
             final String FLAG = RESULT_PREFIX + jobId;
@@ -256,8 +269,18 @@ public class GisSurveyThirdExporter {
         //构建excel数据
         Map<String, List<Map<String, Object>>> excelData = buildExcelData(points, lines, pointLayerTemplates, lineLayerTemplates);
 
+        //清除查询的数据
+        points.clear();
+        lines.clear();
+
         //导出excel
-        return asyncResultManager.writeExcel(excelHeader, excelData, FLAG, "third-export.xlsx");
+        Path result = asyncResultManager.writeExcel(excelHeader, excelData, FLAG, "third-export.xlsx");
+
+        //清除shape数据
+        excelHeader.clear();
+        excelData.clear();
+
+        return result;
     }
 
     /**
@@ -276,8 +299,17 @@ public class GisSurveyThirdExporter {
         //构建shape数据
         Map<SimpleFeatureType, List<Map<String, Object>>> shapeData = buildShapeData(points, lines, pointLayerTemplates, lineLayerTemplates);
 
+        //清除查询的数据
+        points.clear();
+        lines.clear();
+
         //导出shape
-        return asyncResultManager.writeShape(shapeData, FLAG, "third-export.zip");
+        Path result = asyncResultManager.writeShape(shapeData, FLAG, "third-export.zip");
+
+        //清除shape数据
+        shapeData.clear();
+
+        return result;
     }
 
 
@@ -287,13 +319,12 @@ public class GisSurveyThirdExporter {
      * @param datas 数据
      * @return 图层key集合
      */
-    private List<String> getLayerKeys(List<GisSurveyLayerApply> datas) {
+    private Set<String> getLayerKeys(List<GisSurveyLayerApply> datas) {
         //去重图层
         return datas.parallelStream()
                 .map(GisSurveyLayerApply::getLayer)
                 .filter(StringUtils::isNotBlank)
-                .distinct()
-                .collect(Collectors.toList());
+                .collect(Collectors.toSet());
     }
 
     /**
@@ -435,12 +466,12 @@ public class GisSurveyThirdExporter {
 
         //创建点类型
         final SimpleFeatureType POINT_TYPE = DataUtilities.createType(
-                "point",
+                GisMetadataDefine.TYPE_KINE.POINT,
                 String.format("%s%s", GisSurveyExcelDefine.FILE_HANDLE.POINT_SPEC, pointTemplateSpec)
         );
         //创建线类型
         final SimpleFeatureType LINE_TYPE = DataUtilities.createType(
-                "line",
+                GisMetadataDefine.TYPE_KINE.LINE,
                 String.format("%s%s", GisSurveyExcelDefine.FILE_HANDLE.LINE_SPEC, lineTemplateSpec)
         );
 

+ 150 - 72
src/main/java/com/shkpr/service/alambizplugin/components/GisSurveyThirdImporter.java

@@ -18,27 +18,29 @@ import com.shkpr.service.alambizplugin.constants.CommCRSDefine;
 import com.shkpr.service.alambizplugin.constants.ExcelEnum;
 import com.shkpr.service.alambizplugin.constants.GisMetadataDefine;
 import com.shkpr.service.alambizplugin.constants.GisSurveyExcelDefine;
-import com.shkpr.service.alambizplugin.constants.GisSurveyImportStatusEnum;
+import com.shkpr.service.alambizplugin.constants.GisSurveyThirdImportKeys;
 import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
 import com.shkpr.service.alambizplugin.dbdao.services.intef.GisMetadataLayerTemplateService;
 import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveyJobInfoService;
+import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveyLayerApplyService;
 import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveyLayerApplyThirdCopyService;
 import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveyProjectInfoService;
+import com.shkpr.service.alambizplugin.dto.CommAsyncResult;
 import com.shkpr.service.alambizplugin.dto.GisMetadataLayerTemplate;
 import com.shkpr.service.alambizplugin.dto.GisMetadataPropertyTemplate;
 import com.shkpr.service.alambizplugin.dto.GisSurveyCondition;
 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.locationtech.jts.geom.Coordinate;
 import org.locationtech.jts.geom.Geometry;
 import org.locationtech.jts.geom.GeometryFactory;
+import org.locationtech.jts.geom.LineString;
+import org.locationtech.jts.geom.MultiLineString;
 import org.locationtech.jts.geom.PrecisionModel;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.scheduling.annotation.AsyncResult;
@@ -71,33 +73,43 @@ import java.util.stream.Collectors;
 @Component
 public class GisSurveyThirdImporter {
     /**
+     * 结果前缀
+     */
+    public final static String RESULT_PREFIX = "third-import-";
+    /**
      * log
      */
     private final String mStrClassName;
     private final String mBizType;
+
     private final GeometryFactory geometryFactory;
+    private final AsyncResultManager asyncResultManager;
     private final GisSurveyProjectInfoService projectInfoService;
     private final GisSurveyJobInfoService jobInfoService;
     private final GisMetadataLayerTemplateService layerTemplateService;
     private final GisSurveyLayerApplyThirdCopyService layerApplyThirdCopyService;
+    private final GisSurveyLayerApplyService layerApplyService;
     private final DuplicatePointsFinder duplicatePointsFinder;
     private final InvalidLinesFinder invalidLinesFinder;
     private final InvalidPropertiesFinder invalidPropertiesFinder;
 
-    public GisSurveyThirdImporter(GisSurveyProjectInfoService projectInfoService
+    public GisSurveyThirdImporter(AsyncResultManager asyncResultManager, GisSurveyProjectInfoService projectInfoService
             , GisSurveyJobInfoService jobInfoService
             , GisMetadataLayerTemplateService layerTemplateService
             , GisSurveyLayerApplyThirdCopyService layerApplyThirdCopyService
+            , GisSurveyLayerApplyService layerApplyService
             , DuplicatePointsFinder duplicatePointsFinder
             , InvalidLinesFinder invalidLinesFinder
             , InvalidPropertiesFinder invalidPropertiesFinder) {
         mStrClassName = "GisSurveyThirdImporter";
         mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
         geometryFactory = new GeometryFactory(new PrecisionModel(), 4490);
+        this.asyncResultManager = asyncResultManager;
         this.projectInfoService = projectInfoService;
         this.jobInfoService = jobInfoService;
         this.layerTemplateService = layerTemplateService;
         this.layerApplyThirdCopyService = layerApplyThirdCopyService;
+        this.layerApplyService = layerApplyService;
         this.duplicatePointsFinder = duplicatePointsFinder;
         this.invalidLinesFinder = invalidLinesFinder;
         this.invalidPropertiesFinder = invalidPropertiesFinder;
@@ -113,13 +125,15 @@ public class GisSurveyThirdImporter {
      * @return 系统检查返回
      */
     @Async
-    public ListenableFuture<GisSurveyThirdImportResult> thirdImportTask(GisSurveyThirdImportParams params, List<InputStream> inputStreams
-            , Consumer<GisSurveyThirdImportSubtask> onStartSubtask, Consumer<String> onDeprecatedSubtask) {
+    public ListenableFuture<CommAsyncResult<Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>>>> thirdImportTask(
+            GisSurveyThirdImportParams params, List<InputStream> inputStreams
+            , Consumer<Map<String, ListenableFuture<?>>> onStartSubtask, Consumer<String> onDeprecatedSubtask) {
         //构建返回
-        GisSurveyThirdImportResult result = GisSurveyThirdImportResult.fail(params);
+        CommAsyncResult<Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>>> result
+                = CommAsyncResult.fail(params.getJobId());
         result.setOperator(params.getOperator());
         //无效属性任务
-        ListenableFuture<GisSurveyThirdImportResultDetail<Map<String, List<GisSurveyThirdImportElement>>>> invalidPropertiesFuture = null;
+        ListenableFuture<Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>>> invalidPropertiesFuture = null;
         //重复点号任务
         ListenableFuture<GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>> duplicatePointsFuture = null;
         //无效线任务
@@ -148,35 +162,53 @@ public class GisSurveyThirdImporter {
             List<GisMetadataLayerTemplate> pointLayerTemplates = layerTemplateService.findByNatureAndNameIn(params.getNature(), pointLayerNames);
             List<GisMetadataLayerTemplate> lineLayerTemplates = layerTemplateService.findByNatureAndNameIn(params.getNature(), lineLayerNames);
 
+            //结果flag
+            final String FLAG = RESULT_PREFIX + params.getJobId();
+            //创建临时文件夹
+            if (!asyncResultManager.createTempDirectory(FLAG))
+                return new AsyncResult<>(result);
+
+            //子任务
+            Map<String, ListenableFuture<?>> subtask = new HashMap<>();
+
             //无效属性检查
             invalidPropertiesFuture = invalidPropertiesFinder.findInvalidProperties(points, lines
-                    , pointLayerTemplates, lineLayerTemplates, params.getCheckConstraint(), projectConstraints);
+                    , pointLayerTemplates, lineLayerTemplates, params.getCheckConstraint(), projectConstraints, params.getJobId());
+            subtask.put(GisSurveyThirdImportKeys.INVALID_PROPERTIES, invalidPropertiesFuture);
             //重复点检查
-            duplicatePointsFuture = duplicatePointsFinder.findDuplicatePoints(points, pointLayerTemplates);
+            duplicatePointsFuture = duplicatePointsFinder.findDuplicatePoints(points, pointLayerTemplates, params.getJobId());
+            subtask.put(GisSurveyThirdImportKeys.DUPLICATE_POINTS, duplicatePointsFuture);
             //无效线检查
-            invalidLinesFuture = invalidLinesFinder.finderInvalidLines(points, lines, pointLayerTemplates, lineLayerTemplates);
+            invalidLinesFuture = invalidLinesFinder.finderInvalidLines(points, lines, pointLayerTemplates, lineLayerTemplates, params.getJobId());
+            subtask.put(GisSurveyThirdImportKeys.INVALID_LINES, invalidLinesFuture);
 
             //返回子任务
-            onStartSubtask.accept(
-                    new GisSurveyThirdImportSubtask(invalidPropertiesFuture, duplicatePointsFuture, invalidLinesFuture)
-            );
-
-            //等待结果
-            GisSurveyThirdImportResultDetail<Map<String, List<GisSurveyThirdImportElement>>> invalidPropertiesResult = invalidPropertiesFuture.get();
-            //存入无效属性结果
-            result.setInvalidLayersResult(untarInvalidProperties(invalidPropertiesResult, GisSurveyExcelDefine.RESULT.INVALID_LAYERS));
-            result.setMissingRequirementsResult(untarInvalidProperties(invalidPropertiesResult, GisSurveyExcelDefine.RESULT.MISSING_REQUIREMENTS));
-            result.setInvalidTypesResult(untarInvalidProperties(invalidPropertiesResult, GisSurveyExcelDefine.RESULT.INVALID_TYPES));
-            result.setOutRangesResult(untarInvalidProperties(invalidPropertiesResult, GisSurveyExcelDefine.RESULT.OUT_RANGES));
-            result.setOutConstraintResult(untarInvalidProperties(invalidPropertiesResult, GisSurveyExcelDefine.RESULT.OUT_CONSTRAINT));
-            //存入重复点结果
-            result.setDuplicatePointsResult(duplicatePointsFuture.get());
-            //存入无效线结果
-            result.setInvalidLinesResult(invalidLinesFuture.get());
+            onStartSubtask.accept(subtask);
+
+            //数据
+            Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>> data = new HashMap<>();
+
+            //等待子任务
+            Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>> invalidPropertiesResult = invalidPropertiesFuture.get();
+            //存入无效属性数据
+            data.put(GisSurveyThirdImportKeys.INVALID_LAYERS, invalidPropertiesResult.get(GisSurveyThirdImportKeys.INVALID_LAYERS));
+            data.put(GisSurveyThirdImportKeys.MISSING_REQUIREMENTS, invalidPropertiesResult.get(GisSurveyThirdImportKeys.MISSING_REQUIREMENTS));
+            data.put(GisSurveyThirdImportKeys.INVALID_TYPES, invalidPropertiesResult.get(GisSurveyThirdImportKeys.INVALID_TYPES));
+            data.put(GisSurveyThirdImportKeys.OUT_RANGES, invalidPropertiesResult.get(GisSurveyThirdImportKeys.OUT_RANGES));
+            data.put(GisSurveyThirdImportKeys.OUT_CONSTRAINT, invalidPropertiesResult.get(GisSurveyThirdImportKeys.OUT_CONSTRAINT));
+            //存入重复点数据
+            data.put(GisSurveyThirdImportKeys.DUPLICATE_POINTS, duplicatePointsFuture.get());
+            //存入无效线数据
+            data.put(GisSurveyThirdImportKeys.INVALID_LINES, invalidLinesFuture.get());
+            //存入数据
+            result.setData(data);
+
+            //替换结果
+            asyncResultManager.replaceResult(FLAG);
 
             //结果未通过
-            if (!checkResult(result)) {
-                result.setImportStatus(GisSurveyImportStatusEnum.DATA_ERROR.getCode());
+            if (!checkResult(data)) {
+                result.setStatus(CommAsyncStatusEnum.RESULT_ERROR.getCode());
                 result.setCompleteTime(LocalDateTime.now());
                 LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
                         , String.format(
@@ -213,7 +245,7 @@ public class GisSurveyThirdImporter {
             }
 
             //完成任务
-            result.setImportStatus(GisSurveyImportStatusEnum.SUCCESS.getCode());
+            result.setStatus(CommAsyncStatusEnum.SUCCESS.getCode());
             result.setCompleteTime(LocalDateTime.now());
 
             LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
@@ -241,7 +273,7 @@ public class GisSurveyThirdImporter {
             if (invalidLinesFuture != null) invalidLinesFuture.cancel(true);
 
             //失败信息
-            result.setImportStatus(CommAsyncStatusEnum.FAIL.getCode());
+            result.setStatus(CommAsyncStatusEnum.FAIL.getCode());
             result.setCompleteTime(LocalDateTime.now());
 
             //弃用子任务
@@ -251,6 +283,43 @@ public class GisSurveyThirdImporter {
     }
 
     /**
+     * 提交导入任务
+     *
+     * @param jobId    任务id
+     * @param operator 操作人
+     * @return 提交状态
+     */
+    @Async
+    public ListenableFuture<CommAsyncResult<Boolean>> commitImportTask(String jobId, String operator) {
+        //构建返回
+        CommAsyncResult<Boolean> result = CommAsyncResult.fail(jobId);
+        result.setOperator(operator);
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                , String.format(
+                        "开始执合并导入;任务id: %s"
+                        , jobId
+                )
+        );
+
+        //合并副表
+        Boolean merged = layerApplyService.mergeCopy(jobId, operator);
+
+        //完成任务
+        result.setStatus(CommAsyncStatusEnum.SUCCESS.getCode());
+        result.setCompleteTime(LocalDateTime.now());
+        result.setData(merged);
+
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                , String.format(
+                        "结束执行合并导入;任务id: %s, 用时(毫秒):%d",
+                        jobId,
+                        Duration.between(result.getRequestTime(), result.getCompleteTime()).toMillis()
+                )
+        );
+        return new AsyncResult<>(result);
+    }
+
+    /**
      * 解析excel
      *
      * @param inputStreams 输入流
@@ -304,35 +373,25 @@ public class GisSurveyThirdImporter {
     }
 
     /**
-     * 解包无效属性
+     * 检查数据
      *
-     * @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 结果
+     * @param data 数据
      * @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> outConstraint = result.getOutConstraintResult().getResults();
-        List<GisSurveyThirdImportElement> duplicatePoints = result.getDuplicatePointsResult().getResults();
-        List<GisSurveyThirdImportElement> invalidLines = result.getInvalidLinesResult().getResults();
+    private Boolean checkResult(Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>> data) {
+        //检查key
+        if (!data.containsKey(GisSurveyThirdImportKeys.INVALID_LAYERS) || !data.containsKey(GisSurveyThirdImportKeys.MISSING_REQUIREMENTS) ||
+                !data.containsKey(GisSurveyThirdImportKeys.INVALID_TYPES) || !data.containsKey(GisSurveyThirdImportKeys.OUT_RANGES) ||
+                !data.containsKey(GisSurveyThirdImportKeys.OUT_CONSTRAINT) || !data.containsKey(GisSurveyThirdImportKeys.DUPLICATE_POINTS) ||
+                !data.containsKey(GisSurveyThirdImportKeys.INVALID_LINES)) return false;
+        //获取结果
+        List<GisSurveyThirdImportElement> invalidLayers = data.get(GisSurveyThirdImportKeys.INVALID_LAYERS).getResults();
+        List<GisSurveyThirdImportElement> missingRequirements = data.get(GisSurveyThirdImportKeys.MISSING_REQUIREMENTS).getResults();
+        List<GisSurveyThirdImportElement> invalidTypesResult = data.get(GisSurveyThirdImportKeys.INVALID_TYPES).getResults();
+        List<GisSurveyThirdImportElement> outRanges = data.get(GisSurveyThirdImportKeys.OUT_RANGES).getResults();
+        List<GisSurveyThirdImportElement> outConstraint = data.get(GisSurveyThirdImportKeys.OUT_CONSTRAINT).getResults();
+        List<GisSurveyThirdImportElement> duplicatePoints = data.get(GisSurveyThirdImportKeys.DUPLICATE_POINTS).getResults();
+        List<GisSurveyThirdImportElement> invalidLines = data.get(GisSurveyThirdImportKeys.INVALID_LINES).getResults();
         //检查是否都为空
         return CollectionUtils.isEmpty(invalidLayers) && CollectionUtils.isEmpty(missingRequirements) &&
                 CollectionUtils.isEmpty(invalidTypesResult) && CollectionUtils.isEmpty(outRanges) &&
@@ -370,8 +429,8 @@ public class GisSurveyThirdImporter {
 
         //采集元素象集合
         List<GisSurveyLayerApplyThirdCopy> result = new ArrayList<>();
-        //点映射,用于线写入上下游节点
-        Map<String, String> pointNoMapping = new HashMap<>();
+        //点映射,用于线写入上下游节点
+        Map<String, GisSurveyLayerApplyThirdCopy> pointMapping = new HashMap<>();
         //格式化点
         for (Map<String, String> point : points) {
             //获取模版
@@ -379,19 +438,25 @@ public class GisSurveyThirdImporter {
             //解码点对象
             GisSurveyLayerApplyThirdCopy layerApply = decodePointToLayerApply(point, layerTemplate, params);
             //存入点号
-            pointNoMapping.put(layerApply.getNo(), layerApply.getCode());
+            pointMapping.put(layerApply.getNo(), layerApply);
 
             result.add(layerApply);
         }
+        //清除点缓存
+        points.clear();
+
         //格式化线
         for (Map<String, String> line : lines) {
             //获取模版
             GisMetadataLayerTemplate layerTemplate = lineTemplateMap.get(line.get(GisSurveyExcelDefine.FILE.LINE_LAYER));
             //解码对象
-            GisSurveyLayerApplyThirdCopy layerApply = decodeLineToLayerApply(line, layerTemplate, params, pointNoMapping);
+            GisSurveyLayerApplyThirdCopy layerApply = decodeLineToLayerApply(line, layerTemplate, params, pointMapping);
 
             result.add(layerApply);
         }
+        //清除点映射和线缓存
+        pointMapping.clear();
+        lines.clear();
 
         long end = System.currentTimeMillis();
         LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
@@ -491,13 +556,14 @@ public class GisSurveyThirdImporter {
     /**
      * 解码线数据到采集元素对象
      *
-     * @param line           线数据
-     * @param layerTemplate  图层模版
-     * @param params         导入参数
-     * @param pointNoMapping 点号映射
+     * @param line          线数据
+     * @param layerTemplate 图层模版
+     * @param params        导入参数
+     * @param pointMapping  点号映射
      * @return 采集元素拷贝对象
      */
-    private GisSurveyLayerApplyThirdCopy decodeLineToLayerApply(Map<String, String> line, GisMetadataLayerTemplate layerTemplate, GisSurveyThirdImportParams params, Map<String, String> pointNoMapping) {
+    private GisSurveyLayerApplyThirdCopy decodeLineToLayerApply(Map<String, String> line, GisMetadataLayerTemplate layerTemplate
+            , GisSurveyThirdImportParams params, Map<String, GisSurveyLayerApplyThirdCopy> pointMapping) {
         GisSurveyLayerApplyThirdCopy layerApply = new GisSurveyLayerApplyThirdCopy();
         //必填项
         layerApply.setJobId(params.getJobId());
@@ -507,14 +573,26 @@ public class GisSurveyThirdImporter {
         //默认值
         layerApply.setApply(GisSurveyExcelDefine.DEFAULT_VALUE.APPLY);
         layerApply.setSource(GisSurveyExcelDefine.DEFAULT_VALUE.SOURCE);
-        //上游节点
+        //上游节点
         String upNoStr = ThirdImportTemplateUtils.getValue(line, layerTemplate, GisSurveyExcelDefine.TEMPLATE.UP_NO);
-        if (StringUtils.isNotBlank(upNoStr)) {
-            layerApply.setUpNode(pointNoMapping.get(upNoStr));
-        }
+        GisSurveyLayerApplyThirdCopy upNo = StringUtils.isNotBlank(upNoStr) ? pointMapping.get(upNoStr) : null;
+        if (upNo != null) layerApply.setUpNode(upNo.getCode());
+        //下游节点
         String downNoStr = ThirdImportTemplateUtils.getValue(line, layerTemplate, GisSurveyExcelDefine.TEMPLATE.DOWN_NO);
-        if (StringUtils.isNotBlank(downNoStr)) {
-            layerApply.setDownNode(pointNoMapping.get(downNoStr));
+        GisSurveyLayerApplyThirdCopy downNo = StringUtils.isNotBlank(downNoStr) ? pointMapping.get(downNoStr) : null;
+        if (downNo != null) layerApply.setDownNode(downNo.getCode());
+        //gis
+        if (upNo != null && downNo != null && upNo.getGis() != null && downNo.getGis() != null) {
+            //上下游坐标
+            Coordinate upCoordinate = upNo.getGis().getCoordinate();
+            Coordinate downCoordinate = downNo.getGis().getCoordinate();
+            //创建线
+            LineString lineString = upCoordinate != null && downCoordinate != null ?
+                    geometryFactory.createLineString(new Coordinate[]{upCoordinate, downCoordinate}) : null;
+            //创建多线
+            MultiLineString multiLineString = new MultiLineString(new LineString[]{lineString}, geometryFactory);
+            //设置gis
+            if (lineString != null) layerApply.setGis(multiLineString);
         }
         //遍历属性模版
         List<GisSurveyPropertyValueThirdCopy> propertyValueList = new ArrayList<>();

+ 2 - 2
src/main/java/com/shkpr/service/alambizplugin/components/checker/CrossLinesFinder.java

@@ -11,7 +11,7 @@ import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyLine;
 import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckElement;
 import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckId;
 import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckResultDetail;
-import org.locationtech.jts.geom.LineString;
+import org.locationtech.jts.geom.MultiLineString;
 import org.locationtech.jts.index.strtree.STRtree;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.scheduling.annotation.AsyncResult;
@@ -70,7 +70,7 @@ public class CrossLinesFinder {
         //元素存入索引
         for (GisSurveyLayerApplyLine layerApplyLine : lines) {
             if (layerApplyLine.getGis() == null) continue;
-            LineString line = layerApplyLine.getGis();
+            MultiLineString line = layerApplyLine.getGis();
             tree.insert(line.getEnvelopeInternal(), layerApplyLine);
         }
         tree.build();

+ 64 - 10
src/main/java/com/shkpr/service/alambizplugin/components/checker/DuplicatePointsFinder.java

@@ -5,11 +5,14 @@ import com.global.base.log.LogPrintMgr;
 import com.shkpr.service.alambizplugin.commtools.BeanUtil;
 import com.shkpr.service.alambizplugin.commtools.ThirdImportTemplateUtils;
 import com.shkpr.service.alambizplugin.components.AsyncResultManager;
+import com.shkpr.service.alambizplugin.components.GisSurveyThirdImporter;
 import com.shkpr.service.alambizplugin.constants.GisMetadataDefine;
 import com.shkpr.service.alambizplugin.constants.GisSurveyExcelDefine;
 import com.shkpr.service.alambizplugin.constants.GisSurveySystemCheckKeys;
 import com.shkpr.service.alambizplugin.constants.GisSurveySystemCheckResultHead;
 import com.shkpr.service.alambizplugin.constants.GisSurveyTemplateDefine;
+import com.shkpr.service.alambizplugin.constants.GisSurveyThirdImportKeys;
+import com.shkpr.service.alambizplugin.constants.GisSurveyThirdImportResultHead;
 import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
 import com.shkpr.service.alambizplugin.dto.*;
 import com.shkpr.service.alambizplugin.exception.UncheckedInterruptedException;
@@ -74,11 +77,12 @@ public class DuplicatePointsFinder {
      *
      * @param points              点集合
      * @param pointLayerTemplates 点图层模版
+     * @param jobId               任务id
      * @return 重复点
      */
     @Async
-    public ListenableFuture<GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>> findDuplicatePoints(
-            List<Map<String, String>> points, List<GisMetadataLayerTemplate> pointLayerTemplates) throws InterruptedException {
+    public ListenableFuture<GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>> findDuplicatePoints(List<Map<String, String>> points
+            , List<GisMetadataLayerTemplate> pointLayerTemplates, String jobId) throws InterruptedException {
         LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始执行寻找重复点   ======>");
         long begin = System.currentTimeMillis();
 
@@ -112,7 +116,12 @@ public class DuplicatePointsFinder {
                     })
                     //过滤组内大于1
                     .filter(group -> StringUtils.isNotBlank(group.getKey()) && group.getValue().size() > 1)
-                    .map(entry -> new GisSurveyThirdImportElement(GisMetadataDefine.TYPE_KINE.POINT, entry.getKey(), null, null))
+                    .map(entry ->
+                            new GisSurveyThirdImportElement(GisMetadataDefine.TYPE_KINE.POINT, entry.getKey(),
+                                    null, null,
+                                    GisSurveyExcelDefine.MESSAGE.DUPLICATE_POINTS
+                            )
+                    )
                     .collect(Collectors.toList());
 
             long end = System.currentTimeMillis();
@@ -122,7 +131,7 @@ public class DuplicatePointsFinder {
                             , (end - begin)
                     )
             );
-            return new AsyncResult<>(new GisSurveyThirdImportResultDetail<>(true, groupElements));
+            return new AsyncResult<>(createThirdImportResult(groupElements, jobId, begin));
         } catch (UncheckedInterruptedException e) {
             throw e.getCause();
         }
@@ -233,7 +242,7 @@ public class DuplicatePointsFinder {
                     })
                     .filter(it -> it.size() > 1)
                     .collect(Collectors.toList());
-            return new AsyncResult<>(createResult(collect, systemCheckId, begin));
+            return new AsyncResult<>(createSystemCheckResult(collect, systemCheckId, begin));
         } catch (UncheckedInterruptedException e) {
             throw e.getCause();
         }
@@ -320,14 +329,43 @@ public class DuplicatePointsFinder {
     }
 
     /**
-     * 创建结果
+     * 创建第三方导入结果
+     *
+     * @param data  数据
+     * @param jobId 任务id
+     * @param begin 开始时间
+     * @return 结果
+     */
+    private GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>> createThirdImportResult(
+            List<GisSurveyThirdImportElement> data, String jobId, long begin) {
+        long end = System.currentTimeMillis();
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                , String.format(
+                        "结束执行寻找重复点,用时(毫秒):%d"
+                        , (end - begin)
+                )
+        );
+
+        //结果flag
+        final String FLAG = GisSurveyThirdImporter.RESULT_PREFIX + jobId;
+        //写入excel结果
+        Path excelPath = asyncResultManager.writeExcel(GisSurveyThirdImportResultHead.DUPLICATE_POINTS
+                , buildThirdImportExcel(data), FLAG, GisSurveyThirdImportKeys.DUPLICATE_POINTS + ".xlsx");
+
+        //构建结果
+        return new GisSurveyThirdImportResultDetail<>(true
+                , data, FLAG + "/" + excelPath.getFileName());
+    }
+
+    /**
+     * 创建系统检查结果
      *
      * @param data          数据
      * @param systemCheckId 系统检查id
      * @param begin         开始时间
      * @return 结果
      */
-    private GisSurveySystemCheckResultDetail createResult(List<List<GisSurveySystemCheckElement>> data
+    private GisSurveySystemCheckResultDetail createSystemCheckResult(List<List<GisSurveySystemCheckElement>> data
             , GisSurveySystemCheckId systemCheckId, long begin) {
         long end = System.currentTimeMillis();
         LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
@@ -344,7 +382,7 @@ public class DuplicatePointsFinder {
         //写入json和excel结果
         Path jsonPath = asyncResultManager.writeJson(data, FLAG, GisSurveySystemCheckKeys.DUPLICATE_POINTS + ".json");
         Path excelPath = asyncResultManager.writeExcel(GisSurveySystemCheckResultHead.DUPLICATE_POINTS
-                , buildExcel(data), FLAG, GisSurveySystemCheckKeys.DUPLICATE_POINTS + ".xlsx");
+                , buildSystemCheckExcel(data), FLAG, GisSurveySystemCheckKeys.DUPLICATE_POINTS + ".xlsx");
 
         //构建结果
         return new GisSurveySystemCheckResultDetail(true
@@ -354,12 +392,28 @@ public class DuplicatePointsFinder {
     }
 
     /**
-     * 构建excel数据
+     * 构建第三方导入excel数据
+     *
+     * @param data 数据
+     * @return excel数据
+     */
+    private List<Map<String, Object>> buildThirdImportExcel(List<GisSurveyThirdImportElement> data) {
+        return data.stream().map(element -> {
+            Map<String, Object> map = new HashMap<>();
+            map.put(GisSurveyThirdImportResultHead.KEYS.KIND, element.getKind());
+            map.put(GisSurveyThirdImportResultHead.KEYS.NO, element.getNo());
+            map.put(GisSurveyThirdImportResultHead.KEYS.MESSAGE, element.getMessage());
+            return map;
+        }).collect(Collectors.toList());
+    }
+
+    /**
+     * 构建系统检查excel数据
      *
      * @param data 数据
      * @return excel数据
      */
-    private List<Map<String, Object>> buildExcel(List<List<GisSurveySystemCheckElement>> data) {
+    private List<Map<String, Object>> buildSystemCheckExcel(List<List<GisSurveySystemCheckElement>> data) {
         return IntStream.range(0, data.size())
                 .boxed()
                 .flatMap(i -> data.get(i).stream().map(element -> {

+ 104 - 48
src/main/java/com/shkpr/service/alambizplugin/components/checker/InvalidLinesFinder.java

@@ -4,24 +4,22 @@ import com.global.base.log.LogLevelFlag;
 import com.global.base.log.LogPrintMgr;
 import com.google.common.collect.Lists;
 import com.shkpr.service.alambizplugin.commtools.BeanUtil;
+import com.shkpr.service.alambizplugin.commtools.GeomUtil;
 import com.shkpr.service.alambizplugin.commtools.ThirdImportTemplateUtils;
 import com.shkpr.service.alambizplugin.components.AsyncResultManager;
+import com.shkpr.service.alambizplugin.components.GisSurveyThirdImporter;
 import com.shkpr.service.alambizplugin.constants.GisMetadataDefine;
 import com.shkpr.service.alambizplugin.constants.GisSurveyExcelDefine;
 import com.shkpr.service.alambizplugin.constants.GisSurveySystemCheckKeys;
 import com.shkpr.service.alambizplugin.constants.GisSurveySystemCheckResultHead;
+import com.shkpr.service.alambizplugin.constants.GisSurveyTemplateDefine;
+import com.shkpr.service.alambizplugin.constants.GisSurveyThirdImportKeys;
+import com.shkpr.service.alambizplugin.constants.GisSurveyThirdImportResultHead;
 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.GisSurveyLayerApplyLine;
-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.*;
 import com.shkpr.service.alambizplugin.exception.UncheckedInterruptedException;
 import org.apache.commons.lang3.StringUtils;
+import org.locationtech.jts.geom.Coordinate;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.scheduling.annotation.AsyncResult;
 import org.springframework.stereotype.Component;
@@ -64,12 +62,14 @@ public class InvalidLinesFinder {
      * @param lines               线集合
      * @param pointLayerTemplates 点图层模版
      * @param lineLayerTemplates  线图层模版
+     * @param jobId               任务ID
      * @return 线分组
      */
     @Async
     public ListenableFuture<GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>> finderInvalidLines(
             List<Map<String, String>> points, List<Map<String, String>> lines,
-            List<GisMetadataLayerTemplate> pointLayerTemplates, List<GisMetadataLayerTemplate> lineLayerTemplates) throws InterruptedException {
+            List<GisMetadataLayerTemplate> pointLayerTemplates, List<GisMetadataLayerTemplate> lineLayerTemplates,
+            String jobId) throws InterruptedException {
         LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始执行寻找无效线   ======>");
         long begin = System.currentTimeMillis();
 
@@ -82,8 +82,8 @@ public class InvalidLinesFinder {
                             , (end - begin)
                     )
             );
-            return new AsyncResult<>(new GisSurveyThirdImportResultDetail<>(true,
-                    lines.stream()
+            return new AsyncResult<>(createThirdImportResult(
+                    lines.parallelStream()
                             //转结果
                             .map(line -> {
                                 //获取模版
@@ -102,9 +102,12 @@ public class InvalidLinesFinder {
                                 return new GisSurveyThirdImportElement(GisMetadataDefine.TYPE_KINE.LINE,
                                         ThirdImportTemplateUtils.getValue(line, upNoTemplate),
                                         ThirdImportTemplateUtils.getValue(line, downNoTemplate),
-                                        line.get(GisSurveyExcelDefine.FILE.LINE_LAYER), String.join(",", propertyNames));
+                                        line.get(GisSurveyExcelDefine.FILE.LINE_LAYER), String.join(",", propertyNames),
+                                        GisSurveyExcelDefine.MESSAGE.INVALID_LINES_ALL
+                                );
                             })
-                            .collect(Collectors.toList())
+                            .collect(Collectors.toList()),
+                    jobId, begin
             ));
         }
         //如线为空,则无无效线
@@ -116,9 +119,7 @@ public class InvalidLinesFinder {
                             , (end - begin)
                     )
             );
-            return new AsyncResult<>(new GisSurveyThirdImportResultDetail<>(
-                    true, Lists.newArrayList()
-            ));
+            return new AsyncResult<>(createThirdImportResult(Lists.newArrayList(), jobId, begin));
         }
 
         //点号集合
@@ -144,7 +145,7 @@ public class InvalidLinesFinder {
             String upNo = ThirdImportTemplateUtils.getValue(line, upNoTemplate);
             boolean notContainsUp = StringUtils.isBlank(upNo) || !nos.contains(upNo);
             String downNo = ThirdImportTemplateUtils.getValue(line, downNoTemplate);
-            boolean notContainsDown = StringUtils.isBlank(upNo) || !nos.contains(downNo);
+            boolean notContainsDown = StringUtils.isBlank(downNo) || !nos.contains(downNo);
             //不包含上节点或下节点,则收集
             if (notContainsUp || notContainsDown) {
                 //根据条件构造表头
@@ -157,18 +158,14 @@ public class InvalidLinesFinder {
                 }
                 //存入结果
                 results.add(new GisSurveyThirdImportElement(GisMetadataDefine.TYPE_KINE.LINE, upNo, downNo,
-                        line.get(GisSurveyExcelDefine.FILE.LINE_LAYER), String.join(",", propertyNames)));
+                        line.get(GisSurveyExcelDefine.FILE.LINE_LAYER), String.join(",", propertyNames),
+                        StringUtils.isBlank(upNo) || StringUtils.isBlank(downNo) ?
+                                GisSurveyExcelDefine.MESSAGE.INVALID_LINES_NULL : GisSurveyExcelDefine.MESSAGE.INVALID_LINES
+                ));
             }
         }
 
-        long end = System.currentTimeMillis();
-        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
-                , String.format(
-                        "结束执行寻找无效线,用时(毫秒):%d"
-                        , (end - begin)
-                )
-        );
-        return new AsyncResult<>(new GisSurveyThirdImportResultDetail<>(true, results));
+        return new AsyncResult<>(createThirdImportResult(results, jobId, begin));
     }
 
     /**
@@ -180,7 +177,12 @@ public class InvalidLinesFinder {
      */
     @Async
     public ListenableFuture<GisSurveySystemCheckResultDetail> finderInvalidLines(
-            List<GisSurveyLayerApplyPoint> points, List<GisSurveyLayerApplyLine> lines, GisSurveySystemCheckId systemCheckId) {
+            List<GisSurveyLayerApplyPoint> points, List<GisSurveyLayerApplyLine> lines,
+            GisSurveySystemCheckDefine define, GisSurveySystemCheckId systemCheckId) {
+        //经纬度公差
+        double lngTolerance = GeomUtil.getTolerance(define, GisSurveyTemplateDefine.LNG);
+        double latTolerance = GeomUtil.getTolerance(define, GisSurveyTemplateDefine.LAT);
+
         LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始执行寻找无效线   ======>");
         long begin = System.currentTimeMillis();
 
@@ -195,36 +197,63 @@ public class InvalidLinesFinder {
                     //转为返回元素
                     .map(line -> BeanUtil.copy(line, GisSurveySystemCheckElement.class))
                     .collect(Collectors.toList());
-            return new AsyncResult<>(createResult(elements, systemCheckId, begin));
+            return new AsyncResult<>(createSystemCheckResult(elements, systemCheckId, begin));
         }
         //如线为空,则无无效线
-        if (lines.isEmpty()) return new AsyncResult<>(createResult(Lists.newArrayList(), systemCheckId, begin));
-
-        //点编码集合
-        Set<String> pointCodes = points.parallelStream()
+        if (lines.isEmpty())
+            return new AsyncResult<>(createSystemCheckResult(Lists.newArrayList(), systemCheckId, begin));
+        //联通
+        Map<String, GisSurveyLayerApplyPoint> connectedPoints = points.parallelStream()
                 //响应中断
                 .peek(line -> {
                     if (Thread.currentThread().isInterrupted())
                         throw new UncheckedInterruptedException(new InterruptedException());
                 })
-                //获取点号,并去重
-                .map(GisSurveyLayerApplyPoint::getCode)
-                .filter(Objects::nonNull)
-                .collect(Collectors.toSet());
-
-        //并行流寻找重复点号
+                .filter(point -> Objects.nonNull(point) && Objects.nonNull(point.getCode()))
+                //获取点编码
+                .collect(Collectors.toMap(GisSurveyLayerApplyPoint::getCode, point -> point));
+        //并行流寻找无效线
         List<GisSurveySystemCheckElement> elements = lines.parallelStream()
                 //响应中断
                 .peek(line -> {
                     if (Thread.currentThread().isInterrupted())
                         throw new UncheckedInterruptedException(new InterruptedException());
                 })
-                //过滤上下游节点都不在点集合中
-                .filter(line -> !pointCodes.contains(line.getUpNode())
-                        || !pointCodes.contains(line.getDownNode()))
+                //过滤无效线
+                .filter(line -> {
+                    //线格式判断
+                    if (line.getGis() == null || line.getGis().getCoordinates().length < 2 ||
+                            StringUtils.isAnyBlank(line.getUpNode(), line.getDownNode())) return true;
+                    //判断下游节点不存在
+                    if (!connectedPoints.containsKey(line.getUpNode()) || !connectedPoints.containsKey(line.getDownNode()))
+                        return true;
+                    //判断上游节点gis包含
+                    GisSurveyLayerApplyPoint upPoint = connectedPoints.get(line.getUpNode());
+                    if (!GeomUtil.calcContain(line, upPoint, lngTolerance, latTolerance)) return true;
+                    //判断下游节点gis包含
+                    GisSurveyLayerApplyPoint downPoint = connectedPoints.get(line.getDownNode());
+                    if (!GeomUtil.calcContain(line, downPoint, lngTolerance, latTolerance)) return true;
+                    //线坐标
+                    Coordinate[] coordinates = line.getGis().getCoordinates();
+                    //判断线长度小于误差
+                    return Math.sqrt(lngTolerance * lngTolerance + latTolerance * latTolerance) >=
+                            GeomUtil.calcLength(coordinates[0], coordinates[coordinates.length - 1]);
+                })
                 .map(line -> BeanUtil.copy(line, GisSurveySystemCheckElement.class))
                 .collect(Collectors.toList());
 
+        return new AsyncResult<>(createSystemCheckResult(elements, systemCheckId, begin));
+    }
+
+    /**
+     * 创建第三方导入结果
+     *
+     * @param data  数据
+     * @param jobId 任务id
+     * @param begin 开始时间
+     * @return 结果
+     */
+    private GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>> createThirdImportResult(List<GisSurveyThirdImportElement> data, String jobId, long begin) {
         long end = System.currentTimeMillis();
         LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
                 , String.format(
@@ -232,18 +261,27 @@ public class InvalidLinesFinder {
                         , (end - begin)
                 )
         );
-        return new AsyncResult<>(createResult(elements, systemCheckId, begin));
+
+        //结果flag
+        final String FLAG = GisSurveyThirdImporter.RESULT_PREFIX + jobId;
+        //excel结果
+        Path excelPath = asyncResultManager.writeExcel(GisSurveyThirdImportResultHead.INVALID_LINES,
+                buildThirdImportExcel(data), FLAG, GisSurveyThirdImportKeys.INVALID_LINES + ".xlsx");
+
+        //构建结果
+        return new GisSurveyThirdImportResultDetail<>(true
+                , data, FLAG + "/" + excelPath.getFileName());
     }
 
     /**
-     * 创建结果
+     * 创建系统检查结果
      *
      * @param data          数据
      * @param systemCheckId 系统检查id
      * @param begin         开始时间
      * @return 结果
      */
-    private GisSurveySystemCheckResultDetail createResult(List<GisSurveySystemCheckElement> data
+    private GisSurveySystemCheckResultDetail createSystemCheckResult(List<GisSurveySystemCheckElement> data
             , GisSurveySystemCheckId systemCheckId, long begin) {
         long end = System.currentTimeMillis();
         LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
@@ -260,7 +298,7 @@ public class InvalidLinesFinder {
         //写入json和excel结果
         Path jsonPath = asyncResultManager.writeJson(data, FLAG, GisSurveySystemCheckKeys.INVALID_LINES + ".json");
         Path excelPath = asyncResultManager.writeExcel(GisSurveySystemCheckResultHead.INVALID_LINES,
-                buildExcel(data), FLAG, GisSurveySystemCheckKeys.INVALID_LINES + ".xlsx");
+                buildSystemCheckExcel(data), FLAG, GisSurveySystemCheckKeys.INVALID_LINES + ".xlsx");
 
         //构建结果
         return new GisSurveySystemCheckResultDetail(true
@@ -270,12 +308,30 @@ public class InvalidLinesFinder {
     }
 
     /**
-     * 构建excel数据
+     * 构建第三方导入excel数据
+     *
+     * @param data 数据
+     * @return excel数据
+     */
+    private List<Map<String, Object>> buildThirdImportExcel(List<GisSurveyThirdImportElement> data) {
+        return data.stream().map(element -> {
+            Map<String, Object> map = new HashMap<>();
+            map.put(GisSurveyThirdImportResultHead.KEYS.LAYER_NAME, element.getLayerName());
+            map.put(GisSurveyThirdImportResultHead.KEYS.UP_NO, element.getUpNO());
+            map.put(GisSurveyThirdImportResultHead.KEYS.DOWN_NO, element.getDownNO());
+            map.put(GisSurveyThirdImportResultHead.KEYS.PROPERTY_NAME, element.getPropertyName());
+            map.put(GisSurveyThirdImportResultHead.KEYS.MESSAGE, element.getMessage());
+            return map;
+        }).collect(Collectors.toList());
+    }
+
+    /**
+     * 构建系统检查excel数据
      *
      * @param data 数据
      * @return excel数据
      */
-    private List<Map<String, Object>> buildExcel(List<GisSurveySystemCheckElement> data) {
+    private List<Map<String, Object>> buildSystemCheckExcel(List<GisSurveySystemCheckElement> data) {
         return data.stream().map(element -> {
             Map<String, Object> map = new HashMap<>();
             map.put(GisSurveySystemCheckResultHead.KEYS.UP_NO, element.getUpNo());

+ 154 - 32
src/main/java/com/shkpr/service/alambizplugin/components/checker/InvalidPropertiesFinder.java

@@ -4,8 +4,12 @@ import com.global.base.log.LogLevelFlag;
 import com.global.base.log.LogPrintMgr;
 import com.shkpr.service.alambizplugin.commtools.BeanUtil;
 import com.shkpr.service.alambizplugin.commtools.ThirdImportTemplateUtils;
+import com.shkpr.service.alambizplugin.components.AsyncResultManager;
+import com.shkpr.service.alambizplugin.components.GisSurveyThirdImporter;
 import com.shkpr.service.alambizplugin.constants.GisMetadataDefine;
 import com.shkpr.service.alambizplugin.constants.GisSurveyExcelDefine;
+import com.shkpr.service.alambizplugin.constants.GisSurveyThirdImportKeys;
+import com.shkpr.service.alambizplugin.constants.GisSurveyThirdImportResultHead;
 import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
 import com.shkpr.service.alambizplugin.dto.GisMetadataLayerTemplate;
 import com.shkpr.service.alambizplugin.dto.GisMetadataPropertyTemplate;
@@ -20,6 +24,7 @@ import org.springframework.scheduling.annotation.AsyncResult;
 import org.springframework.stereotype.Component;
 import org.springframework.util.concurrent.ListenableFuture;
 
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -49,9 +54,12 @@ public class InvalidPropertiesFinder {
     private final String mStrClassName;
     private final String mBizType;
 
-    public InvalidPropertiesFinder() {
+    private final AsyncResultManager asyncResultManager;
+
+    public InvalidPropertiesFinder(AsyncResultManager asyncResultManager) {
         mStrClassName = "InvalidPropertiesFinder";
         mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
+        this.asyncResultManager = asyncResultManager;
     }
 
     /**
@@ -63,12 +71,15 @@ public class InvalidPropertiesFinder {
      * @param lineLayerTemplates  线图层模版集合
      * @param checkConstraint     检查约束
      * @param projectConstraints  项目约束条件
+     * @param jobId               任务id
      * @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, Boolean checkConstraint, List<GisSurveyCondition> projectConstraints) throws InterruptedException {
+    public ListenableFuture<Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>>> findInvalidProperties(
+            List<Map<String, String>> points, List<Map<String, String>> lines
+            , List<GisMetadataLayerTemplate> pointLayerTemplates, List<GisMetadataLayerTemplate> lineLayerTemplates
+            , Boolean checkConstraint, List<GisSurveyCondition> projectConstraints
+            , String jobId) throws InterruptedException {
         LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始执行寻找无效属性   ======>");
         long begin = System.currentTimeMillis();
 
@@ -95,21 +106,25 @@ public class InvalidPropertiesFinder {
                         GisMetadataDefine.TYPE_KINE.POINT,
                         null,
                         point.get(GisSurveyExcelDefine.FILE.POINT_LAYER),
-                        null
+                        null,
+                        GisSurveyExcelDefine.MESSAGE.INVALID_LAYERS
                 ));
-            else
+            else {
                 //图层存在则检查图层
                 checkLayer(point, layerTemplate, checkConstraint, projectConstraints, missingRequirementsResult, invalidTypesResult, outConstraintResult);
-            //检查坐标超出范围
-            if (checkOutRanges(point, layerTemplate))
-                outRangesResult.add(
-                        new GisSurveyThirdImportElement(
-                                GisMetadataDefine.TYPE_KINE.POINT,
-                                ThirdImportTemplateUtils.getValue(point, layerTemplate, GisSurveyExcelDefine.TEMPLATE.NO),
-                                point.get(GisSurveyExcelDefine.FILE.POINT_LAYER),
-                                null
-                        )
-                );
+                //检查坐标超出范围
+                Boolean outRanged = checkOutRanges(point, layerTemplate);
+                if (outRanged == null || outRanged)
+                    outRangesResult.add(
+                            new GisSurveyThirdImportElement(
+                                    GisMetadataDefine.TYPE_KINE.POINT,
+                                    ThirdImportTemplateUtils.getValue(point, layerTemplate, GisSurveyExcelDefine.TEMPLATE.NO),
+                                    point.get(GisSurveyExcelDefine.FILE.POINT_LAYER),
+                                    null,
+                                    outRanged == null ? GisSurveyExcelDefine.MESSAGE.OUT_RANGES_NULL : GisSurveyExcelDefine.MESSAGE.OUT_RANGES
+                            )
+                    );
+            }
         }
         //检查线属性
         for (Map<String, String> line : lines) {
@@ -125,13 +140,24 @@ public class InvalidPropertiesFinder {
                         null,
                         null,
                         line.get(GisSurveyExcelDefine.FILE.LINE_LAYER),
-                        null
+                        null,
+                        GisSurveyExcelDefine.MESSAGE.INVALID_LAYERS
                 ));
             else
                 //图层存在则检查图层
                 checkLayer(line, layerTemplate, checkConstraint, projectConstraints, missingRequirementsResult, invalidTypesResult, outConstraintResult);
         }
 
+        //无效图层去重
+        invalidLayersResult = new ArrayList<>(invalidLayersResult.stream()
+                .filter(e -> Objects.nonNull(e.getLayerName()))
+                .collect(Collectors.toMap(
+                        GisSurveyThirdImportElement::getLayerName,
+                        it -> it,
+                        (it1, it2) -> it1
+                ))
+                .values());
+
         long end = System.currentTimeMillis();
         LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
                 , String.format(
@@ -140,14 +166,8 @@ public class InvalidPropertiesFinder {
                 )
         );
 
-        //构建结果
-        Map<String, List<GisSurveyThirdImportElement>> result = new HashMap<>();
-        result.put(GisSurveyExcelDefine.RESULT.INVALID_LAYERS, invalidLayersResult);
-        result.put(GisSurveyExcelDefine.RESULT.MISSING_REQUIREMENTS, missingRequirementsResult);
-        result.put(GisSurveyExcelDefine.RESULT.INVALID_TYPES, invalidTypesResult);
-        result.put(GisSurveyExcelDefine.RESULT.OUT_RANGES, outRangesResult);
-        result.put(GisSurveyExcelDefine.RESULT.OUT_CONSTRAINT, outConstraintResult);
-        return new AsyncResult<>(new GisSurveyThirdImportResultDetail<>(true, result));
+        return new AsyncResult<>(createResult(invalidLayersResult, missingRequirementsResult, invalidTypesResult,
+                outRangesResult, outConstraintResult, jobId, begin));
     }
 
     /**
@@ -161,9 +181,9 @@ public class InvalidPropertiesFinder {
         String latStr = ThirdImportTemplateUtils.getValue(point, layerTemplate, GisSurveyExcelDefine.TEMPLATE.LAT);
         String lngStr = ThirdImportTemplateUtils.getValue(point, layerTemplate, GisSurveyExcelDefine.TEMPLATE.LNG);
         //检查是否字符串
-        if (StringUtils.isBlank(latStr) || StringUtils.isBlank(lngStr)) return true;
+        if (StringUtils.isBlank(latStr) || StringUtils.isBlank(lngStr)) return null;
         //检查是否可解析
-        if (!NumberUtils.isParsable(latStr) || !NumberUtils.isParsable(lngStr)) return true;
+        if (!NumberUtils.isParsable(latStr) || !NumberUtils.isParsable(lngStr)) return null;
         //解析
         double lat = Double.parseDouble(latStr);
         double lng = Double.parseDouble(lngStr);
@@ -204,7 +224,8 @@ public class InvalidPropertiesFinder {
                 if (StringUtils.isBlank(value)) {
                     GisSurveyThirdImportElement gisSurveyThirdImportElement = GisSurveyThirdImportElement.create(data,
                             layerTemplate,
-                            propertyTemplate.getName()
+                            propertyTemplate.getName(),
+                            GisSurveyExcelDefine.MESSAGE.MISSING_REQUIREMENTS
                     );
                     missingRequirementsResult.add(gisSurveyThirdImportElement);
                     //值存在
@@ -220,7 +241,8 @@ public class InvalidPropertiesFinder {
                             && !NumberUtils.isParsable(value)) {
                         invalidTypesResult.add(GisSurveyThirdImportElement.create(data,
                                 layerTemplate,
-                                propertyTemplate.getName()
+                                propertyTemplate.getName(),
+                                GisSurveyExcelDefine.MESSAGE.INVALID_TYPES
                         ));
                     }
                 }
@@ -273,7 +295,8 @@ public class InvalidPropertiesFinder {
             //如列表不包含值,则超出约束
             if (!ranges.contains(value)) {
                 outConstraintResult.add(GisSurveyThirdImportElement.create(data, layerTemplate,
-                        propertyTemplate.getName(), value, constraint
+                        propertyTemplate.getName(), value, constraint,
+                        GisSurveyExcelDefine.MESSAGE.OUT_CONSTRAINT
                 ));
             }
         }
@@ -286,7 +309,9 @@ public class InvalidPropertiesFinder {
                 double min = Double.parseDouble(minStr);
                 if (!NumberUtils.isParsable(value) || Double.parseDouble(value) < min) {
                     outConstraintResult.add(GisSurveyThirdImportElement.create(data, layerTemplate,
-                            propertyTemplate.getName(), value, constraint));
+                            propertyTemplate.getName(), value, constraint,
+                            GisSurveyExcelDefine.MESSAGE.OUT_CONSTRAINT
+                    ));
                 }
             }
             //最大值判断
@@ -295,9 +320,106 @@ public class InvalidPropertiesFinder {
                 double max = Double.parseDouble(maxStr);
                 if (!NumberUtils.isParsable(value) || Double.parseDouble(value) > max) {
                     outConstraintResult.add(GisSurveyThirdImportElement.create(data, layerTemplate,
-                            propertyTemplate.getName(), value, constraint));
+                            propertyTemplate.getName(), value, constraint,
+                            GisSurveyExcelDefine.MESSAGE.OUT_CONSTRAINT
+                    ));
                 }
             }
         }
     }
+
+    /**
+     * 创建结果
+     *
+     * @param invalidLayersResult       无效图层结果
+     * @param missingRequirementsResult 缺失必填结果
+     * @param invalidTypesResult        无效类型结果
+     * @param outRangesResult           超出范围结果
+     * @param outConstraintResult       超出约束结果
+     * @param jobId                     任务id
+     * @param begin                     开始时间
+     * @return 结果
+     */
+    private Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>> createResult(
+            List<GisSurveyThirdImportElement> invalidLayersResult,
+            List<GisSurveyThirdImportElement> missingRequirementsResult,
+            List<GisSurveyThirdImportElement> invalidTypesResult,
+            List<GisSurveyThirdImportElement> outRangesResult,
+            List<GisSurveyThirdImportElement> outConstraintResult,
+            String jobId, long begin) {
+        long end = System.currentTimeMillis();
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                , String.format(
+                        "结束执行寻找无效线,用时(毫秒):%d"
+                        , (end - begin)
+                )
+        );
+
+        //结果flag
+        final String FLAG = GisSurveyThirdImporter.RESULT_PREFIX + jobId;
+
+        //无效图层构建excel和详情
+        Path invalidLayersExcelPath = asyncResultManager.writeExcel(GisSurveyThirdImportResultHead.INVALID_LAYERS,
+                buildExcel(invalidLayersResult), FLAG, GisSurveyThirdImportKeys.INVALID_LAYERS + ".xlsx");
+        GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>> invalidLayersDetail
+                = new GisSurveyThirdImportResultDetail<>(true, invalidLayersResult
+                , FLAG + "/" + invalidLayersExcelPath.getFileName());
+        //缺失必填构建excel和详情
+        Path missingRequirementsExcelPath = asyncResultManager.writeExcel(GisSurveyThirdImportResultHead.MISSING_REQUIREMENTS,
+                buildExcel(missingRequirementsResult), FLAG, GisSurveyThirdImportKeys.MISSING_REQUIREMENTS + ".xlsx");
+        GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>> missingRequirementsDetail
+                = new GisSurveyThirdImportResultDetail<>(true, missingRequirementsResult
+                , FLAG + "/" + missingRequirementsExcelPath.getFileName());
+        //无效类型构建excel和详情
+        Path invalidTypesExcelPath = asyncResultManager.writeExcel(GisSurveyThirdImportResultHead.INVALID_TYPES,
+                buildExcel(invalidTypesResult), FLAG, GisSurveyThirdImportKeys.INVALID_TYPES + ".xlsx");
+        GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>> invalidTypesDetail
+                = new GisSurveyThirdImportResultDetail<>(true, invalidTypesResult
+                , FLAG + "/" + invalidTypesExcelPath.getFileName());
+        //超出范围构建excel和详情
+        Path outRangesExcelPath = asyncResultManager.writeExcel(GisSurveyThirdImportResultHead.OUT_RANGES,
+                buildExcel(outRangesResult), FLAG, GisSurveyThirdImportKeys.OUT_RANGES + ".xlsx");
+        GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>> outRangesDetail
+                = new GisSurveyThirdImportResultDetail<>(true, outRangesResult
+                , FLAG + "/" + outRangesExcelPath.getFileName());
+        //超出约束构建excel和详情
+        Path outConstraintExcelPath = asyncResultManager.writeExcel(GisSurveyThirdImportResultHead.OUT_CONSTRAINT,
+                buildExcel(outConstraintResult), FLAG, GisSurveyThirdImportKeys.OUT_CONSTRAINT + ".xlsx");
+        GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>> outConstraintDetail
+                = new GisSurveyThirdImportResultDetail<>(true, outConstraintResult
+                , FLAG + "/" + outConstraintExcelPath.getFileName());
+
+        //构建结果
+        Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>> result = new HashMap<>();
+        result.put(GisSurveyThirdImportKeys.INVALID_LAYERS, invalidLayersDetail);
+        result.put(GisSurveyThirdImportKeys.MISSING_REQUIREMENTS, missingRequirementsDetail);
+        result.put(GisSurveyThirdImportKeys.INVALID_TYPES, invalidTypesDetail);
+        result.put(GisSurveyThirdImportKeys.OUT_RANGES, outRangesDetail);
+        result.put(GisSurveyThirdImportKeys.OUT_CONSTRAINT, outConstraintDetail);
+
+        return result;
+    }
+
+    /**
+     * 构建第三方导入excel数据
+     *
+     * @param data 数据
+     * @return excel数据
+     */
+    private List<Map<String, Object>> buildExcel(List<GisSurveyThirdImportElement> data) {
+        return data.stream().map(element -> {
+            Map<String, Object> map = new HashMap<>();
+            map.put(GisSurveyThirdImportResultHead.KEYS.KIND, element.getKind());
+            map.put(GisSurveyThirdImportResultHead.KEYS.LAYER_NAME, element.getLayerName());
+            map.put(GisSurveyThirdImportResultHead.KEYS.NO, element.getNo());
+            map.put(GisSurveyThirdImportResultHead.KEYS.UP_NO, element.getUpNO());
+            map.put(GisSurveyThirdImportResultHead.KEYS.DOWN_NO, element.getDownNO());
+            map.put(GisSurveyThirdImportResultHead.KEYS.PROPERTY_NAME, element.getPropertyName());
+            map.put(GisSurveyThirdImportResultHead.KEYS.VALUE, element.getValue());
+            if (element.getCondition() != null)
+                map.put(GisSurveyThirdImportResultHead.KEYS.CONDITION, element.getCondition().getRanges());
+            map.put(GisSurveyThirdImportResultHead.KEYS.MESSAGE, element.getMessage());
+            return map;
+        }).collect(Collectors.toList());
+    }
 }

+ 39 - 19
src/main/java/com/shkpr/service/alambizplugin/components/checker/IsolatedPointsFinder.java

@@ -4,31 +4,33 @@ 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.BeanUtil;
+import com.shkpr.service.alambizplugin.commtools.GeomUtil;
 import com.shkpr.service.alambizplugin.components.AsyncResultManager;
 import com.shkpr.service.alambizplugin.constants.GisSurveySystemCheckKeys;
 import com.shkpr.service.alambizplugin.constants.GisSurveySystemCheckResultHead;
+import com.shkpr.service.alambizplugin.constants.GisSurveyTemplateDefine;
 import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
 import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyLine;
 import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyPoint;
+import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckDefine;
 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.exception.UncheckedInterruptedException;
-import org.apache.commons.lang3.StringUtils;
 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.nio.file.Path;
+import java.util.AbstractMap;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.Set;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * 寻找孤立点
@@ -54,12 +56,17 @@ public class IsolatedPointsFinder {
      *
      * @param points        点集合
      * @param lines         线集合
+     * @param define        系统检查定义
      * @param systemCheckId 系统检查id
      * @return 孤立点集合
      */
     @Async
     public ListenableFuture<GisSurveySystemCheckResultDetail> findIsolatedPoints(List<GisSurveyLayerApplyPoint> points
-            , List<GisSurveyLayerApplyLine> lines, GisSurveySystemCheckId systemCheckId) throws InterruptedException {
+            , List<GisSurveyLayerApplyLine> lines, GisSurveySystemCheckDefine define, GisSurveySystemCheckId systemCheckId) throws InterruptedException {
+        //经纬度公差
+        double lngTolerance = GeomUtil.getTolerance(define, GisSurveyTemplateDefine.LNG);
+        double latTolerance = GeomUtil.getTolerance(define, GisSurveyTemplateDefine.LAT);
+
         LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始执行寻找孤立点========>");
         long begin = System.currentTimeMillis();
 
@@ -81,19 +88,24 @@ public class IsolatedPointsFinder {
             if (lines.isEmpty()) return new AsyncResult<>(createResult(Collections.emptyList(), systemCheckId, begin));
             //点为空,则无孤立点
             if (points.isEmpty()) return new AsyncResult<>(createResult(Collections.emptyList(), systemCheckId, begin));
-            //计算预期最大容量,避免频繁扩容
-            int expectedMaxSize = (int) (((long) lines.size() << 1) / .75f + 1);
-            //联通点code
-            Set<String> connectedPoints = new HashSet<>(expectedMaxSize);
-            //遍历所有线,标记参与的点
-            for (GisSurveyLayerApplyLine line : lines) {
-                //响应中断
-                if (Thread.interrupted()) throw new InterruptedException();
-                //上下游节点判空
-                if (StringUtils.isBlank(line.getUpNode()) || StringUtils.isBlank(line.getDownNode())) continue;
-                connectedPoints.add(line.getUpNode());
-                connectedPoints.add(line.getDownNode());
-            }
+            //联通线
+            Map<String, List<GisSurveyLayerApplyLine>> connectedLines = lines.parallelStream()
+                    //响应中断
+                    .peek(it -> {
+                        if (Thread.currentThread().isInterrupted())
+                            throw new UncheckedInterruptedException(new InterruptedException());
+                    })
+                    //上下节点分组
+                    .flatMap(line -> Stream.of(
+                            new AbstractMap.SimpleEntry<>(line.getUpNode(), line),
+                            new AbstractMap.SimpleEntry<>(line.getDownNode(), line)
+                    ))
+                    //过滤空,并合并
+                    .filter(it -> Objects.nonNull(it.getKey()) && Objects.nonNull(it.getValue()))
+                    .collect(Collectors.groupingBy(
+                            AbstractMap.SimpleEntry::getKey,
+                            Collectors.mapping(Map.Entry::getValue, Collectors.toList())
+                    ));
             //使用并行流找出孤立点
             List<GisSurveySystemCheckElement> elements = points.parallelStream()
                     //响应中断
@@ -101,10 +113,18 @@ public class IsolatedPointsFinder {
                         if (Thread.currentThread().isInterrupted())
                             throw new UncheckedInterruptedException(new InterruptedException());
                     })
+                    //排除空点
+                    .filter(point -> Objects.nonNull(point) && Objects.nonNull(point.getCode()))
+                    //过滤连通点
+                    .filter(point -> {
+                        //判断是否和线连通
+                        if (!connectedLines.containsKey(point.getCode())) return true;
+                        //遍历连通的线,判断是否有包含关系
+                        return connectedLines.get(point.getCode()).stream()
+                                .noneMatch(line -> GeomUtil.calcContain(line, point, lngTolerance, latTolerance));
+                    })
                     //转为返回元素
                     .map(point -> BeanUtil.copy(point, GisSurveySystemCheckElement.class))
-                    //过滤连通点
-                    .filter(element -> Objects.nonNull(element) && !connectedPoints.contains(element.getCode()))
                     .collect(Collectors.toList());
             return new AsyncResult<>(createResult(elements, systemCheckId, begin));
         } catch (UncheckedInterruptedException e) {

+ 10 - 10
src/main/java/com/shkpr/service/alambizplugin/components/checker/OverlapLinesFinder.java

@@ -15,7 +15,7 @@ import org.apache.commons.collections4.CollectionUtils;
 import org.locationtech.jts.algorithm.Orientation;
 import org.locationtech.jts.geom.Coordinate;
 import org.locationtech.jts.geom.LineSegment;
-import org.locationtech.jts.geom.LineString;
+import org.locationtech.jts.geom.MultiLineString;
 import org.locationtech.jts.index.strtree.STRtree;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.scheduling.annotation.AsyncResult;
@@ -77,7 +77,7 @@ public class OverlapLinesFinder {
         //元素存入索引
         for (GisSurveyLayerApplyLine layerApplyLine : lines) {
             if (layerApplyLine.getGis() == null) continue;
-            LineString line = layerApplyLine.getGis();
+            MultiLineString line = layerApplyLine.getGis();
             tree.insert(line.getEnvelopeInternal(), layerApplyLine);
         }
         tree.build();
@@ -154,10 +154,10 @@ public class OverlapLinesFinder {
      */
     public boolean calcFullOverlap(GisSurveyLayerApplyLine line1, GisSurveyLayerApplyLine line2) {
         //取出四个点
-        Coordinate a = line1.getGis().getCoordinateN(0);
-        Coordinate b = line1.getGis().getCoordinateN(1);
-        Coordinate c = line2.getGis().getCoordinateN(0);
-        Coordinate d = line2.getGis().getCoordinateN(1);
+        Coordinate a = line1.getGis().getCoordinates()[0];
+        Coordinate b = line1.getGis().getCoordinates()[1];
+        Coordinate c = line2.getGis().getCoordinates()[0];
+        Coordinate d = line2.getGis().getCoordinates()[1];
         if (a == null || b == null || c == null || d == null) return false;
         return (a.equals2D(c) && b.equals2D(d)) || (a.equals2D(d) && b.equals2D(c));
     }
@@ -171,10 +171,10 @@ public class OverlapLinesFinder {
      */
     public boolean calcPartialOverlap(GisSurveyLayerApplyLine line1, GisSurveyLayerApplyLine line2) {
         //取出四个点
-        Coordinate a = line1.getGis().getCoordinateN(0);
-        Coordinate b = line1.getGis().getCoordinateN(1);
-        Coordinate c = line2.getGis().getCoordinateN(0);
-        Coordinate d = line2.getGis().getCoordinateN(1);
+        Coordinate a = line1.getGis().getCoordinates()[0];
+        Coordinate b = line1.getGis().getCoordinates()[1];
+        Coordinate c = line2.getGis().getCoordinates()[0];
+        Coordinate d = line2.getGis().getCoordinates()[1];
         //点数量判断
         if (a == null || b == null || c == null || d == null) return false;
         //检查C和D是否在AB的直线上(叉积为0,则方向一致)

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

@@ -33,6 +33,7 @@ public class ApiURI {
     public static final String URI_XXX_THIRD_IMPORT_CANCEL = "third-import-cancel";
     public static final String URI_XXX_THIRD_IMPORT_PREVIEW = "third-import-preview";
     public static final String URI_XXX_THIRD_IMPORT_COMMIT = "third-import-commit";
+    public static final String URI_XXX_THIRD_IMPORT_COMMIT_GET = "third-import-commit-get";
     public static final String URI_XXX_THIRD_EXPORT = "third-export";
     public static final String URI_XXX_THIRD_EXPORT_GET = "third-export-get";
     public static final String URI_XXX_CAD_CONVERT = "cad-convert";

+ 5 - 1
src/main/java/com/shkpr/service/alambizplugin/constants/CommAsyncStatusEnum.java

@@ -27,7 +27,11 @@ public enum CommAsyncStatusEnum {
     /**
      * 不存在
      */
-    NOT_EXISTS(3);
+    NOT_EXISTS(3),
+    /**
+     * 结果错误
+     */
+    RESULT_ERROR(4);
     /**
      * code
      */

+ 42 - 7
src/main/java/com/shkpr/service/alambizplugin/constants/GisSurveyExcelDefine.java

@@ -63,13 +63,48 @@ public interface GisSurveyExcelDefine {
     }
 
     /**
-     * 结果key
+     * 原因
      */
-    interface RESULT {
-        String INVALID_LAYERS = "invalidLayersResult";
-        String MISSING_REQUIREMENTS = "missingRequirementsResult";
-        String INVALID_TYPES = "invalidTypesResult";
-        String OUT_RANGES = "outRangesResult";
-        String OUT_CONSTRAINT = "outConstraint";
+    interface MESSAGE {
+        /**
+         * 无效图层
+         */
+        String INVALID_LAYERS = "未找到该图层,请检查点/线类型是否在模版配置中";
+        /**
+         * 缺失必填
+         */
+        String MISSING_REQUIREMENTS = "必填项缺失,请检查是否有该字段或该字段是否为空";
+        /**
+         * 无效类型
+         */
+        String INVALID_TYPES = "值类型无效,无法解析为十进制数字";
+        /**
+         * 超出范围
+         */
+        String OUT_RANGES = "坐标点超出范围,请检查坐标值";
+        /**
+         * 超出范围(空值)
+         */
+        String OUT_RANGES_NULL = "坐标点解析失败,请检查坐标点值或坐标模版配置";
+        /**
+         * 超出约束
+         */
+        String OUT_CONSTRAINT = "值超出约束,请对照范围填写";
+        /**
+         * 重复点号
+         */
+        String DUPLICATE_POINTS = "点号重复,请去除重复数据";
+        /**
+         * 无效线
+         */
+        String INVALID_LINES = "点表中不存在该线上下游节点或该节点模板有问题";
+        /**
+         * 无效线(空值)
+         */
+        String INVALID_LINES_NULL = "线上下节点解析失败,请检查上下节点值或上下节点模版配置";
+        /**
+         * 无效线(全为无效线)
+         */
+        String INVALID_LINES_ALL = "点表为空,请完善线上下节点对应的点信息";
     }
 }

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

@@ -1,39 +0,0 @@
-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;
-}

+ 42 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/GisSurveyThirdImportKeys.java

@@ -0,0 +1,42 @@
+package com.shkpr.service.alambizplugin.constants;
+
+/**
+ * 第三方导入key
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+public interface GisSurveyThirdImportKeys {
+    /**
+     * 无效属性
+     */
+    String INVALID_PROPERTIES = "InvalidProperties";
+    /**
+     * 无效图层
+     */
+    String INVALID_LAYERS = "invalidLayers";
+    /**
+     * 缺失必填
+     */
+    String MISSING_REQUIREMENTS = "missingRequirements";
+    /**
+     * 无效类型
+     */
+    String INVALID_TYPES = "invalidTypes";
+    /**
+     * 超出范围
+     */
+    String OUT_RANGES = "outRanges";
+    /**
+     * 超出约束
+     */
+    String OUT_CONSTRAINT = "outConstraint";
+    /**
+     * 重复点号
+     */
+    String DUPLICATE_POINTS = "duplicatePoints";
+    /**
+     * 无效线
+     */
+    String INVALID_LINES = "invalidLines";
+}

+ 134 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/GisSurveyThirdImportResultHead.java

@@ -0,0 +1,134 @@
+package com.shkpr.service.alambizplugin.constants;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * 第三方导入结果表头
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+public class GisSurveyThirdImportResultHead {
+    /**
+     * 无效图层
+     */
+    public final static Map<String, String> INVALID_LAYERS = new LinkedHashMap<String, String>() {{
+        put(KEYS.KIND, "元素分类");
+        put(KEYS.LAYER_NAME, "图层名称");
+        put(KEYS.MESSAGE, "原因");
+    }};
+
+    /**
+     * 缺失必填
+     */
+    public final static Map<String, String> MISSING_REQUIREMENTS = new LinkedHashMap<String, String>() {{
+        put(KEYS.KIND, "元素分类");
+        put(KEYS.LAYER_NAME, "图层名称");
+        put(KEYS.NO, "点号");
+        put(KEYS.UP_NO, "起点号");
+        put(KEYS.DOWN_NO, "终点号");
+        put(KEYS.PROPERTY_NAME, "属性名称");
+        put(KEYS.MESSAGE, "原因");
+    }};
+
+    /**
+     * 无效类型
+     */
+    public final static Map<String, String> INVALID_TYPES = new LinkedHashMap<String, String>() {{
+        put(KEYS.KIND, "元素分类");
+        put(KEYS.LAYER_NAME, "图层名称");
+        put(KEYS.NO, "点号");
+        put(KEYS.UP_NO, "起点号");
+        put(KEYS.DOWN_NO, "终点号");
+        put(KEYS.PROPERTY_NAME, "属性名称");
+        put(KEYS.MESSAGE, "原因");
+    }};
+
+    /**
+     * 超出范围
+     */
+    public final static Map<String, String> OUT_RANGES = new LinkedHashMap<String, String>() {{
+        put(KEYS.KIND, "元素分类");
+        put(KEYS.LAYER_NAME, "图层名称");
+        put(KEYS.NO, "点号");
+        put(KEYS.MESSAGE, "原因");
+    }};
+
+    /**
+     * 超出约束
+     */
+    public final static Map<String, String> OUT_CONSTRAINT = new LinkedHashMap<String, String>() {{
+        put(KEYS.KIND, "元素分类");
+        put(KEYS.LAYER_NAME, "图层名称");
+        put(KEYS.NO, "点号");
+        put(KEYS.UP_NO, "起点号");
+        put(KEYS.DOWN_NO, "终点号");
+        put(KEYS.PROPERTY_NAME, "属性名称");
+        put(KEYS.VALUE, "值");
+        put(KEYS.CONDITION, "范围");
+        put(KEYS.MESSAGE, "原因");
+    }};
+
+    /**
+     * 重复点
+     */
+    public final static Map<String, String> DUPLICATE_POINTS = new LinkedHashMap<String, String>() {{
+        put(KEYS.KIND, "元素分类");
+        put(KEYS.NO, "点号");
+        put(KEYS.MESSAGE, "原因");
+    }};
+
+    /**
+     * 无效线
+     */
+    public final static Map<String, String> INVALID_LINES = new LinkedHashMap<String, String>() {{
+        put(KEYS.LAYER_NAME, "图层名称");
+        put(KEYS.UP_NO, "起点号");
+        put(KEYS.DOWN_NO, "终点号");
+        put(KEYS.PROPERTY_NAME, "属性名称");
+        put(KEYS.MESSAGE, "原因");
+    }};
+
+    /**
+     * 键
+     */
+    public interface KEYS {
+        /**
+         * 点号
+         */
+        String NO = "no";
+        /**
+         * 起点号
+         */
+        String UP_NO = "upNo";
+        /**
+         * 终点号
+         */
+        String DOWN_NO = "downNo";
+        /**
+         * 元素分类
+         */
+        String KIND = "kind";
+        /**
+         * 图层名称
+         */
+        String LAYER_NAME = "layerName";
+        /**
+         * 属性名称
+         */
+        String PROPERTY_NAME = "propertyName";
+        /**
+         * 值
+         */
+        String VALUE = "value";
+        /**
+         * 约束条件
+         */
+        String CONDITION = "condition";
+        /**
+         * 原因
+         */
+        String MESSAGE = "message";
+    }
+}

+ 122 - 28
src/main/java/com/shkpr/service/alambizplugin/controller/ApiGisSurveyController.java

@@ -20,19 +20,18 @@ import com.shkpr.service.alambizplugin.constants.CadEnum;
 import com.shkpr.service.alambizplugin.constants.CommAsyncStatusEnum;
 import com.shkpr.service.alambizplugin.constants.CommCRSDefine;
 import com.shkpr.service.alambizplugin.constants.FileTypeEnum;
-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.controllerserializer.GeometrySerializer;
 import com.shkpr.service.alambizplugin.controllervalid.CommonParamValidSK;
 import com.shkpr.service.alambizplugin.dbdao.services.GisSurveyLayerApplyThirdCopyServiceImpl;
-import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveyLayerApplyService;
 import com.shkpr.service.alambizplugin.dto.CommAsyncResult;
 import com.shkpr.service.alambizplugin.dto.CommCRSInfo;
 import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyThirdCopy;
 import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckResultDetail;
-import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportResult;
+import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportElement;
+import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportResultDetail;
 import com.shkpr.service.alambizplugin.dto.PageResponse;
 import com.shkpr.service.alambizplugin.dto.ResponseRes;
 import com.shkpr.service.alambizplugin.exception.SelfException;
@@ -72,6 +71,7 @@ public class ApiGisSurveyController {
     private final AtomicInteger mSeqThirdImportCancelReq;
     private final AtomicInteger mSeqThirdImportPreviewReq;
     private final AtomicInteger mSeqThirdImportCommitReq;
+    private final AtomicInteger mSeqThirdImportCommitGetReq;
     private final AtomicInteger mSeqCadConvertReq;
     private final AtomicInteger mSeqThirdExportReq;
     private final AtomicInteger mSeqThirdExportGetReq;
@@ -85,7 +85,6 @@ public class ApiGisSurveyController {
     private final GisSurveyThirdImportBizService thirdImportBizService;
     private final GisSurveyThirdExportBizService thirdExportBizService;
     private final GisSurveyCadConvertBizService cadConvertBizService;
-    private final GisSurveyLayerApplyService layerApplyService;
     private final GisSurveyLayerApplyThirdCopyServiceImpl layerApplyThirdCopyService;
 
     public ApiGisSurveyController(ObjectMapper objectMapper
@@ -93,7 +92,6 @@ public class ApiGisSurveyController {
             , GisSurveyThirdImportBizService thirdImportBizService
             , GisSurveyThirdExportBizService thirdExportBizService
             , GisSurveyCadConvertBizService cadConvertBizService
-            , GisSurveyLayerApplyService layerApplyService
             , GisSurveyLayerApplyThirdCopyServiceImpl layerApplyThirdCopyService) {
         mStrClassName = "ApiGisSurveyController";
         mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
@@ -104,6 +102,7 @@ public class ApiGisSurveyController {
         mSeqThirdImportCancelReq = new AtomicInteger(0);
         mSeqThirdImportPreviewReq = new AtomicInteger(0);
         mSeqThirdImportCommitReq = new AtomicInteger(0);
+        mSeqThirdImportCommitGetReq = new AtomicInteger(0);
         mSeqThirdExportReq = new AtomicInteger(0);
         mSeqThirdExportGetReq = new AtomicInteger(0);
         mSeqCadConvertReq = new AtomicInteger(0);
@@ -115,7 +114,6 @@ public class ApiGisSurveyController {
         this.thirdImportBizService = thirdImportBizService;
         this.thirdExportBizService = thirdExportBizService;
         this.cadConvertBizService = cadConvertBizService;
-        this.layerApplyService = layerApplyService;
         this.layerApplyThirdCopyService = layerApplyThirdCopyService;
     }
 
@@ -279,7 +277,6 @@ public class ApiGisSurveyController {
      * @param nature        用水性质,supply/drain
      * @param sourceCRSCode 源坐标系code
      * @param resetNo       是否重置点号
-     * @param ignoreFail    是否忽略失败
      * @return 第三方导入结果
      */
     @PostMapping(value = ApiURI.URI_XXX_THIRD_IMPORT)
@@ -292,8 +289,7 @@ public class ApiGisSurveyController {
             , @RequestParam(value = "nature", required = false) String nature
             , @RequestParam(value = "sourceCRSCode", required = false, defaultValue = CommCRSDefine.CGCS2000) String sourceCRSCode
             , @RequestParam(value = "resetNo", required = false) Boolean resetNo
-            , @RequestParam(value = "checkConstraint", required = false, defaultValue = "false") Boolean checkConstraint
-            , @RequestParam(value = "ignoreFail", required = false, defaultValue = "false") String ignoreFail) throws SelfException {
+            , @RequestParam(value = "checkConstraint", required = false, defaultValue = "false") Boolean checkConstraint) throws SelfException {
         //入参校验
         final String URI_PATH = request.getRequestURI();
         final String strPlatform = CommTool.getPlatformByAgent(strClientType, strUserAgent);
@@ -308,7 +304,7 @@ public class ApiGisSurveyController {
         }
         //构建入参数
         GisSurveyThirdImportParams params = new GisSurveyThirdImportParams(files, operator, jobId, nature, sourceCRSCode,
-                resetNo, checkConstraint, Boolean.parseBoolean(ignoreFail));
+                resetNo, checkConstraint);
         //begin
         long llReqBefore = System.currentTimeMillis();
         String strRunSeq = String.format("%d-%d", llReqBefore, mSeqThirdImportReq.incrementAndGet());
@@ -324,7 +320,8 @@ public class ApiGisSurveyController {
         resResult.setResmsg(ResponseCode.RESULT_ASYNC_TASK_FAILED.toStrMsg());
 
         //执行第三方导入
-        GisSurveyThirdImportResult result = thirdImportBizService.thirdImport(params);
+        CommAsyncResult<Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>>>
+                result = thirdImportBizService.thirdImport(params);
         String resultStr = null;
         try {
             if (result != null) resultStr = objectMapper.writeValueAsString(result);
@@ -334,13 +331,13 @@ public class ApiGisSurveyController {
         }
 
         //执行成功
-        if (resultStr != null && !Objects.equals(result.getImportStatus(), GisSurveyImportStatusEnum.FAIL.getCode())) {
+        if (resultStr != null && !Objects.equals(result.getStatus(), CommAsyncStatusEnum.FAIL.getCode())) {
             resResult.setRescode(ResponseCode.RESULT_NORMAL.toStrCode());
             resResult.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg());
             resResult.setResdata(resultStr);
         }
         //执行失败
-        if (resultStr != null && Objects.equals(result.getImportStatus(), GisSurveyImportStatusEnum.FAIL.getCode())) {
+        if (resultStr != null && Objects.equals(result.getStatus(), CommAsyncStatusEnum.FAIL.getCode())) {
             resResult.setResdata(resultStr);
         }
         //结果为空
@@ -369,15 +366,13 @@ public class ApiGisSurveyController {
      * @param strClientType 客户端类型
      * @param strUserAgent  用户信息
      * @param jobId         任务id
-     * @param ignoreFail    是否忽略错误
      * @return 第三方导入结果
      */
     @GetMapping(value = ApiURI.URI_XXX_THIRD_IMPORT_GET)
     public ResponseRes<String> thirdImportGet(HttpServletRequest request
             , @RequestHeader(value = ApiURI.HEADER_CLIENT_TYPE, required = false) String strClientType
             , @RequestHeader(value = ApiURI.HEADER_USER_AGENT, required = false) String strUserAgent
-            , @RequestParam(value = "jobId", required = false) String jobId
-            , @RequestParam(value = "ignoreFail", required = false, defaultValue = "false") String ignoreFail) throws SelfException {
+            , @RequestParam(value = "jobId", required = false) String jobId) throws SelfException {
         //入参校验
         final String URI_PATH = request.getRequestURI();
         final String strPlatform = CommTool.getPlatformByAgent(strClientType, strUserAgent);
@@ -391,7 +386,7 @@ public class ApiGisSurveyController {
         }
 
         //构建入参数
-        GisSurveyThirdImportParams params = new GisSurveyThirdImportParams(jobId, Boolean.parseBoolean(ignoreFail));
+        GisSurveyThirdImportParams params = new GisSurveyThirdImportParams(jobId);
         //begin
         long llReqBefore = System.currentTimeMillis();
         String strRunSeq = String.format("%d-%d", llReqBefore, mSeqThirdImportGetReq.incrementAndGet());
@@ -407,8 +402,9 @@ public class ApiGisSurveyController {
         resResult.setRescode(ResponseCode.RESULT_ASYNC_TASK_FAILED.toStrCode());
         resResult.setResmsg(ResponseCode.RESULT_ASYNC_TASK_FAILED.toStrMsg());
 
-        //执行cad转换
-        GisSurveyThirdImportResult result = thirdImportBizService.getResult(params);
+        //执行
+        CommAsyncResult<Map<String, GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>>>
+                result = thirdImportBizService.getImportResult(params);
         String resultStr = null;
         try {
             if (result != null) resultStr = objectMapper.writeValueAsString(result);
@@ -418,13 +414,13 @@ public class ApiGisSurveyController {
         }
 
         //执行成功
-        if (resultStr != null && !Objects.equals(result.getImportStatus(), CommAsyncStatusEnum.FAIL.getCode())) {
+        if (resultStr != null && !Objects.equals(result.getStatus(), CommAsyncStatusEnum.FAIL.getCode())) {
             resResult.setRescode(ResponseCode.RESULT_NORMAL.toStrCode());
             resResult.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg());
             resResult.setResdata(resultStr);
         }
         //执行失败
-        if (resultStr != null && Objects.equals(result.getImportStatus(), CommAsyncStatusEnum.FAIL.getCode())) {
+        if (resultStr != null && Objects.equals(result.getStatus(), CommAsyncStatusEnum.FAIL.getCode())) {
             resResult.setResdata(resultStr);
         }
         //不存在
@@ -581,18 +577,18 @@ public class ApiGisSurveyController {
 
 
     /**
-     * 提交第三方导入
+     * 第三方导入提交
      *
      * @param request       request
      * @param strClientType 客户端类型
      * @param strUserAgent  用户信息
      * @param jobId         任务id
      * @param operator      操作人
-     * @return 清除状态
+     * @return 提交状态
      * @throws SelfException selfException
      */
     @GetMapping(value = ApiURI.URI_XXX_THIRD_IMPORT_COMMIT)
-    public ResponseRes<?> commitImport(HttpServletRequest request
+    public ResponseRes<String> 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, @RequestParam("operator") String operator) throws Exception {
@@ -618,16 +614,114 @@ public class ApiGisSurveyController {
                         , strRunSeq
                         , jobId));
         //构建result
-        ResponseRes<?> resResult = new ResponseRes<>();
+        ResponseRes<String> resResult = new ResponseRes<>();
         resResult.setRescode(ResponseCode.RESULT_ASYNC_TASK_FAILED.toStrCode());
         resResult.setResmsg(ResponseCode.RESULT_ASYNC_TASK_FAILED.toStrMsg());
 
         //提交导入
-        Boolean commitStatus = layerApplyService.mergeCopy(jobId, operator);
-        //成功
-        if (Objects.equals(commitStatus, Boolean.TRUE)) {
+        CommAsyncResult<Boolean> result = thirdImportBizService.commitImport(jobId, operator);
+        String resultStr = null;
+        try {
+            if (result != null) resultStr = objectMapper.writeValueAsString(result);
+        } catch (JsonProcessingException e) {
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
+                    , String.format("Json序列化异常: error:%s", e));
+        }
+
+        //执行成功
+        if (resultStr != null && !Objects.equals(result.getStatus(), CommAsyncStatusEnum.FAIL.getCode())) {
+            resResult.setRescode(ResponseCode.RESULT_NORMAL.toStrCode());
+            resResult.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg());
+            resResult.setResdata(resultStr);
+        }
+        //执行失败
+        if (resultStr != null && Objects.equals(result.getStatus(), CommAsyncStatusEnum.FAIL.getCode())) {
+            resResult.setResdata(resultStr);
+        }
+        //不存在
+        if (resultStr == null) {
+            resResult.setRescode(ResponseCode.RESULT_ASYNC_TASK_NOT_FOUND.toStrCode());
+            resResult.setResmsg(ResponseCode.RESULT_ASYNC_TASK_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_GET)
+    public ResponseRes<String> 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) || StringUtils.length(jobId) > 64) {
+            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, mSeqThirdImportCommitGetReq.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<String> resResult = new ResponseRes<>();
+        resResult.setRescode(ResponseCode.RESULT_ASYNC_TASK_FAILED.toStrCode());
+        resResult.setResmsg(ResponseCode.RESULT_ASYNC_TASK_FAILED.toStrMsg());
+
+        //提交导入
+        CommAsyncResult<Boolean> result = thirdImportBizService.getCommitResult(jobId);
+        String resultStr = null;
+        try {
+            if (result != null) resultStr = objectMapper.writeValueAsString(result);
+        } catch (JsonProcessingException e) {
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
+                    , String.format("Json序列化异常: error:%s", e));
+        }
+
+        //执行成功
+        if (resultStr != null && !Objects.equals(result.getStatus(), CommAsyncStatusEnum.FAIL.getCode())) {
             resResult.setRescode(ResponseCode.RESULT_NORMAL.toStrCode());
             resResult.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg());
+            resResult.setResdata(resultStr);
+        }
+        //执行失败
+        if (resultStr != null && Objects.equals(result.getStatus(), CommAsyncStatusEnum.FAIL.getCode())) {
+            resResult.setResdata(resultStr);
+        }
+        //不存在
+        if (resultStr == null) {
+            resResult.setRescode(ResponseCode.RESULT_ASYNC_TASK_NOT_FOUND.toStrCode());
+            resResult.setResmsg(ResponseCode.RESULT_ASYNC_TASK_NOT_FOUND.toStrMsg());
         }
 
         //end

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

@@ -27,6 +27,7 @@ public class ApiJWTGisSurveyBizFilter extends JWTAuthenticationFilter {
         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_PREVIEW), "GET");
         msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_GIS_SURVEY_H, ApiURI.URI_XXX_THIRD_IMPORT_COMMIT), "GET");
+        msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_GIS_SURVEY_H, ApiURI.URI_XXX_THIRD_IMPORT_COMMIT_GET), "GET");
         msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_GIS_SURVEY_H, ApiURI.URI_XXX_THIRD_EXPORT), "POST");
         msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_GIS_SURVEY_H, ApiURI.URI_XXX_THIRD_EXPORT_GET), "GET");
         msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_GIS_SURVEY_H, ApiURI.URI_XXX_CAD_CONVERT), "POST");

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

@@ -16,36 +16,36 @@ import org.apache.ibatis.cursor.Cursor;
 @Mapper
 public interface GisSurveyLayerApplyMapper {
     /**
-     * 根据项目id查询新增点
+     * 根据项目id查询新增/修改
      *
      * @param projId 项目id
      * @return 点集合
      */
-    Cursor<GisSurveyLayerApplyPoint> findAddPointByProjId(@Param("projId") String projId);
+    Cursor<GisSurveyLayerApplyPoint> findAddUpdatePointByProjId(@Param("projId") String projId);
 
     /**
-     * 根据项目id查询新增线
+     * 根据项目id查询新增/修改线
      *
      * @param projId 项目id
      * @return 线集合
      */
-    Cursor<GisSurveyLayerApplyLine> findAddLineByProjId(@Param("projId") String projId);
+    Cursor<GisSurveyLayerApplyLine> findAddUpdateLineByProjId(@Param("projId") String projId);
 
     /**
-     * 根据任务id查询新增点
+     * 根据任务id查询新增/修改
      *
      * @param jobId 任务id
      * @return 点集合
      */
-    Cursor<GisSurveyLayerApplyPoint> findAddPointByJobId(@Param("jobId") String jobId);
+    Cursor<GisSurveyLayerApplyPoint> findAddUpdatePointByJobId(@Param("jobId") String jobId);
 
     /**
-     * 根据任务id查询新增线
+     * 根据任务id查询新增/修改线
      *
      * @param jobId 任务id
      * @return 线集合
      */
-    Cursor<GisSurveyLayerApplyLine> findAddLineByJobId(@Param("jobId") String jobId);
+    Cursor<GisSurveyLayerApplyLine> findAddUpdateLineByJobId(@Param("jobId") String jobId);
 
     /**
      * 根据任务id和类型查询

+ 0 - 107
src/main/java/com/shkpr/service/alambizplugin/dbdao/pgtype/GeomLineStringTypeHandlePg.java

@@ -1,107 +0,0 @@
-package com.shkpr.service.alambizplugin.dbdao.pgtype;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.ibatis.type.BaseTypeHandler;
-import org.apache.ibatis.type.JdbcType;
-import org.apache.ibatis.type.MappedJdbcTypes;
-import org.apache.ibatis.type.MappedTypes;
-import org.locationtech.jts.geom.Coordinate;
-import org.locationtech.jts.geom.GeometryFactory;
-import org.locationtech.jts.geom.LineString;
-import org.locationtech.jts.geom.PrecisionModel;
-
-import java.io.IOException;
-import java.math.BigDecimal;
-import java.sql.CallableStatement;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-/**
- * 地理线段类型处理器
- *
- * @author 欧阳劲驰
- * @since 1.0.0
- */
-@MappedTypes({LineString.class})
-@MappedJdbcTypes(JdbcType.VARCHAR)
-public class GeomLineStringTypeHandlePg extends BaseTypeHandler<LineString> {
-    private static final GeometryFactory factory = new GeometryFactory(new PrecisionModel(), 4490);
-    private static final ObjectMapper objectMapper = new ObjectMapper();
-
-    /**
-     * 解析
-     *
-     * @param lineStr 值
-     * @return 线段
-     * @throws SQLException sql异常
-     */
-    public static LineString parseLineString(String lineStr) throws SQLException {
-        //非空校验
-        if (lineStr == null || lineStr.isEmpty()) return null;
-        try {
-            //序列化
-            double[][] coordinates = objectMapper.readValue(lineStr, double[][].class);
-            //判断格式
-            if (coordinates.length == 2 && coordinates[0].length == 2 && coordinates[1].length == 2) {
-                //获取值
-                double x0 = coordinates[0][0];
-                double y0 = coordinates[0][1];
-                double x1 = coordinates[1][0];
-                double y1 = coordinates[1][1];
-                //构建线
-                return factory.createLineString(new Coordinate[]{new Coordinate(x0, y0), new Coordinate(x1, y1)});
-            }
-        } catch (IOException e) {
-            throw new SQLException("线段格式无效: " + lineStr);
-        }
-        throw new SQLException("线段格式无效: " + lineStr);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void setNonNullParameter(PreparedStatement ps, int i, LineString lineString, JdbcType jdbcType)
-            throws SQLException {
-        //将 LineString 序列化为 [[x1,y1],[x2,y2]] 字符串
-        if (lineString != null && lineString.getCoordinates() != null && lineString.getCoordinates().length == 2) {
-            Coordinate p0 = lineString.getCoordinateN(0);
-            Coordinate p1 = lineString.getCoordinateN(1);
-            String value = String.format("[[%s,%s],[%s,%s]]",
-                    BigDecimal.valueOf(p0.x).toPlainString(),
-                    BigDecimal.valueOf(p0.y).toPlainString(),
-                    BigDecimal.valueOf(p1.x).toPlainString(),
-                    BigDecimal.valueOf(p1.y).toPlainString()
-            );
-            ps.setString(i, value);
-        } else {
-            //处理空值
-            ps.setNull(i, JdbcType.VARCHAR.TYPE_CODE);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public LineString getNullableResult(ResultSet rs, String columnName) throws SQLException {
-        return rs.wasNull() ? null : parseLineString(rs.getString(columnName));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public LineString getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
-        return rs.wasNull() ? null : parseLineString(rs.getString(columnIndex));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public LineString getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
-        return cs.wasNull() ? null : parseLineString(cs.getString(columnIndex));
-    }
-}

+ 109 - 0
src/main/java/com/shkpr/service/alambizplugin/dbdao/pgtype/GeomMultiLineStringTypeHandlePg.java

@@ -0,0 +1,109 @@
+package com.shkpr.service.alambizplugin.dbdao.pgtype;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.shkpr.service.alambizplugin.commtools.GeomUtil;
+import org.apache.ibatis.type.BaseTypeHandler;
+import org.apache.ibatis.type.JdbcType;
+import org.apache.ibatis.type.MappedJdbcTypes;
+import org.apache.ibatis.type.MappedTypes;
+import org.locationtech.jts.geom.MultiLineString;
+
+import java.io.IOException;
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * 地理多线类型处理器
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@MappedTypes({MultiLineString.class})
+@MappedJdbcTypes(JdbcType.VARCHAR)
+public class GeomMultiLineStringTypeHandlePg extends BaseTypeHandler<MultiLineString> {
+    private static final ObjectMapper objectMapper = new ObjectMapper();
+
+    /**
+     * 解析
+     *
+     * @param lineStr 值
+     * @return 多线
+     * @throws SQLException sql异常
+     */
+    public static MultiLineString parseString(String lineStr) throws SQLException {
+        //非空校验
+        if (lineStr == null || lineStr.isEmpty()) return null;
+        try {
+            //序列化
+            double[][][] array = objectMapper.readValue(lineStr, double[][][].class);
+            //构建线
+            return GeomUtil.ofArray(array);
+        } catch (IOException e) {
+            throw new SQLException("多线格式无效: " + lineStr);
+        }
+    }
+
+    /**
+     * 从多线对象转数据库字符串
+     *
+     * @param multiLineString 多线
+     * @return 字符串
+     * @throws SQLException sql异常
+     */
+    public static String toString(MultiLineString multiLineString) throws SQLException {
+        if (multiLineString == null) return null;
+        try {
+            //转数组
+            double[][][] array = GeomUtil.toArray(multiLineString);
+            //反序列化
+            return objectMapper.writeValueAsString(array);
+        } catch (IOException e) {
+            throw new SQLException("多线格式无效: " + multiLineString);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setNonNullParameter(PreparedStatement ps, int i, MultiLineString multiLineString, JdbcType jdbcType)
+            throws SQLException {
+        if (multiLineString != null && multiLineString.getCoordinates() != null) {
+            //将点序列化化为字符串
+            String lineStr = toString(multiLineString);
+            if (lineStr != null) {
+                ps.setString(i, lineStr);
+                return;
+            }
+        }
+        //处理空值
+        ps.setNull(i, JdbcType.VARCHAR.TYPE_CODE);
+
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public MultiLineString getNullableResult(ResultSet rs, String columnName) throws SQLException {
+        return rs.wasNull() ? null : parseString(rs.getString(columnName));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public MultiLineString getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
+        return rs.wasNull() ? null : parseString(rs.getString(columnIndex));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public MultiLineString getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
+        return cs.wasNull() ? null : parseString(cs.getString(columnIndex));
+    }
+}

+ 40 - 20
src/main/java/com/shkpr/service/alambizplugin/dbdao/pgtype/GeomPointTypeHandlePg.java

@@ -1,6 +1,7 @@
 package com.shkpr.service.alambizplugin.dbdao.pgtype;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.shkpr.service.alambizplugin.commtools.GeomUtil;
 import org.apache.ibatis.type.BaseTypeHandler;
 import org.apache.ibatis.type.JdbcType;
 import org.apache.ibatis.type.MappedJdbcTypes;
@@ -11,7 +12,6 @@ import org.locationtech.jts.geom.Point;
 import org.locationtech.jts.geom.PrecisionModel;
 
 import java.io.IOException;
-import java.math.BigDecimal;
 import java.sql.CallableStatement;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
@@ -37,19 +37,18 @@ public class GeomPointTypeHandlePg extends BaseTypeHandler<Point> {
      * @return 点
      * @throws SQLException sql异常
      */
-    public static Point parsePoint(String pointStr) throws SQLException {
+    public static Point parseString(String pointStr) throws SQLException {
         //非空校验
         if (pointStr == null || pointStr.isEmpty()) return null;
         try {
             //序列化
-            double[] coordinate = objectMapper.readValue(pointStr, double[].class);
+            double[] array = objectMapper.readValue(pointStr, double[].class);
             //判断格式
-            if (coordinate.length == 2) {
-                //获取值
-                double longitude = coordinate[0];
-                double latitude = coordinate[1];
+            if (array.length == 2) {
+                //转坐标
+                Coordinate coordinate = GeomUtil.ofArray(array);
                 //构建点
-                return factory.createPoint(new Coordinate(longitude, latitude));
+                return factory.createPoint(coordinate);
             }
         } catch (IOException e) {
             throw new SQLException("点格式无效: " + pointStr);
@@ -58,21 +57,42 @@ public class GeomPointTypeHandlePg extends BaseTypeHandler<Point> {
     }
 
     /**
+     * 从Point对象转数据库字符串
+     *
+     * @param point 点
+     * @return 字符串
+     * @throws SQLException sql异常
+     */
+    public static String toString(Point point) throws SQLException {
+        if (point == null) return null;
+        //获取坐标
+        Coordinate coordinate = point.getCoordinate();
+        if (coordinate == null) return null;
+        try {
+            //转数组
+            double[] array = GeomUtil.toArray(coordinate);
+            //反序列化
+            return objectMapper.writeValueAsString(array);
+        } catch (IOException e) {
+            throw new SQLException("点格式无效: " + point);
+        }
+    }
+
+    /**
      * 将Java类型Point写入数据库
      */
     @Override
     public void setNonNullParameter(PreparedStatement ps, int i, Point point, JdbcType jdbcType) throws SQLException {
         if (point != null && point.getCoordinate() != null) {
-            //将 Point 序列化化为 [x,y] 字符串
-            String pointStr = String.format("[%s,%s]",
-                    BigDecimal.valueOf(point.getX()).toPlainString(),
-                    BigDecimal.valueOf(point.getY()).toPlainString()
-            );
-            ps.setString(i, pointStr);
-        } else {
-            //处理空值
-            ps.setNull(i, Types.VARCHAR);
+            //将点序列化化为字符串
+            String pointStr = toString(point);
+            if (pointStr != null) {
+                ps.setString(i, pointStr);
+                return;
+            }
         }
+        //处理空值
+        ps.setNull(i, Types.VARCHAR);
     }
 
     /**
@@ -81,7 +101,7 @@ public class GeomPointTypeHandlePg extends BaseTypeHandler<Point> {
     @Override
     public Point getNullableResult(ResultSet rs, String columnName) throws SQLException {
         String pointStr = rs.getString(columnName);
-        return rs.wasNull() ? null : parsePoint(pointStr);
+        return rs.wasNull() ? null : parseString(pointStr);
     }
 
     /**
@@ -90,7 +110,7 @@ public class GeomPointTypeHandlePg extends BaseTypeHandler<Point> {
     @Override
     public Point getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
         String pointStr = rs.getString(columnIndex);
-        return rs.wasNull() ? null : parsePoint(pointStr);
+        return rs.wasNull() ? null : parseString(pointStr);
     }
 
     /**
@@ -99,6 +119,6 @@ public class GeomPointTypeHandlePg extends BaseTypeHandler<Point> {
     @Override
     public Point getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
         String pointStr = cs.getString(columnIndex);
-        return cs.wasNull() ? null : parsePoint(pointStr);
+        return cs.wasNull() ? null : parseString(pointStr);
     }
 }

+ 54 - 54
src/main/java/com/shkpr/service/alambizplugin/dbdao/pgtype/GeomTypeHandlePg.java

@@ -6,13 +6,11 @@ import org.apache.ibatis.type.BaseTypeHandler;
 import org.apache.ibatis.type.JdbcType;
 import org.apache.ibatis.type.MappedJdbcTypes;
 import org.apache.ibatis.type.MappedTypes;
-import org.locationtech.jts.geom.Coordinate;
 import org.locationtech.jts.geom.Geometry;
-import org.locationtech.jts.geom.LineString;
+import org.locationtech.jts.geom.MultiLineString;
 import org.locationtech.jts.geom.Point;
 
 import java.io.IOException;
-import java.math.BigDecimal;
 import java.sql.CallableStatement;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
@@ -29,54 +27,6 @@ import java.sql.SQLException;
 public class GeomTypeHandlePg extends BaseTypeHandler<Geometry> {
     private static final ObjectMapper objectMapper = new ObjectMapper();
 
-    @Override
-    public void setNonNullParameter(PreparedStatement ps, int i, Geometry geometry, JdbcType jdbcType) throws SQLException {
-        if (geometry instanceof Point) {
-            //将 Point 序列化化为 [x,y] 字符串
-            Point point = (Point) geometry;
-            if (point.getCoordinate() != null) {
-                String pointStr = String.format("[%s,%s]",
-                        BigDecimal.valueOf(point.getX()).toPlainString(),
-                        BigDecimal.valueOf(point.getY()).toPlainString()
-                );
-                ps.setString(i, pointStr);
-                return;
-            }
-        } else if (geometry instanceof LineString) {
-            //将 LineString 序列化为 [[x1,y1],[x2,y2]] 字符串
-            LineString lineString = (LineString) geometry;
-            if (lineString.getCoordinates() != null && lineString.getCoordinates().length == 2) {
-                Coordinate p0 = lineString.getCoordinateN(0);
-                Coordinate p1 = lineString.getCoordinateN(1);
-                String value = String.format("[[%s,%s],[%s,%s]]",
-                        BigDecimal.valueOf(p0.x).toPlainString(),
-                        BigDecimal.valueOf(p0.y).toPlainString(),
-                        BigDecimal.valueOf(p1.x).toPlainString(),
-                        BigDecimal.valueOf(p1.y).toPlainString()
-                );
-                ps.setString(i, value);
-                return;
-            }
-        }
-        //处理空值
-        ps.setNull(i, JdbcType.VARCHAR.TYPE_CODE);
-    }
-
-    @Override
-    public Geometry getNullableResult(ResultSet rs, String columnName) throws SQLException {
-        return rs.wasNull() ? null : parseGeom(rs.getString(columnName));
-    }
-
-    @Override
-    public Geometry getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
-        return rs.wasNull() ? null : parseGeom(rs.getString(columnIndex));
-    }
-
-    @Override
-    public Geometry getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
-        return cs.wasNull() ? null : parseGeom(cs.getString(columnIndex));
-    }
-
     /**
      * 解析
      *
@@ -84,7 +34,7 @@ public class GeomTypeHandlePg extends BaseTypeHandler<Geometry> {
      * @return 地理对象
      * @throws SQLException sql异常
      */
-    public Geometry parseGeom(String geomStr) throws SQLException {
+    public static Geometry parseGeom(String geomStr) throws SQLException {
         //非空校验
         if (geomStr == null || geomStr.isEmpty()) return null;
         try {
@@ -92,11 +42,11 @@ public class GeomTypeHandlePg extends BaseTypeHandler<Geometry> {
             if (jsonNode.isArray() && jsonNode.size() > 0) {
                 //点处理
                 if (jsonNode.get(0).isNumber() && jsonNode.get(1).isNumber()) {
-                    return GeomPointTypeHandlePg.parsePoint(geomStr);
+                    return GeomPointTypeHandlePg.parseString(geomStr);
                 }
                 //线处理
                 else if (jsonNode.get(0).isArray()) {
-                    return GeomLineStringTypeHandlePg.parseLineString(geomStr);
+                    return GeomMultiLineStringTypeHandlePg.parseString(geomStr);
                 }
             }
 
@@ -105,4 +55,54 @@ public class GeomTypeHandlePg extends BaseTypeHandler<Geometry> {
         }
         throw new SQLException("地理数据格式无效: " + geomStr);
     }
+
+    /**
+     * 从Geometry对象转数据库字符串
+     *
+     * @param geometry 点
+     * @return 字符串
+     * @throws SQLException sql异常
+     */
+    public static String toGeomString(Geometry geometry) throws SQLException {
+        if (geometry instanceof Point) {
+            Point point = (Point) geometry;
+            //转字符串
+            return GeomPointTypeHandlePg.toString(point);
+
+        } else if (geometry instanceof MultiLineString) {
+            MultiLineString multiLineString = (MultiLineString) geometry;
+            //转字符串
+            return GeomMultiLineStringTypeHandlePg.toString(multiLineString);
+        }
+        return null;
+    }
+
+    @Override
+    public void setNonNullParameter(PreparedStatement ps, int i, Geometry geometry, JdbcType jdbcType) throws SQLException {
+        if (geometry != null && geometry.getCoordinate() != null) {
+            //将geom序列化化为字符串
+            String geomString = toGeomString(geometry);
+            if (geomString != null) {
+                ps.setString(i, geomString);
+                return;
+            }
+        }
+        //处理空值
+        ps.setNull(i, JdbcType.VARCHAR.TYPE_CODE);
+    }
+
+    @Override
+    public Geometry getNullableResult(ResultSet rs, String columnName) throws SQLException {
+        return rs.wasNull() ? null : parseGeom(rs.getString(columnName));
+    }
+
+    @Override
+    public Geometry getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
+        return rs.wasNull() ? null : parseGeom(rs.getString(columnIndex));
+    }
+
+    @Override
+    public Geometry getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
+        return cs.wasNull() ? null : parseGeom(cs.getString(columnIndex));
+    }
 }

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

@@ -71,7 +71,7 @@ public class GisSurveyLayerApplyServiceImpl implements GisSurveyLayerApplyServic
         );
         long begin = System.currentTimeMillis();
         //获取游标
-        try (Cursor<GisSurveyLayerApplyPoint> cursor = layerApplyMapper.findAddPointByProjId(projId)) {
+        try (Cursor<GisSurveyLayerApplyPoint> cursor = layerApplyMapper.findAddUpdatePointByProjId(projId)) {
             //迭代游标
             for (GisSurveyLayerApplyPoint point : cursor) {
                 //检查线程中断,并响应
@@ -118,7 +118,7 @@ public class GisSurveyLayerApplyServiceImpl implements GisSurveyLayerApplyServic
         );
         long begin = System.currentTimeMillis();
         //获取游标
-        try (Cursor<GisSurveyLayerApplyLine> cursor = layerApplyMapper.findAddLineByProjId(projId)) {
+        try (Cursor<GisSurveyLayerApplyLine> cursor = layerApplyMapper.findAddUpdateLineByProjId(projId)) {
             //迭代游标
             for (GisSurveyLayerApplyLine point : cursor) {
                 //检查线程中断,并响应
@@ -165,7 +165,7 @@ public class GisSurveyLayerApplyServiceImpl implements GisSurveyLayerApplyServic
         );
         long begin = System.currentTimeMillis();
         //获取游标
-        try (Cursor<GisSurveyLayerApplyPoint> cursor = layerApplyMapper.findAddPointByJobId(jobId)) {
+        try (Cursor<GisSurveyLayerApplyPoint> cursor = layerApplyMapper.findAddUpdatePointByJobId(jobId)) {
             //迭代游标
             for (GisSurveyLayerApplyPoint gisSurveyLayerApplyPoint : cursor) {
                 //检查线程中断,并响应
@@ -212,7 +212,7 @@ public class GisSurveyLayerApplyServiceImpl implements GisSurveyLayerApplyServic
         );
         long begin = System.currentTimeMillis();
         //获取游标
-        try (Cursor<GisSurveyLayerApplyLine> cursor = layerApplyMapper.findAddLineByJobId(jobId)) {
+        try (Cursor<GisSurveyLayerApplyLine> cursor = layerApplyMapper.findAddUpdateLineByJobId(jobId)) {
             //迭代游标
             for (GisSurveyLayerApplyLine line : cursor) {
                 //检查线程中断,并响应

+ 2 - 3
src/main/java/com/shkpr/service/alambizplugin/dto/CommAsyncResult.java

@@ -2,7 +2,6 @@ package com.shkpr.service.alambizplugin.dto;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.shkpr.service.alambizplugin.constants.CommAsyncStatusEnum;
-import com.shkpr.service.alambizplugin.constants.GisSurveyImportStatusEnum;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -19,7 +18,7 @@ import java.util.Map;
 @Data
 public class CommAsyncResult<T> {
     /**
-     * 转换id
+     * id
      */
     private String id;
     /**
@@ -63,7 +62,7 @@ public class CommAsyncResult<T> {
     public static <T> CommAsyncResult<T> inProgress(String id, LocalDateTime requestTime, String operator) {
         CommAsyncResult<T> result = new CommAsyncResult<>();
         result.setId(id);
-        result.setStatus(GisSurveyImportStatusEnum.IN_PROGRESS.getCode());
+        result.setStatus(CommAsyncStatusEnum.IN_PROGRESS.getCode());
         result.setRequestTime(requestTime);
         result.setOperator(operator);
         return result;

+ 2 - 2
src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyLayerApplyLine.java

@@ -1,7 +1,7 @@
 package com.shkpr.service.alambizplugin.dto;
 
 import lombok.Data;
-import org.locationtech.jts.geom.LineString;
+import org.locationtech.jts.geom.MultiLineString;
 
 /**
  * 采集元素处理申请线
@@ -34,7 +34,7 @@ public class GisSurveyLayerApplyLine {
     /**
      * 坐标值
      */
-    private LineString gis;
+    private MultiLineString gis;
     /**
      * 操作标记:add/update/delete
      */

+ 17 - 7
src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyThirdImportElement.java

@@ -51,27 +51,36 @@ public class GisSurveyThirdImportElement {
      */
     private String value;
 
-    public GisSurveyThirdImportElement(String kind, String no, String layerName, String propertyName) {
+    /**
+     * 原因
+     */
+    private String message;
+
+    public GisSurveyThirdImportElement(String kind, String no, String layerName, String propertyName, String message) {
         this.kind = kind;
         this.no = no;
         this.layerName = layerName;
         this.propertyName = propertyName;
+        this.message = message;
     }
 
-    public GisSurveyThirdImportElement(String kind, String upNO, String downNO, String layerName, String propertyName) {
+    public GisSurveyThirdImportElement(String kind, String upNO, String downNO, String layerName, String propertyName, String message) {
         this.kind = kind;
         this.upNO = upNO;
         this.downNO = downNO;
         this.layerName = layerName;
         this.propertyName = propertyName;
+        this.message = message;
     }
 
-    public static GisSurveyThirdImportElement create(Map<String, String> data, GisMetadataLayerTemplate layerTemplate, String propertyName) {
+    public static GisSurveyThirdImportElement create(Map<String, String> data, GisMetadataLayerTemplate layerTemplate
+            , String propertyName, String message) {
         if (Objects.equals(GisMetadataDefine.TYPE_KINE.POINT, layerTemplate.getKind())) {
             return new GisSurveyThirdImportElement(GisMetadataDefine.TYPE_KINE.POINT,
                     ThirdImportTemplateUtils.getValue(data, layerTemplate, GisSurveyExcelDefine.TEMPLATE.NO),
                     layerTemplate.getName(),
-                    propertyName
+                    propertyName,
+                    message
             );
         }
         if (Objects.equals(GisMetadataDefine.TYPE_KINE.LINE, layerTemplate.getKind())) {
@@ -79,15 +88,16 @@ public class GisSurveyThirdImportElement {
                     ThirdImportTemplateUtils.getValue(data, layerTemplate, GisSurveyExcelDefine.TEMPLATE.UP_NO),
                     ThirdImportTemplateUtils.getValue(data, layerTemplate, GisSurveyExcelDefine.TEMPLATE.DOWN_NO),
                     layerTemplate.getName(),
-                    propertyName
+                    propertyName,
+                    message
             );
         }
         return null;
     }
 
     public static GisSurveyThirdImportElement create(Map<String, String> data, GisMetadataLayerTemplate layerTemplate
-            , String propertyName, String value, GisSurveyCondition condition) {
-        GisSurveyThirdImportElement element = create(data, layerTemplate, propertyName);
+            , String propertyName, String value, GisSurveyCondition condition, String message) {
+        GisSurveyThirdImportElement element = create(data, layerTemplate, propertyName, message);
         if (element == null) return null;
         element.setValue(value);
         element.setCondition(condition);

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

@@ -1,131 +0,0 @@
-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>> outConstraintResult = new GisSurveyThirdImportResultDetail<>();
-
-    /**
-     * 重复点号结果
-     */
-    private GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>> duplicatePointsResult = new GisSurveyThirdImportResultDetail<>();
-
-    /**
-     * 无效线结果
-     */
-    private GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>> invalidLinesResult = new GisSurveyThirdImportResultDetail<>();
-
-    /**
-     * 进行中
-     */
-    public static GisSurveyThirdImportResult inProgress(GisSurveyThirdImportParams params, GisSurveyThirdImportSubtask subtask, LocalDateTime requestTime,String operator) {
-        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());
-                result.getOutConstraintResult().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);
-        result.setOperator(operator);
-        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;
-    }
-}

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

@@ -24,4 +24,12 @@ public class GisSurveyThirdImportResultDetail<T> {
      * 结果
      */
     private T results;
+    /**
+     * excel地址
+     */
+    private String excelPath;
+
+    public GisSurveyThirdImportResultDetail(Boolean done) {
+        this.done = done;
+    }
 }

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

@@ -1,30 +0,0 @@
-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;
-}

+ 4 - 0
src/main/resources/application.properties

@@ -2,6 +2,9 @@
 spring.application.name=v1-alam-biz-plugin
 # 项目contextPath
 server.servlet.context-path= /
+#文件大小配置
+spring.servlet.multipart.max-file-size= 200MB
+spring.servlet.multipart.max-request-size= 200MB
 # 错误页,指定发生错误时,跳转的URL。请查看BasicErrorController源码便知
 server.error.path= /
 # 服务端口
@@ -147,6 +150,7 @@ cad-convert.rasterization-min-height=800
 async-task.system-check-timeout=PT1H
 async-task.system-check-result-lag=PT30M
 async-task.third-import-timeout=PT30M
+async-task.commit-import-timeout=PT30M
 async-task.third-export-timeout=PT30M
 async-task.third-export-result-lag=PT1S
 async-task.cad-convert-timeout=PT10M

+ 12 - 12
src/main/resources/mapper/GisSurveyLayerApplyMapper.xml

@@ -50,7 +50,7 @@
         <result column="name" jdbcType="VARCHAR" property="name"/>
         <result column="kind" jdbcType="VARCHAR" property="kind"/>
         <result column="gis" jdbcType="VARCHAR" property="gis"
-                typeHandler="com.shkpr.service.alambizplugin.dbdao.pgtype.GeomLineStringTypeHandlePg"/>
+                typeHandler="com.shkpr.service.alambizplugin.dbdao.pgtype.GeomMultiLineStringTypeHandlePg"/>
         <result column="apply" jdbcType="VARCHAR" property="apply"/>
         <result column="source" jdbcType="SMALLINT" property="source"/>
         <result column="up_node" jdbcType="VARCHAR" property="upNode"/>
@@ -61,7 +61,7 @@
         <result column="survey_length" jdbcType="VARCHAR" property="surveyLength"/>
     </resultMap>
 
-    <select id="findAddPointByProjId" fetchSize="3000" resultMap="Point">
+    <select id="findAddUpdatePointByProjId" fetchSize="3000" resultMap="Point">
         select la.code, la.job_id, la.layer, la.kind, la.gis, la.apply, la.source, la.elevation, la.no,
         case when lt.name is null then
         (select td.name from k2_type_define td where td.key = la.layer and td.kind = 7)
@@ -72,13 +72,13 @@
         left join k3_gis_metadata_layer_template lt on pit.nature = lt.nature and la.layer = lt.key
         where pit.uid = #{projId,jdbcType=VARCHAR}
         and jo.disused = 0
-        and la.apply = 'add' and la.kind = 'point'
+        and (la.apply = 'add' or la.apply = 'update') and la.kind = 'point'
     </select>
 
-    <select id="findAddLineByProjId" fetchSize="3000" resultMap="Line">
+    <select id="findAddUpdateLineByProjId" fetchSize="3000" resultMap="Line">
         select la.code, la.job_id, la.layer, la.kind, la.apply, la.source, la.up_node, la.down_node,
         un.no as up_no, dn.no as down_no,
-        case when un.code is not null and dn.code is not null then concat('[', un.gis, ',', dn.gis, ']') else la.gis end
+        case when un.code is not null and dn.code is not null then concat('[[', un.gis, ',', dn.gis, ']]') else la.gis end
         as gis,
         abs(coalesce(un.elevation, 0)::numeric - coalesce(dn.elevation, 0)::numeric) as elevation_diff,
         sl.value as survey_length,
@@ -97,10 +97,10 @@
         left join k3_gis_metadata_layer_template lt on pit.nature = lt.nature and la.layer = lt.key
         where pit.uid = #{projId,jdbcType=VARCHAR}
         and jo.disused = 0
-        and la.apply = 'add' and la.kind = 'line';
+        and (la.apply = 'add' or la.apply = 'update') and la.kind = 'line';
     </select>
 
-    <select id="findAddPointByJobId" fetchSize="3000" resultMap="Point">
+    <select id="findAddUpdatePointByJobId" fetchSize="3000" resultMap="Point">
         select la.code, la.job_id, la.layer, la.kind, la.gis, la.apply, la.source, la.elevation, la.no,
         case when lt.name is null then
         (select td.name from k2_type_define td where td.key = la.layer and td.kind = 7)
@@ -110,13 +110,13 @@
         join k3_gis_survey_project_info pit on jo.proj_id = pit.uid
         left join k3_gis_metadata_layer_template lt on pit.nature = lt.nature and la.layer = lt.key
         where jo.uid = #{jobId,jdbcType=VARCHAR}
-        and la.apply = 'add' and la.kind = 'point'
+        and (la.apply = 'add' or la.apply = 'update') and la.kind = 'point'
     </select>
 
-    <select id="findAddLineByJobId" fetchSize="3000" resultMap="Line">
+    <select id="findAddUpdateLineByJobId" fetchSize="3000" resultMap="Line">
         select la.code, la.job_id, la.layer, la.kind, la.apply, la.source, la.up_node, la.down_node,
         un.no as up_no, dn.no as down_no,
-        case when un.code is not null and dn.code is not null then concat('[', un.gis, ',', dn.gis, ']') else la.gis end
+        case when un.code is not null and dn.code is not null then concat('[[', un.gis, ',', dn.gis, ']]') else la.gis end
         as gis,
         abs(coalesce(un.elevation, 0)::numeric - coalesce(dn.elevation, 0)::numeric) as elevation_diff,
         sl.value as survey_length,
@@ -134,14 +134,14 @@
         'survey_length'
         left join k3_gis_metadata_layer_template lt on pit.nature = lt.nature and la.layer = lt.key
         where jo.uid = #{jobId,jdbcType=VARCHAR}
-        and la.apply = 'add' and la.kind = 'line';
+        and (la.apply = 'add' or la.apply = 'update') and la.kind = 'line';
     </select>
 
     <select id="findAllByJobIdAndKind" fetchSize="3000" resultMap="BaseResultMap">
         select la.code, la.job_id, la.layer, la.kind, la.apply, la.source, la.up_node, la.down_node,la.elevation,
         la.depth, la.no,
         case when la.kind = 'line' and un.code is not null and dn.code is not null
-        then concat('[', un.gis, ',', dn.gis, ']') else la.gis end as gis,
+        then concat('[[', un.gis, ',', dn.gis, ']]') else la.gis end as gis,
         case when lt.name is null then
         (select td.name from k2_type_define td where td.key = la.layer and td.kind = 7)
         else lt.name end as name,

+ 2 - 1
src/main/resources/mapper/GisSurveyLayerApplyThirdCopyMapper.xml

@@ -116,7 +116,8 @@
         from (
         select la.code, la.job_id, la.layer, la.kind, la.apply, la.source, la.up_node, la.down_node,
         la.elevation, la.depth, la.no,
-        case when un.code is not null and dn.code is not null then concat('[', un.gis, ',', dn.gis, ']') else la.gis end
+        case when un.code is not null and dn.code is not null then concat('[[', un.gis, ',', dn.gis, ']]') else la.gis
+        end
         as gis
         from k3_gis_survey_layer_apply_third_copy la
         left join k3_gis_survey_layer_apply_third_copy as un