Kaynağa Gözat

实现第三方导出

欧阳劲驰 1 ay önce
ebeveyn
işleme
be53b97227
27 değiştirilmiş dosya ile 1281 ekleme ve 66 silme
  1. 25 0
      pom.xml
  2. 131 0
      src/main/java/com/shkpr/service/alambizplugin/bizservice/GisSurveyThirdExportBizService.java
  3. 30 0
      src/main/java/com/shkpr/service/alambizplugin/commproperties/TempFileProperties.java
  4. 60 0
      src/main/java/com/shkpr/service/alambizplugin/commtools/CompressorUtils.java
  5. 95 61
      src/main/java/com/shkpr/service/alambizplugin/commtools/ExcelUtils.java
  6. 88 0
      src/main/java/com/shkpr/service/alambizplugin/commtools/ShapeUtils.java
  7. 272 0
      src/main/java/com/shkpr/service/alambizplugin/components/GisSurveyThirdExporter.java
  8. 7 1
      src/main/java/com/shkpr/service/alambizplugin/configuration/WebMvcConfiguration.java
  9. 2 0
      src/main/java/com/shkpr/service/alambizplugin/constants/ApiURI.java
  10. 35 0
      src/main/java/com/shkpr/service/alambizplugin/constants/CommAsyncStatusEnum.java
  11. 59 0
      src/main/java/com/shkpr/service/alambizplugin/constants/GisTypeEnum.java
  12. 78 1
      src/main/java/com/shkpr/service/alambizplugin/controller/ApiGisSurveyController.java
  13. 3 0
      src/main/java/com/shkpr/service/alambizplugin/controllerfilter/JWTAuthenticationFilter.java
  14. 1 0
      src/main/java/com/shkpr/service/alambizplugin/controllerfilter/third/ApiJWTGisSurveyBizFilter.java
  15. 7 1
      src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisMetadataLayerTemplateMapper.java
  16. 10 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisSurveyLayerApplyMapper.java
  17. 12 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/services/GisMetadataLayerTemplateServiceImpl.java
  18. 52 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/services/GisSurveyLayerApplyServiceImpl.java
  19. 8 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/services/intef/GisMetadataLayerTemplateService.java
  20. 11 0
      src/main/java/com/shkpr/service/alambizplugin/dbdao/services/intef/GisSurveyLayerApplyService.java
  21. 76 0
      src/main/java/com/shkpr/service/alambizplugin/dto/CommAsyncResult.java
  22. 109 0
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyLayerApply.java
  23. 5 2
      src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyPropertyValue.java
  24. 3 0
      src/main/resources/application.properties
  25. 47 0
      src/main/resources/mapper/GisMetadataLayerTemplateMapper.xml
  26. 42 0
      src/main/resources/mapper/GisSurveyLayerApplyMapper.xml
  27. 13 0
      src/main/resources/mapper/GisSurveyPropertyValueMapper.xml

+ 25 - 0
pom.xml

@@ -23,6 +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>
     </properties>
 
     <!--工具包jar版本不一致,解决方案,以下配置促使本应用工程中的相应jar强制使用规定版本-->
@@ -217,6 +218,12 @@
         </dependency>
 
         <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-compress</artifactId>
+            <version>1.27.1</version>
+        </dependency>
+
+        <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-thymeleaf</artifactId>
         </dependency>
@@ -336,6 +343,18 @@
             <scope>system</scope>
             <systemPath>${project.basedir}/libs/aspose-cad-23.9.jar</systemPath>
         </dependency>
+        <!--gt-shapefile-->
+        <dependency>
+            <groupId>org.geotools</groupId>
+            <artifactId>gt-shapefile</artifactId>
+            <version>${geotools.version}</version>
+        </dependency>
+        <!--gt-epsg-->
+        <dependency>
+            <groupId>org.geotools</groupId>
+            <artifactId>gt-epsg-hsql</artifactId>
+            <version>${geotools.version}</version>
+        </dependency>
     </dependencies>
 
     <repositories>
@@ -350,6 +369,12 @@
             <url>http://maven.geo-solutions.it/</url>
             <name>geoserver-manager repository</name>
         </repository>
+        <repository>
+            <id>osgeo</id>
+            <name>OSGeo Release Repository</name>
+            <url>https://repo.osgeo.org/repository/release/</url>
+            <releases><enabled>true</enabled> </releases>
+        </repository>
     </repositories>
 
     <build>

+ 131 - 0
src/main/java/com/shkpr/service/alambizplugin/bizservice/GisSurveyThirdExportBizService.java

@@ -0,0 +1,131 @@
+package com.shkpr.service.alambizplugin.bizservice;
+
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.alambizplugin.components.GisSurveyThirdExporter;
+import com.shkpr.service.alambizplugin.constants.CommAsyncStatusEnum;
+import com.shkpr.service.alambizplugin.constants.GisSurveConvertStatusEnum;
+import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
+import com.shkpr.service.alambizplugin.dto.CommAsyncResult;
+import org.springframework.stereotype.Component;
+import org.springframework.util.concurrent.ListenableFuture;
+
+import java.time.LocalDateTime;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * 第三方导出管理service
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Component
+public class GisSurveyThirdExportBizService {
+    /**
+     * 任务缓存
+     */
+    private final static Map<String, ListenableFuture<CommAsyncResult<String>>> TASK_CACHE = new ConcurrentHashMap<>();
+    /**
+     * 开始时间缓存
+     */
+    private final static Map<String, LocalDateTime> TIME_CACHE = new ConcurrentHashMap<>();
+    /**
+     * log
+     */
+    private final String mStrClassName;
+    private final String mBizType;
+
+    private final GisSurveyThirdExporter thirdExporter;
+
+
+    public GisSurveyThirdExportBizService(GisSurveyThirdExporter thirdExporter) {
+        mStrClassName = "GisSurveyThirdExportBizService";
+        mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
+        this.thirdExporter = thirdExporter;
+    }
+
+    /**
+     * 第三方导出
+     *
+     * @param jobId 任务id
+     * @return 转换结果
+     */
+    public CommAsyncResult<String> thirdExport(String jobId) {
+        //如已有结果,则直接返回
+        CommAsyncResult<String> result = getResult(jobId);
+        if (result != null) return result;
+
+        //启动任务
+        startTask(jobId);
+        //返回进行中
+        return CommAsyncResult.inProgress(jobId, LocalDateTime.now());
+
+    }
+
+    /**
+     * 获取结果
+     *
+     * @param jobId 任务id
+     * @return 结果
+     */
+    public CommAsyncResult<String> getResult(String jobId) {
+        //获取已存在的任务
+        ListenableFuture<CommAsyncResult<String>> previousFuture = TASK_CACHE.get(jobId);
+
+        //判断完成
+        if (previousFuture != null && previousFuture.isDone()) {
+            try {
+                //获取结果
+                CommAsyncResult<String> result = previousFuture.get();
+                //如成功/失败,则直接返回
+                if (Objects.equals(result.getStatus(), CommAsyncStatusEnum.FAIL.getCode()) ||
+                        Objects.equals(result.getStatus(), GisSurveConvertStatusEnum.SUCCESS.getCode()))
+                    removeCache(jobId);
+                return result;
+            } catch (InterruptedException | ExecutionException e) {
+                //打印报错信息
+                LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
+                        , String.format("查询转换导出异常 任务id:%s error:%s", jobId, e)
+                );
+                return CommAsyncResult.fail(jobId);
+            }
+        }
+
+        //进行中判断(未完成且未清除)
+        if (previousFuture != null && !previousFuture.isDone() && !previousFuture.isCancelled())
+            return CommAsyncResult.inProgress(jobId, TIME_CACHE.get(jobId));
+
+        return null;
+    }
+
+    /**
+     * 启动任务
+     *
+     * @param jobId 任务id
+     */
+    private void startTask(String jobId) {
+        //获取已存在的任务
+        ListenableFuture<CommAsyncResult<String>> previousFuture = TASK_CACHE.get(jobId);
+        //已结束判断,删除缓存
+        if (previousFuture != null && (previousFuture.isDone() || previousFuture.isCancelled())) removeCache(jobId);
+        //执行异步任务
+        ListenableFuture<CommAsyncResult<String>> checkFuture = thirdExporter.thirdExportTask(jobId);
+        //缓存任务句柄
+        TASK_CACHE.put(jobId, checkFuture);
+        //缓存时间
+        TIME_CACHE.put(jobId, LocalDateTime.now());
+    }
+
+    /**
+     * 清除缓存
+     *
+     * @param jobId 任务id
+     */
+    private void removeCache(String jobId) {
+        TASK_CACHE.remove(jobId);
+        TIME_CACHE.remove(jobId);
+    }
+}

