7 Commits 0623eada0a ... 552e3ede4a

Autor SHA1 Nachricht Datum
  欧阳劲驰 552e3ede4a 重做重叠点检查算法,改为street索引+并查集的方式,用于快速检索出按浮动值分组的重复点 vor 3 Wochen
  欧阳劲驰 341cec9682 修复项目约束元素类型不一致的问题,模版约束增加key和元素类型回显 vor 3 Wochen
  欧阳劲驰 27941e99db 第三方导出增加超出约束检查 vor 3 Wochen
  欧阳劲驰 a056cc70b3 重置点号增加上下游点号重置 vor 1 Monat
  欧阳劲驰 dc673c5213 重置点号增加上下游点号重置 vor 1 Monat
  欧阳劲驰 e64516687f 第三方导入,表头匹配改为大小写不敏感 vor 1 Monat
  欧阳劲驰 1506ea0b1b 修复点号规则为空时,查询可能异常的问题 vor 1 Monat
29 geänderte Dateien mit 660 neuen und 116 gelöschten Zeilen
  1. 4 0
      src/main/java/com/shkpr/service/alambizplugin/apiparam/GisSurveyThirdImportParams.java
  2. 10 6
      src/main/java/com/shkpr/service/alambizplugin/bizservice/GisSurveySystemCheckBizService.java
  3. 5 2
      src/main/java/com/shkpr/service/alambizplugin/commtools/ExcelUtils.java
  4. 10 3
      src/main/java/com/shkpr/service/alambizplugin/components/GisSurveySystemChecker.java
  5. 52 11
      src/main/java/com/shkpr/service/alambizplugin/components/GisSurveyThirdImporter.java
  6. 217 37
      src/main/java/com/shkpr/service/alambizplugin/components/checker/DuplicatePointsFinder.java
  7. 121 23
      src/main/java/com/shkpr/service/alambizplugin/components/checker/InvalidPropertiesFinder.java
  8. 1 1
      src/main/java/com/shkpr/service/alambizplugin/components/checker/IsolatedLinesFinder.java
  9. 1 0
      src/main/java/com/shkpr/service/alambizplugin/constants/GisSurveyExcelDefine.java
  10. 21 0
      src/main/java/com/shkpr/service/alambizplugin/constants/GisSurveyTemplateDefine.java
  11. 2 1
      src/main/java/com/shkpr/service/alambizplugin/controller/ApiGisSurveyController.java
  12. 1 1
      src/main/java/com/shkpr/service/alambizplugin/controllerserializer/GeometryDeserializer.java
  13. 11 1
      src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisSurveyProjectInfoMapper.java
  14. 4 3
      src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisSurveySystemCheckDefineMapper.java
  15. 1 1
      src/main/java/com/shkpr/service/alambizplugin/dbdao/services/GisSurveyLayerApplyServiceImpl.java
  16. 13 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/services/GisSurveyProjectInfoServiceImpl.java
  17. 5 4
      src/main/java/com/shkpr/service/alambizplugin/dbdao/services/GisSurveySystemCheckDefineServiceImpl.java
  18. 10 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/services/intef/GisSurveyProjectInfoService.java
  19. 5 3
      src/main/java/com/shkpr/service/alambizplugin/dbdao/services/intef/GisSurveySystemCheckDefineService.java
  20. 7 1
      src/main/java/com/shkpr/service/alambizplugin/dto/GisMetadataPropertyTemplate.java
  21. 39 0
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyCondition.java
  22. 19 12
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveySystemCheckDefine.java
  23. 25 0
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveySystemCheckDeviation.java
  24. 19 0
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyThirdImportElement.java
  25. 6 0
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyThirdImportResult.java
  26. 5 1
      src/main/resources/mapper/GisMetadataLayerTemplateMapper.xml
  27. 4 1
      src/main/resources/mapper/GisSurveyJobInfoMapper.xml
  28. 27 1
      src/main/resources/mapper/GisSurveyProjectInfoMapper.xml
  29. 15 3
      src/main/resources/mapper/GisSurveySystemCheckDefineMapper.xml

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