+ 30 - 0
src/main/java/com/shkpr/service/alambizplugin/commproperties/TempFileProperties.java

@@ -0,0 +1,30 @@
+package com.shkpr.service.alambizplugin.commproperties;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import java.nio.file.Path;
+import java.time.Duration;
+
+/**
+ * 临时文件属性
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Getter
+@Setter
+@ConfigurationProperties(prefix = "temp-file")
+@Configuration
+public class TempFileProperties {
+    /**
+     * 资源路径
+     */
+    private Path resourcePath;
+    /**
+     * 文件生命周期
+     */
+    private Duration lifecycle;
+}

+ 60 - 0
src/main/java/com/shkpr/service/alambizplugin/commtools/CompressorUtils.java

@@ -0,0 +1,60 @@
+package com.shkpr.service.alambizplugin.commtools;
+
+import org.apache.commons.compress.archivers.ArchiveEntry;
+import org.apache.commons.compress.archivers.ArchiveException;
+import org.apache.commons.compress.archivers.ArchiveOutputStream;
+import org.apache.commons.compress.archivers.ArchiveStreamFactory;
+import org.apache.commons.io.IOUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.stream.Stream;
+
+/**
+ * 压缩工具类
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+public class CompressorUtils {
+    //归档流工厂
+    private final static ArchiveStreamFactory archiveStreamFactory = new ArchiveStreamFactory();
+
+    /**
+     * 归档zip
+     *
+     * @param sourcePath 资源路径
+     */
+    public static Path archivalZip(Path sourcePath) throws IOException, ArchiveException {
+        //zip路径
+        Path zipPath = sourcePath.resolveSibling(sourcePath.getFileName().toString() + ".zip");
+        //开启归档输出流
+        try (ArchiveOutputStream<ArchiveEntry> zipOut =
+                     archiveStreamFactory.createArchiveOutputStream(ArchiveStreamFactory.ZIP, Files.newOutputStream(zipPath))) {
+            //递归文件夹
+            try (Stream<Path> walk = Files.walk(sourcePath)) {
+                //过滤常规文件
+                walk.filter(Files::isRegularFile)
+                        .forEach(path -> {
+                            try {
+                                ArchiveEntry entry = zipOut.createArchiveEntry(path.toFile(), path.getFileName().toString());
+                                zipOut.putArchiveEntry(entry);
+                                try (InputStream in = Files.newInputStream(path)) {
+                                    IOUtils.copy(in, zipOut);
+                                }
+                                zipOut.closeArchiveEntry();
+                            } catch (IOException e) {
+                                throw new UncheckedIOException(e);
+                            }
+                        });
+            }
+            zipOut.finish();
+        } catch (UncheckedIOException e) {
+            throw e.getCause();
+        }
+        return zipPath;
+    }
+}

+ 95 - 61
src/main/java/com/shkpr/service/alambizplugin/commtools/ExcelUtils.java

@@ -7,18 +7,7 @@ import com.shkpr.service.alambizplugin.constants.ExcelEnum;
 import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellType;
-import org.apache.poi.ss.usermodel.DateUtil;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFCell;
-import org.apache.poi.xssf.usermodel.XSSFCellStyle;
-import org.apache.poi.xssf.usermodel.XSSFFont;
-import org.apache.poi.xssf.usermodel.XSSFRichTextString;
-import org.apache.poi.xssf.usermodel.XSSFRow;
-import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 
 import java.io.IOException;
@@ -31,10 +20,11 @@ import java.nio.file.Paths;
 import java.text.DecimalFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Date;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
@@ -292,63 +282,85 @@ public class ExcelUtils {
         }
     }
 
-
     /**
-     * @param rowsWithColsData
-     * @param outputStream
+     * 写入文件
+     *
+     * @param headers      表头信息
+     * @param datas        数据
+     * @param outputStream 输出流
+     * @param excelEnum    excel枚举
      */
-    public static void writeExcel(List<List<Object>> rowsWithColsData, OutputStream outputStream, boolean hasHeader) {
-        if (rowsWithColsData == null || rowsWithColsData.size() <= 0 || outputStream == null)
-            return;
-        XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
-        XSSFSheet xssfSheet = xssfWorkbook.createSheet("sheet1");
+    public static void writeFile(Map<String, Map<String, String>> headers, Map<String, List<Map<String, Object>>> datas
+            , OutputStream outputStream, ExcelEnum excelEnum) {
+        //创建表
+        try (Workbook workbook = excelEnum == ExcelEnum.XLSX ? new XSSFWorkbook() : new HSSFWorkbook()) {
+            //表头样式
+            CellStyle headerStyle = workbook.createCellStyle();
+            headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
+            headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
 
-        XSSFCellStyle colHeaderStyle = null;
-        if (hasHeader) {
-            colHeaderStyle = xssfWorkbook.createCellStyle();
-            XSSFFont colHeaderFont = xssfWorkbook.createFont();
-            colHeaderFont.setBold(true);
-            colHeaderStyle.setFont(colHeaderFont);
-        }
+            Font headerFont = workbook.createFont();
+            headerFont.setBold(true);
 
-        for (int i = 0, j = rowsWithColsData.size(); i < j; i++) {
-            XSSFRow xssfRow = xssfSheet.createRow(i);
-            List<Object> columnData = rowsWithColsData.get(i);
-            if (columnData == null)
-                continue;
+            headerStyle.setFont(headerFont);
 
-            for (int m = 0, n = columnData.size(); m < n; m++) {
-                XSSFCell xssfCell = xssfRow.createCell(m);
-                Object col = columnData.get(m);
-                if (i == 0 && colHeaderStyle != null)
-                    xssfCell.setCellStyle(colHeaderStyle);
+            //遍历页
+            for (Map.Entry<String, Map<String, String>> headersEntry : headers.entrySet()) {
+                //创建页
+                Sheet sheet = workbook.createSheet(headersEntry.getKey());
+                if (!datas.containsKey(headersEntry.getKey())) continue;
+                //写入页
+                writeSheet(headersEntry.getValue(), datas.get(headersEntry.getKey()), sheet, headerStyle);
+            }
+            //写入文件
+            workbook.write(outputStream);
+        } catch (IOException e) {
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
+                    , String.format("excel文件写入失败 msg:%s", e.getMessage())
+            );
+        }
 
-                if (col == null) {
-                    xssfCell.setCellValue("");
-                } else {
-                    if (col instanceof String) {
-                        xssfCell.setCellValue(new XSSFRichTextString((String) col));
-                    } else if (col instanceof Date) {
-                        xssfCell.setCellValue((Date) col);
-                    } else if (col instanceof Boolean) {
-                        xssfCell.setCellValue((Boolean) col);
-                    } else if (col instanceof Double) {
-                        xssfCell.setCellValue((Double) col);
-                    } else
-                        xssfCell.setCellValue(new XSSFRichTextString(String.valueOf(col)));
-                }
+    }
 
-                if (i != 0 && i == j - 1)
-                    xssfSheet.autoSizeColumn(m);
+    /**
+     * 写入页
+     *
+     * @param header      表头
+     * @param data        数据
+     * @param sheet       页
+     * @param headerStyle 头样式
+     */
+    public static void writeSheet(Map<String, String> header, List<Map<String, Object>> data
+            , Sheet sheet, CellStyle headerStyle) {
+        //表头键
+        List<String> headerKeys = new ArrayList<>();
+        //表头行
+        Row headRow = sheet.createRow(0);
+        //遍历表头
+        for (Map.Entry<String, String> headerEntry : header.entrySet()) {
+            //缓存键
+            headerKeys.add(headerEntry.getKey());
+            //设置值和样式
+            Cell cell = headRow.createCell(headerKeys.size() - 1);
+            setCellValue(cell, headerEntry.getValue());
+            cell.setCellStyle(headerStyle);
+        }
+        //遍历数据
+        for (int i = 0; i < data.size(); i++) {
+            Map<String, Object> item = data.get(i);
+            Row row = sheet.createRow(i + 1);
+            //遍历表头键
+            for (int j = 0, headerKeysSize = headerKeys.size(); j < headerKeysSize; j++) {
+                //根据表头键,设置值
+                String headerKey = headerKeys.get(j);
+                Cell cell = row.createCell(j);
+                setCellValue(cell, item.get(headerKey));
             }
         }
-
-        try {
-            xssfWorkbook.write(outputStream);
-            outputStream.flush();
-            outputStream.close();
-        } catch (IOException e) {
-            e.printStackTrace();
+        //设置自动宽度
+        for (int i = 0; i < header.size(); i++) {
+            sheet.autoSizeColumn(i, true);
+            sheet.setColumnWidth(i, sheet.getColumnWidth(i) * 12 / 10);
         }
     }
 
@@ -392,6 +404,28 @@ public class ExcelUtils {
     }
 
     /**
+     * 设置单元格值
+     *
+     * @param cell  单元格
+     * @param value 值
+     */
+    private static void setCellValue(Cell cell, Object value) {
+        if (value == null) cell.setCellValue("");
+        else if (value instanceof String) cell.setCellValue((String) value);
+        else if (value instanceof Integer) cell.setCellValue((Integer) value);
+        else if (value instanceof Double) cell.setCellValue((Double) value);
+        else if (value instanceof Boolean) cell.setCellValue((Boolean) value);
+        else if (value instanceof Long) cell.setCellValue((Long) value);
+        else if (value instanceof Float) cell.setCellValue((Float) value);
+        else if (value instanceof Short) cell.setCellValue((Short) value);
+        else if (value instanceof Byte) cell.setCellValue((Byte) value);
+        else if (value instanceof Character) cell.setCellValue(value.toString());
+        else if (value instanceof Collection<?>)
+            cell.setCellValue(((Collection<?>) value).stream().map(Objects::toString).collect(Collectors.joining(",")));
+        else cell.setCellValue(value.toString());
+    }
+
+    /**
      * 设置数据值
      *
      * @param data  数据

+ 88 - 0
src/main/java/com/shkpr/service/alambizplugin/commtools/ShapeUtils.java

@@ -0,0 +1,88 @@
+package com.shkpr.service.alambizplugin.commtools;
+
+import com.shkpr.service.alambizplugin.constants.GisTypeEnum;
+import org.geotools.data.Transaction;
+import org.geotools.data.collection.ListFeatureCollection;
+import org.geotools.data.shapefile.ShapefileDataStore;
+import org.geotools.data.shapefile.ShapefileDataStoreFactory;
+import org.geotools.data.simple.SimpleFeatureStore;
+import org.geotools.feature.simple.SimpleFeatureBuilder;
+import org.locationtech.jts.geom.Geometry;
+import org.opengis.feature.simple.SimpleFeatureType;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * ShapeFile工具
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+public class ShapeUtils {
+    //缓存库工厂
+    private static final ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
+
+    /**
+     * 输出shape文件
+     *
+     * @param geometryData  地理对象数据(key为gis类型)
+     * @param directoryPath 文件夹路径
+     * @throws IOException io异常
+     */
+    public static void writeShape(Map<String, List<Geometry>> geometryData, Path directoryPath) throws IOException {
+        for (Map.Entry<String, List<Geometry>> entry : geometryData.entrySet()) {
+            String key = entry.getKey();
+            List<Geometry> data = entry.getValue();
+
+            GisTypeEnum gisTypeEnum = GisTypeEnum.get(key);
+            if (gisTypeEnum != null) writeShape(data, Paths.get(directoryPath + "/" + key + ".shp"), gisTypeEnum);
+        }
+    }
+
+    /**
+     * 输出shape文件
+     *
+     * @param geometries 地理对象集合
+     * @param filePath   文件路径
+     * @param gisType    gis类型
+     * @throws IOException io异常
+     */
+    public static void writeShape(List<Geometry> geometries, Path filePath, GisTypeEnum gisType) throws IOException {
+        //类型
+        final SimpleFeatureType TYPE = GisTypeEnum.featureType(gisType);
+        if (TYPE == null) return;
+        //特征构建
+        final SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
+        //特征集合
+        ListFeatureCollection collection = new ListFeatureCollection(TYPE);
+        geometries.forEach(geometry -> {
+            featureBuilder.set("the_geom", geometry);
+            collection.add(featureBuilder.buildFeature(null));
+        });
+
+        //从文件构建数据缓存库
+        Map<String, Serializable> params = new HashMap<>();
+        params.put(ShapefileDataStoreFactory.URLP.key, filePath.toUri().toURL());
+        params.put(ShapefileDataStoreFactory.CREATE_SPATIAL_INDEX.key, Boolean.TRUE);
+
+        ShapefileDataStore dataStore = (ShapefileDataStore) dataStoreFactory.createDataStore(params);
+        dataStore.createSchema(TYPE);
+
+        //启动事务
+        try (Transaction transaction = Transaction.AUTO_COMMIT) {
+            //从文件缓存库获取特征缓存库
+            SimpleFeatureStore featureStore = (SimpleFeatureStore) dataStore.getFeatureSource();
+            //设置事务
+            featureStore.setTransaction(transaction);
+
+            //写入特征集合
+            featureStore.addFeatures(collection);
+        }
+    }
+}

+ 272 - 0
src/main/java/com/shkpr/service/alambizplugin/components/GisSurveyThirdExporter.java

@@ -0,0 +1,272 @@
+package com.shkpr.service.alambizplugin.components;
+
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.alambizplugin.commproperties.TempFileProperties;
+import com.shkpr.service.alambizplugin.commtools.CompressorUtils;
+import com.shkpr.service.alambizplugin.commtools.ExcelUtils;
+import com.shkpr.service.alambizplugin.commtools.ShapeUtils;
+import com.shkpr.service.alambizplugin.constants.CommAsyncStatusEnum;
+import com.shkpr.service.alambizplugin.constants.ExcelEnum;
+import com.shkpr.service.alambizplugin.constants.GisMetadataDefine;
+import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
+import com.shkpr.service.alambizplugin.dbdao.services.intef.GisMetadataLayerTemplateService;
+import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveyLayerApplyService;
+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.GisSurveyLayerApply;
+import com.shkpr.service.alambizplugin.dto.GisSurveyPropertyValue;
+import org.apache.commons.compress.archivers.ArchiveException;
+import org.apache.commons.lang3.StringUtils;
+import org.locationtech.jts.geom.Geometry;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.AsyncResult;
+import org.springframework.stereotype.Component;
+import org.springframework.util.concurrent.ListenableFuture;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * 第三方导出执行器
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Component
+public class GisSurveyThirdExporter {
+    /**
+     * log
+     */
+    private final String mStrClassName;
+    private final String mBizType;
+    private final TempFileProperties tempFileProperties;
+    private final GisMetadataLayerTemplateService layerTemplateService;
+    private final GisSurveyLayerApplyService gisSurveyLayerApplyService;
+
+
+    public GisSurveyThirdExporter(TempFileProperties tempFileProperties
+            , GisMetadataLayerTemplateService layerTemplateService, GisSurveyLayerApplyService gisSurveyLayerApplyService) {
+        mStrClassName = "GisSurveyThirdExporter";
+        mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
+        this.tempFileProperties = tempFileProperties;
+        this.layerTemplateService = layerTemplateService;
+        this.gisSurveyLayerApplyService = gisSurveyLayerApplyService;
+    }
+
+    /**
+     * 第三方导出任务
+     *
+     * @param jobId 任务id
+     * @return 导出结果
+     */
+    @Async
+    public ListenableFuture<CommAsyncResult<String>> thirdExportTask(String jobId) {
+        //构建返回
+        CommAsyncResult<String> result = CommAsyncResult.fail(jobId);
+        try {
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                    , String.format(
+                            "开始执行第三方导出;任务id: %s"
+                            , jobId
+                    )
+            );
+
+            //查询点线数据
+            List<GisSurveyLayerApply> points = gisSurveyLayerApplyService.findAllByJobIdAndKind(jobId, GisMetadataDefine.TYPE_KINE.POINT);
+            List<GisSurveyLayerApply> lines = gisSurveyLayerApplyService.findAllByJobIdAndKind(jobId, GisMetadataDefine.TYPE_KINE.LINE);
+            //获取图层key
+            List<String> pointLayer = getLayerKeys(points);
+            List<String> lineLayer = getLayerKeys(lines);
+            //查询点图层模版
+            List<GisMetadataLayerTemplate> pointLayerTemplates = layerTemplateService.findByKeyIn(pointLayer);
+            //查询线图层模版
+            List<GisMetadataLayerTemplate> lineLayerTemplates = layerTemplateService.findByKeyIn(lineLayer);
+
+            //构建excel头
+            Map<String, Map<String, String>> excelHeader = buildExcelHeader(pointLayerTemplates, lineLayerTemplates);
+
+            //构建excel数据
+            Map<String, List<Map<String, Object>>> excelData = buildExcelData(points, lines);
+            //构建shape数据
+            Map<String, List<Geometry>> shapeData = buildShapeData(points, lines);
+
+            //创建临时文件夹
+            Path directory = Files.createTempDirectory(tempFileProperties.getResourcePath(), "third-export-");
+
+            //导出excel
+            File excelFile = new File(directory + "/" + "output.xlsx");
+            ExcelUtils.writeFile(excelHeader, excelData, Files.newOutputStream(excelFile.toPath()), ExcelEnum.XLSX);
+            //导出shape
+            ShapeUtils.writeShape(shapeData, directory);
+
+            //压缩文件夹
+            Path zipPath = CompressorUtils.archivalZip(directory);
+            if (!Files.exists(zipPath)) {
+                //打印报错信息
+                LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
+                        , String.format("第三方导出zip压缩失败 任务id:%s", jobId)
+                );
+                return new AsyncResult<>(result);
+            }
+
+            //导出
+            result.setStatus(CommAsyncStatusEnum.SUCCESS.getCode());
+            result.setCompleteTime(LocalDateTime.now());
+            result.setData(zipPath.getFileName().toString());
+
+            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);
+        } catch (InterruptedException | IOException | ArchiveException e) {
+            //打印报错信息
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
+                    , String.format("第三方导出异常 任务id:%s error:%s", jobId, e)
+            );
+            return new AsyncResult<>(result);
+        }
+    }
+
+    /**
+     * 获取图层key
+     *
+     * @param datas 数据
+     * @return 图层key集合
+     */
+    private List<String> getLayerKeys(List<GisSurveyLayerApply> datas) {
+        //去重图层
+        return datas.parallelStream()
+                .map(GisSurveyLayerApply::getLayer)
+                .filter(StringUtils::isNotBlank)
+                .distinct()
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * 构建excel头
+     *
+     * @param pointLayerTemplates 点图层模版
+     * @param lineLayerTemplates  线图层模版
+     * @return excel数据
+     */
+    private Map<String, Map<String, String>> buildExcelHeader(List<GisMetadataLayerTemplate> pointLayerTemplates
+            , List<GisMetadataLayerTemplate> lineLayerTemplates) {
+        //点excel头
+        Map<String, String> pointExcelHeader = pointLayerTemplates.stream()
+                .flatMap(it -> it.getPropertyTemplates().stream())
+                .sorted(Comparator.comparing(GisMetadataPropertyTemplate::getOrdering))
+                .collect(Collectors.toMap(GisMetadataPropertyTemplate::getKey, GisMetadataPropertyTemplate::getName
+                        , (it1, it2) -> it1, LinkedHashMap::new));
+        //线excel头
+        Map<String, String> lineExcelHeader = lineLayerTemplates.stream()
+                .flatMap(it -> it.getPropertyTemplates().stream())
+                .collect(Collectors.toMap(GisMetadataPropertyTemplate::getKey, GisMetadataPropertyTemplate::getName
+                        , (it1, it2) -> it1, LinkedHashMap::new));
+        //excel头
+        Map<String, Map<String, String>> excelHeader = new HashMap<>();
+        excelHeader.put(GisMetadataDefine.TYPE_KINE.POINT, pointExcelHeader);
+        excelHeader.put(GisMetadataDefine.TYPE_KINE.LINE, lineExcelHeader);
+
+        return excelHeader;
+    }
+
+    /**
+     * 构建excel数据
+     *
+     * @param points 点元素
+     * @param lines  线元素
+     * @return excel数据
+     */
+    private Map<String, List<Map<String, Object>>> buildExcelData(List<GisSurveyLayerApply> points, List<GisSurveyLayerApply> lines) {
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始构建excel数据   ======>");
+        long begin = System.currentTimeMillis();
+
+        //点excel数据
+        List<Map<String, Object>> pointExcelData = points.parallelStream().map(it ->
+                it.getPropertyValues().stream()
+                        .filter(it1 -> !StringUtils.isAnyBlank(it1.getProperty(), it1.getValue()))
+                        .collect(Collectors.toMap(
+                                GisSurveyPropertyValue::getProperty,
+                                gisSurveyPropertyValue -> (Object) gisSurveyPropertyValue.getValue()
+                        ))
+        ).collect(Collectors.toList());
+        //线excel数据
+        List<Map<String, Object>> lineExcelData = lines.parallelStream().map(it ->
+                it.getPropertyValues().stream()
+                        .filter(it1 -> !StringUtils.isAnyBlank(it1.getProperty(), it1.getValue()))
+                        .collect(Collectors.toMap(
+                                GisSurveyPropertyValue::getProperty,
+                                gisSurveyPropertyValue -> (Object) gisSurveyPropertyValue.getValue()
+                        ))
+        ).collect(Collectors.toList());
+
+        //excel数据
+        Map<String, List<Map<String, Object>>> excelData = new HashMap<>();
+        excelData.put(GisMetadataDefine.TYPE_KINE.POINT, pointExcelData);
+        excelData.put(GisMetadataDefine.TYPE_KINE.LINE, lineExcelData);
+
+        long end = System.currentTimeMillis();
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                , String.format(
+                        "结束构建excel数据,用时(毫秒):%d"
+                        , (end - begin)
+                )
+        );
+        return excelData;
+    }
+
+    /**
+     * 构建shape数据
+     *
+     * @param points 点元素
+     * @param lines  线元素
+     * @return excel数据
+     */
+    private Map<String, List<Geometry>> buildShapeData(List<GisSurveyLayerApply> points, List<GisSurveyLayerApply> lines) {
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始构建shape数据   ======>");
+        long begin = System.currentTimeMillis();
+
+        //点excel数据
+        List<Geometry> pointExcelData = points.parallelStream()
+                .map(GisSurveyLayerApply::getGis)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+        //线excel数据
+        List<Geometry> lineExcelData = lines.parallelStream()
+                .map(GisSurveyLayerApply::getGis)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+
+        //excel数据
+        Map<String, List<Geometry>> shapeData = new HashMap<>();
+        shapeData.put(GisMetadataDefine.TYPE_KINE.POINT, pointExcelData);
+        shapeData.put(GisMetadataDefine.TYPE_KINE.LINE, lineExcelData);
+
+        long end = System.currentTimeMillis();
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                , String.format(
+                        "结束构建shape数据,用时(毫秒):%d"
+                        , (end - begin)
+                )
+        );
+        return shapeData;
+    }
+}