@@ -40,6 +40,10 @@ public class GisSurveyThirdImportParams {
      */
     private Boolean resetNo;
     /**
+     * 是否检查约束
+     */
+    private Boolean checkConstraint;
+    /**
      * 忽略失败
      */
     private Boolean ignoreFail;

+ 10 - 6
src/main/java/com/shkpr/service/alambizplugin/bizservice/GisSurveySystemCheckBizService.java

@@ -15,6 +15,7 @@ import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveyProjectInfo
 import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveySystemCheckDefineService;
 import com.shkpr.service.alambizplugin.dto.CommAsyncCache;
 import com.shkpr.service.alambizplugin.dto.CommAsyncResult;
+import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckDefine;
 import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckId;
 import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckResultDetail;
 import org.apache.commons.collections4.CollectionUtils;
@@ -114,7 +115,8 @@ public class GisSurveySystemCheckBizService {
         //回填元素更新时间
         params.setRefreshTime(refreshTime);
         //获取支持检查项
-        List<String> supportedKeys = systemCheckDefineService.findKeys();
+        List<GisSurveySystemCheckDefine> systemCheckDefines = systemCheckDefineService.findAll();
+        List<String> supportedKeys = systemCheckDefines.stream().map(GisSurveySystemCheckDefine::getKey).collect(Collectors.toList());
         //对入参取交集
         params.getSubitemKeys().retainAll(supportedKeys);
         //设置启动项
@@ -141,7 +143,7 @@ public class GisSurveySystemCheckBizService {
 
         //启动检查任务
         if (Boolean.TRUE.equals(params.getCheckStart()) && CollectionUtils.isNotEmpty(params.getStartSubitemKeys())) {
-            startTask(systemCheckId, params);
+            startTask(systemCheckId, params, systemCheckDefines);
             //如需要返回上次结果,则直接返回结果
             if (Boolean.TRUE.equals(params.getReturnLastResult())) return fileResult;
             //返回进行中
@@ -269,17 +271,19 @@ public class GisSurveySystemCheckBizService {
     /**
      * 启动任务
      *
-     * @param systemCheckId 系统检查id
-     * @param params        检查参数
+     * @param systemCheckId      系统检查id
+     * @param params             检查参数
+     * @param systemCheckDefines 系统检查定义
      */
-    private void startTask(GisSurveySystemCheckId systemCheckId, GisSurveyCheckParams params) {
+    private void startTask(GisSurveySystemCheckId systemCheckId, GisSurveyCheckParams params, List<GisSurveySystemCheckDefine> systemCheckDefines) {
         //获取已存在的任务
         ListenableFuture<CommAsyncResult<Map<String, GisSurveySystemCheckResultDetail>>> previousFuture = TASK_CACHE.get(systemCheckId);
         //已结束判断,删除缓存
         if (previousFuture != null && (previousFuture.isDone() || previousFuture.isCancelled()))
             removeCache(systemCheckId);
         //异步执行系统检查任务
-        ListenableFuture<CommAsyncResult<Map<String, GisSurveySystemCheckResultDetail>>> future = systemChecker.systemCheckTask(params,
+        ListenableFuture<CommAsyncResult<Map<String, GisSurveySystemCheckResultDetail>>> future = systemChecker.systemCheckTask(
+                params, systemCheckDefines,
                 //缓存子任务句柄
                 subtask -> SUBTASK_CACHE.put(systemCheckId, subtask),
                 //删除子任务句柄

+ 5 - 2
src/main/java/com/shkpr/service/alambizplugin/commtools/ExcelUtils.java

@@ -5,6 +5,7 @@ import com.global.base.log.LogPrintMgr;
 import com.shkpr.service.alambizplugin.annotation.ExcelMapping;
 import com.shkpr.service.alambizplugin.constants.ExcelEnum;
 import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
+import org.apache.commons.collections4.map.CaseInsensitiveMap;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 import org.apache.poi.ss.usermodel.*;
@@ -141,7 +142,7 @@ public class ExcelUtils {
                     .mapToObj(row::getCell)
                     .allMatch(cell -> cell == null || cell.getCellTypeEnum() == CellType.BLANK)) continue;
             //数据
-            Map<String, String> data = new HashMap<>();
+            Map<String, String> data = new CaseInsensitiveMap<>();
             //遍历字段映射
             for (Map.Entry<Integer, String> entry : fieldMap.entrySet()) {
                 //获取单元格
@@ -252,7 +253,9 @@ public class ExcelUtils {
                                         //过滤相同的值
                                         .filter(index -> headerRow.getCell(index).getStringCellValue().equals(excelMappingValue))
                                         .findFirst().orElse(-1);
-                            }, Function.identity()
+                            }, Function.identity(),
+                            (it1, it2) -> it2,
+                            CaseInsensitiveMap::new
                     ));
             //遍历行
             for (Row row : sheet) {

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

@@ -20,6 +20,7 @@ import com.shkpr.service.alambizplugin.dbdao.services.intef.TypeDefineService;
 import com.shkpr.service.alambizplugin.dto.CommAsyncResult;
 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.GisSurveySystemCheckId;
 import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckResultDetail;
 import com.shkpr.service.alambizplugin.dto.TypeDefine;
@@ -36,6 +37,7 @@ import java.time.LocalDateTime;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.ExecutionException;
 import java.util.function.Consumer;
 
@@ -89,13 +91,14 @@ public class GisSurveySystemChecker {
      * 系统检查任务
      *
      * @param params              系统检查参数
+     * @param systemCheckDefines  系统检查定义
      * @param onStartSubtask      启动子任务
      * @param onDeprecatedSubtask 弃用子任务(完成数据收集/取消)
      * @return 系统检查返回
      */
     @Async
     public ListenableFuture<CommAsyncResult<Map<String, GisSurveySystemCheckResultDetail>>> systemCheckTask(
-            GisSurveyCheckParams params
+            GisSurveyCheckParams params, List<GisSurveySystemCheckDefine> systemCheckDefines
             , Consumer<Map<String, ListenableFuture<GisSurveySystemCheckResultDetail>>> onStartSubtask
             , Consumer<GisSurveySystemCheckId> onDeprecatedSubtask) {
         //系统检查id
@@ -145,9 +148,13 @@ public class GisSurveySystemChecker {
                 points = gisSurveyLayerApplyService.findAddPointByJobId(systemCheckId.getCode());
                 lines = gisSurveyLayerApplyService.findAddLineByJobId(systemCheckId.getCode());
             }
+
             //查询经纬度类型定义
             List<TypeDefine> typeDefines = typeDefineService.findLatLng();
-
+            //重复点定义
+            GisSurveySystemCheckDefine duplicatePointsDefine = systemCheckDefines.stream().
+                    filter(it -> Objects.equals(GisSurveySystemCheckKeys.DUPLICATE_POINTS, it.getKey()))
+                    .findFirst().orElse(null);
 
             //结果flag
             final String FLAG = systemCheckId.getFlag();
@@ -175,7 +182,7 @@ public class GisSurveySystemChecker {
             //重复点检查
             if (points != null) {
                 if (params.getStartSubitemKeys().contains(GisSurveySystemCheckKeys.DUPLICATE_POINTS)) {
-                    duplicatePointsFuture = duplicatePointsFinder.findDuplicatePoints(points, typeDefines, systemCheckId);
+                    duplicatePointsFuture = duplicatePointsFinder.findDuplicatePoints(points, typeDefines, duplicatePointsDefine, systemCheckId);
                     subtask.put(GisSurveySystemCheckKeys.DUPLICATE_POINTS, duplicatePointsFuture);
                 }
             }

+ 52 - 11
src/main/java/com/shkpr/service/alambizplugin/components/GisSurveyThirdImporter.java

@@ -21,8 +21,10 @@ 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.GisSurveyLayerApplyThirdCopyService;
+import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveyProjectInfoService;
 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;
@@ -52,6 +54,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutionException;
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
@@ -71,24 +74,31 @@ public class GisSurveyThirdImporter {
     private final String mStrClassName;
     private final String mBizType;
     private final GeometryFactory geometryFactory;
+    private final GisSurveyProjectInfoService projectInfoService;
+    private final GisSurveyJobInfoService jobInfoService;
     private final GisMetadataLayerTemplateService layerTemplateService;
-    private final GisSurveyLayerApplyThirdCopyService gisSurveyLayerApplyThirdCopyService;
+    private final GisSurveyLayerApplyThirdCopyService layerApplyThirdCopyService;
     private final DuplicatePointsFinder duplicatePointsFinder;
     private final InvalidLinesFinder invalidLinesFinder;
     private final InvalidPropertiesFinder invalidPropertiesFinder;
-    private final GisSurveyJobInfoService gisSurveyJobInfoService;
 
-    public GisSurveyThirdImporter(GisMetadataLayerTemplateService layerTemplateService, GisSurveyLayerApplyThirdCopyService gisSurveyLayerApplyThirdCopyService
-            , DuplicatePointsFinder duplicatePointsFinder, InvalidLinesFinder invalidLinesFinder, InvalidPropertiesFinder invalidPropertiesFinder, GisSurveyJobInfoService gisSurveyJobInfoService) {
+    public GisSurveyThirdImporter(GisSurveyProjectInfoService projectInfoService
+            , GisSurveyJobInfoService jobInfoService
+            , GisMetadataLayerTemplateService layerTemplateService
+            , GisSurveyLayerApplyThirdCopyService layerApplyThirdCopyService
+            , DuplicatePointsFinder duplicatePointsFinder
+            , InvalidLinesFinder invalidLinesFinder
+            , InvalidPropertiesFinder invalidPropertiesFinder) {
         mStrClassName = "GisSurveyThirdImporter";
         mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
         geometryFactory = new GeometryFactory(new PrecisionModel(), 4490);
+        this.projectInfoService = projectInfoService;
+        this.jobInfoService = jobInfoService;
         this.layerTemplateService = layerTemplateService;
-        this.gisSurveyLayerApplyThirdCopyService = gisSurveyLayerApplyThirdCopyService;
+        this.layerApplyThirdCopyService = layerApplyThirdCopyService;
         this.duplicatePointsFinder = duplicatePointsFinder;
         this.invalidLinesFinder = invalidLinesFinder;
         this.invalidPropertiesFinder = invalidPropertiesFinder;
-        this.gisSurveyJobInfoService = gisSurveyJobInfoService;
     }
 
     /**
@@ -127,6 +137,8 @@ public class GisSurveyThirdImporter {
             //解析excel
             parseExcel(inputStreams, points, lines);
 
+            //项目约束条件
+            List<GisSurveyCondition> projectConstraints = projectInfoService.findConstraintsByJobId(params.getJobId());
             //提取图层名
             List<String> pointLayerNames = getLayerNames(points, GisSurveyExcelDefine.FILE.POINT_LAYER);
             List<String> lineLayerNames = getLayerNames(lines, GisSurveyExcelDefine.FILE.LINE_LAYER);
@@ -135,7 +147,8 @@ public class GisSurveyThirdImporter {
             List<GisMetadataLayerTemplate> lineLayerTemplates = layerTemplateService.findByNatureAndNameIn(params.getNature(), lineLayerNames);
 
             //无效属性检查
-            invalidPropertiesFuture = invalidPropertiesFinder.findInvalidProperties(points, lines, pointLayerTemplates, lineLayerTemplates);
+            invalidPropertiesFuture = invalidPropertiesFinder.findInvalidProperties(points, lines
+                    , pointLayerTemplates, lineLayerTemplates, params.getCheckConstraint(), projectConstraints);
             //重复点检查
             duplicatePointsFuture = duplicatePointsFinder.findDuplicatePoints(points, pointLayerTemplates);
             //无效线检查
@@ -153,6 +166,7 @@ public class GisSurveyThirdImporter {
             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());
             //存入无效线结果
@@ -181,7 +195,7 @@ public class GisSurveyThirdImporter {
             if (params.getResetNo()) resetNo(params.getJobId(), layerApplyList);
 
             //批量写入
-            Boolean saved = gisSurveyLayerApplyThirdCopyService.saveAll(params.getJobId(), layerApplyList);
+            Boolean saved = layerApplyThirdCopyService.saveAll(params.getJobId(), layerApplyList);
             if (!saved) {
                 result.setCompleteTime(LocalDateTime.now());
                 LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
@@ -314,12 +328,14 @@ public class GisSurveyThirdImporter {
         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();
         //检查是否都为空
         return CollectionUtils.isEmpty(invalidLayers) && CollectionUtils.isEmpty(missingRequirements) &&
                 CollectionUtils.isEmpty(invalidTypesResult) && CollectionUtils.isEmpty(outRanges) &&
-                CollectionUtils.isEmpty(duplicatePoints) && CollectionUtils.isEmpty(invalidLines);
+                CollectionUtils.isEmpty(outConstraint) && CollectionUtils.isEmpty(duplicatePoints) &&
+                CollectionUtils.isEmpty(invalidLines);
     }
 
     /**
@@ -547,8 +563,11 @@ public class GisSurveyThirdImporter {
         long begin = System.currentTimeMillis();
 
         //点号规则
-        final List<RuleFormatSetting> ruleFormat = gisSurveyJobInfoService.findRuleFormat(jobId);
-        //并行遍历元素
+        final List<RuleFormatSetting> ruleFormat = jobInfoService.findRuleFormat(jobId);
+        //点号映射
+        Map<String, String> noMapping = new ConcurrentHashMap<>();
+
+        //并行遍历元素,处理点的点号
         layerApplyList.parallelStream()
                 .filter(la -> Objects.equals(la.getKind(), GisMetadataDefine.TYPE_KINE.POINT))
                 .forEach(la -> {
@@ -566,7 +585,29 @@ public class GisSurveyThirdImporter {
                     la.getPropertyValues().stream()
                             .filter(it -> Objects.equals(it.getProperty(), GisSurveyExcelDefine.TEMPLATE.NO))
                             .forEach(it -> it.setValue(no));
+                    //设置点号映射
+                    noMapping.put(la.getCode(), no);
                 });
+        //处理线的上下点号
+        layerApplyList.parallelStream()
+                .filter(la -> Objects.equals(la.getKind(), GisMetadataDefine.TYPE_KINE.LINE))
+                .forEach(la -> {
+                    //处理上点号
+                    if (noMapping.containsKey(la.getUpNode())) {
+                        //设置属性点号
+                        la.getPropertyValues().stream()
+                                .filter(it -> Objects.equals(it.getProperty(), GisSurveyExcelDefine.TEMPLATE.UP_NO))
+                                .forEach(it -> it.setValue(noMapping.get(la.getUpNode())));
+                    }
+                    //处理下点号
+                    if (noMapping.containsKey(la.getDownNode())) {
+                        //设置属性点号
+                        la.getPropertyValues().stream()
+                                .filter(it -> Objects.equals(it.getProperty(), GisSurveyExcelDefine.TEMPLATE.DOWN_NO))
+                                .forEach(it -> it.setValue(noMapping.get(la.getDownNode())));
+                    }
+                });
+
 
         long end = System.currentTimeMillis();
         LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName

+ 217 - 37
src/main/java/com/shkpr/service/alambizplugin/components/checker/DuplicatePointsFinder.java

@@ -9,18 +9,15 @@ 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.LogFlagBusiType;
-import com.shkpr.service.alambizplugin.dto.GisMetadataLayerTemplate;
-import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyPoint;
-import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckElement;
-import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckId;
-import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckResultDetail;
-import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportElement;
-import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportResultDetail;
-import com.shkpr.service.alambizplugin.dto.TypeDefine;
+import 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.locationtech.jts.geom.Envelope;
+import org.locationtech.jts.index.strtree.STRtree;
+import org.locationtech.jts.util.NumberUtil;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.scheduling.annotation.AsyncResult;
 import org.springframework.stereotype.Component;
@@ -29,9 +26,12 @@ import org.springframework.util.concurrent.ListenableFuture;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
@@ -134,53 +134,106 @@ public class DuplicatePointsFinder {
      *
      * @param points      点集合
      * @param typeDefines 类型定义
+     * @param define      系统检查定义
      * @return 重复点
      */
     @Async
     public ListenableFuture<GisSurveySystemCheckResultDetail> findDuplicatePoints(List<GisSurveyLayerApplyPoint> points
-            , List<TypeDefine> typeDefines, GisSurveySystemCheckId systemCheckId) throws InterruptedException {
+            , List<TypeDefine> typeDefines, GisSurveySystemCheckDefine define, GisSurveySystemCheckId systemCheckId) throws InterruptedException {
         //经纬度精度
-        int lonScale = getScale(typeDefines, LNG_KEY);
+        int lngScale = getScale(typeDefines, LNG_KEY);
         int latScale = getScale(typeDefines, LAT_KEY);
+        //偏差集合
+        List<GisSurveySystemCheckDeviation> deviations = define != null ? define.getDeviation() : Collections.emptyList();
+        //经纬度公差
+        double lngTolerance = deviations.stream()
+                .filter(deviation -> Objects.equals(GisSurveyTemplateDefine.LNG, deviation.getProperty()))
+                .map(GisSurveySystemCheckDeviation::getTolerance)
+                .findFirst().orElse(0d);
+        double latTolerance = deviations.stream()
+                .filter(deviation -> Objects.equals(GisSurveyTemplateDefine.LAT, deviation.getProperty()))
+                .map(GisSurveySystemCheckDeviation::getTolerance)
+                .findFirst().orElse(0d);
+        //高程公差
+        double elevationTolerance = deviations.stream()
+                .filter(deviation -> Objects.equals(GisSurveyTemplateDefine.ELEVATION, deviation.getProperty()))
+                .map(GisSurveySystemCheckDeviation::getTolerance)
+                .findFirst().orElse(0d);
 
         LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName,
-                String.format("开始执行寻找重复点 经度精度:%s 纬度精度:%s   ======>", lonScale, latScale));
+                String.format("开始执行寻找重复点 经度精度:%s 纬度精度:%s 经度公差:%s 纬度公差:%s 高程公差:%s  ======>",
+                        lngScale, latScale, lngTolerance, latTolerance, elevationTolerance));
         long begin = System.currentTimeMillis();
 
-        try {
-            //根据经纬度分组
-            Map<String, List<GisSurveyLayerApplyPoint>> keyToPoints = points.parallelStream()
-                    //响应中断
-                    .peek(it -> {
-                        if (Thread.currentThread().isInterrupted())
-                            throw new UncheckedInterruptedException(new InterruptedException());
-                    })
-                    .collect(Collectors.groupingBy(point -> {
-                        //抹去经纬度精度,并设置为分组条件
-                        Coordinate coordinate = point.getGis().getCoordinate();
-                        BigDecimal bdLon = new BigDecimal(Double.toString(coordinate.getX())).setScale(lonScale, RoundingMode.DOWN);
-                        BigDecimal bdLat = new BigDecimal(Double.toString(coordinate.getY())).setScale(latScale, RoundingMode.DOWN);
-                        return String.format("%s%s%s", bdLon.toPlainString(), bdLat.toPlainString(), point.getElevation());
-                    }, Collectors.toList()));
+        //创建空间索引
+        STRtree tree = new STRtree();
+        //元素存入索引
+        for (GisSurveyLayerApplyPoint point : points) {
+            if (point.getGis() == null) continue;
+            tree.insert(
+                    calcEnvelope(point.getGis().getCoordinate(), lngScale, latScale, lngTolerance, latTolerance),
+                    point
+            );
+        }
+        tree.build();
+
+        //创建并查集
+        UnionFind uf = new UnionFind(points);
+
+        //遍历点元素,并合并并查集
+        for (GisSurveyLayerApplyPoint point1 : points) {
+            if (point1.getGis() == null) continue;
             //响应中断
             if (Thread.interrupted()) throw new InterruptedException();
-            //并行流寻找重复点
-            List<List<GisSurveySystemCheckElement>> groupElements = keyToPoints.values().parallelStream()
+
+            //查询索引内元素
+            List<?> candidates = tree.query(calcEnvelope(
+                    point1.getGis().getCoordinate(),
+                    lngScale, latScale,
+                    lngTolerance, latTolerance));
+            for (Object candidate : candidates) {
+                GisSurveyLayerApplyPoint point2 = (GisSurveyLayerApplyPoint) candidate;
+                //排除code相同的元素
+                if (Objects.equals(point1.getCode(), point2.getCode()) || point2.getGis() == null) continue;
+                //响应中断
+                if (Thread.interrupted()) throw new InterruptedException();
+                //判断是否完全重叠
+                if (calcFullOverlap(point1, point2, lngScale, latScale, lngTolerance, latTolerance, elevationTolerance)) {
+                    //合并重叠点
+                    uf.union(point1.getCode(), point2.getCode());
+                }
+            }
+        }
+
+        //按并查集结果分组
+        Map<Integer, List<GisSurveySystemCheckElement>> groupMap = new HashMap<>();
+        for (GisSurveyLayerApplyPoint point : points) {
+            if (point.getGis() == null) continue;
+            //响应中断
+            if (Thread.interrupted()) throw new InterruptedException();
+            //获取并查集的索引
+            Integer index = uf.getIndex(point.getCode());
+            if (index == null) continue;
+            //获取父节点的索引
+            int root = uf.find(index);
+            //获取当前父节点组
+            List<GisSurveySystemCheckElement> group = groupMap
+                    .computeIfAbsent(root, k -> new ArrayList<>());
+            //填入当前元素
+            group.add(BeanUtil.copy(point, GisSurveySystemCheckElement.class));
+        }
+
+        try {
+            //并行流过滤大于2的元素
+            List<List<GisSurveySystemCheckElement>> collect = groupMap.values().parallelStream()
                     //响应中断
                     .peek(it -> {
                         if (Thread.currentThread().isInterrupted())
                             throw new UncheckedInterruptedException(new InterruptedException());
                     })
-                    //过滤组内大于1
-                    .filter(group -> group.size() > 1)
-                    //转为返回元素
-                    .map(group -> group.stream()
-                            .map(point -> BeanUtil.copy(point, GisSurveySystemCheckElement.class))
-                            .collect(Collectors.toList())
-                    )
+                    .filter(it -> it.size() > 1)
                     .collect(Collectors.toList());
-
-            return new AsyncResult<>(createResult(groupElements, systemCheckId, begin));
+            return new AsyncResult<>(createResult(collect, systemCheckId, begin));
         } catch (UncheckedInterruptedException e) {
             throw e.getCause();
         }
@@ -214,6 +267,59 @@ public class DuplicatePointsFinder {
     }
 
     /**
+     * 计算边界
+     *
+     * @param coordinate   坐标
+     * @param lngScale     经度精度
+     * @param latScale     经度精度
+     * @param lngTolerance 经度公差
+     * @param latTolerance 纬度公差
+     * @return 边界
+     */
+    private Envelope calcEnvelope(Coordinate coordinate, int lngScale, int latScale, double lngTolerance, double latTolerance) {
+        //抹去经纬度精度
+        BigDecimal bdLng = new BigDecimal(Double.toString(coordinate.getX())).setScale(lngScale, RoundingMode.DOWN);
+        BigDecimal bdLat = new BigDecimal(Double.toString(coordinate.getY())).setScale(latScale, RoundingMode.DOWN);
+
+        //计算公差边界
+        double minX = bdLng.subtract(BigDecimal.valueOf(lngTolerance)).doubleValue();
+        double maxX = bdLng.add(BigDecimal.valueOf(lngTolerance)).doubleValue();
+        double minY = bdLat.subtract(BigDecimal.valueOf(latTolerance)).doubleValue();
+        double maxY = bdLat.add(BigDecimal.valueOf(latTolerance)).doubleValue();
+
+        return new Envelope(minX, maxX, minY, maxY);
+    }
+
+    /**
+     * 计算完全重叠
+     *
+     * @param point1             点1
+     * @param point2             点2
+     * @param lngScale           经度精度
+     * @param latScale           经度精度
+     * @param lngTolerance       经度公差
+     * @param latTolerance       纬度公差
+     * @param elevationTolerance 高程公差
+     * @return 重叠状态
+     */
+    private boolean calcFullOverlap(GisSurveyLayerApplyPoint point1, GisSurveyLayerApplyPoint point2
+            , int lngScale, int latScale
+            , double lngTolerance, double latTolerance, double elevationTolerance) {
+        //获取点1xyz
+        double x1 = BigDecimal.valueOf(point1.getGis().getX()).setScale(lngScale, RoundingMode.DOWN).doubleValue();
+        double y1 = BigDecimal.valueOf(point1.getGis().getY()).setScale(latScale, RoundingMode.DOWN).doubleValue();
+        double z1 = point1.getElevation();
+        //获取点2xyz
+        double x2 = BigDecimal.valueOf(point2.getGis().getX()).setScale(lngScale, RoundingMode.DOWN).doubleValue();
+        double y2 = BigDecimal.valueOf(point2.getGis().getY()).setScale(latScale, RoundingMode.DOWN).doubleValue();
+        double z2 = point2.getElevation();
+        //比较xyz
+        if (!NumberUtil.equalsWithTolerance(x1, x2, lngTolerance)) return false;
+        if (!NumberUtil.equalsWithTolerance(y1, y2, latTolerance)) return false;
+        return NumberUtil.equalsWithTolerance(z1, z2, elevationTolerance);
+    }
+
+    /**
      * 创建结果
      *
      * @param data          数据
@@ -265,4 +371,78 @@ public class DuplicatePointsFinder {
                     return map;
                 })).collect(Collectors.toList());
     }
+
+    /**
+     * 并查集最
+     * <p>简单的实现</p>
+     */
+    private static class UnionFind {
+        // 点标识符(code)到索引的映射
+        private final Map<String, Integer> indexMapping = new HashMap<>();
+        //父节点信息
+        private final int[] parent;
+        //树高度
+        private final short[] rank;
+
+        public UnionFind(List<GisSurveyLayerApplyPoint> points) {
+            //过滤有效点
+            List<GisSurveyLayerApplyPoint> validPoints = points.stream()
+                    .filter(p -> p.getGis() != null)
+                    .collect(Collectors.toList());
+            //初始化关系和树高度
+            parent = new int[validPoints.size()];
+            rank = new short[validPoints.size()];
+            //初始化,每个节点的父节点是自己
+            for (int i = 0; i < validPoints.size(); i++) {
+                parent[i] = i;
+                rank[i] = 0;
+                indexMapping.put(validPoints.get(i).getCode(), i);
+            }
+        }
+
+        /**
+         * 查找根节点
+         *
+         * @param i 当前节点索引
+         * @return 根结点
+         */
+        public int find(int i) {
+            //路径压缩
+            if (parent[i] != i) parent[i] = find(parent[i]);
+            return parent[i];
+        }
+
+        /**
+         * 获取索引
+         *
+         * @param code 节点code
+         * @return 并查集索引
+         */
+        public Integer getIndex(String code) {
+            return indexMapping.get(code);
+        }
+
+        /**
+         * 合并两个节点关系
+         *
+         * @param code1 节点1的code
+         * @param code2 节点2的code
+         */
+        public void union(String code1, String code2) {
+            //获取索引
+            int i1 = indexMapping.get(code1);
+            int i2 = indexMapping.get(code2);
+            //获取根节点
+            int root1 = find(i1);
+            int root2 = find(i2);
+            // 已在同一根节点
+            if (root1 == root2) return;
+            //按秩合并,如 当前根秩 大于 目标根秩,则 目标根 为 当前根 的下游线
+            if (rank[root1] > rank[root2]) parent[root2] = root1;
+            else {
+                parent[root1] = root2;
+                if (rank[root1] == rank[root2]) rank[root2]++;
+            }
+        }
+    }
 }

+ 121 - 23
src/main/java/com/shkpr/service/alambizplugin/components/checker/InvalidPropertiesFinder.java

@@ -2,6 +2,7 @@ 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.commtools.ThirdImportTemplateUtils;
 import com.shkpr.service.alambizplugin.constants.GisMetadataDefine;
@@ -9,8 +10,10 @@ import com.shkpr.service.alambizplugin.constants.GisSurveyExcelDefine;
 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.GisSurveyCondition;
 import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportElement;
 import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportResultDetail;
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.math.NumberUtils;
 import org.springframework.scheduling.annotation.Async;
@@ -23,6 +26,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * 无效属性查找器
@@ -57,12 +61,14 @@ public class InvalidPropertiesFinder {
      * @param lines               线集合
      * @param pointLayerTemplates 点图层模版集合
      * @param lineLayerTemplates  线图层模版集合
+     * @param checkConstraint     检查约束
+     * @param projectConstraints  项目约束条件
      * @return 重复点
      */
     @Async
     public ListenableFuture<GisSurveyThirdImportResultDetail<Map<String, List<GisSurveyThirdImportElement>>>> findInvalidProperties(
             List<Map<String, String>> points, List<Map<String, String>> lines, List<GisMetadataLayerTemplate> pointLayerTemplates
-            , List<GisMetadataLayerTemplate> lineLayerTemplates) throws InterruptedException {
+            , List<GisMetadataLayerTemplate> lineLayerTemplates, Boolean checkConstraint, List<GisSurveyCondition> projectConstraints) throws InterruptedException {
         LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始执行寻找无效属性   ======>");
         long begin = System.currentTimeMillis();
 
@@ -74,6 +80,8 @@ public class InvalidPropertiesFinder {
         List<GisSurveyThirdImportElement> invalidTypesResult = new ArrayList<>();
         //超出范围结果
         List<GisSurveyThirdImportElement> outRangesResult = new ArrayList<>();
+        //超出约束结果
+        List<GisSurveyThirdImportElement> outConstraintResult = new ArrayList<>();
         //检查点属性
         for (Map<String, String> point : points) {
             //响应中断
@@ -91,7 +99,7 @@ public class InvalidPropertiesFinder {
                 ));
             else
                 //图层存在则检查图层
-                checkLayer(point, layerTemplate, missingRequirementsResult, invalidTypesResult);
+                checkLayer(point, layerTemplate, checkConstraint, projectConstraints, missingRequirementsResult, invalidTypesResult, outConstraintResult);
             //检查坐标超出范围
             if (checkOutRanges(point, layerTemplate))
                 outRangesResult.add(
@@ -121,7 +129,7 @@ public class InvalidPropertiesFinder {
                 ));
             else
                 //图层存在则检查图层
-                checkLayer(line, layerTemplate, missingRequirementsResult, invalidTypesResult);
+                checkLayer(line, layerTemplate, checkConstraint, projectConstraints, missingRequirementsResult, invalidTypesResult, outConstraintResult);
         }
 
         long end = System.currentTimeMillis();
@@ -138,6 +146,7 @@ public class InvalidPropertiesFinder {
         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));
     }
 
@@ -167,39 +176,128 @@ public class InvalidPropertiesFinder {
      *
      * @param data                      数据
      * @param layerTemplate             图层模版
+     * @param checkConstraint           检查超出约束
+     * @param projectConstraints        项目约束
      * @param missingRequirementsResult 缺少必填结果
      * @param invalidTypesResult        无效类型结果
+     * @param outConstraintResult       超出约束结果
      */
     public void checkLayer(Map<String, String> data, GisMetadataLayerTemplate layerTemplate
-            , List<GisSurveyThirdImportElement> missingRequirementsResult
-            , List<GisSurveyThirdImportElement> invalidTypesResult) {
+            , Boolean checkConstraint, List<GisSurveyCondition> projectConstraints, List<GisSurveyThirdImportElement> missingRequirementsResult
+            , List<GisSurveyThirdImportElement> invalidTypesResult, List<GisSurveyThirdImportElement> outConstraintResult) {
+        //项目约束映射
+        Map<String, GisSurveyCondition> projectConstraintsMapping = projectConstraints.stream()
+                .filter(constraint -> Objects.equals(layerTemplate.getKind(), constraint.getKind()))
+                .collect(Collectors.toMap(GisSurveyCondition::getProperty, it -> it));
         //遍历图层属性模版
         for (GisMetadataPropertyTemplate propertyTemplate : layerTemplate.getPropertyTemplates()) {
-            //排除非必填
-            if (propertyTemplate.getRequired() != 1 || propertyTemplate.getStatus() != 1)
-                continue;
             //排除编码
             if (Objects.equals(GisSurveyExcelDefine.TEMPLATE.CODE, propertyTemplate.getKey())
                     || Objects.equals(GisSurveyExcelDefine.TEMPLATE.UP_NODE, propertyTemplate.getKey())
                     || Objects.equals(GisSurveyExcelDefine.TEMPLATE.DOWN_NODE, propertyTemplate.getKey()))
                 continue;
-            //模版名称
-            String templateName = propertyTemplate.getName();
-            //必填不存在则存入缺少必填
-            if (data.get(templateName) == null || StringUtils.isBlank(data.get(templateName))) {
-                GisSurveyThirdImportElement gisSurveyThirdImportElement = GisSurveyThirdImportElement.create(data,
-                        layerTemplate,
-                        propertyTemplate.getName()
+            //当前属性值
+            String value = data.get(propertyTemplate.getName());
+            //必填
+            if (propertyTemplate.getRequired() == 1 && propertyTemplate.getStatus() == 1) {
+                //值不存在则存入缺少必填
+                if (StringUtils.isBlank(value)) {
+                    GisSurveyThirdImportElement gisSurveyThirdImportElement = GisSurveyThirdImportElement.create(data,
+                            layerTemplate,
+                            propertyTemplate.getName()
+                    );
+                    missingRequirementsResult.add(gisSurveyThirdImportElement);
+                    //值存在
+                } else {
+                    //判断超出约束
+                    checkOutConstraint(
+                            projectConstraintsMapping.get(propertyTemplate.getKey()),
+                            data, layerTemplate, propertyTemplate, value, outConstraintResult
+                    );
+                    //判断数字类型
+                    if ((GisSurveyExcelDefine.DATA_TYPE.INT.equals(propertyTemplate.getType()) ||
+                            GisSurveyExcelDefine.DATA_TYPE.DOUBLE.equals(propertyTemplate.getType()))
+                            && !NumberUtils.isParsable(value)) {
+                        invalidTypesResult.add(GisSurveyThirdImportElement.create(data,
+                                layerTemplate,
+                                propertyTemplate.getName()
+                        ));
+                    }
+                }
+            }
+            //非必填
+            else {
+                //判断超出约束
+                if (checkConstraint && StringUtils.isNotBlank(value)) checkOutConstraint(
+                        projectConstraintsMapping.get(propertyTemplate.getKey()),
+                        data, layerTemplate, propertyTemplate, value, outConstraintResult
                 );
-                missingRequirementsResult.add(gisSurveyThirdImportElement);
-            } else if ((GisSurveyExcelDefine.DATA_TYPE.INT.equals(propertyTemplate.getType()) ||
-                    GisSurveyExcelDefine.DATA_TYPE.DOUBLE.equals(propertyTemplate.getType()))
-                    && !NumberUtils.isParsable(data.get(templateName)))
-                //存在且类型为数字,则判断数字类型
-                invalidTypesResult.add(GisSurveyThirdImportElement.create(data,
-                        layerTemplate,
-                        propertyTemplate.getName()
+            }
+        }
+    }
+
+    /**
+     * 检查超出约束
+     *
+     * @param projectConstraint   项目约束
+     * @param data                数据
+     * @param layerTemplate       图层模版
+     * @param propertyTemplate    属性模版
+     * @param value               值
+     * @param outConstraintResult 超出约束结果
+     */
+    public void checkOutConstraint(GisSurveyCondition projectConstraint, Map<String, String> data
+            , GisMetadataLayerTemplate layerTemplate, GisMetadataPropertyTemplate propertyTemplate
+            , String value, List<GisSurveyThirdImportElement> outConstraintResult) {
+        GisSurveyCondition constraint = null;
+        //模版约束
+        if (StringUtils.isNotBlank(propertyTemplate.getMode()) && CollectionUtils.isNotEmpty(propertyTemplate.getRanges())) {
+            constraint = BeanUtil.copy(propertyTemplate, GisSurveyCondition.class);
+            if (constraint != null) {
+                constraint.setProperty(propertyTemplate.getKey());
+                constraint.setKind(layerTemplate.getKind());
+            }
+        }
+        //项目约束
+        if (projectConstraint != null) {
+            constraint = projectConstraint;
+        }
+        if (constraint == null || StringUtils.isBlank(value)) return;
+        //约束模式
+        String mode = constraint.getMode();
+        //约束范围
+        List<String> ranges = constraint.getRanges();
+        if (StringUtils.isBlank(mode) || CollectionUtils.isEmpty(ranges)) return;
+        //列表约束
+        if (Objects.equals("list", constraint.getMode())) {
+            //如列表不包含值,则超出约束
+            if (!ranges.contains(value)) {
+                outConstraintResult.add(GisSurveyThirdImportElement.create(data, layerTemplate,
+                        propertyTemplate.getName(), value, constraint
                 ));
+            }
+        }
+        //极值约束
+        else if (Objects.equals("extremum", constraint.getMode())) {
+            if (ranges.size() != 2) return;
+            //最小值判断
+            String minStr = ranges.get(0);
+            if (StringUtils.isNotBlank(minStr) && NumberUtils.isParsable(minStr)) {
+                double min = Double.parseDouble(minStr);
+                if (!NumberUtils.isParsable(value) || Double.parseDouble(value) < min) {
+                    outConstraintResult.add(GisSurveyThirdImportElement.create(data, layerTemplate,
+                            propertyTemplate.getName(), value, constraint));
+                }
+            }
+            //最大值判断
+            String maxStr = ranges.get(1);
+            if (StringUtils.isNotBlank(maxStr) && NumberUtils.isParsable(maxStr)) {
+                double max = Double.parseDouble(maxStr);
+                if (!NumberUtils.isParsable(value) || Double.parseDouble(value) > max) {
+                    outConstraintResult.add(GisSurveyThirdImportElement.create(data, layerTemplate,
+                            propertyTemplate.getName(), value, constraint));
+                }
+            }
         }
     }
 }

+ 1 - 1
src/main/java/com/shkpr/service/alambizplugin/components/checker/IsolatedLinesFinder.java

@@ -182,7 +182,7 @@ public class IsolatedLinesFinder {
         }
 
         /**
-         * 更新节点对应的根线映射
+         * 更新节点对应的根线映射
          *
          * @param node        节点
          * @param currentRoot 当前节点的根线

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

@@ -70,5 +70,6 @@ public interface GisSurveyExcelDefine {
         String MISSING_REQUIREMENTS = "missingRequirementsResult";
         String INVALID_TYPES = "invalidTypesResult";
         String OUT_RANGES = "outRangesResult";
+        String OUT_CONSTRAINT = "outConstraint";
     }
 }

+ 21 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/GisSurveyTemplateDefine.java

@@ -0,0 +1,21 @@
+package com.shkpr.service.alambizplugin.constants;
+
+/**
+ * 模版定义
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+public interface GisSurveyTemplateDefine {
+    String LAYER = "layer";
+    String CODE = "code";
+    String NO = "no";
+    String UP_NO = "up_no";
+    String DOWN_NO = "down_no";
+    String LNG = "lng";
+    String LAT = "lat";
+    String UP_NODE = "up_node";
+    String DOWN_NODE = "down_node";
+    String ELEVATION = "elevation";
+    String DEPTH = "depth";
+}

+ 2 - 1
src/main/java/com/shkpr/service/alambizplugin/controller/ApiGisSurveyController.java

@@ -279,6 +279,7 @@ public class ApiGisSurveyController {
             , @RequestParam(value = "jobId", required = false) String jobId
             , @RequestParam(value = "nature", required = false) String nature
             , @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 {
         //入参校验
         final String URI_PATH = request.getRequestURI();
@@ -293,7 +294,7 @@ public class ApiGisSurveyController {
                     , ResponseCode.STATUS_ERROR_PARAM_FORMAT.toStrMsg()));
         }
         //构建入参数
-        GisSurveyThirdImportParams params = new GisSurveyThirdImportParams(files, operator, jobId, nature, resetNo, Boolean.parseBoolean(ignoreFail));
+        GisSurveyThirdImportParams params = new GisSurveyThirdImportParams(files, operator, jobId, nature, resetNo, checkConstraint, Boolean.parseBoolean(ignoreFail));
         //begin
         long llReqBefore = System.currentTimeMillis();
         String strRunSeq = String.format("%d-%d", llReqBefore, mSeqThirdImportReq.incrementAndGet());

+ 1 - 1
src/main/java/com/shkpr/service/alambizplugin/controllerserializer/GeometryDeserializer.java

@@ -25,7 +25,7 @@ public class GeometryDeserializer extends JsonDeserializer<Geometry> {
     public Geometry deserialize(JsonParser p, DeserializationContext ctx) throws IOException {
         try {
             //读取GeoJson并转换为Geom
-            return new GeoJsonReader().read(p.getValueAsString());
+            return new GeoJsonReader().read(p.readValueAsTree().toString());
         } catch (ParseException e) {
             log.error("反序列化geom异常:{}", e.getMessage());
             return null;

+ 11 - 1
src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisSurveyProjectInfoMapper.java

@@ -1,9 +1,11 @@
 package com.shkpr.service.alambizplugin.dbdao.mapper;
 
+import com.shkpr.service.alambizplugin.dto.GisSurveyCondition;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
 import java.time.LocalDateTime;
+import java.util.List;
 
 /**
  * 采集项目基本信息mapper
@@ -22,11 +24,19 @@ public interface GisSurveyProjectInfoMapper {
     LocalDateTime findRefreshTimeByUid(@Param("uid") String uid);
 
     /**
+     * 根据uid查询约束
+     *
+     * @param jobId 任务id
+     * @return 约束条件
+     */
+    List<GisSurveyCondition> findConstraintsByJobId(@Param("jobId") String jobId);
+
+    /**
      * 根据任务id更新刷新时间
      *
      * @param jobId       任务id
      * @param refreshTime 刷新时间
      * @return 刷新时间
      */
-    int updateRefreshTimeByUid(@Param("jobId") String jobId, @Param("refreshTime") Long refreshTime);
+    int updateRefreshTimeByJobId(@Param("jobId") String jobId, @Param("refreshTime") Long refreshTime);
 }

+ 4 - 3
src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisSurveySystemCheckDefineMapper.java

@@ -1,5 +1,6 @@
 package com.shkpr.service.alambizplugin.dbdao.mapper;
 
+import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckDefine;
 import org.apache.ibatis.annotations.Mapper;
 
 import java.util.List;
@@ -13,9 +14,9 @@ import java.util.List;
 @Mapper
 public interface GisSurveySystemCheckDefineMapper {
     /**
-     * 获取key集合
+     * 获取全部
      *
-     * @return key集合
+     * @return 系统检查定义集合
      */
-    List<String> findKeys();
+    List<GisSurveySystemCheckDefine> findAll();
 }

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

@@ -347,7 +347,7 @@ public class GisSurveyLayerApplyServiceImpl implements GisSurveyLayerApplyServic
 
                 //更新刷新时间
                 long timestamp = System.currentTimeMillis();
-                int projectUpdated = projectInfoMapper.updateRefreshTimeByUid(jobId, timestamp);
+                int projectUpdated = projectInfoMapper.updateRefreshTimeByJobId(jobId, timestamp);
                 int jobUpdated = jobInfoMapper.updateRefreshTimeActionStatusByUid(jobId, timestamp, timestamp,
                         GisSurveyExcelDefine.DEFAULT_VALUE.ACTION, GisSurveyExcelDefine.DEFAULT_VALUE.STATUS);
                 //写入任务状态

+ 13 - 0
src/main/java/com/shkpr/service/alambizplugin/dbdao/services/GisSurveyProjectInfoServiceImpl.java

@@ -2,9 +2,11 @@ package com.shkpr.service.alambizplugin.dbdao.services;
 
 import com.shkpr.service.alambizplugin.dbdao.mapper.GisSurveyProjectInfoMapper;
 import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveyProjectInfoService;
+import com.shkpr.service.alambizplugin.dto.GisSurveyCondition;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
+import java.util.List;
 
 /**
  * 采集项目基本信息service实现
@@ -31,4 +33,15 @@ public class GisSurveyProjectInfoServiceImpl implements GisSurveyProjectInfoServ
     public LocalDateTime findRefreshTimeByUid(String uid) {
         return projectInfoMapper.findRefreshTimeByUid(uid);
     }
+
+    /**
+     * 根据uid查询约束
+     *
+     * @param jobId 任务id
+     * @return 约束条件
+     */
+    @Override
+    public List<GisSurveyCondition> findConstraintsByJobId(String jobId) {
+        return projectInfoMapper.findConstraintsByJobId(jobId);
+    }
 }

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

@@ -2,6 +2,7 @@ package com.shkpr.service.alambizplugin.dbdao.services;
 
 import com.shkpr.service.alambizplugin.dbdao.mapper.GisSurveySystemCheckDefineMapper;
 import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveySystemCheckDefineService;
+import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckDefine;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
@@ -22,12 +23,12 @@ public class GisSurveySystemCheckDefineServiceImpl implements GisSurveySystemChe
     }
 
     /**
-     * 获取key集合
+     * 获取全部
      *
-     * @return key集合
+     * @return 系统检查定义集合
      */
     @Override
-    public List<String> findKeys() {
-        return systemCheckDefineMapper.findKeys();
+    public List<GisSurveySystemCheckDefine> findAll() {
+        return systemCheckDefineMapper.findAll();
     }
 }

+ 10 - 0
src/main/java/com/shkpr/service/alambizplugin/dbdao/services/intef/GisSurveyProjectInfoService.java

@@ -1,8 +1,10 @@
 package com.shkpr.service.alambizplugin.dbdao.services.intef;
 
+import com.shkpr.service.alambizplugin.dto.GisSurveyCondition;
 import org.apache.ibatis.annotations.Param;
 
 import java.time.LocalDateTime;
+import java.util.List;
 
 /**
  * 采集项目基本信息service
@@ -18,4 +20,12 @@ public interface GisSurveyProjectInfoService {
      * @return 刷新时间
      */
     LocalDateTime findRefreshTimeByUid(@Param("uid") String uid);
+
+    /**
+     * 根据uid查询约束
+     *
+     * @param jobId 任务id
+     * @return 约束条件
+     */
+    List<GisSurveyCondition> findConstraintsByJobId(String jobId);
 }

+ 5 - 3
src/main/java/com/shkpr/service/alambizplugin/dbdao/services/intef/GisSurveySystemCheckDefineService.java

@@ -1,5 +1,7 @@
 package com.shkpr.service.alambizplugin.dbdao.services.intef;
 
+import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckDefine;
+
 import java.util.List;
 
 /**
@@ -10,9 +12,9 @@ import java.util.List;
  */
 public interface GisSurveySystemCheckDefineService {
     /**
-     * 获取key集合
+     * 获取全部
      *
-     * @return key集合
+     * @return 系统检查定义集合
      */
-    List<String> findKeys();
+    List<GisSurveySystemCheckDefine> findAll();
 }

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

@@ -3,6 +3,7 @@ package com.shkpr.service.alambizplugin.dto;
 import lombok.Data;
 
 import java.time.LocalDateTime;
+import java.util.List;
 
 /**
  * gis元数据图层属性定义模板
@@ -42,7 +43,12 @@ public class GisMetadataPropertyTemplate {
     /**
      * 取值范围列表
      */
-    private String ranges;
+    private List<String> ranges;
+
+    /**
+     * 元素属性约束方式,如:list/extremum
+     */
+    private String mode;
 
     /**
      * 控件输入类型

+ 39 - 0
src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyCondition.java

@@ -0,0 +1,39 @@
+package com.shkpr.service.alambizplugin.dto;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 约束条件
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Data
+public class GisSurveyCondition {
+    /**
+     * 元素类别,如:point/line/face
+     */
+    private String kind;
+    /**
+     * 元素属性标识符key
+     */
+    private String property;
+    /**
+     * 元素属性取值类型,如:string/double/int
+     */
+    private String type;
+    /**
+     * 元素属性约束方式,如:list/extremum
+     */
+    private String mode;
+    /**
+     * 元素属性取值单位
+     */
+    private String unit;
+    /**
+     * 元素属性取值约束列表
+     */
+    private List<String> ranges;
+}

+ 19 - 12
src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveySystemCheckDefine.java

@@ -2,38 +2,45 @@ package com.shkpr.service.alambizplugin.dto;
 
 import lombok.Data;
 
+import java.util.List;
+
 /**
  * 系统检查项定义
  */
 @Data
 public class GisSurveySystemCheckDefine {
     /**
-    * 检查项key
-    */
+     * 检查项key
+     */
     private String key;
 
     /**
-    * 检查项名称
-    */
+     * 检查项名称
+     */
     private String name;
 
     /**
-    * 相关函数(预留备用)
-    */
+     * 相关函数(预留备用)
+     */
     private String functions;
 
     /**
-    * 相关参数(预留备用)
-    */
+     * 相关参数(预留备用)
+     */
     private String params;
 
     /**
-    * 详细描述
-    */
+     * 详细描述
+     */
     private String remarks;
 
     /**
-    * 显示顺序
-    */
+     * 显示顺序
+     */
     private Short ordering;
+
+    /**
+     * 有关偏差浮动值
+     */
+    private List<GisSurveySystemCheckDeviation> deviation;
 }

+ 25 - 0
src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveySystemCheckDeviation.java

@@ -0,0 +1,25 @@
+package com.shkpr.service.alambizplugin.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 系统检查浮动值
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class GisSurveySystemCheckDeviation {
+    /**
+     * 属性
+     */
+    private String property;
+    /**
+     * 公差
+     */
+    private Double tolerance;
+}

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

@@ -41,6 +41,16 @@ public class GisSurveyThirdImportElement {
      */
     private String propertyName;
 
+    /**
+     * 约束条件
+     */
+    private GisSurveyCondition condition;
+
+    /**
+     * 值
+     */
+    private String value;
+
     public GisSurveyThirdImportElement(String kind, String no, String layerName, String propertyName) {
         this.kind = kind;
         this.no = no;
@@ -74,4 +84,13 @@ public class GisSurveyThirdImportElement {
         }
         return null;
     }
+
+    public static GisSurveyThirdImportElement create(Map<String, String> data, GisMetadataLayerTemplate layerTemplate
+            , String propertyName, String value, GisSurveyCondition condition) {
+        GisSurveyThirdImportElement element = create(data, layerTemplate, propertyName);
+        if (element == null) return null;
+        element.setValue(value);
+        element.setCondition(condition);
+        return element;
+    }
 }

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

@@ -65,6 +65,11 @@ public class GisSurveyThirdImportResult {
     private GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>> outRangesResult = new GisSurveyThirdImportResultDetail<>();
 
     /**
+     * 超出约束结果
+     */
+    private GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>> outConstraintResult = new GisSurveyThirdImportResultDetail<>();
+
+    /**
      * 重复点号结果
      */
     private GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>> duplicatePointsResult = new GisSurveyThirdImportResultDetail<>();
@@ -88,6 +93,7 @@ public class GisSurveyThirdImportResult {
                 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());

+ 5 - 1
src/main/resources/mapper/GisMetadataLayerTemplateMapper.xml

@@ -26,7 +26,9 @@
             <result column="property_id" jdbcType="BIGINT" property="id"/>
             <result column="property_name" jdbcType="VARCHAR" property="name"/>
             <result column="property_type" jdbcType="VARCHAR" property="type"/>
-            <result column="property_ranges" jdbcType="VARCHAR" property="ranges"/>
+            <result column="property_ranges" jdbcType="VARCHAR" property="ranges"
+                    typeHandler="com.shkpr.service.alambizplugin.dbdao.pgtype.ListStrTypeHandlerPg"/>
+            <result column="property_mode" jdbcType="VARCHAR" property="mode"/>
             <result column="property_widget" jdbcType="VARCHAR" property="widget"/>
             <result column="property_defaults" jdbcType="VARCHAR" property="defaults"/>
             <result column="property_required" jdbcType="SMALLINT" property="required"/>
@@ -66,6 +68,7 @@
         mpt.name as property_name,
         mpt.type as property_type,
         mpt.ranges as property_ranges,
+        mpt.mode as property_mode,
         mpt.widget as property_widget,
         mpt.defaults as property_defaults,
         mpt.required as property_required,
@@ -113,6 +116,7 @@
         mpt.name as property_name,
         mpt.type as property_type,
         mpt.ranges as property_ranges,
+        mpt.mode as property_mode,
         mpt.widget as property_widget,
         mpt.defaults as property_defaults,
         mpt.required as property_required,

+ 4 - 1
src/main/resources/mapper/GisSurveyJobInfoMapper.xml

@@ -14,7 +14,10 @@
         (rf->>'ordering')::int2 as ordering
         from
         v_k3_gis_survey_job_info,
-        jsonb_array_elements(rule_format::jsonb) as rf
+        jsonb_array_elements(coalesce(
+        nullif(rule_format, '')::jsonb,
+        '[]'::jsonb
+        )) as rf
         where uid = #{uid,jdbcType=VARCHAR};
     </select>
 

+ 27 - 1
src/main/resources/mapper/GisSurveyProjectInfoMapper.xml

@@ -1,13 +1,39 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.shkpr.service.alambizplugin.dbdao.mapper.GisSurveyProjectInfoMapper">
+    <resultMap id="GisSurveyCondition" type="com.shkpr.service.alambizplugin.dto.GisSurveyCondition">
+        <result property="kind" column="kind"/>
+        <result property="property" column="property"/>
+        <result property="type" column="type"/>
+        <result property="mode" column="mode"/>
+        <result property="unit" column="unit"/>
+        <result property="ranges" column="ranges" jdbcType="VARCHAR"
+                    typeHandler="com.shkpr.service.alambizplugin.dbdao.pgtype.ListStrTypeHandlerPg"/>
+    </resultMap>
+
     <select id="findRefreshTimeByUid" resultType="java.time.LocalDateTime">
         select to_timestamp(refresh_time / 1000.0) AT TIME ZONE 'PRC'
         from k3_gis_survey_project_info
         where uid = #{uid,jdbcType=VARCHAR};
     </select>
 
-    <update id="updateRefreshTimeByUid">
+    <select id="findConstraintsByJobId" resultMap="GisSurveyCondition">
+        select c ->> 'kind' as kind,
+        c ->> 'property' as property,
+        c ->> 'type' as type,
+        c ->> 'mode' as mode,
+        c ->> 'unit' as unit,
+        c ->> 'ranges' as ranges
+        from k3_gis_survey_job_info ji
+        join k3_gis_survey_project_info pit on ji.proj_id = pit.uid,
+        jsonb_array_elements((coalesce(
+        nullif(pit.constraints, '')::jsonb,
+        '[]'::jsonb
+        ))) as c
+        where ji.uid = #{jobId,jdbcType=VARCHAR};
+    </select>
+
+    <update id="updateRefreshTimeByJobId">
         update k3_gis_survey_project_info pi
         set refresh_time = #{refreshTime,jdbcType=BIGINT}
         where exists (select 1 from k3_gis_survey_job_info ji where ji.uid=#{jobId,jdbcType=VARCHAR} )

+ 15 - 3
src/main/resources/mapper/GisSurveySystemCheckDefineMapper.xml

@@ -9,10 +9,22 @@
         <result column="params" jdbcType="VARCHAR" property="params"/>
         <result column="remarks" jdbcType="VARCHAR" property="remarks"/>
         <result column="ordering" jdbcType="SMALLINT" property="ordering"/>
+        <collection property="deviation" ofType="com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckDeviation">
+            <result column="deviation_property" jdbcType="VARCHAR" property="property"/>
+            <result column="deviation_tolerance" jdbcType="SMALLINT" property="tolerance"/>
+        </collection>
     </resultMap>
 
-    <select id="findKeys" resultType="java.lang.String">
-        select key
-        from k3_gis_survey_system_check_define
+    <select id="findAll" resultMap="BaseResultMap">
+        select key,
+               name,
+               functions,
+               params,
+               remarks,
+               ordering,
+               d ->> 'property'  as deviation_property,
+               d ->> 'tolerance' as deviation_tolerance
+        from k3_gis_survey_system_check_define scd
+                 left join jsonb_array_elements((coalesce(nullif(scd.deviation, '')::jsonb, '[]'::jsonb))) as d on true
     </select>
 </mapper>