+ 7 - 1
src/main/java/com/shkpr/service/alambizplugin/configuration/WebMvcConfiguration.java

@@ -3,6 +3,7 @@ package com.shkpr.service.alambizplugin.configuration;
 import com.shkpr.service.alambizplugin.SpringContextUtil;
 import com.shkpr.service.alambizplugin.commproperties.GisSurveyCadConvertProperties;
 import com.shkpr.service.alambizplugin.commproperties.GisSurveySystemCheckProperties;
+import com.shkpr.service.alambizplugin.commproperties.TempFileProperties;
 import com.shkpr.service.alambizplugin.constants.ApiURI;
 import com.shkpr.service.alambizplugin.interfaces.URIInterceptorIntef;
 import org.springframework.context.annotation.Bean;
@@ -33,11 +34,13 @@ import java.util.TreeMap;
 public class WebMvcConfiguration implements WebMvcConfigurer {
     private final GisSurveySystemCheckProperties systemCheckProperties;
     private final GisSurveyCadConvertProperties cadConvertProperties;
+    private final TempFileProperties tempFileProperties;
 
     public WebMvcConfiguration(GisSurveySystemCheckProperties systemCheckProperties
-    , GisSurveyCadConvertProperties cadConvertProperties) {
+    , GisSurveyCadConvertProperties cadConvertProperties,TempFileProperties tempFileProperties) {
         this.systemCheckProperties = systemCheckProperties;
         this.cadConvertProperties = cadConvertProperties;
+        this.tempFileProperties = tempFileProperties;
     }
 
     /**
@@ -51,6 +54,9 @@ public class WebMvcConfiguration implements WebMvcConfigurer {
         //cad转换文件映射
         registry.addResourceHandler(ApiURI.URI_GIS_SURVEY_H + "/" + ApiURI.URI_XXX_CAD_CONVERT_TEMPS + "/**")
                 .addResourceLocations("file:" + cadConvertProperties.getResourcePath() + "/");
+        //临时文件映射
+        registry.addResourceHandler(ApiURI.URI_GIS_SURVEY_H + "/" + ApiURI.URI_XXX_TEMP_FILES + "/**")
+                .addResourceLocations("file:" + tempFileProperties.getResourcePath() + "/");
     }
 
     @Override

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

@@ -33,9 +33,11 @@ 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_EXPORT = "third-export";
     public static final String URI_XXX_CAD_CONVERT = "cad-convert";
     public static final String URI_XXX_CAD_CONVERT_GET = "cad-convert-get";
     public static final String URI_XXX_CAD_CONVERT_TEMPS = "cad-convert-temps";
+    public static final String URI_XXX_TEMP_FILES = "temp-files";
 
     public static final String URI_ACCESS_TOKEN_CHECK = "/kpr-plugin/apply/access-token-check";
     public static final String URI_FILE_BUSI_XXX = "/files/**";

+ 35 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/CommAsyncStatusEnum.java

@@ -0,0 +1,35 @@
+package com.shkpr.service.alambizplugin.constants;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 通用异步状态枚举
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@AllArgsConstructor
+@Getter
+public enum CommAsyncStatusEnum {
+    /**
+     * 进行中
+     */
+    IN_PROGRESS(0),
+    /**
+     * 成功
+     */
+    SUCCESS(1),
+    /**
+     * 失败
+     */
+    FAIL(2),
+    /**
+     * 不存在
+     */
+    NOT_EXISTS(3);
+    /**
+     * code
+     */
+    private final Integer code;
+}

+ 59 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/GisTypeEnum.java

@@ -0,0 +1,59 @@
+package com.shkpr.service.alambizplugin.constants;
+
+import org.geotools.data.DataUtilities;
+import org.opengis.feature.simple.SimpleFeatureType;
+
+/**
+ * gis类型枚举
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+public enum GisTypeEnum {
+    //点
+    POINT,
+    //线
+    LINE;
+
+    /**
+     * 获取枚举
+     *
+     * @param kine 类型
+     * @return gis枚举
+     */
+    public static GisTypeEnum get(String kine) {
+        switch (kine) {
+            case GisMetadataDefine.TYPE_KINE.POINT:
+                return POINT;
+            case GisMetadataDefine.TYPE_KINE.LINE:
+                return LINE;
+        }
+        return null;
+    }
+
+    /**
+     * 特征类型
+     *
+     * @param typeEnum 类型枚举
+     * @return 特征类型
+     */
+    public static SimpleFeatureType featureType(GisTypeEnum typeEnum) {
+        try {
+            switch (typeEnum) {
+                case POINT:
+                    return DataUtilities.createType(
+                            "Point",
+                            "the_geom:Point:srid=4490,name:String"
+                    );
+                case LINE:
+                    return DataUtilities.createType(
+                            "LineString",
+                            "the_geom:LineString:srid=4490,name:String"
+                    );
+            }
+            return null;
+        } catch (Exception e) {
+            return null;
+        }
+    }
+}

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

@@ -6,10 +6,12 @@ import com.shkpr.service.alambizplugin.apiparam.GisSurveyCheckParams;
 import com.shkpr.service.alambizplugin.apiparam.GisSurveyThirdImportParams;
 import com.shkpr.service.alambizplugin.bizservice.GisSurveyCadConvertBizService;
 import com.shkpr.service.alambizplugin.bizservice.GisSurveySystemCheckBizService;
+import com.shkpr.service.alambizplugin.bizservice.GisSurveyThirdExportBizService;
 import com.shkpr.service.alambizplugin.bizservice.GisSurveyThirdImportBizService;
 import com.shkpr.service.alambizplugin.commtools.CommTool;
 import com.shkpr.service.alambizplugin.constants.ApiURI;
 import com.shkpr.service.alambizplugin.constants.CadEnum;
+import com.shkpr.service.alambizplugin.constants.CommAsyncStatusEnum;
 import com.shkpr.service.alambizplugin.constants.GisSurveConvertStatusEnum;
 import com.shkpr.service.alambizplugin.constants.GisSurveyCheckStatusEnum;
 import com.shkpr.service.alambizplugin.constants.GisSurveyImportStatusEnum;
@@ -19,6 +21,7 @@ import com.shkpr.service.alambizplugin.controllerfilter.TokenAuthenticationServi
 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.GisSurveyCadConvertResult;
 import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyThirdCopy;
 import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckResult;
@@ -61,16 +64,20 @@ public class ApiGisSurveyController {
     private final AtomicInteger mSeqThirdImportPreviewReq;
     private final AtomicInteger mSeqThirdImportCommitReq;
     private final AtomicInteger mSeqCadConvertReq;
+    private final AtomicInteger mSeqThirdExportReq;
     private final AtomicInteger mSeqCadConvertGetReq;
 
     private final GisSurveySystemCheckBizService systemCheckBizService;
     private final GisSurveyThirdImportBizService thirdImportBizService;
+    private final GisSurveyThirdExportBizService thirdExportBizService;
     private final GisSurveyCadConvertBizService cadConvertBizService;
     private final GisSurveyLayerApplyService layerApplyService;
     private final GisSurveyLayerApplyThirdCopyServiceImpl layerApplyThirdCopyService;
 
     public ApiGisSurveyController(GisSurveySystemCheckBizService systemCheckBizService
-            , GisSurveyThirdImportBizService thirdImportBizService, GisSurveyCadConvertBizService cadConvertBizService
+            , GisSurveyThirdImportBizService thirdImportBizService
+            , GisSurveyThirdExportBizService thirdExportBizService
+            , GisSurveyCadConvertBizService cadConvertBizService
             , GisSurveyLayerApplyService layerApplyService
             , GisSurveyLayerApplyThirdCopyServiceImpl layerApplyThirdCopyService) {
         mStrClassName = "ApiGisSurveyController";
@@ -82,10 +89,12 @@ public class ApiGisSurveyController {
         mSeqThirdImportCancelReq = new AtomicInteger(0);
         mSeqThirdImportPreviewReq = new AtomicInteger(0);
         mSeqThirdImportCommitReq = new AtomicInteger(0);
+        mSeqThirdExportReq = new AtomicInteger(0);
         mSeqCadConvertReq = new AtomicInteger(0);
         mSeqCadConvertGetReq = new AtomicInteger(0);
         this.systemCheckBizService = systemCheckBizService;
         this.thirdImportBizService = thirdImportBizService;
+        this.thirdExportBizService = thirdExportBizService;
         this.cadConvertBizService = cadConvertBizService;
         this.layerApplyService = layerApplyService;
         this.layerApplyThirdCopyService = layerApplyThirdCopyService;
@@ -583,6 +592,74 @@ public class ApiGisSurveyController {
     }
 
     /**
+     * 执行第三方导出
+     *
+     * @param request         request
+     * @param strClientType   客户端类型
+     * @param strUserAgent    用户信息
+     * @param jobId      任务id
+     * @return cad转换结果
+     */
+    @GetMapping(value = ApiURI.URI_XXX_THIRD_EXPORT)
+    public ResponseRes<CommAsyncResult<String>> thirdExport(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) throws SelfException {
+        //入参校验
+        final String URI_PATH = request.getRequestURI();
+        final String strPlatform = CommTool.getPlatformByAgent(strClientType, strUserAgent);
+        final String strUserId = (String) request.getAttribute(TokenAuthenticationService.HEADER_USERID);
+        if (StringUtils.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, mSeqThirdExportReq.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<CommAsyncResult<String>> resResult = new ResponseRes<>();
+        resResult.setRescode(ResponseCode.RESULT_ASYNC_TASK_FAILED.toStrCode());
+        resResult.setResmsg(ResponseCode.RESULT_ASYNC_TASK_FAILED.toStrMsg());
+
+        //执行第三方导出
+        CommAsyncResult<String> result = thirdExportBizService.thirdExport(jobId);
+
+        //执行成功
+        if (result != null && !Objects.equals(result.getStatus(), CommAsyncStatusEnum.FAIL.getCode())) {
+            resResult.setRescode(ResponseCode.RESULT_NORMAL.toStrCode());
+            resResult.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg());
+            resResult.setResdata(result);
+        }
+        //执行失败
+        if (result != null && Objects.equals(result.getStatus(), CommAsyncStatusEnum.FAIL.getCode())) {
+            resResult.setResdata(result);
+        }
+
+        //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;
+    }
+
+    /**
      * 执行cad转换
      *
      * @param request         request

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

@@ -70,6 +70,9 @@ public class JWTAuthenticationFilter extends BasicAuthenticationFilter {
                 || this.mPathMatcher.match(
                 String.format("%s%s", request.getContextPath(), ApiURI.URI_GIS_SURVEY_H + "/" + ApiURI.URI_XXX_CAD_CONVERT_TEMPS + "/**"),
                 request.getRequestURI())
+                || this.mPathMatcher.match(
+                String.format("%s%s", request.getContextPath(), ApiURI.URI_GIS_SURVEY_H + "/" + ApiURI.URI_XXX_TEMP_FILES + "/**"),
+                request.getRequestURI())
         )) {
             chain.doFilter(request, response);
             return;

+ 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_EXPORT), "GET");
         msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_GIS_SURVEY_H, ApiURI.URI_XXX_CAD_CONVERT), "POST");
         msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_GIS_SURVEY_H, ApiURI.URI_XXX_CAD_CONVERT_GET), "GET");
     }

+ 7 - 1
src/main/java/com/shkpr/service/alambizplugin/dbdao/mapper/GisMetadataLayerTemplateMapper.java

@@ -14,7 +14,6 @@ import java.util.List;
  */
 @Mapper
 public interface GisMetadataLayerTemplateMapper {
-
     /**
      * 根据用水类别和图层名集合查询
      *
@@ -24,4 +23,11 @@ public interface GisMetadataLayerTemplateMapper {
      */
     List<GisMetadataLayerTemplate> findByNatureAndNameIn(@Param("nature") String nature, @Param("names") List<String> names);
 
+    /**
+     * 根据用图层标识符集合查询
+     *
+     * @param keys 图层标识符集合
+     * @return 图层定义模版
+     */
+    List<GisMetadataLayerTemplate> findByKeyIn(@Param("keys") List<String> keys);
 }

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

@@ -1,5 +1,6 @@
 package com.shkpr.service.alambizplugin.dbdao.mapper;
 
+import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApply;
 import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyLine;
 import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyPoint;
 import org.apache.ibatis.annotations.Mapper;
@@ -47,6 +48,15 @@ public interface GisSurveyLayerApplyMapper {
     Cursor<GisSurveyLayerApplyLine> findAddLineByJobId(@Param("jobId") String jobId);
 
     /**
+     * 根据任务id和类型查询
+     *
+     * @param jobId 任务id
+     * @param kind  类型
+     * @return 实体
+     */
+    Cursor<GisSurveyLayerApply> findAllByJobIdAndKind(@Param("jobId") String jobId, @Param("kind") String kind);
+
+    /**
      * 根据任务id合并副表
      *
      * @param jobId 任务id

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

@@ -36,4 +36,16 @@ public class GisMetadataLayerTemplateServiceImpl implements GisMetadataLayerTemp
         if (CollectionUtils.isEmpty(names)) return Collections.emptyList();
         return layerTemplateMapper.findByNatureAndNameIn(nature, names);
     }
+
+    /**
+     * 根据用图层标识符集合查询
+     *
+     * @param keys 图层标识符集合
+     * @return 图层定义模版
+     */
+    @Override
+    public List<GisMetadataLayerTemplate> findByKeyIn(List<String> keys) {
+        if (CollectionUtils.isEmpty(keys)) return Collections.emptyList();
+        return layerTemplateMapper.findByKeyIn(keys);
+    }
 }

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

@@ -12,6 +12,7 @@ import com.shkpr.service.alambizplugin.dbdao.mapper.GisSurveyProjectInfoMapper;
 import com.shkpr.service.alambizplugin.dbdao.mapper.GisSurveyPropertyValueMapper;
 import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveyLayerApplyService;
 import com.shkpr.service.alambizplugin.dto.GisSurveyJobStatusTrack;
+import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApply;
 import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyLine;
 import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyPoint;
 import org.apache.ibatis.cursor.Cursor;
@@ -241,6 +242,57 @@ public class GisSurveyLayerApplyServiceImpl implements GisSurveyLayerApplyServic
     }
 
     /**
+     * 根据任务id和类型查询
+     *
+     * @param jobId 任务id
+     * @param kind  类型
+     * @return 采集集合
+     * @throws InterruptedException 中断异常
+     */
+    @Transactional(transactionManager = "mainDbTransactionManager")
+    public List<GisSurveyLayerApply> findAllByJobIdAndKind(String jobId, String kind) throws InterruptedException {
+        //数据集合
+        List<GisSurveyLayerApply> layerApplies = new ArrayList<>();
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                , String.format(
+                        "开始根据任务id和类型查询采集元素,开启事务和游标 任务ID:%s 类型:%s"
+                        , jobId
+                        , kind
+                )
+        );
+        long begin = System.currentTimeMillis();
+        //获取游标
+        try (Cursor<GisSurveyLayerApply> cursor = layerApplyMapper.findAllByJobIdAndKind(jobId, kind)) {
+            //迭代游标
+            for (GisSurveyLayerApply layerApply : cursor) {
+                //检查线程中断,并响应
+                if (Thread.interrupted()) throw new InterruptedException();
+                //检查游标完成
+                if (cursor.isConsumed()) return layerApplies;
+                layerApplies.add(layerApply);
+            }
+            long end = System.currentTimeMillis();
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                    , String.format(
+                            "结束根据任务id和类型查询采集元素,关闭事务和游标 任务ID:%s 类型:%s 用时(毫秒):%d"
+                            , jobId
+                            , kind
+                            , (end - begin)
+                    )
+            );
+        } catch (IOException ioException) {
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
+                    , String.format(
+                            "关闭游标失败 任务ID:%s msg:%s"
+                            , jobId
+                            , ioException.getMessage()
+                    )
+            );
+        }
+        return layerApplies;
+    }
+
+    /**
      * 合并副表
      *
      * @param jobId    任务id

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

@@ -19,4 +19,12 @@ public interface GisMetadataLayerTemplateService {
      * @return 图层定义模版
      */
     List<GisMetadataLayerTemplate> findByNatureAndNameIn(String nature, List<String> names);
+
+    /**
+     * 根据用图层标识符集合查询
+     *
+     * @param keys 图层标识符集合
+     * @return 图层定义模版
+     */
+    List<GisMetadataLayerTemplate> findByKeyIn(List<String> keys);
 }

+ 11 - 0
src/main/java/com/shkpr/service/alambizplugin/dbdao/services/intef/GisSurveyLayerApplyService.java

@@ -1,5 +1,6 @@
 package com.shkpr.service.alambizplugin.dbdao.services.intef;
 
+import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApply;
 import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyLine;
 import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyPoint;
 
@@ -45,6 +46,16 @@ public interface GisSurveyLayerApplyService {
     List<GisSurveyLayerApplyLine> findAddLineByJobId(String jobId) throws InterruptedException;
 
     /**
+     * 根据任务id和类型查询
+     *
+     * @param jobId 任务id
+     * @param kind  类型
+     * @return 采集集合
+     * @throws InterruptedException 中断异常
+     */
+    List<GisSurveyLayerApply> findAllByJobIdAndKind(String jobId, String kind) throws InterruptedException;
+
+    /**
      * 合并副表
      *
      * @param jobId    任务id

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

@@ -0,0 +1,76 @@
+package com.shkpr.service.alambizplugin.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.shkpr.service.alambizplugin.constants.GisSurveConvertStatusEnum;
+import com.shkpr.service.alambizplugin.constants.GisSurveyImportStatusEnum;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+/**
+ * 通用异步结构
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Data
+public class CommAsyncResult<T> {
+    /**
+     * 转换id
+     */
+    private String id;
+    /**
+     * 检查状态:0:进行中,1:成功,2:失败,3:不存在
+     */
+    private Integer status;
+    /**
+     * 结果数据
+     */
+    private T data;
+    /**
+     * 请求检查时间
+     */
+    @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;
+
+    /**
+     * 进行中
+     */
+    public static <T> CommAsyncResult<T> inProgress(String convertId, LocalDateTime requestTime) {
+        CommAsyncResult<T> result = new CommAsyncResult<>();
+        result.setId(convertId);
+        result.setStatus(GisSurveyImportStatusEnum.IN_PROGRESS.getCode());
+        result.setRequestTime(requestTime);
+        return result;
+    }
+
+    /**
+     * 成功
+     */
+    public static <T> CommAsyncResult<T> success(String convertId) {
+        CommAsyncResult<T> result = new CommAsyncResult<>();
+        result.setId(convertId);
+        result.setStatus(GisSurveConvertStatusEnum.SUCCESS.getCode());
+        result.setRequestTime(LocalDateTime.now());
+        return result;
+    }
+
+    /**
+     * 失败
+     */
+    public static <T> CommAsyncResult<T> fail(String convertId) {
+        CommAsyncResult<T> result = new CommAsyncResult<>();
+        result.setId(convertId);
+        result.setStatus(GisSurveConvertStatusEnum.FAIL.getCode());
+        result.setRequestTime(LocalDateTime.now());
+        return result;
+    }
+}

+ 109 - 0
src/main/java/com/shkpr/service/alambizplugin/dto/GisSurveyLayerApply.java

@@ -0,0 +1,109 @@
+package com.shkpr.service.alambizplugin.dto;
+
+import lombok.Data;
+import org.locationtech.jts.geom.Geometry;
+
+import java.util.List;
+
+/**
+ * 采集元素处理申请表
+ */
+@Data
+public class GisSurveyLayerApply {
+    /**
+     * 主键
+     */
+    private Long id;
+
+    /**
+     * 所属任务的唯一ID
+     */
+    private String jobId;
+
+    /**
+     * 元素唯一编码
+     */
+    private String code;
+
+    /**
+     * 元素类型标识符
+     */
+    private String layer;
+
+    /**
+     * 元素分类:point--点;line--线;face--面
+     */
+    private String kind;
+
+    /**
+     * 坐标值
+     */
+    private Geometry gis;
+
+    /**
+     * 坐标采集方式
+     */
+    private String gisMode;
+
+    /**
+     * 操作标记:add/update/delete
+     */
+    private String apply;
+
+    /**
+     * 数据来源:0--APP;1--Web;255--第三方导入
+     */
+    private Short source;
+
+    /**
+     * 线的起点唯一编码
+     */
+    private String upNode;
+
+    /**
+     * 线的终点唯一编码
+     */
+    private String downNode;
+
+    /**
+     * 最近审核备注说明
+     */
+    private String checkNote;
+
+    /**
+     * 最近审核时间
+     */
+    private Long checkTime;
+
+    /**
+     * 最近审核人
+     */
+    private String checker;
+
+    private Long lastTime;
+
+    /**
+     * 审核结果:-1--待审核;0--未通过;1--已通过
+     */
+    private Short pass;
+
+    /**
+     * 点的高程
+     */
+    private Double elevation;
+
+    /**
+     * 点的埋深
+     */
+    private Double depth;
+
+    /**
+     * 点的序号
+     */
+    private String no;
+
+    /**
+     * 属性值
+     */
+    private List<GisSurveyPropertyValue> propertyValues;
+}

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

@@ -8,6 +8,11 @@ import lombok.Data;
 @Data
 public class GisSurveyPropertyValue {
     /**
+     * 主键
+     */
+    private Long id;
+
+    /**
     * 所属任务的唯一ID
     */
     private String jobId;
@@ -22,8 +27,6 @@ public class GisSurveyPropertyValue {
     */
     private String property;
 
-    private Long id;
-
     /**
     * 取值
     */

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

@@ -161,6 +161,9 @@ cad-convert.resource-path=/home/kprCloud/alam_dma_kpr_plugin/cad-convert-temps/
 cad-convert.rasterization-min-width=800
 #栅格化最小高度
 cad-convert.rasterization-min-height=800
+#=============临时文件========================
+temp-file.resource-path=/home/kprCloud/alam_dma_kpr_plugin/temp-files/
+temp-file.lifecycle=15m
 
 
 

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

@@ -89,4 +89,51 @@
             #{item,jdbcType=VARCHAR}
         </foreach>
     </select>
+
+    <select id="findByKeyIn" resultMap="BaseResultMap">
+        select mlt.id,
+        mlt.nature,
+        mlt.kind,
+        mlt.key,
+        mlt.name,
+        mlt.icon,
+        mlt.color,
+        mlt.status,
+        mlt.remark,
+        mlt.creator,
+        mlt.param1,
+        mlt.param2,
+        mlt.create_time,
+        mlt.update_time,
+        mlt.ordering,
+        mpt.id as property_id,
+        mpt.nature as property_nature,
+        mpt.layer as property_layer,
+        mpt.key as property_key,
+        mpt.name as property_name,
+        mpt.type as property_type,
+        mpt.ranges as property_ranges,
+        mpt.widget as property_widget,
+        mpt.defaults as property_defaults,
+        mpt.required as property_required,
+        mpt.ordering as property_ordering,
+        mpt.source as property_source,
+        mpt.unit as property_unit,
+        mpt.editable as property_editable,
+        mpt.precisions as property_precisions,
+        mpt.status as property_status,
+        mpt.remark as property_remark,
+        mpt.creator as property_creator,
+        mpt.create_time as property_create_time,
+        mpt.update_time as property_update_time
+        from k3_gis_metadata_layer_template mlt
+        left join k3_gis_metadata_property_template mpt
+        on mlt.nature = mpt.nature and mlt.key = mpt.layer
+        where mlt.key in
+        <foreach item="item" index="index" collection="keys"
+                 open="(" separator="," close=")">
+            #{item,jdbcType=VARCHAR}
+        </foreach>
+        order by mpt.ordering
+    </select>
 </mapper>

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

@@ -1,6 +1,31 @@
 <?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.GisSurveyLayerApplyMapper">
+    <resultMap id="BaseResultMap" type="com.shkpr.service.alambizplugin.dto.GisSurveyLayerApply">
+        <!--@Table k3_gis_survey_layer_apply-->
+        <id column="job_id" jdbcType="VARCHAR" property="jobId"/>
+        <id column="code" jdbcType="VARCHAR" property="code"/>
+        <result column="layer" jdbcType="VARCHAR" property="layer"/>
+        <result column="kind" jdbcType="VARCHAR" property="kind"/>
+        <result column="gis" jdbcType="VARCHAR" property="gis"
+                typeHandler="com.shkpr.service.alambizplugin.dbdao.pgtype.GeomTypeHandlePg"/>
+        <result column="apply" jdbcType="VARCHAR" property="apply"/>
+        <result column="source" jdbcType="SMALLINT" property="source"/>
+        <result column="up_node" jdbcType="VARCHAR" property="upNode"/>
+        <result column="down_node" jdbcType="VARCHAR" property="downNode"/>
+        <result column="elevation" jdbcType="DOUBLE" property="elevation"/>
+        <result column="depth" jdbcType="DOUBLE" property="depth"/>
+        <result column="no" jdbcType="VARCHAR" property="no"/>
+        <collection property="propertyValues"
+                    ofType="com.shkpr.service.alambizplugin.dto.GisSurveyPropertyValue">
+            <!--@Table k3_gis_survey_property_value-->
+            <id column="property_job_id" jdbcType="VARCHAR" property="jobId"/>
+            <id column="property_code" jdbcType="VARCHAR" property="code"/>
+            <id column="property_property" jdbcType="VARCHAR" property="property"/>
+            <result column="property_value" jdbcType="VARCHAR" property="value"/>
+        </collection>
+    </resultMap>
+
     <resultMap id="Point" type="com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyPoint">
         <!--@Table k3_gis_survey_layer_apply-->
         <id column="code" jdbcType="VARCHAR" property="code"/>
@@ -78,6 +103,23 @@
         and la.apply = 'add' and la.kind = 'line';
     </select>
 
+    <select id="findAllByJobIdAndKind" 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,
+        pv.property as property_property, pv.code as property_code, pv.job_id as property_job_id,
+        pv.value as property_value
+        from k3_gis_survey_layer_apply as la
+        join k3_gis_survey_job_info jo on la.job_id = jo.uid
+        left join k3_gis_survey_layer_apply as un
+        on la.up_node = un.code and un.kind = 'point' and la.job_id = un.job_id
+        left join k3_gis_survey_layer_apply as dn
+        on la.down_node = dn.code and dn.kind = 'point' and la.job_id = dn.job_id
+        left join k3_gis_survey_property_value pv on la.code = pv.code and la.job_id = pv.job_id
+        where la.job_id = #{jobId,jdbcType=VARCHAR} and la.kind = #{kind,jdbcType=VARCHAR}
+    </select>
+
     <insert id="mergeCopyByJobId">
         insert into k3_gis_survey_layer_apply(code, job_id, layer, kind, gis, apply, source, up_node,
         down_node,elevation,depth,no)

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

@@ -1,6 +1,19 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.shkpr.service.alambizplugin.dbdao.mapper.GisSurveyPropertyValueMapper">
+    <resultMap id="BaseResultMap" type="com.shkpr.service.alambizplugin.dto.GisSurveyPropertyValue">
+        <!--@Table k3_gis_survey_property_value-->
+        <id column="job_id" jdbcType="VARCHAR" property="jobId" />
+        <id column="code" jdbcType="VARCHAR" property="code" />
+        <id column="property" jdbcType="VARCHAR" property="property" />
+        <result column="id" jdbcType="BIGINT" property="id" />
+        <result column="value" jdbcType="VARCHAR" property="value" />
+        <result column="pass" jdbcType="SMALLINT" property="pass" />
+        <result column="check_note" jdbcType="VARCHAR" property="checkNote" />
+        <result column="check_data" jdbcType="VARCHAR" property="checkData" />
+        <result column="check_edit" jdbcType="SMALLINT" property="checkEdit" />
+    </resultMap>
+
     <insert id="mergeCopyByJobId">
         insert into k3_gis_survey_property_value (property, code, job_id, value)
         select property, code, job_id, value