From 6bb5cf46f74a58e046354e1c482a3a6f5fab7565 Mon Sep 17 00:00:00 2001 From: zzw <2029503428@qq.com> Date: Tue, 2 Jun 2026 17:10:47 +0800 Subject: [PATCH] =?UTF-8?q?QGIS=E5=9C=B0=E9=9C=87=E4=B8=93=E9=A2=98?= =?UTF-8?q?=E5=9B=BE=E4=BA=A7=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 64 +- src/main/java/com/gis/xian/bo/DlqMessage.java | 22 + .../com/gis/xian/config/DataSourceConfig.java | 13 +- .../com/gis/xian/constant/BaseConstants.java | 116 +++ .../xian/controller/DZEqEventController.java | 43 ++ .../gis/xian/core/config/RabbitConfig.java | 100 +++ .../xian/core/config/RestClientConfig.java | 29 + .../gis/xian/core/rabbitmq/DlqConsumer.java | 114 +++ .../gis/xian/core/rabbitmq/DlqOperate.java | 54 ++ .../com/gis/xian/dto/base/ActiveFaultDTO.java | 24 + .../gis/xian/dto/base/ShanXiCitiesDTO.java | 22 + .../gis/xian/dto/base/ShanXiCountyDTO.java | 22 + .../com/gis/xian/dto/base/ShanXiTownsDTO.java | 22 + .../com/gis/xian/dto/dzxx/DZXXCenterDTO.java | 26 + .../gis/xian/dto/dzxx/DZXXDistanceDTO.java | 23 + .../gis/xian/dto/dzxx/DZXXInfluenceDTO.java | 26 + .../com/gis/xian/dto/pub/DZInfluenceDTO.java | 24 + .../com/gis/xian/dto/pub/DZProductDTO.java | 30 + .../com/gis/xian/dto/pub/EqAssessmentDTO.java | 27 + .../com/gis/xian/dto/pub/EqTriggerDTO.java | 31 + .../com/gis/xian/dto/pub/IntyGeoJsonDTO.java | 43 ++ .../com/gis/xian/dto/pub/RAssessmentDTO.java | 28 + .../com/gis/xian/entity/base/ActiveFault.java | 206 ++++++ .../com/gis/xian/entity/base/SXCities.java | 38 + .../com/gis/xian/entity/base/SXCounty.java | 47 ++ .../com/gis/xian/entity/base/SXTowns.java | 44 ++ .../com/gis/xian/entity/dzxx/DZXXCenter.java | 75 ++ .../gis/xian/entity/dzxx/DZXXDistance.java | 46 ++ .../gis/xian/entity/dzxx/DZXXInfluence.java | 58 ++ .../com/gis/xian/entity/pub/DZEqEvent.java | 71 ++ .../com/gis/xian/entity/pub/DZEqQueue.java | 55 ++ .../com/gis/xian/entity/pub/DZInfluence.java | 57 ++ .../com/gis/xian/entity/pub/DZProduct.java | 55 ++ .../java/com/gis/xian/enums/BaseEnums.java | 33 + .../java/com/gis/xian/enums/EqMapsEnums.java | 41 ++ .../com/gis/xian/enums/RainMapsEnums.java | 37 + .../gis/xian/handler/EarthquakeHandler.java | 112 +++ .../gis/xian/handler/EllipseToWktHandler.java | 158 ++++ .../gis/xian/handler/GeoDistanceHandler.java | 219 ++++++ .../com/gis/xian/handler/GeoFilesHandler.java | 103 +++ .../gis/xian/handler/GeometryTypeHandler.java | 138 ++++ .../xian/mapper/base/ActiveFaultMapper.java | 15 + .../xian/mapper/base/ShanXiCitiesMapper.java | 15 + .../xian/mapper/base/ShanXiCountyMapper.java | 15 + .../xian/mapper/base/ShanXiTownsMapper.java | 15 + .../xian/mapper/dzxx/DZXXCenterMapper.java | 15 + .../xian/mapper/dzxx/DZXXDistanceMapper.java | 15 + .../xian/mapper/dzxx/DZXXInfluenceMapper.java | 15 + .../gis/xian/mapper/pub/DZEqEventMapper.java | 15 + .../gis/xian/mapper/pub/DZEqQueueMapper.java | 15 + .../xian/mapper/pub/DZInfluenceMapper.java | 15 + .../gis/xian/mapper/pub/DZProductMapper.java | 15 + .../java/com/gis/xian/params/QgisArgs.java | 32 + src/main/java/com/gis/xian/query/EqQuery.java | 20 + .../com/gis/xian/query/IntensityQuery.java | 20 + .../java/com/gis/xian/query/ProductQuery.java | 22 + .../service/base/IActiveFaultService.java | 19 + .../service/base/IShanXiCitiesService.java | 21 + .../service/base/IShanXiCountyService.java | 26 + .../service/base/IShanXiTownsService.java | 25 + .../base/impl/ActiveFaultServiceImpl.java | 145 ++++ .../base/impl/ShanXiCitiesServiceImpl.java | 136 ++++ .../base/impl/ShanXiCountyServiceImpl.java | 109 +++ .../base/impl/ShanXiTownsServiceImpl.java | 109 +++ .../xian/service/dzxx/IDZXXCenterService.java | 19 + .../service/dzxx/IDZXXDistanceService.java | 19 + .../service/dzxx/IDZXXInfluenceService.java | 29 + .../dzxx/impl/DZXXCenterServiceImpl.java | 56 ++ .../dzxx/impl/DZXXDistanceServiceImpl.java | 157 ++++ .../dzxx/impl/DZXXInfluenceServiceImpl.java | 206 ++++++ .../gis/xian/service/ex/ServeException.java | 27 + .../xian/service/pub/IDZEqEventService.java | 22 + .../xian/service/pub/IDZEqQueueService.java | 21 + .../xian/service/pub/IDZInfluenceService.java | 25 + .../xian/service/pub/IDZProductService.java | 25 + .../gis/xian/service/pub/IFeignService.java | 18 + .../pub/impl/DZEqEventServiceImpl.java | 104 +++ .../pub/impl/DZEqQueueServiceImpl.java | 170 +++++ .../pub/impl/DZInfluenceServiceImpl.java | 120 +++ .../pub/impl/DZProductServiceImpl.java | 209 ++++++ .../service/pub/impl/FeignServiceImpl.java | 97 +++ .../com/gis/xian/task/InitializeData.java | 12 +- .../java/com/gis/xian/utils/BaseUtils.java | 70 ++ .../java/com/gis/xian/utils/StringUtils.java | 682 ++++++++++++++++++ .../gis/xian/utils/http/HttpRestClient.java | 198 +++++ src/main/resources/application-dev.yml | 31 +- src/main/resources/application-prod.yml | 27 +- src/main/resources/application.yml | 10 +- .../database/application-database-dev.yml | 8 +- .../database/application-database-prod.yml | 8 +- 90 files changed, 5689 insertions(+), 26 deletions(-) create mode 100644 src/main/java/com/gis/xian/bo/DlqMessage.java create mode 100644 src/main/java/com/gis/xian/constant/BaseConstants.java create mode 100644 src/main/java/com/gis/xian/controller/DZEqEventController.java create mode 100644 src/main/java/com/gis/xian/core/config/RabbitConfig.java create mode 100644 src/main/java/com/gis/xian/core/config/RestClientConfig.java create mode 100644 src/main/java/com/gis/xian/core/rabbitmq/DlqConsumer.java create mode 100644 src/main/java/com/gis/xian/core/rabbitmq/DlqOperate.java create mode 100644 src/main/java/com/gis/xian/dto/base/ActiveFaultDTO.java create mode 100644 src/main/java/com/gis/xian/dto/base/ShanXiCitiesDTO.java create mode 100644 src/main/java/com/gis/xian/dto/base/ShanXiCountyDTO.java create mode 100644 src/main/java/com/gis/xian/dto/base/ShanXiTownsDTO.java create mode 100644 src/main/java/com/gis/xian/dto/dzxx/DZXXCenterDTO.java create mode 100644 src/main/java/com/gis/xian/dto/dzxx/DZXXDistanceDTO.java create mode 100644 src/main/java/com/gis/xian/dto/dzxx/DZXXInfluenceDTO.java create mode 100644 src/main/java/com/gis/xian/dto/pub/DZInfluenceDTO.java create mode 100644 src/main/java/com/gis/xian/dto/pub/DZProductDTO.java create mode 100644 src/main/java/com/gis/xian/dto/pub/EqAssessmentDTO.java create mode 100644 src/main/java/com/gis/xian/dto/pub/EqTriggerDTO.java create mode 100644 src/main/java/com/gis/xian/dto/pub/IntyGeoJsonDTO.java create mode 100644 src/main/java/com/gis/xian/dto/pub/RAssessmentDTO.java create mode 100644 src/main/java/com/gis/xian/entity/base/ActiveFault.java create mode 100644 src/main/java/com/gis/xian/entity/base/SXCities.java create mode 100644 src/main/java/com/gis/xian/entity/base/SXCounty.java create mode 100644 src/main/java/com/gis/xian/entity/base/SXTowns.java create mode 100644 src/main/java/com/gis/xian/entity/dzxx/DZXXCenter.java create mode 100644 src/main/java/com/gis/xian/entity/dzxx/DZXXDistance.java create mode 100644 src/main/java/com/gis/xian/entity/dzxx/DZXXInfluence.java create mode 100644 src/main/java/com/gis/xian/entity/pub/DZEqEvent.java create mode 100644 src/main/java/com/gis/xian/entity/pub/DZEqQueue.java create mode 100644 src/main/java/com/gis/xian/entity/pub/DZInfluence.java create mode 100644 src/main/java/com/gis/xian/entity/pub/DZProduct.java create mode 100644 src/main/java/com/gis/xian/enums/BaseEnums.java create mode 100644 src/main/java/com/gis/xian/enums/EqMapsEnums.java create mode 100644 src/main/java/com/gis/xian/enums/RainMapsEnums.java create mode 100644 src/main/java/com/gis/xian/handler/EarthquakeHandler.java create mode 100644 src/main/java/com/gis/xian/handler/EllipseToWktHandler.java create mode 100644 src/main/java/com/gis/xian/handler/GeoDistanceHandler.java create mode 100644 src/main/java/com/gis/xian/handler/GeoFilesHandler.java create mode 100644 src/main/java/com/gis/xian/handler/GeometryTypeHandler.java create mode 100644 src/main/java/com/gis/xian/mapper/base/ActiveFaultMapper.java create mode 100644 src/main/java/com/gis/xian/mapper/base/ShanXiCitiesMapper.java create mode 100644 src/main/java/com/gis/xian/mapper/base/ShanXiCountyMapper.java create mode 100644 src/main/java/com/gis/xian/mapper/base/ShanXiTownsMapper.java create mode 100644 src/main/java/com/gis/xian/mapper/dzxx/DZXXCenterMapper.java create mode 100644 src/main/java/com/gis/xian/mapper/dzxx/DZXXDistanceMapper.java create mode 100644 src/main/java/com/gis/xian/mapper/dzxx/DZXXInfluenceMapper.java create mode 100644 src/main/java/com/gis/xian/mapper/pub/DZEqEventMapper.java create mode 100644 src/main/java/com/gis/xian/mapper/pub/DZEqQueueMapper.java create mode 100644 src/main/java/com/gis/xian/mapper/pub/DZInfluenceMapper.java create mode 100644 src/main/java/com/gis/xian/mapper/pub/DZProductMapper.java create mode 100644 src/main/java/com/gis/xian/params/QgisArgs.java create mode 100644 src/main/java/com/gis/xian/query/EqQuery.java create mode 100644 src/main/java/com/gis/xian/query/IntensityQuery.java create mode 100644 src/main/java/com/gis/xian/query/ProductQuery.java create mode 100644 src/main/java/com/gis/xian/service/base/IActiveFaultService.java create mode 100644 src/main/java/com/gis/xian/service/base/IShanXiCitiesService.java create mode 100644 src/main/java/com/gis/xian/service/base/IShanXiCountyService.java create mode 100644 src/main/java/com/gis/xian/service/base/IShanXiTownsService.java create mode 100644 src/main/java/com/gis/xian/service/base/impl/ActiveFaultServiceImpl.java create mode 100644 src/main/java/com/gis/xian/service/base/impl/ShanXiCitiesServiceImpl.java create mode 100644 src/main/java/com/gis/xian/service/base/impl/ShanXiCountyServiceImpl.java create mode 100644 src/main/java/com/gis/xian/service/base/impl/ShanXiTownsServiceImpl.java create mode 100644 src/main/java/com/gis/xian/service/dzxx/IDZXXCenterService.java create mode 100644 src/main/java/com/gis/xian/service/dzxx/IDZXXDistanceService.java create mode 100644 src/main/java/com/gis/xian/service/dzxx/IDZXXInfluenceService.java create mode 100644 src/main/java/com/gis/xian/service/dzxx/impl/DZXXCenterServiceImpl.java create mode 100644 src/main/java/com/gis/xian/service/dzxx/impl/DZXXDistanceServiceImpl.java create mode 100644 src/main/java/com/gis/xian/service/dzxx/impl/DZXXInfluenceServiceImpl.java create mode 100644 src/main/java/com/gis/xian/service/ex/ServeException.java create mode 100644 src/main/java/com/gis/xian/service/pub/IDZEqEventService.java create mode 100644 src/main/java/com/gis/xian/service/pub/IDZEqQueueService.java create mode 100644 src/main/java/com/gis/xian/service/pub/IDZInfluenceService.java create mode 100644 src/main/java/com/gis/xian/service/pub/IDZProductService.java create mode 100644 src/main/java/com/gis/xian/service/pub/IFeignService.java create mode 100644 src/main/java/com/gis/xian/service/pub/impl/DZEqEventServiceImpl.java create mode 100644 src/main/java/com/gis/xian/service/pub/impl/DZEqQueueServiceImpl.java create mode 100644 src/main/java/com/gis/xian/service/pub/impl/DZInfluenceServiceImpl.java create mode 100644 src/main/java/com/gis/xian/service/pub/impl/DZProductServiceImpl.java create mode 100644 src/main/java/com/gis/xian/service/pub/impl/FeignServiceImpl.java create mode 100644 src/main/java/com/gis/xian/utils/BaseUtils.java create mode 100644 src/main/java/com/gis/xian/utils/StringUtils.java create mode 100644 src/main/java/com/gis/xian/utils/http/HttpRestClient.java diff --git a/pom.xml b/pom.xml index e9dc294..4f8df2d 100644 --- a/pom.xml +++ b/pom.xml @@ -7,12 +7,12 @@ 17 17 UTF-8 - 3.0.5 1.2.27 42.7.8 1.18.42 1.82 2.0.60 + 3.5.9 @@ -53,11 +53,11 @@ spring-boot-starter-validation - + - org.mybatis.spring.boot - mybatis-spring-boot-starter - ${mybatis.spring.version} + com.baomidou + mybatis-plus-spring-boot3-starter + ${mybatis-plus.version} @@ -72,7 +72,7 @@ org.postgresql postgresql ${postgresql.version} - runtime + @@ -126,6 +126,54 @@ spring-boot-starter-test test + + + + org.locationtech.jts + jts-core + 1.19.0 + + + + + org.mybatis + mybatis-typehandlers-jsr310 + 1.0.2 + + + + + net.postgis + postgis-jdbc + 2021.1.0 + + + + org.hibernate.orm + hibernate-spatial + 6.2.0.Final + + + + + org.locationtech.proj4j + proj4j + 1.1.4 + + + + + org.apache.commons + commons-lang3 + + + + + org.springframework.boot + spring-boot-starter-amqp + 2.7.3 + + @@ -139,7 +187,7 @@ true - + prod @@ -173,7 +221,7 @@ - + org.apache.maven.plugins diff --git a/src/main/java/com/gis/xian/bo/DlqMessage.java b/src/main/java/com/gis/xian/bo/DlqMessage.java new file mode 100644 index 0000000..9f2b98e --- /dev/null +++ b/src/main/java/com/gis/xian/bo/DlqMessage.java @@ -0,0 +1,22 @@ +package com.gis.xian.bo; + +import com.gis.xian.params.QgisArgs; +import lombok.Builder; +import lombok.Data; + +/** + * @author zzw + * @description: 死信队列参数 + * @date 2026/5/26 下午5:04 + */ +@Data +@Builder +public class DlqMessage { + + private QgisArgs qgisArgs; // 原始参数 + private String failReason; // 失败原因 + private Long failTime; // 失败时间戳 + private Integer retryCount; // 已重试次数 + + +} diff --git a/src/main/java/com/gis/xian/config/DataSourceConfig.java b/src/main/java/com/gis/xian/config/DataSourceConfig.java index b5ed33c..bd29f36 100644 --- a/src/main/java/com/gis/xian/config/DataSourceConfig.java +++ b/src/main/java/com/gis/xian/config/DataSourceConfig.java @@ -12,19 +12,25 @@ import java.util.Map; @Configuration public class DataSourceConfig { - + @Bean @ConfigurationProperties("spring.datasource.master") public DataSource master() { return DruidDataSourceBuilder.create().build(); } - + @Bean @ConfigurationProperties("spring.datasource.slave") public DataSource slave() { return DruidDataSourceBuilder.create().build(); } - + + @Bean + @ConfigurationProperties("spring.datasource.slave1") + public DataSource slave1() { + return DruidDataSourceBuilder.create().build(); + } + @Bean @Primary public DataSource dataSource() { @@ -32,6 +38,7 @@ public class DataSourceConfig { Map map = new HashMap<>(); map.put("master", master()); map.put("slave", slave()); + map.put("slave1", slave1()); ds.setTargetDataSources(map); ds.setDefaultTargetDataSource(master()); return ds; diff --git a/src/main/java/com/gis/xian/constant/BaseConstants.java b/src/main/java/com/gis/xian/constant/BaseConstants.java new file mode 100644 index 0000000..0c51346 --- /dev/null +++ b/src/main/java/com/gis/xian/constant/BaseConstants.java @@ -0,0 +1,116 @@ +package com.gis.xian.constant; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author zzw + * @description: 公共常量类 + * @date 2026/5/25 下午5:30 + */ +public class BaseConstants { + + + + // url + public static final String EQ_MAPS_TEMPLATE_PATH = "D:/home/dzxx/maps/eq/"; // 地震专题图模板路径 + public static final String RAIN_MAPS_TEMPLATE_PATH = "D:/home/dzxx/maps/rain/"; // 暴雨专题图模板路径 + public static final String INTENSITY_GEOJSON_PATH = "D:/home/dzxx/output/influence/"; // 影响场保存路径 + public static final String EQ_MAPS_OUTPUT_PATH = "D:/home/dzxx/output/eq/map/"; // 地震专题图文件输出路径 + public static final String RAIN_MAPS_OUTPUT_PATH = "D:/home/dzxx/output/rain/map/"; // 暴雨专题图文件输出路径 + public static final String EQ_DOCUMENT_OUTPUT_PATH = "D:/home/dzxx/output/eq/地震应急预评估报告.docx"; // 地震评估报告文件输出路径 + public static final String RAIN_DOCUMENT_OUTPUT_PATH = "D:/home/dzxx/output/rain/暴雨应急预评估报告.docx"; // 暴雨评估报告文件输出路径 + + // ip + public static final String HTTP_QGIS_THEMATIC = "http://localhost:18998/qgis/make/map"; // 专题图 + + // 提示语 + public static final String PARAMS_ERROR = "参数有误,请重新传入!"; + public static final String RESULT_ERROR = "结果空值!"; + public static final String QUEUE_ID_ERROR = "queueId不能为空!"; + public static final String PRODUCTS_ERROR = "获取产品失败!"; + public static final String POM_ERROR = "经纬度坐标错误!"; + public static final String EQ_SERVER_ERROR = "地震业务出错!"; + public static final String RAIN_SERVER_ERROR = "暴雨业务出错!"; + public static final String ASSESS_SERVER_ERROR = "评估业务出错!"; + public static final String INFLUENCE_CONVERT_ERROR = "影响场转换GeoJson出错!"; + public static final String UPLOAD_FAILED = "文件上传失败"; + public static final String FILE_NOT_FOUND_ERROR = "文件不存在"; + public static final String EQ_DISASTER_MAP = "地震专题图"; + public static final String RAIN_DISASTER_MAP = "暴雨专题图"; + public static final String EQ_DISASTER_DOCUMENT = "地震评估文档"; + public static final String RAIN_DISASTER_DOCUMENT = "暴雨评估文档"; + public static final String THEMATIC_FAILED = "专题图获取失败"; + public static final String FILE_FAILED = "评估报告获取失败"; + + // 功能常量 + public static final int TOKEN_EXPIRED = 30; // token过期时间 + public static final String AUTH_USERNAME = "authorize_user"; // 授权用户名 + public static final String AUTH_PWD = "ApiOpen#123"; + public static final int NUM_VERTICES = 100; // 椭圆边缘顶点数 + public static final String CITY_CODE = "511800"; // 西安市行政编码 + public static final Integer AUTOMATIC = 0; // 自动 + public static final Integer MANUAL = 1; // 手动 + public static final Integer EQ_TOTAL_FILES = 20; // 38张地震专题图(A3、A4) + 1个影响场文件 + public static final Integer RAIN_TOTAL_FILES = 15; // 30张地震专题图(A3、A4) + public static final Map SEISMIC_INTENSITY_MAPPING = new HashMap() // 烈度映射 + {{ + put(4, "Ⅳ"); + put(5, "Ⅴ"); + put(6, "Ⅵ"); + put(7, "Ⅶ"); + put(8, "Ⅷ"); + put(9, "Ⅸ"); + put(10, "Ⅹ"); + put(11, "Ⅺ"); + put(12, "Ⅻ"); + }}; + public static final Map ADMINISTRATIVE_CODE = new HashMap() {{ // 西安行政区划代码 + put("新城区", "610102"); + put("碑林区", "610103"); + put("莲湖区", "610104"); + put("雁塔区", "610113"); + put("灞桥区", "610111"); + put("未央区", "610112"); + put("阎良区", "610114"); + put("临潼区", "610115"); + put("长安区", "610116"); + put("高陵区", "610117"); + put("鄠邑区", "610118"); + put("蓝田县", "610122"); + put("周至县", "610124"); + }}; + + // RabbitMQ 常量 + public final static String MAPS_QUEUE = "maps"; // 专题图类队列 + public final static String DOCUMENTS_QUEUE = "documents"; // 文档类队列 + public final static String DLQ_QUEUE = "dlq"; // 死信队列 + public final static String ASSESS_EXCHANGE = "assess"; // 定义普通交换机名称 + public final static String DLX_EXCHANGE = "dlx"; // 定义普通交换机名称 + + // 制图参数常量 + public final static String MAP_LAYOUT_A3 = "A3"; // A3 画幅尺寸 + public final static String MAP_LAYOUT_A4 = "A4"; // A4 画幅尺寸 + public final static String MAP_UNIT = "制图单位:西安市应急管理局"; + public final static String MAP_TIME = "制图时间:"; + public final static String EQ_TEST = "(测试地震)"; + public final static String EQ_NORMAL = "(真实地震)"; + public final static String EQ_EXERCISE = "(演练地震)"; + public final static String RAIN_TEST = "(测试降雨)"; + public final static String RAIN_NORMAL = "(真实降雨)"; + public final static String RAIN_EXERCISE = "(演练降雨)"; + public static final Map EQ_TYPE = new HashMap() // 地震类型映射 + {{ + put("T", EQ_TEST); + put("Z", EQ_NORMAL); + put("Y", EQ_EXERCISE); + }}; + public static final Map RAIN_TYPE = new HashMap() // 暴雨类型映射 + {{ + put("T", RAIN_TEST); + put("Z", RAIN_NORMAL); + put("Y", RAIN_EXERCISE); + }}; + + +} diff --git a/src/main/java/com/gis/xian/controller/DZEqEventController.java b/src/main/java/com/gis/xian/controller/DZEqEventController.java new file mode 100644 index 0000000..95acd5d --- /dev/null +++ b/src/main/java/com/gis/xian/controller/DZEqEventController.java @@ -0,0 +1,43 @@ +package com.gis.xian.controller; + +import com.gis.xian.constant.BaseConstants; +import com.gis.xian.domain.ApiResponse; +import com.gis.xian.dto.pub.EqTriggerDTO; +import com.gis.xian.query.EqQuery; +import com.gis.xian.service.pub.IDZEqEventService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * @author zzw + * @description: QGIS地震事件触发 + * @date 2026/5/25 下午3:12 + */ +@Slf4j +@RestController +@RequestMapping("/open") +public class DZEqEventController { + @Autowired + private IDZEqEventService idzEqEventService; + + @PostMapping("/eq/trigger") + public ApiResponse trigger(@RequestBody @Validated EqTriggerDTO trigger) { + EqQuery query = idzEqEventService.trigger(trigger); + if (query == null) { + return ApiResponse.error(BaseConstants.RESULT_ERROR); + } + return ApiResponse.ok(query); + } + + @PostMapping("/eq/delete/{Id}") + public ApiResponse delete(@PathVariable Long Id) { + Boolean deleted = idzEqEventService.deletedById(Id); + if (!deleted) { + return ApiResponse.error("删除失败!"); + } + return ApiResponse.ok("删除成功!"); + } + +} diff --git a/src/main/java/com/gis/xian/core/config/RabbitConfig.java b/src/main/java/com/gis/xian/core/config/RabbitConfig.java new file mode 100644 index 0000000..fed4714 --- /dev/null +++ b/src/main/java/com/gis/xian/core/config/RabbitConfig.java @@ -0,0 +1,100 @@ +package com.gis.xian.core.config; + +import com.gis.xian.constant.BaseConstants; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.core.*; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.connection.CorrelationData; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author zzw + * @description: RabbitMq 配置 + * @date 2026/5/26 下午6:36 + */ +@Slf4j +@Configuration +public class RabbitConfig { + + + + // 专题图队列 + @Bean + public Queue mapsQueue() { + return new Queue(BaseConstants.MAPS_QUEUE, true); + } + + // 文档队列 + @Bean + public Queue documents() { + return new Queue(BaseConstants.DOCUMENTS_QUEUE, true); + } + + // 死信队列 + @Bean + public Queue dlqQueue() { + return new Queue(BaseConstants.DLQ_QUEUE, true); + } + + // 定义主题交换机 + @Bean + public TopicExchange exchange() { + return new TopicExchange(BaseConstants.ASSESS_EXCHANGE); + } + + // 定义死信交换机 + @Bean + public DirectExchange dlxExchange() { + return new DirectExchange (BaseConstants.DLX_EXCHANGE); + } + // 将 mapsQueue 队列和 assess 交换机绑定,而且绑定的键值为 maps + // 这样只要是消息携带的路由键是 maps,才会分发到该队列 + @Bean + public Binding bindingExchangeMessageOfMaps() { + return BindingBuilder.bind(mapsQueue()).to(exchange()).with(BaseConstants.MAPS_QUEUE); + } + + @Bean + public Binding bindingExchangeMessageOfDocuments() { + return BindingBuilder.bind(documents()).to(exchange()).with(BaseConstants.DOCUMENTS_QUEUE); + } + + @Bean + public Binding bindingExchangeMessageOfFiles() { + return BindingBuilder.bind(dlqQueue()).to(exchange()).with(BaseConstants.DLQ_QUEUE); + } + + // 设置消息回调函数 自动确认消息 ack + @Bean + public RabbitTemplate createRabbitTemplate(ConnectionFactory connectionFactory) { + RabbitTemplate rabbitTemplate = new RabbitTemplate(); + rabbitTemplate.setConnectionFactory(connectionFactory); + // 设置开启Mandatory,才能触发回调函数,无论消息推送结果怎么样都强制调用回调函数 + rabbitTemplate.setMandatory(true); + + // 1. 确认回调 (ConfirmCallback) - 建议使用 Lambda 简化写法 + rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> { + if (ack) { + System.out.println("✅ 消息成功发送到 Exchange"); + } else { + System.err.println("❌ 消息发送到 Exchange 失败: " + cause); + } + }); + + // 2. 退回回调 (ReturnsCallback) - 修复报错的核心部分 + rabbitTemplate.setReturnsCallback(returnedMessage -> { + System.out.println("⚠️ 消息无法路由被退回!"); + System.out.println("回复码 replyCode: " + returnedMessage.getReplyCode()); + System.out.println("回复文本 replyText: " + returnedMessage.getReplyText()); + System.out.println("交换机 exchange: " + returnedMessage.getExchange()); + System.out.println("路由键 routingKey: " + returnedMessage.getRoutingKey()); + // 获取原始消息内容 + String msgBody = new String(returnedMessage.getMessage().getBody()); + System.out.println("被退回的消息内容: " + msgBody); + }); + + return rabbitTemplate; + } +} diff --git a/src/main/java/com/gis/xian/core/config/RestClientConfig.java b/src/main/java/com/gis/xian/core/config/RestClientConfig.java new file mode 100644 index 0000000..b63a074 --- /dev/null +++ b/src/main/java/com/gis/xian/core/config/RestClientConfig.java @@ -0,0 +1,29 @@ +package com.gis.xian.core.config; + +import com.gis.xian.utils.http.HttpRestClient; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +/** + * @author zzw + * @description: 第三方请求配置类 + * @date 2026/5/26 下午6:40 + */ +@Configuration +public class RestClientConfig { + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } + + @Bean + public HttpRestClient httpRestClient(RestTemplate restTemplate) { + HttpRestClient client = new HttpRestClient(restTemplate); + // 添加全局默认请求头 + // client.addDefaultHeader("X-App-Id", "my-app-id"); + return client; + } +} + diff --git a/src/main/java/com/gis/xian/core/rabbitmq/DlqConsumer.java b/src/main/java/com/gis/xian/core/rabbitmq/DlqConsumer.java new file mode 100644 index 0000000..601153a --- /dev/null +++ b/src/main/java/com/gis/xian/core/rabbitmq/DlqConsumer.java @@ -0,0 +1,114 @@ +package com.gis.xian.core.rabbitmq; + +import com.alibaba.fastjson2.JSON; +import com.gis.xian.bo.DlqMessage; +import com.gis.xian.constant.BaseConstants; +import com.gis.xian.enums.BaseEnums; +import com.gis.xian.params.QgisArgs; +import com.gis.xian.service.pub.IDZEqQueueService; +import com.gis.xian.utils.BaseUtils; +import com.gis.xian.utils.http.HttpRestClient; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.stereotype.Component; + +/** + * @author zzw + * @description: DlqConsumer + * @date 2026/5/26 下午6:40 + */ +@Slf4j +@Component +public class DlqConsumer { + + @Resource + private HttpRestClient restclient; + @Resource + private RabbitTemplate rabbitTemplate; + @Autowired + private IDZEqQueueService idzEqQueueService; + + // 最大重试次数 + private int maxRetry = 3; + + // 死信队列消费者 + @RabbitListener(queues = BaseConstants.DLQ_QUEUE) + public void handleDlqMessage(DlqMessage dlqMessage) { + QgisArgs arg = dlqMessage.getQgisArgs(); + int currentRetryCount = dlqMessage.getRetryCount(); + + try { + log.info("处理死信队列消息! 参数ID:{} 重试次数:{}", arg.getId(), currentRetryCount); + + // 判断是否超过最大重试次数 + if (currentRetryCount >= maxRetry) { + log.error("消息重试次数已达上限! 参数ID:{} 失败原因:{}", arg.getId(), dlqMessage.getFailReason()); + // 处理:告警+记录到失败表+人工介入 + sendAlarm(arg, dlqMessage); + saveToFailTable(dlqMessage); + return; + } + + // 重试处理逻辑(复用原invoke的核心逻辑) + ParameterizedTypeReference res = new ParameterizedTypeReference() { + }; + String mapName = restclient.post(BaseConstants.HTTP_QGIS_THEMATIC, JSON.toJSON(arg), res); + + if (mapName == null || mapName.equals("")) { + throw new Exception("重试后产出图件仍失败"); + } + + // 重试成功:记录日志 + 推送原业务消息 + log.info("死信消息处理成功! 参数ID:{} 图件名称:{}", arg.getId(), mapName); + // 更新进度 + double p = 0; + if (arg.getDisaster() == BaseConstants.EQ_DISASTER_MAP) { + p = BaseUtils.compute(arg.getId() + 1, 0); + } + if (arg.getDisaster() == BaseConstants.RAIN_DISASTER_MAP) { + p = BaseUtils.compute(arg.getId() + 1, 1); + } + idzEqQueueService.updated(arg.getEvent(), arg.getQueueId(), p, BaseEnums.CALCULATING.getCode()); + // 推送原业务消息 + rabbitTemplate.convertAndSend(BaseConstants.ASSESS_EXCHANGE, BaseConstants.MAPS_QUEUE, arg); + + } catch (Exception e) { + log.error("死信消息重试失败! 参数ID:{} 重试次数:{}", arg.getId(), currentRetryCount, e); + // 重试失败:更新重试次数,重新发送到死信队列(设置延迟) + dlqMessage.setRetryCount(currentRetryCount + 1); + dlqMessage.setFailReason(dlqMessage.getFailReason() + " | 重试失败:" + e.getMessage()); + // 延迟发送(需要安装rabbitmq_delayed_message_exchange插件) + rabbitTemplate.convertAndSend( + BaseConstants.DLX_EXCHANGE, + BaseConstants.DLQ_QUEUE, + dlqMessage, + message -> { + // 设置延迟时间(指数退避:10s, 30s, 60s) + long delay = 10000 * (long) Math.pow(3, currentRetryCount); +// message.getMessageProperties().setDelay((int) delay); + message.getMessageProperties().setHeader("x-delay", (int) delay); + return message; + } + ); + log.info("死信消息已重新投递! 参数ID:{} 下次重试延迟:{}ms", arg.getId(), + 10000 * (long) Math.pow(3, currentRetryCount)); + } + } + + // 发送告警(邮件/短信/钉钉等) + private void sendAlarm(QgisArgs arg, DlqMessage dlqMessage) { + // 实现告警逻辑:调用钉钉机器人/邮件接口等 + log.error("【告警】图件处理失败需要人工介入! 参数ID:{} 失败原因:{}", arg.getId(), dlqMessage.getFailReason()); + } + + // 保存失败记录到数据库 + private void saveToFailTable(DlqMessage dlqMessage) { + // 实现数据库存储逻辑,便于人工排查和处理 + log.info("失败记录已保存到数据库! 参数ID:{}", dlqMessage.getQgisArgs().getId()); + } +} + diff --git a/src/main/java/com/gis/xian/core/rabbitmq/DlqOperate.java b/src/main/java/com/gis/xian/core/rabbitmq/DlqOperate.java new file mode 100644 index 0000000..4cbc441 --- /dev/null +++ b/src/main/java/com/gis/xian/core/rabbitmq/DlqOperate.java @@ -0,0 +1,54 @@ +package com.gis.xian.core.rabbitmq; + +import com.gis.xian.bo.DlqMessage; +import com.gis.xian.constant.BaseConstants; +import com.gis.xian.params.QgisArgs; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.stereotype.Component; + +/** + * @author zzw + * @description: 死信队列 + * @date 2026/5/26 下午4:59 + */ +@Slf4j +@Component +public class DlqOperate { + + @Resource + private RabbitTemplate rabbitTemplate; + + /** + * 发送消息到死信队列 + * + * @param arg 失败的参数 + * @param reason 失败原因 + * @param e 异常信息 + */ + public void sendToDlq(QgisArgs arg, String reason, Exception e) { + try { + // 封装死信消息体,包含原始参数、失败原因、异常信息、重试次数等 + DlqMessage dlqMessage = DlqMessage.builder() + .qgisArgs(arg) + .failReason(reason + (e != null ? " | " + e.getMessage() : "")) + .failTime(System.currentTimeMillis()) + .retryCount(0) // 初始重试次数为0 + .build(); + // 发送到死信队列 + rabbitTemplate.convertAndSend( + BaseConstants.DLX_EXCHANGE, + BaseConstants.DLQ_QUEUE, + dlqMessage + ); + log.info("消息已发送到死信队列! 参数ID:{}", arg.getId()); + } catch (Exception ex) { + log.error("发送死信队列失败! 参数ID:{}", arg.getId(), ex); + // 记录到数据库,避免消息丢失 + // saveToDb(arg, reason, e); + } + } + + +} diff --git a/src/main/java/com/gis/xian/dto/base/ActiveFaultDTO.java b/src/main/java/com/gis/xian/dto/base/ActiveFaultDTO.java new file mode 100644 index 0000000..6a06e0a --- /dev/null +++ b/src/main/java/com/gis/xian/dto/base/ActiveFaultDTO.java @@ -0,0 +1,24 @@ +package com.gis.xian.dto.base; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; +import org.locationtech.jts.geom.Geometry; + +/** + * @author zzw + * @description: 活动断层DTO类 + * @date 2026/5/26 上午10:20 + */ +@Data +public class ActiveFaultDTO { + + private String name; // 断层名称 + private Integer strike; // 走向 + private Integer direction; // 倾向 + private Integer clination; // 倾角 + private Double shapeLen; //形状长度 + @JsonSerialize(using = ToStringSerializer.class) + private Geometry geometry; // 范围 + private Double distance; +} diff --git a/src/main/java/com/gis/xian/dto/base/ShanXiCitiesDTO.java b/src/main/java/com/gis/xian/dto/base/ShanXiCitiesDTO.java new file mode 100644 index 0000000..5b2edd0 --- /dev/null +++ b/src/main/java/com/gis/xian/dto/base/ShanXiCitiesDTO.java @@ -0,0 +1,22 @@ +package com.gis.xian.dto.base; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; +import org.locationtech.jts.geom.Geometry; + +/** + * @author zzw + * @description: 陕西市州 + * @date 2026/5/26 上午8:36 + */ +@Data +public class ShanXiCitiesDTO { + + private String NAME; + private Double X; + private Double Y; + @JsonSerialize(using = ToStringSerializer.class) + private Geometry geometry; + private Double distance; +} diff --git a/src/main/java/com/gis/xian/dto/base/ShanXiCountyDTO.java b/src/main/java/com/gis/xian/dto/base/ShanXiCountyDTO.java new file mode 100644 index 0000000..f3623a8 --- /dev/null +++ b/src/main/java/com/gis/xian/dto/base/ShanXiCountyDTO.java @@ -0,0 +1,22 @@ +package com.gis.xian.dto.base; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; +import org.locationtech.jts.geom.Geometry; + +/** + * @author zzw + * @description: 陕西省区县 + * @date 2026/5/26 上午9:48 + */ +@Data +public class ShanXiCountyDTO { + + private String NAME; + private Double X; + private Double Y; + @JsonSerialize(using = ToStringSerializer.class) + private Geometry geometry; + private Double distance; +} diff --git a/src/main/java/com/gis/xian/dto/base/ShanXiTownsDTO.java b/src/main/java/com/gis/xian/dto/base/ShanXiTownsDTO.java new file mode 100644 index 0000000..f06565a --- /dev/null +++ b/src/main/java/com/gis/xian/dto/base/ShanXiTownsDTO.java @@ -0,0 +1,22 @@ +package com.gis.xian.dto.base; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; +import org.locationtech.jts.geom.Geometry; + +/** + * @author zzw + * @description: 陕西省乡镇 + * @date 2026/5/26 上午9:57 + */ +@Data +public class ShanXiTownsDTO { + + private String NAME; + private Double X; + private Double Y; + @JsonSerialize(using = ToStringSerializer.class) + private Geometry geometry; + private Double distance; +} diff --git a/src/main/java/com/gis/xian/dto/dzxx/DZXXCenterDTO.java b/src/main/java/com/gis/xian/dto/dzxx/DZXXCenterDTO.java new file mode 100644 index 0000000..d387d56 --- /dev/null +++ b/src/main/java/com/gis/xian/dto/dzxx/DZXXCenterDTO.java @@ -0,0 +1,26 @@ +package com.gis.xian.dto.dzxx; + +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author zzw + * @description: 地震信息触发类 + * @date 2026/5/25 下午5:19 + */ +@Data +public class DZXXCenterDTO { + + private String event; + private LocalDateTime eqTime; + private Double longitude; + private Double latitude; + private String eqAddr; + private Double eqMagnitude; + private Double eqDepth; + private String eqFullName; + private String eqName; + private String eqType; + +} diff --git a/src/main/java/com/gis/xian/dto/dzxx/DZXXDistanceDTO.java b/src/main/java/com/gis/xian/dto/dzxx/DZXXDistanceDTO.java new file mode 100644 index 0000000..ded9d23 --- /dev/null +++ b/src/main/java/com/gis/xian/dto/dzxx/DZXXDistanceDTO.java @@ -0,0 +1,23 @@ +package com.gis.xian.dto.dzxx; + +import lombok.Data; +import org.locationtech.jts.geom.Geometry; + +/** + * @author zzw + * @description: DZXXDistanceDTO + * @date 2026/5/26 上午10:03 + */ +@Data +public class DZXXDistanceDTO { + + private Geometry geom; + private String eqQueueId; + private Integer distanceId; // 市1、县2、镇3 + private String pId; // 行政id + private String pname; // 省市县镇名称 + private String bgmc; // 行政区划等级 + private Double distance; // 距离 + private String remark; + +} diff --git a/src/main/java/com/gis/xian/dto/dzxx/DZXXInfluenceDTO.java b/src/main/java/com/gis/xian/dto/dzxx/DZXXInfluenceDTO.java new file mode 100644 index 0000000..bde5413 --- /dev/null +++ b/src/main/java/com/gis/xian/dto/dzxx/DZXXInfluenceDTO.java @@ -0,0 +1,26 @@ +package com.gis.xian.dto.dzxx; + +import lombok.Data; +import org.locationtech.jts.geom.Geometry; + +/** + * @author zzw + * @description: 地震影响场DTO + * @date 2026/5/26 上午10:11 + */ +@Data +public class DZXXInfluenceDTO { + + private Geometry geom; + private String eqQueueId; + private String event; + private String eqName; + private Integer inty; // 烈度值 + private String sInty; + private double area; + private double longUranium; + private double shortUranium; + private double direction; + private double longitude; + private double latitude; +} diff --git a/src/main/java/com/gis/xian/dto/pub/DZInfluenceDTO.java b/src/main/java/com/gis/xian/dto/pub/DZInfluenceDTO.java new file mode 100644 index 0000000..1a045e5 --- /dev/null +++ b/src/main/java/com/gis/xian/dto/pub/DZInfluenceDTO.java @@ -0,0 +1,24 @@ +package com.gis.xian.dto.pub; + +import lombok.Data; + +/** + * @author zzw + * @description: 影响场文件 + * @date 2026/5/26 上午10:46 + */ +@Data +public class DZInfluenceDTO { + + private String eqQueueId; + private String event; + private String name; + private String file; + private String path; + private String content; + private String intensityColumn; + private String source; + private Integer isEdit; + private Integer isPg; + +} diff --git a/src/main/java/com/gis/xian/dto/pub/DZProductDTO.java b/src/main/java/com/gis/xian/dto/pub/DZProductDTO.java new file mode 100644 index 0000000..15a41a1 --- /dev/null +++ b/src/main/java/com/gis/xian/dto/pub/DZProductDTO.java @@ -0,0 +1,30 @@ +package com.gis.xian.dto.pub; + +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author zzw + * @description: DZProductDTO + * @date 2026/5/26 上午10:59 + */ +@Data +public class DZProductDTO { + + + private String eqQueueId; + private Integer templetId; // 模板编码id + private String code; // A3 A4 + private LocalDateTime proTime; + private String fileType; // 图片 文档 + private String fileName; + private String filePath; // 模板路径 查询时设置为空 + private String fileExtension; + private Double fileSize; + private String proType; // 暴雨/地震 灾害专题图 暴雨/地震 灾害文档 + private String sourceFile; // 存储位置 + + +} + diff --git a/src/main/java/com/gis/xian/dto/pub/EqAssessmentDTO.java b/src/main/java/com/gis/xian/dto/pub/EqAssessmentDTO.java new file mode 100644 index 0000000..5f1f5be --- /dev/null +++ b/src/main/java/com/gis/xian/dto/pub/EqAssessmentDTO.java @@ -0,0 +1,27 @@ +package com.gis.xian.dto.pub; + +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author zzw + * @description: 地震评估dto类 + * @date 2026/5/25 下午6:04 + */ +@Data +public class EqAssessmentDTO { + + private String event; // 地震编码 + private String eqQueueId; // 评估编码 + private LocalDateTime eqTime; // 地震发生时间 + private Double longitude; // 经度 + private Double latitude; // 纬度 + private String eqAddr; // 地址 + private Double eqMagnitude; // 震级 + private Double eqDepth; // 深度 + private String eqFullName; // 震源名称 + private String eqName; // 震源名称 + private String eqType; // 震源类型 + +} diff --git a/src/main/java/com/gis/xian/dto/pub/EqTriggerDTO.java b/src/main/java/com/gis/xian/dto/pub/EqTriggerDTO.java new file mode 100644 index 0000000..d0df2f8 --- /dev/null +++ b/src/main/java/com/gis/xian/dto/pub/EqTriggerDTO.java @@ -0,0 +1,31 @@ +package com.gis.xian.dto.pub; + +import lombok.Data; +import java.time.LocalDateTime; + +/** + * @author zzw + * @description: 地震触发DTO类 + * @date 2026/5/25 下午4:52 + */ +@Data +public class EqTriggerDTO { + + private String eqName; // 地震名称 + + private String eqAddr; // 震发地点 + + private LocalDateTime eqTime; // 震发时间 + + private Double longitude; // 经度 + + private Double latitude; // 纬度 + + private Double eqDepth; // 震源深度 + + private Double eqMagnitude; // 震级 + + private String eqFullName; // 地震全称 + + private String eqType; // 地震类型(T:测试,Z:正式,Y:演练) +} diff --git a/src/main/java/com/gis/xian/dto/pub/IntyGeoJsonDTO.java b/src/main/java/com/gis/xian/dto/pub/IntyGeoJsonDTO.java new file mode 100644 index 0000000..ca90402 --- /dev/null +++ b/src/main/java/com/gis/xian/dto/pub/IntyGeoJsonDTO.java @@ -0,0 +1,43 @@ +package com.gis.xian.dto.pub; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author zzw + * @description: 影响场geojson格式规范 + * @date 2026/5/26 上午10:43 + */ +@Data +public class IntyGeoJsonDTO { + + private final String type = "FeatureCollection"; + private List features = new ArrayList<>(); + + @Data + public static class GeoJsonFeature { + private final String type = "Feature"; + private GeoJsonGeometry geometry; + private GeoJsonProperties properties = new GeoJsonProperties(); + + @Data + public static class GeoJsonGeometry { + private String type; + private List>> coordinates; // 坐标数组 + } + + @Data + public static class GeoJsonProperties { + private String intensity; // 烈度等级 + private String eqAddr; + private Double longitude; + private Double latitude; + private String description = "地震影响场范围"; + } + } + + +} + diff --git a/src/main/java/com/gis/xian/dto/pub/RAssessmentDTO.java b/src/main/java/com/gis/xian/dto/pub/RAssessmentDTO.java new file mode 100644 index 0000000..db1f9da --- /dev/null +++ b/src/main/java/com/gis/xian/dto/pub/RAssessmentDTO.java @@ -0,0 +1,28 @@ +package com.gis.xian.dto.pub; + +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * @author zzw + * @description: 评估DTO类 + * @date 2026/5/26 下午5:51 + */ +@Data +public class RAssessmentDTO implements Serializable { + + private String rainId; + private String rainQueueId; + private String rainName; // 暴雨名称 + private String position; // 区县 + private double longitude; // 经度 + private double latitude; // 纬度 + private String rainfall; // 降雨量 + private String duration; // 已持续时间 + private String rainType; // 暴雨类型 + private LocalDateTime occurrenceTime; // 发生时间 + + +} diff --git a/src/main/java/com/gis/xian/entity/base/ActiveFault.java b/src/main/java/com/gis/xian/entity/base/ActiveFault.java new file mode 100644 index 0000000..05e92db --- /dev/null +++ b/src/main/java/com/gis/xian/entity/base/ActiveFault.java @@ -0,0 +1,206 @@ +package com.gis.xian.entity.base; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; +import org.locationtech.jts.geom.Geometry; + +/** + * @author zzw + * @description: 陕西省活断层实体 + * @date 2026/5/26 上午10:18 + */ +@Data +@TableName("base.active_fault") +public class ActiveFault { + + @TableId("\"ID\"") + private String ID; + + @TableField("\"SmUserID\"") + private Integer SmUserID; + + @TableField("\"Scale\"") + private Integer Scale; + + @TableField("\"FractureZo\"") + private String FractureZo; + + @TableField("\"Name\"") + private String Name; + + @TableField("\"FaultSegme\"") + private String FaultSegme; + + @TableField("\"StrikeDire\"") + private Integer StrikeDire; + + @TableField("\"Strike\"") + private Integer Strike; + + @TableField("\"Direction\"") + private Integer Direction; + + @TableField("\"Clination\"") + private Integer Clination; + + @TableField("\"Length\"") + private Double Length; + + @TableField("\"TopDepth\"") + private String TopDepth; + + @TableField("\"Width\"") + private Double Width; + + @TableField("\"FractureBe\"") + private Double FractureBe; + + @TableField("\"Feature\"") + private Integer Feature; + + @TableField("\"LatestActi\"") + private Integer LatestActi; + + @TableField("\"StartTimeE\"") + private String StartTimeE; + + @TableField("\"VDisplaceE\"") + private Double VDisplaceE; + + @TableField("\"VDisplac_1\"") + private Double VDisplac_1; + + @TableField("\"HDisplaceE\"") + private Double HDisplaceE; + + @TableField("\"HDisplac_1\"") + private Double HDisplac_1; + + @TableField("\"TDisplaceE\"") + private Double TDisplaceE; + + @TableField("\"TDisplac_1\"") + private Double TDisplac_1; + + @TableField("\"AveVRate\"") + private Double AveVRate; + + @TableField("\"AveVRateEr\"") + private Double AveVRateEr; + + @TableField("\"AveHRate\"") + private Double AveHRate; + + @TableField("\"AveHRateEr\"") + private Double AveHRateEr; + + @TableField("\"StartTimeN\"") + private Double StartTimeN; + + @TableField("\"NewVRate\"") + private Double NewVRate; + + @TableField("\"NewVRateEr\"") + private Double NewVRateEr; + + @TableField("\"NewHRate\"") + private Double NewHRate; + + @TableField("\"NewHRateEr\"") + private Double NewHRateEr; + + @TableField("\"MaxVRate\"") + private Double MaxVRate; + + @TableField("\"MaxVRateEr\"") + private Double MaxVRateEr; + + @TableField("\"MaxHRate\"") + private Double MaxHRate; + + @TableField("\"MaxHRateEr\"") + private Double MaxHRateEr; + + @TableField("\"EQEventCou\"") + private Integer EQEventCou; + + @TableField("\"EQEventRIB\"") + private Integer EQEventRIB; + + @TableField("\"EQEventRIT\"") + private Integer EQEventRIT; + + @TableField("\"Method\"") + private String Method; + + @TableField("\"MaxRupture\"") + private Integer MaxRupture; + + @TableField("\"AverageRup\"") + private Integer AverageRup; + + @TableField("\"ElapseTime\"") + private Integer ElapseTime; + + @TableField("\"SlipDepthE\"") + private Integer SlipDepthE; + + @TableField("\"SlipDept_1\"") + private Integer SlipDept_1; + + @TableField("\"AverageSli\"") + private Double AverageSli; + + @TableField("\"AverageS_1\"") + private Double AverageS_1; + + @TableField("\"CreepRateE\"") + private Double CreepRateE; + + @TableField("\"CreepRat_1\"") + private Double CreepRat_1; + + @TableField("\"CoSeismicM\"") + private Double CoSeismicM; + + @TableField("\"CoSeismi_1\"") + private Double CoSeismi_1; + + @TableField("\"CoSeismicA\"") + private Double CoSeismicA; + + @TableField("\"CoSeismi_2\"") + private Double CoSeismi_2; + + @TableField("\"LatestCoSe\"") + private Double LatestCoSe; + + @TableField("\"LatestCo_1\"") + private Double LatestCo_1; + + @TableField("\"CommentInf\"") + private String CommentInf; + + @TableField("\"Shape_Leng\"") + private Double Shape_Leng; + + @TableField("\"Project\"") + private String Project; + + @TableField("\"Coordinate\"") + private String Coordinate; + + @TableField("\"DateSource\"") + private String DateSource; + + @TableField(value = "\"Geometry\"", typeHandler = com.gis.xian.handler.GeometryTypeHandler.class) + @JsonSerialize(using = ToStringSerializer.class) + private Geometry geometry; + + +} + diff --git a/src/main/java/com/gis/xian/entity/base/SXCities.java b/src/main/java/com/gis/xian/entity/base/SXCities.java new file mode 100644 index 0000000..5051857 --- /dev/null +++ b/src/main/java/com/gis/xian/entity/base/SXCities.java @@ -0,0 +1,38 @@ +package com.gis.xian.entity.base; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; +import org.locationtech.jts.geom.Geometry; + +/** + * @author zzw + * @description: 陕西省市区 + * @date 2026/5/26 上午8:31 + */ +@Data +@TableName("base.sx_zb_city") +public class SXCities { + + @TableField("\"SmUserID\"") + private Integer SmUserID; + @TableField("\"Field_SmUserID\"") + private Integer Field_SmUserID; + @TableField("\"CLASS\"") + private String CLASS; + @TableField("\"NAME\"") + private String NAME; + @TableField("\"NAMEABBR\"") + private String NAMEABBR; + @TableField("\"X\"") + private Double X; + @TableField("\"Y\"") + private Double Y; + @TableField("\"Geometry\"") + @JsonSerialize(using = ToStringSerializer.class) + private Geometry geometry; + + +} diff --git a/src/main/java/com/gis/xian/entity/base/SXCounty.java b/src/main/java/com/gis/xian/entity/base/SXCounty.java new file mode 100644 index 0000000..d5efa46 --- /dev/null +++ b/src/main/java/com/gis/xian/entity/base/SXCounty.java @@ -0,0 +1,47 @@ +package com.gis.xian.entity.base; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; +import org.locationtech.jts.geom.Geometry; + +/** + * @author zzw + * @description: 陕西省区县 + * @date 2026/5/26 上午9:46 + */ +@Data +@TableName("base.sx_zb_county") +public class SXCounty { + + + @TableField("\"SmUserID\"") + private Integer SmUserID; + @TableField("\"Field_SmUserID\"") + private Integer Field_SmUserID; + @TableField("\"Field_Field_SmUserID\"") + private Integer Field_Field_SmUserID; + @TableField("\"CLASS\"") + private String CLASS; + @TableField("\"NAME\"") + private String NAME; + @TableField("\"PINYIN\"") + private String PINYIN; + @TableField("\"GNID\"") + private Integer GNID; + @TableField("\"XZNAME\"") + private String XZNAME; + @TableField("\"X\"") + private Double X; + @TableField("\"Y\"") + private Double Y; + @TableField("\"Geometry\"") + @JsonSerialize(using = ToStringSerializer.class) + private Geometry geometry; + + + +} + diff --git a/src/main/java/com/gis/xian/entity/base/SXTowns.java b/src/main/java/com/gis/xian/entity/base/SXTowns.java new file mode 100644 index 0000000..ecc9195 --- /dev/null +++ b/src/main/java/com/gis/xian/entity/base/SXTowns.java @@ -0,0 +1,44 @@ +package com.gis.xian.entity.base; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; +import org.locationtech.jts.geom.Geometry; + +/** + * @author zzw + * @description: 陕西省乡镇 + * @date 2026/5/26 上午9:56 + */ +@Data +@TableName("base.sx_towns") +public class SXTowns { + + + @TableField("\"SmUserID\"") + private Integer SmUserID; + @TableField("\"Field_SmUserID\"") + private Integer Field_SmUserID; + @TableField("\"CLASS\"") + private String CLASS; + @TableField("\"NAME\"") + private String NAME; + @TableField("\"PINYIN\"") + private String PINYIN; + @TableField("\"GNID\"") + private String GNID; + @TableField("\"XZNAME\"") + private String XZNAME; + @TableField("\"X\"") + private Double X; + @TableField("\"Y\"") + private Double Y; + @TableField("\"Geometry\"") + @JsonSerialize(using = ToStringSerializer.class) + private Geometry geometry; + + + +} diff --git a/src/main/java/com/gis/xian/entity/dzxx/DZXXCenter.java b/src/main/java/com/gis/xian/entity/dzxx/DZXXCenter.java new file mode 100644 index 0000000..1671b43 --- /dev/null +++ b/src/main/java/com/gis/xian/entity/dzxx/DZXXCenter.java @@ -0,0 +1,75 @@ +package com.gis.xian.entity.dzxx; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import org.apache.ibatis.type.JdbcType; +import org.locationtech.jts.geom.Geometry; + +import java.time.LocalDateTime; + +/** + * @author zzw + * @description: 地震信息震中点 + * @date 2026/5/25 下午5:16 + */ +@Data +@TableName("dzxx.dz_gis_center") +public class DZXXCenter { + + @TableId(value = "id", type = IdType.ASSIGN_ID) + private Long Id; + + @TableField(value = "geom", typeHandler = com.gis.xian.handler.GeometryTypeHandler.class) + private Geometry geom; + + @TableField("event") + private String event; + + @TableField("eq_time") + private LocalDateTime eqTime; + + @TableField("eq_addr") + private String eqAddr; + + @TableField("longitude") + private Double longitude; + + @TableField("latitude") + private Double latitude; + + @TableField("eq_magnitude") + private Double eqMagnitude; + + @TableField("eq_depth") + private Double eqDepth; + + @TableField("eq_full_name") + private String eqFullName; + + @TableField("eq_name") + private String eqName; + + @TableField("eq_type") + private String eqType; + + @TableField("eq_addr_code") + private String eqAddrCode; + + @TableField("town_code") + private String townCode; + + @TableLogic + @TableField("del_flag") + private Integer delFlag = 0; + + @TableField(value = "create_by", fill = FieldFill.INSERT_UPDATE) + private String createBy; + + @TableField(value = "create_time", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime createTime; + + @TableField("remark") + private String remark; + + +} diff --git a/src/main/java/com/gis/xian/entity/dzxx/DZXXDistance.java b/src/main/java/com/gis/xian/entity/dzxx/DZXXDistance.java new file mode 100644 index 0000000..8c11e34 --- /dev/null +++ b/src/main/java/com/gis/xian/entity/dzxx/DZXXDistance.java @@ -0,0 +1,46 @@ +package com.gis.xian.entity.dzxx; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import org.locationtech.jts.geom.Geometry; + +import java.time.LocalDateTime; + +/** + * @ClassName DZXXDistance + * @Description 震中距省市县乡镇距离 + * @Author zzw + * @Date 2026/5/25 11:51 + */ +@Data +@TableName("dzxx.dz_gis_distance") +public class DZXXDistance { + + @TableId(value = "id",type = IdType.ASSIGN_ID) + private Long Id; + @TableField("geom") + private Geometry geom; + @TableField("eqqueue_id") + private String eqQueueId; + @TableField("distance_id") + private Integer distanceId; + @TableField("pid") + private String pId; + @TableField("pname") + private String pname; + @TableField("bgmc") + private String bgmc; + @TableField("distance") + private Double distance; + @TableLogic + @TableField("del_flag") + private Integer delFlag = 0; + @TableField(value = "create_by",fill = FieldFill.INSERT_UPDATE) + private String createBy; + @TableField(value = "create_time",fill = FieldFill.INSERT_UPDATE) + private LocalDateTime createTime; + @TableField("remark") + private String remark; + +} + diff --git a/src/main/java/com/gis/xian/entity/dzxx/DZXXInfluence.java b/src/main/java/com/gis/xian/entity/dzxx/DZXXInfluence.java new file mode 100644 index 0000000..d7c36cf --- /dev/null +++ b/src/main/java/com/gis/xian/entity/dzxx/DZXXInfluence.java @@ -0,0 +1,58 @@ +package com.gis.xian.entity.dzxx; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import org.locationtech.jts.geom.Geometry; + +import java.time.LocalDateTime; + +/** + * @author zzw + * @description: 地震烈度影响场 + * @date 2026/5/26 上午10:09 + */ + +@Data +@TableName("dzxx.dz_gis_influence") +public class DZXXInfluence { + + @TableId(value = "id",type = IdType.ASSIGN_ID) + private Long Id; + @TableField("geom") + private Geometry geom; // 椭圆面积 + @TableField("eqqueue_id") + private String eqQueueId; + @TableField("event") + private String event; + @TableField("eqname") + private String eqName; + @TableField("inty") + private Integer inty; // 烈度值 + @TableField("sinty") // 字符烈度值 + private String sInty; + @TableField("type") + private String type; + @TableField("area") + private Double area; // 烈度区面积 + @TableField("long_uranium") + private Double longUranium; + @TableField("short_uranium") + private Double shortUranium; + @TableField("direction") + private Double direction; // 偏转角度 + @TableLogic + @TableField("del_flag") + private Integer delFlag = 0; + @TableField(value = "create_by",fill = FieldFill.INSERT_UPDATE) + private String createBy; + @TableField(value = "create_time",fill = FieldFill.INSERT_UPDATE) + private LocalDateTime createTime; + @TableField("remark") + private String remark; + @TableField("longitude") + private Double longitude; + @TableField("latitude") + private Double latitude; + +} + diff --git a/src/main/java/com/gis/xian/entity/pub/DZEqEvent.java b/src/main/java/com/gis/xian/entity/pub/DZEqEvent.java new file mode 100644 index 0000000..8c59261 --- /dev/null +++ b/src/main/java/com/gis/xian/entity/pub/DZEqEvent.java @@ -0,0 +1,71 @@ +package com.gis.xian.entity.pub; + +import lombok.Data; +import com.baomidou.mybatisplus.annotation.*; + +import java.time.LocalDateTime; + +/** + * @author zzw + * @description: 地震事件表 + * @date 2026/5/25 下午3:24 + */ +@Data +@TableName("public.dz_eqevent") +public class DZEqEvent { + + @TableId(value = "id",type = IdType.ASSIGN_ID) + private Long Id; + @TableField("event") + private String event; + @TableField("eq_time") + private LocalDateTime eqTime; + @TableField("eq_addr") + private String eqAddr; + @TableField("longitude") + private Double longitude; + @TableField("latitude") + private Double latitude; + @TableField("eq_magnitude") + private Double eqMagnitude; + @TableField("eq_depth") + private Double eqDepth; + @TableField("eq_full_name") + private String eqFullName; + @TableField("eq_name") + private String eqName; + @TableField("eq_type") + private String eqType; + @TableField("eq_addr_code") + private String eqAddrCode; + @TableField("town_code") + private String townCode; + @TableField("distance") + private Double distance; + @TableField("region") + private Integer region; + @TableField("damage_type") + private Integer damageType; + @TableField("direction") + private Double direction; + @TableLogic + @TableField("del_flag") + private Integer delFlag = 0; + @TableField(value = "create_by",fill = FieldFill.INSERT_UPDATE) + private String createBy; + @TableField(value = "create_time",fill = FieldFill.INSERT_UPDATE) + private LocalDateTime createTime; + @TableField(value = "create_dept",fill = FieldFill.INSERT_UPDATE) + private String createDept; + @TableField(value = "update_by",fill = FieldFill.INSERT_UPDATE) + private String updateBy; + @TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + @TableField("remark") + private String remark; + @TableField("xyjb") + private String xyjb; // 相应级别 + @TableField("source") + private Integer source; + +} diff --git a/src/main/java/com/gis/xian/entity/pub/DZEqQueue.java b/src/main/java/com/gis/xian/entity/pub/DZEqQueue.java new file mode 100644 index 0000000..fcfceab --- /dev/null +++ b/src/main/java/com/gis/xian/entity/pub/DZEqQueue.java @@ -0,0 +1,55 @@ +package com.gis.xian.entity.pub; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author zzw + * @description: 地震评估表 + * @date 2026/5/25 下午6:01 + */ + +@Data +@TableName("public.dz_eqqueue") +public class DZEqQueue { + + @TableField(value = "id") + private String id; // eqqueueid + @TableField("event") + private String event; + @TableField("batch") + private Integer batch; + @TableField("type") + private Integer type; + @TableField("state") + private Integer state; //评估状态(0未开始,1正在计算,2正常完成,3人工停止,4超时或异常结束, 5不计算) + @TableField("mode") + private Integer mode = 1; // 执行方式(0地震参数 1影响场) + @TableField("begin_time") + private LocalDateTime beginTime; + @TableField("end_time") + private LocalDateTime endTime; + @TableField("progress") + private Double progress; + @TableLogic + @TableField(value = "del_flag", fill = FieldFill.INSERT_UPDATE) + private Integer delFlag; + @TableField(value = "create_by", fill = FieldFill.INSERT_UPDATE) + private String createBy; + @TableField(value = "create_time", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime createTime; + @TableField(value = "create_dept", fill = FieldFill.INSERT_UPDATE) + private Integer createDept; + @TableField(value = "update_by", fill = FieldFill.INSERT_UPDATE) + private String updateBy; + @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + @Version + @TableField(value = "version", fill = FieldFill.INSERT_UPDATE) + private Integer version; // 版本号 + @TableField("remark") + private String remark; + +} diff --git a/src/main/java/com/gis/xian/entity/pub/DZInfluence.java b/src/main/java/com/gis/xian/entity/pub/DZInfluence.java new file mode 100644 index 0000000..d9d2cda --- /dev/null +++ b/src/main/java/com/gis/xian/entity/pub/DZInfluence.java @@ -0,0 +1,57 @@ +package com.gis.xian.entity.pub; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author zzw + * @description: 地震影响场文件表 + * @date 2026/5/26 上午10:36 + */ +@Data +@TableName("public.dz_influence") +public class DZInfluence { + + @TableId(value = "id",type = IdType.ASSIGN_ID) + private Long Id; + @TableField("event") + private String event; + @TableField("name") + private String name; + @TableField("file") + private String file; + @TableField("path") + private String path; + @TableField("content") + private String content; + @TableField("intensity_column") + private String intensityColumn; + @TableField("source") + private String source; + @TableField("is_edit") + private Integer isEdit; + @TableField("is_pg") + private Integer isPg; + @TableLogic + @TableField("del_flag") + private Integer delFlag = 0; + @TableField(value = "create_by",fill = FieldFill.INSERT_UPDATE) + private String createBy; + @TableField(value = "create_time",fill = FieldFill.INSERT_UPDATE) + private LocalDateTime createTime; + @TableField(value = "create_dept",fill = FieldFill.INSERT_UPDATE) + private Integer createDept; + @TableField(value = "update_by",fill = FieldFill.INSERT_UPDATE) + private String updateBy; + @TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + @TableField("remark") + private String remark; + @TableField("eqqueue_id") + private String eqQueueId; + + +} + diff --git a/src/main/java/com/gis/xian/entity/pub/DZProduct.java b/src/main/java/com/gis/xian/entity/pub/DZProduct.java new file mode 100644 index 0000000..327e83d --- /dev/null +++ b/src/main/java/com/gis/xian/entity/pub/DZProduct.java @@ -0,0 +1,55 @@ +package com.gis.xian.entity.pub; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author zzw + * @description: 地震产品产出 + * @date 2026/5/26 上午10:57 + */ +@Data +@TableName("public.dz_product") +public class DZProduct { + + @TableId(value = "id",type = IdType.ASSIGN_ID) + private Long Id; + @TableField("eqqueue_id") + private String eqQueueId; + @TableField("templet_id") + private Integer templetId; // 模板编码id + @TableField("code") + private String code; + @TableField("pro_time") + private LocalDateTime proTime; + @TableField("file_type") + private String fileType; + @TableField("file_name") + private String fileName; + @TableField("file_path") + private String filePath; + @TableField("file_extension") + private String fileExtension; + @TableField("file_size") + private Double fileSize; + @TableField("pro_type") + private String proType; + @TableField("source_file") + private String sourceFile; + @TableField(value = "create_by",fill = FieldFill.INSERT_UPDATE) + private String createBy; + @TableField(value = "create_time",fill = FieldFill.INSERT_UPDATE) + private LocalDateTime createTime; + @TableField(value = "create_dept",fill = FieldFill.INSERT_UPDATE) + private Integer createDept; + @TableField(value = "update_by",fill = FieldFill.INSERT_UPDATE) + private String updateBy; + @TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + @TableField("remark") + private String remark; + +} + diff --git a/src/main/java/com/gis/xian/enums/BaseEnums.java b/src/main/java/com/gis/xian/enums/BaseEnums.java new file mode 100644 index 0000000..04545c4 --- /dev/null +++ b/src/main/java/com/gis/xian/enums/BaseEnums.java @@ -0,0 +1,33 @@ +package com.gis.xian.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author zzw + * @description: 同用枚举 + * @date 2026/5/26 上午10:46 + */ +@Getter +@AllArgsConstructor +public enum BaseEnums { + // 评估枚举 + NOT_STARTED(0, "未开始"), + CALCULATING(1, "正在计算"), + NORMAL_COMPLETED(2, "正常完成"), + MANUAL_STOPPED(3, "人工停止"), + TIMEOUT_OR_EXCEPTION(4, "超时或异常结束"), + NOT_CALCULATE(5, "不计算"), + + // 制图枚举 + NO(10, "不缩放"), + PAN(11, "平移"), + LAYER(12, "单图层"), + M_LAYER(13, "多图层"), + DISTANCE(14, "距离"), // 需要数值。 + M_LAYER2(15, "按图层合并缩放"); + + + private final Integer code; + private final String desc; +} diff --git a/src/main/java/com/gis/xian/enums/EqMapsEnums.java b/src/main/java/com/gis/xian/enums/EqMapsEnums.java new file mode 100644 index 0000000..25c5170 --- /dev/null +++ b/src/main/java/com/gis/xian/enums/EqMapsEnums.java @@ -0,0 +1,41 @@ +package com.gis.xian.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author zzw + * @description: 地震专题图集枚举 + * @date 2026/5/26 上午10:46 + */ +@Getter +@AllArgsConstructor +public enum EqMapsEnums { + + // 制图枚举 + EARTHQUAKE_DISTRIBUTION(1, "地震影响估计范围分布图"), + EARTHQUAKE_RUPTURE(2, "震中附近活动断裂分布图"), + EARTHQUAKE_HOSPITAL(3, "震区医院分布图"), + EARTHQUAKE_RESCUE_TEAM(4, "震中附近救援队伍分布图"), + EARTHQUAKE_RESCUE_MATERIAL(5, "震区附近救援物资分布图"), + EARTHQUAKE_VILLAGES_DISTANCE(6, "震中与乡镇距离图"), + EARTHQUAKE_TRAFFIC(7, "震区交通图"), + EARTHQUAKE_SCHOOL(8, "震区学校分布图"), + EARTHQUAKE_PEOPLE(9, "震区附近人口分布图"), + EARTHQUAKE_SAFE_PLACE(10, "震区附近疏散场地分布图"), + EARTHQUAKE_PUBLIC_PLACE(11, "震区附近公共场所分布图"), + EARTHQUAKE_DANGER_SOURCE(12, "震区危险源分布图"), + EARTHQUAKE_RISK_AREA(13, "震中附近风险区分布图"), + EARTHQUAKE_HIDE_POINT(14, "震区潜在地质灾害分布图"), + EARTHQUAKE_IMPORTANT_OBJECTS(15, "震区附近重要目标分布图"), + EARTHQUAKE_TOURIST_SPOT(16, "震区附近景区分布图"), + EARTHQUAKE_RESERVOIR(17, "震区附近水库分布图"), + EARTHQUAKE_DX(18, "震中地形图"), + EARTHQUAKE_CROPS(19, "震区附近农作物分布图"); + + private final Integer num; + private final String name; + + +} + diff --git a/src/main/java/com/gis/xian/enums/RainMapsEnums.java b/src/main/java/com/gis/xian/enums/RainMapsEnums.java new file mode 100644 index 0000000..615daf9 --- /dev/null +++ b/src/main/java/com/gis/xian/enums/RainMapsEnums.java @@ -0,0 +1,37 @@ +package com.gis.xian.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author zzw + * @description: 暴雨专题图集枚举 + * @date 2026/5/26 上午10:46 + */ +@Getter +@AllArgsConstructor +public enum RainMapsEnums { + + // 制图枚举 + EARTHQUAKE_PEOPLE(1, "暴雨滑坡潜在隐患点及人口分布图"), + EARTHQUAKE_HOSPITAL(2, "暴雨山洪潜在隐患点及人口分布图"), + EARTHQUAKE_HIDE_POINT(3, "暴雨内涝潜在隐患点及人口分布图"), + EARTHQUAKE_VILLAGES_DISTANCE(4, "暴雨避难场所分布图"), + EARTHQUAKE_RESCUE_TEAM(5, "暴雨泥石流潜在隐患点及人口分布图"), + EARTHQUAKE_CROPS(6, "暴雨地灾风险区分布图"), + EARTHQUAKE_DX(7, "暴雨防汛物资分布图"), + EARTHQUAKE_RESERVOIR(8, "暴雨救援队伍分布图"), + EARTHQUAKE_DISTRIBUTION(9, "暴雨城市生命线工程分布图"), + EARTHQUAKE_PUBLIC_PLACE(10, "暴雨附近水库分布图"), + EARTHQUAKE_RESCUE_MATERIAL(11, "暴雨附近医院分布图"), + EARTHQUAKE_IMPORTANT_OBJECTS(12, "暴雨滑坡潜在隐患点及农作物分布图"), + EARTHQUAKE_RISK_AREA(13, "暴雨山洪潜在隐患点及农作物分布图"), + EARTHQUAKE_SAFE_PLACE(14, "暴雨内涝潜在隐患点及农作物分布图"), + EARTHQUAKE_TOURIST_SPOT(15, "暴雨泥石流潜在隐患点及农作物分布图"); + + private final Integer num; + private final String name; + + +} + diff --git a/src/main/java/com/gis/xian/handler/EarthquakeHandler.java b/src/main/java/com/gis/xian/handler/EarthquakeHandler.java new file mode 100644 index 0000000..5f0e071 --- /dev/null +++ b/src/main/java/com/gis/xian/handler/EarthquakeHandler.java @@ -0,0 +1,112 @@ +package com.gis.xian.handler; + +import com.gis.xian.constant.BaseConstants; +import com.gis.xian.enums.EqMapsEnums; +import com.gis.xian.enums.RainMapsEnums; +import com.gis.xian.utils.BaseUtils; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +/** + * @author zzw + * @description: 地震烈度核心服务 + * @date 2026/5/26 上午10:47 + */ +public class EarthquakeHandler { + + + /** + * 获取不同烈度下的面积 + * + * @param a 长轴 + * @param b 短轴 + * @return 返回椭圆的面积 + */ + public static double calculateArea(double a, double b) { + return Math.PI * a * b; + } + + /** + * @param M 震级 + * @param Ia 烈度 + * @author: xiaodemos + * @date: 2025/3/25 10:57 + * @description: 计算椭圆的长轴 + * @return: 返回长轴 + */ + public static double calculateRa(double M, double Ia) { + return (Math.pow(10, (4.0293 + 1.3003 * M - Ia) / 3.6404) - 10) * 1000; + } + + /** + * @param M 震级 + * @param Ib 烈度 + * @author: xiaodemos + * @date: 2025/3/25 10:58 + * @description: 计算椭圆的短轴 + * @return: 返回短轴 + */ + public static double calculateRb(double M, double Ib) { + return (Math.pow(10, (2.3816 + 1.3003 * M - Ib) / 2.8573) - 5) * 1000; + } + + + // 格式化地震三要素信息 + public static String parseInfo(LocalDateTime eqTime, double magnitude, String addr) { + String time = BaseUtils.formatTime(eqTime, true); + return String.format("时间:%s\r\n震级:%s级\r\n位置:%s", time, magnitude, addr); + } + + // 格式化暴雨三要素信息 + public static String parseRInfo(LocalDateTime eqTime, String magnitude, String addr) { + String time = BaseUtils.formatTime(eqTime, true); + return String.format("时间:%s\r\n累计降雨量:%s毫米\r\n已持续:%s小时", time, magnitude, addr); + } + + // 拼接地震图件标题 + public static String combine(String eqName, String eqType, EqMapsEnums map) { + // 地点 + 震级 + String name = eqName; + // 图名称 + 地震类型 + String mapName = map.getName() + BaseConstants.EQ_TYPE.get(eqType); + return String.format("%s", name + mapName); + } + + // 拼接暴雨图件标题 + public static String combineR(String rainName, String rainType, RainMapsEnums map) { + // 地点 + 暴雨名称 + String name = rainName; + // 图名称 + 暴雨类型 + String mapName = map.getName() + BaseConstants.RAIN_TYPE.get(rainType); + return String.format("%s", name + mapName); + } + + // 拼接导出路径 + public static String getPath(String event, String queueId, String size, EqMapsEnums map) { + // 地震事件 + 批次 + String batch = queueId.substring(event.length()); + String path = event + "/" + batch + "/" + size + "/" + map.getName(); + return String.format("%s", BaseConstants.EQ_MAPS_OUTPUT_PATH + path + ".jpg"); + } + + // 拼接导出路径 + public static String getRPath(String rainId, String queueId, String size, RainMapsEnums map) { + // 地震事件 + 批次 + String batch = queueId.substring(rainId.length()); + String path = rainId + "/" + batch + "/" + size + "/" + map.getName(); + return String.format("%s", BaseConstants.RAIN_MAPS_OUTPUT_PATH + path + ".jpg"); + } + + public static String format(LocalDateTime time) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM月dd日HH时mm分"); + String timestamp = time.format(formatter); + return timestamp; + } + + public static String formatTime(LocalDateTime time) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分"); + String timestamp = time.format(formatter); + return timestamp; + } +} diff --git a/src/main/java/com/gis/xian/handler/EllipseToWktHandler.java b/src/main/java/com/gis/xian/handler/EllipseToWktHandler.java new file mode 100644 index 0000000..e59619a --- /dev/null +++ b/src/main/java/com/gis/xian/handler/EllipseToWktHandler.java @@ -0,0 +1,158 @@ +package com.gis.xian.handler; + +import com.gis.xian.query.IntensityQuery; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.Polygon; +import org.locationtech.jts.io.WKTReader; +import org.locationtech.proj4j.*; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.List; + +/** + * @author zzw + * @description: 椭圆烈度衰减圈转换为WKT格式 + * @date 2026/5/26 上午10:25 + */ +@Component +public class EllipseToWktHandler { + // 投影转换工厂 + private final CRSFactory crsFactory = new CRSFactory(); + private final CoordinateTransformFactory ctFactory = new CoordinateTransformFactory(); + GeometryFactory geometryFactory = new GeometryFactory(); + + /** + * 将椭圆参数转换为 POLYGON 格式的 WKT 字符串 + * @param query 椭圆烈度参数 + * @return POLYGON格式的WKT字符串 + */ + public Polygon ellipseToPolygonWkt(IntensityQuery query) { + try { + // 确定UTM投影带并创建转换器 + int utmZone = (int) Math.floor((query.getCenterLon() + 180) / 6) + 1; + String epsgCode = query.getCenterLat() >= 0 ? "EPSG:326" + utmZone : "EPSG:327" + utmZone; + + // 创建坐标参考系(WGS84 -> UTM) + CoordinateReferenceSystem wgs84 = crsFactory.createFromName("EPSG:4326"); + CoordinateReferenceSystem utm = crsFactory.createFromName(epsgCode); + + // 创建转换器 + CoordinateTransform toUtmTransform = ctFactory.createTransform(wgs84, utm); + CoordinateTransform toWgs84Transform = ctFactory.createTransform(utm, wgs84); + + // 将中心点经纬度转换为UTM坐标 + ProjCoordinate centerWgs84 = new ProjCoordinate(query.getCenterLon(), query.getCenterLat()); + ProjCoordinate centerUtm = new ProjCoordinate(); + toUtmTransform.transform(centerWgs84, centerUtm); + double centerX = centerUtm.x; + double centerY = centerUtm.y; + + // 生成椭圆的平面顶点(极坐标方式) + double rotationRad = Math.toRadians(query.getRotation()); + List verticesUtm = new ArrayList<>(); + + // 生成0到2π的角度序列 + double angleStep = 2 * Math.PI / query.getNumVertices(); + for (int i = 0; i < query.getNumVertices(); i++) { + double theta = i * angleStep; + // 椭圆极坐标方程 + double xEllipse = query.getSemiMajor() * Math.cos(theta); + double yEllipse = query.getSemiMinor() * Math.sin(theta); + // 旋转矩阵计算 + double xRot = xEllipse * Math.cos(rotationRad) - yEllipse * Math.sin(rotationRad); + double yRot = xEllipse * Math.sin(rotationRad) + yEllipse * Math.cos(rotationRad); + // 加上中心点坐标 + double xFinal = centerX + xRot; + double yFinal = centerY + yRot; + + verticesUtm.add(new ProjCoordinate(xFinal, yFinal)); + } + + // 将UTM顶点转换回经纬度 + List verticesWgs84 = new ArrayList<>(); + for (ProjCoordinate utmCoord : verticesUtm) { + ProjCoordinate wgs84Coord = new ProjCoordinate(); + toWgs84Transform.transform(utmCoord, wgs84Coord); + verticesWgs84.add(wgs84Coord); + } + + // 拼接WKT字符串(保留6位小数,闭合多边形) + StringBuilder verticesStr = new StringBuilder(); + for (ProjCoordinate coord : verticesWgs84) { + verticesStr.append(roundTo6Decimals(coord.x)) + .append(" ") + .append(roundTo6Decimals(coord.y)) + .append(", "); + } + + // 添加第一个点闭合多边形 + ProjCoordinate firstCoord = verticesWgs84.get(0); + verticesStr.append(roundTo6Decimals(firstCoord.x)) + .append(" ") + .append(roundTo6Decimals(firstCoord.y)); + // 构建最终WKT字符串 + String POLYGON = String.format("POLYGON ((%s)) | 4490", verticesStr); + // 返回Polygon类型 + Polygon polygon = buildPolygonFromWKTString(POLYGON); + + return polygon; + } catch (Exception e) { + throw new RuntimeException("生成烈度多边形失败", e); + } + } + + /** + * 解析WKT获取经纬度范围 + */ + public void printLatLonRange(String wkt) { + // 提取顶点坐标 + String coordsPart = wkt.replace("POLYGON ((", "").replace("))", ""); + String[] coordStrs = coordsPart.split(", "); + + double minLon = Double.MAX_VALUE; + double maxLon = Double.MIN_VALUE; + double minLat = Double.MAX_VALUE; + double maxLat = Double.MIN_VALUE; + + for (String coordStr : coordStrs) { + String[] lonLat = coordStr.split(" "); + double lon = Double.parseDouble(lonLat[0]); + double lat = Double.parseDouble(lonLat[1]); + + minLon = Math.min(minLon, lon); + maxLon = Math.max(maxLon, lon); + minLat = Math.min(minLat, lat); + maxLat = Math.max(maxLat, lat); + } + + System.out.println("\n椭圆的经纬度范围:"); + System.out.printf("经度范围:%.6f ~ %.6f%n", minLon, maxLon); + System.out.printf("纬度范围:%.6f ~ %.6f%n", minLat, maxLat); + } + + /** + * 保留6位小数 + */ + private double roundTo6Decimals(double value) { + return new BigDecimal(value).setScale(6, RoundingMode.HALF_UP).doubleValue(); + } + + // 构建 Polygon 对象 + public Polygon buildPolygonFromWKTString(String wktPolygon) { + try { + // WKT解析器 + WKTReader wktReader = new WKTReader(geometryFactory); + // 解析 POLYGON 字符串 + Geometry geometry = wktReader.read(wktPolygon); + return (Polygon) geometry; + } catch (Exception e) { + throw new RuntimeException("解析 POLYGON 字符串失败", e); + } + } + + +} diff --git a/src/main/java/com/gis/xian/handler/GeoDistanceHandler.java b/src/main/java/com/gis/xian/handler/GeoDistanceHandler.java new file mode 100644 index 0000000..ba859c8 --- /dev/null +++ b/src/main/java/com/gis/xian/handler/GeoDistanceHandler.java @@ -0,0 +1,219 @@ +package com.gis.xian.handler; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.Assert; + +/** + * @author zzw + * @description: 地理距离计算工具类 + * @date 2026/5/26 上午9:41 + */ +@Slf4j +public class GeoDistanceHandler { + + /** + *地球平均半径(千米) + */ + private static final double EARTH_RADIUS = 6371.0; + /** + * 计算两个经纬度点之间的球面距离(单位:千米) + * @param lon1 点1经度 + * @param lat1 点1纬度 + * @param lon2 点2经度 + * @param lat2 点2纬度 + * @return 两点之间的距离(千米) + */ + public static double calculateHaversineDistance(double lon1, double lat1, double lon2, double lat2) { + // 参数校验(经纬度合理范围) + Assert.isTrue(lon1 >= -180 && lon1 <= 180 && lat1 >= -90 && lat1 <= 90, "点1经纬度格式非法"); + Assert.isTrue(lon2 >= -180 && lon2 <= 180 && lat2 >= -90 && lat2 <= 90, "点2经纬度格式非法"); + + // 转换为弧度(Math类三角函数默认使用弧度) + double radLat1 = Math.toRadians(lat1); + double radLon1 = Math.toRadians(lon1); + double radLat2 = Math.toRadians(lat2); + double radLon2 = Math.toRadians(lon2); + + // 计算纬度差、经度差 + double deltaLat = radLat1 - radLat2; + double deltaLon = radLon1 - radLon2; + + // Haversine公式核心计算 + double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + + Math.cos(radLat1) * Math.cos(radLat2) + * Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2); + double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + + // 返回距离(千米) + return EARTH_RADIUS * c; + } + + /** + * 计算震中点到断层的最短球面距离(单位:千米) + * @param lon 震中经度 + * @param lat 震中纬度 + * @param lonA 线段端点A经度 + * @param latA 线段端点A纬度 + * @param lonB 线段端点B经度 + * @param latB 线段端点B纬度 + * @return 震中到线段的最短距离(千米) + */ + public static double calculateDistanceFromPointToLineString(double lon, double lat, double lonA, double latA, double lonB, double latB) { + // 将经纬度转换为平面直角坐标系近似值 + double x = lon; + double y = lat; + double xA = lonA; + double yA = latA; + double xB = lonB; + double yB = latB; + + // 计算向量AB和向量AP + double vectorABx = xB - xA; + double vectorABy = yB - yA; + double vectorAPx = x - xA; + double vectorAPy = y - yA; + + // 计算点P在AB线段上的投影参数t(判断垂足是否在线段内) + // t = (AP · AB) / |AB|² + double dotProduct = vectorAPx * vectorABx + vectorAPy * vectorABy; // 点积 + double abLengthSquared = vectorABx * vectorABx + vectorABy * vectorABy; // AB长度的平方 + + // 线段AB是一个点(A和B坐标重合),直接返回点到点的距离 + if (abLengthSquared < 1e-10) { + return calculateHaversineDistance(lon, lat, lonA, latA); + } + + // 确定垂足位置 + double t = Math.max(0, Math.min(1, dotProduct / abLengthSquared)); // t限制在[0,1]之间(线段范围内) + + // 计算垂足点C的坐标(平面坐标) + double xC = xA + t * vectorABx; + double yC = yA + t * vectorABy; + + // 计算震中点到垂足点C的球面距离(最终最短距离) + return calculateHaversineDistance(lon, lat, xC, yC); + } + + /** + * 解析LINESTRING格式字符串,提取所有端点坐标 + * @param wktLineString LINESTRING格式的WKT字符串 + * @return 端点坐标二维数组([经度, 纬度]) + */ + public static double[][] parseLineStringCoordinates(String wktLineString) { + // 先判空并去除首尾多余空格 + if (wktLineString == null || wktLineString.trim().isEmpty()) { + throw new IllegalArgumentException("WKT字符串不能为空或空白"); + } + String cleanWkt = wktLineString.trim(); + + // 截取括号内的坐标字符串 + int startIndex = cleanWkt.indexOf("(") + 1; // 找到第一个左括号,取其后一位 + int endIndex = cleanWkt.lastIndexOf(")"); // 找到最后一个右括号 + String coordStr = cleanWkt.substring(startIndex, endIndex).trim(); + + // 括号内无坐标数据 + if (coordStr.isEmpty()) { + throw new IllegalArgumentException("LINESTRING内无有效坐标数据"); + } + + // 按逗号分割多个坐标点 + String[] pointStrArray = coordStr.split(","); + double[][] coordinates = new double[pointStrArray.length][2]; + + // 解析每个坐标点(经度 纬度) + for (int i = 0; i < pointStrArray.length; i++) { + String pointStr = pointStrArray[i].trim(); + // 容错:单个坐标点为空 + if (pointStr.isEmpty()) { + throw new IllegalArgumentException("LINESTRING内存在空坐标点,索引:" + i); + } + + String[] lonLat = pointStr.split("\\s+"); + if (lonLat.length != 2) { + throw new IllegalArgumentException("LINESTRING内坐标格式无效:" + pointStr); + } + + try { + double lon = Double.parseDouble(lonLat[0]); + double lat = Double.parseDouble(lonLat[1]); + coordinates[i][0] = lon; // 经度 + coordinates[i][1] = lat; // 纬度 + } catch (NumberFormatException e) { + throw new IllegalArgumentException("LINESTRING内坐标无法转换为数字:" + pointStr, e); + } + } + + return coordinates; + } + + /** + * 解析POINT格式WKT字符串,提取经纬度坐标 + * @param wktPoint POINT格式的WKT字符串 + * @return 坐标数组 [经度, 纬度] + */ + public static double[] parsePointCoordinates(String wktPoint) { + // 判空和去除首尾空格 + if (wktPoint == null || wktPoint.trim().isEmpty()) { + throw new IllegalArgumentException("POINT类型WKT字符串不能为空或空白"); + } + String cleanWkt = wktPoint.trim(); + + // 校验POINT格式前缀和后缀 + boolean isValidPrefix = cleanWkt.startsWith("POINT(") || cleanWkt.startsWith("POINT ("); + boolean isValidSuffix = cleanWkt.endsWith(")"); + if (!isValidPrefix || !isValidSuffix) { + throw new IllegalArgumentException("无效的POINT格式WKT字符串:" + wktPoint); + } + + // 截取括号内的坐标字符串 + int startIndex = cleanWkt.indexOf("(") + 1; + int endIndex = cleanWkt.lastIndexOf(")"); + String coordStr = cleanWkt.substring(startIndex, endIndex).trim(); + + // 校验括号内是否有有效坐标 + if (coordStr.isEmpty()) { + throw new IllegalArgumentException("POINT内无有效坐标数据:" + wktPoint); + } + + // 分割经度和纬度(支持任意数量空格分隔) + String[] lonLat = coordStr.split("\\s+"); + if (lonLat.length != 2) { + throw new IllegalArgumentException("POINT坐标格式无效,需为 经度 纬度 格式:" + coordStr); + } + + // 转换为数字并返回 + try { + double lon = Double.parseDouble(lonLat[0]); + double lat = Double.parseDouble(lonLat[1]); + // 校验经纬度范围 + Assert.isTrue(lon >= -180 && lon <= 180, "经度超出合法范围[-180,180]:" + lon); + Assert.isTrue(lat >= -90 && lat <= 90, "纬度超出合法范围[-90,90]:" + lat); + return new double[]{lon, lat}; + } catch (NumberFormatException e) { + throw new IllegalArgumentException("POINT坐标无法转换为数字:" + coordStr, e); + } + } + + /** + * 计算震中点到行政区划点(POINT类型)的球面距离(单位:千米) + * @param epicenterLon 震中经度 + * @param epicenterLat 震中纬度 + * @param regionWktPoint 行政区划点的POINT格式WKT字符串 + * @return 震中到该行政区划点的距离(千米) + */ + public static double calculateDistanceFromEpicenterToRegionPoint(double epicenterLon, double epicenterLat, String regionWktPoint) { + try { + // 行政区划点经纬度 + double[] regionCoord = parsePointCoordinates(regionWktPoint); + double regionLon = regionCoord[0]; + double regionLat = regionCoord[1]; + + // 球面距离公式计算距离 + return calculateHaversineDistance(epicenterLon, epicenterLat, regionLon, regionLat); + } catch (Exception e) { + log.error("计算震中到行政区划点距离失败,WKT字符串:{},异常信息:{}", regionWktPoint, e.getMessage(), e); + throw new RuntimeException("计算行政区划点距离失败", e); + } + } + +} diff --git a/src/main/java/com/gis/xian/handler/GeoFilesHandler.java b/src/main/java/com/gis/xian/handler/GeoFilesHandler.java new file mode 100644 index 0000000..2bc07ca --- /dev/null +++ b/src/main/java/com/gis/xian/handler/GeoFilesHandler.java @@ -0,0 +1,103 @@ +package com.gis.xian.handler; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gis.xian.constant.BaseConstants; +import com.gis.xian.dto.dzxx.DZXXInfluenceDTO; +import com.gis.xian.dto.pub.IntyGeoJsonDTO; +import lombok.extern.slf4j.Slf4j; +import org.locationtech.jts.geom.CoordinateSequence; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.LinearRing; +import org.locationtech.jts.geom.Polygon; +import org.locationtech.jts.io.WKTReader; +import org.springframework.stereotype.Component; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; + +/** + * @author zzw + * @description: 处理空间数据文件形式 + * @date 2026/5/26 上午10:41 + */ +@Slf4j +@Component +public class GeoFilesHandler { + + private static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory(); + private static final WKTReader WKT_READER = new WKTReader(GEOMETRY_FACTORY); + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + public void writeGeoJsonToFile(IntyGeoJsonDTO featureCollection, String fileName) throws IOException { + // 序列化 + String geoJsonStr = OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(featureCollection); + // geojson文件路径 + String path = BaseConstants.INTENSITY_GEOJSON_PATH + fileName + ".geojson"; + // 创建文件目录 + File file = new File(path); + File parentDir = file.getParentFile(); + if (parentDir != null && !parentDir.exists()) { + boolean mkdirs = parentDir.mkdirs(); + if (!mkdirs) { + throw new IOException("创建GeoJson文件目录失败!" + parentDir.getAbsolutePath()); + } + } + + // 写入文件 + try (BufferedWriter writer = Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8)) { + writer.write(geoJsonStr); + } + } + + // 将JTS转换为GeoJSON坐标 + private List> convertCoordinateSequenceToGeoJson(CoordinateSequence cs) { + List> coordinates = new ArrayList<>(); + for (int i = 0; i < cs.size(); i++) { + double lon = cs.getX(i); // 经度 + double lat = cs.getY(i); // 纬度 + List point = new ArrayList<>(); + point.add(lon); + point.add(lat); + coordinates.add(point); + } + return coordinates; + } + + // 将JTS Polygon转换为GeoJSON Feature对象 + public IntyGeoJsonDTO.GeoJsonFeature convertPolygonToGeoJsonFeature(Polygon polygon, DZXXInfluenceDTO dzxx) { + IntyGeoJsonDTO.GeoJsonFeature feature = new IntyGeoJsonDTO.GeoJsonFeature(); + IntyGeoJsonDTO.GeoJsonFeature.GeoJsonGeometry geometry = new IntyGeoJsonDTO.GeoJsonFeature.GeoJsonGeometry(); + + // 设置几何类型 + geometry.setType("Polygon"); + + // 转换JTS坐标为GeoJSON坐标格式 + List>> coordinates = new ArrayList<>(); + LinearRing exteriorRing = polygon.getExteriorRing(); + List> exteriorCoordinates = convertCoordinateSequenceToGeoJson(exteriorRing.getCoordinateSequence()); + coordinates.add(exteriorCoordinates); + + // 处理内部环 + for (int i = 0; i < polygon.getNumInteriorRing(); i++) { + LinearRing interiorRing = polygon.getInteriorRingN(i); + coordinates.add(convertCoordinateSequenceToGeoJson(interiorRing.getCoordinateSequence())); + } + + geometry.setCoordinates(coordinates); + feature.setGeometry(geometry); + + // 烈度等级 + feature.getProperties().setEqAddr(dzxx.getEqName()); + feature.getProperties().setLatitude(dzxx.getLatitude()); + feature.getProperties().setLongitude(dzxx.getLongitude()); + feature.getProperties().setDescription(""); + feature.getProperties().setIntensity("烈度:" + dzxx.getSInty() + "度"); + return feature; + } + +} diff --git a/src/main/java/com/gis/xian/handler/GeometryTypeHandler.java b/src/main/java/com/gis/xian/handler/GeometryTypeHandler.java new file mode 100644 index 0000000..47d84c3 --- /dev/null +++ b/src/main/java/com/gis/xian/handler/GeometryTypeHandler.java @@ -0,0 +1,138 @@ +package com.gis.xian.handler; + +import net.postgis.jdbc.PGgeometry; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; +import org.apache.ibatis.type.MappedTypes; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.PrecisionModel; +import org.locationtech.jts.io.WKTReader; +import org.locationtech.jts.io.WKTWriter; +import org.postgresql.util.PGobject; +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * 修复编译报错版:PostgreSQL geometry → JTS Geometry 类型处理器 + * 解决 JTS Geometry 与 PostGIS Geometry 类的冲突问题 + */ +@MappedTypes(Geometry.class) // 实体类字段类型(JTS 的 Geometry) +@MappedJdbcTypes(JdbcType.OTHER) // 数据库 geometry 对应 JDBC 类型 OTHER +public class GeometryTypeHandler extends BaseTypeHandler { + + // WKT 解析器(JTS → 数据库,线程安全) + private static final WKTReader WKT_READER = new WKTReader(); + // WKT 生成器(数据库 → JTS,线程安全) + private static final WKTWriter WKT_WRITER = new WKTWriter(); + + private static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory( + new PrecisionModel(PrecisionModel.FLOATING), + 4490 + ); + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, Geometry parameter, JdbcType jdbcType) throws SQLException { + try { + // 将 JTS 的 Geometry 转为标准 WKT 字符串 + String wktText = WKT_WRITER.write(parameter); + // 用 WKT 字符串创建 PGgeometry 对象 + PGgeometry pgGeometry = new PGgeometry(wktText); + // 存入 PreparedStatement + ps.setObject(i, pgGeometry); + } catch (Exception e) { + throw new SQLException("将 JTS Geometry 转为 PGgeometry 失败", e); + } + } + + @Override + public Geometry getNullableResult(ResultSet rs, String columnName) throws SQLException { + return convertToGeometry(rs.getObject(columnName)); + } + + @Override + public Geometry getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + return convertToGeometry(rs.getObject(columnIndex)); + } + + @Override + public Geometry getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { + return convertToGeometry(cs.getObject(columnIndex)); + } + + private Geometry convertToGeometry(Object value) { + // 处理 null 值 + if (value == null) { + return null; + } + + String wktText = null; + try { + // 兼容 PostGIS 的 PGgeometry 格式 + if (value instanceof PGgeometry) { + PGgeometry pgGeometry = (PGgeometry) value; + // 转为标准 WKT 文本 + wktText = pgGeometry.toString(); + } + // 兼容 PostgreSQL 的 PGobject 格式 + else if (value instanceof PGobject) { + PGobject pgObject = (PGobject) value; + String pgValue = pgObject.getValue(); + if (pgValue != null && !pgValue.trim().isEmpty()) { + wktText = new PGgeometry(pgValue).toString(); + } + } + // 兼容纯 WKT 字符串格式 + else if (value instanceof String) { + wktText = (String) value; + } + // 未知格式直接返回 null + else { + return null; + } + + // 通用清洗 WKT 字符串 + String pureWkt = cleanWkt(wktText); + if (pureWkt != null && !pureWkt.trim().isEmpty() && !"NULL".equalsIgnoreCase(pureWkt)) { + Geometry geometry = WKT_READER.read(pureWkt); + // 给几何对象设置 SRID=4490 + geometry.setSRID(4490); + return geometry; + } + return null; + + } catch (Exception e) { + System.err.println("解析 geometry 字段失败,原始 WKT:" + wktText + ",异常:" + e.getMessage()); + return null; + } + } + + /** + * 通用版 WKT 清洗方法:支持 Point、LINESTRING 等常见几何类型 + */ + private String cleanWkt(String wkt) { + if (wkt == null) { + return null; + } + // 步骤1:去除所有不可见字符(换行、回车、制表符) + String cleaned = wkt.replaceAll("[\n\r\t]", ""); + // 步骤2:去除 SRID 前缀(如 "SRID=4326;") + cleaned = cleaned.replaceAll("^SRID=\\d+;", ""); + // 步骤3:将多个连续空格替换为单个空格(避免坐标间多空格干扰) + cleaned = cleaned.replaceAll("\\s+", " "); + // 步骤4:去除几何类型与括号间的多余空格(适配 Point、LINESTRING) + cleaned = cleaned.replaceAll("(POINT|LINESTRING|POLYGON)\\s*\\(", "$1("); + cleaned = cleaned.replaceAll("\\)\\s*$", ")"); + // 步骤5:去除首尾多余空格 + cleaned = cleaned.trim(); + // 步骤6:验证是否为支持的几何类型(可根据需求扩展) + if (!cleaned.startsWith("POINT(") && !cleaned.startsWith("LINESTRING(") && !cleaned.startsWith("POLYGON(")) { + System.err.println("不支持的几何类型,WKT:" + cleaned); + return null; + } + return cleaned; + } +} diff --git a/src/main/java/com/gis/xian/mapper/base/ActiveFaultMapper.java b/src/main/java/com/gis/xian/mapper/base/ActiveFaultMapper.java new file mode 100644 index 0000000..a687da8 --- /dev/null +++ b/src/main/java/com/gis/xian/mapper/base/ActiveFaultMapper.java @@ -0,0 +1,15 @@ +package com.gis.xian.mapper.base; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gis.xian.config.DataSource; +import com.gis.xian.entity.base.ActiveFault; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author zzw + * @description: ShanXiCitiesMapper + * @date 2026/5/25 下午5:21 + */ +@Mapper +public interface ActiveFaultMapper extends BaseMapper { +} diff --git a/src/main/java/com/gis/xian/mapper/base/ShanXiCitiesMapper.java b/src/main/java/com/gis/xian/mapper/base/ShanXiCitiesMapper.java new file mode 100644 index 0000000..745866f --- /dev/null +++ b/src/main/java/com/gis/xian/mapper/base/ShanXiCitiesMapper.java @@ -0,0 +1,15 @@ +package com.gis.xian.mapper.base; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gis.xian.config.DataSource; +import com.gis.xian.entity.base.SXCities; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author zzw + * @description: ShanXiCitiesMapper + * @date 2026/5/25 下午5:21 + */ +@Mapper +public interface ShanXiCitiesMapper extends BaseMapper { +} diff --git a/src/main/java/com/gis/xian/mapper/base/ShanXiCountyMapper.java b/src/main/java/com/gis/xian/mapper/base/ShanXiCountyMapper.java new file mode 100644 index 0000000..ed54ebe --- /dev/null +++ b/src/main/java/com/gis/xian/mapper/base/ShanXiCountyMapper.java @@ -0,0 +1,15 @@ +package com.gis.xian.mapper.base; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gis.xian.config.DataSource; +import com.gis.xian.entity.base.SXCounty; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author zzw + * @description: ShanXiCountyMapper + * @date 2026/5/25 下午5:21 + */ +@Mapper +public interface ShanXiCountyMapper extends BaseMapper { +} diff --git a/src/main/java/com/gis/xian/mapper/base/ShanXiTownsMapper.java b/src/main/java/com/gis/xian/mapper/base/ShanXiTownsMapper.java new file mode 100644 index 0000000..8709104 --- /dev/null +++ b/src/main/java/com/gis/xian/mapper/base/ShanXiTownsMapper.java @@ -0,0 +1,15 @@ +package com.gis.xian.mapper.base; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gis.xian.config.DataSource; +import com.gis.xian.entity.base.SXTowns; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author zzw + * @description: ShanXiCountyMapper + * @date 2026/5/25 下午5:21 + */ +@Mapper +public interface ShanXiTownsMapper extends BaseMapper { +} diff --git a/src/main/java/com/gis/xian/mapper/dzxx/DZXXCenterMapper.java b/src/main/java/com/gis/xian/mapper/dzxx/DZXXCenterMapper.java new file mode 100644 index 0000000..2069dfc --- /dev/null +++ b/src/main/java/com/gis/xian/mapper/dzxx/DZXXCenterMapper.java @@ -0,0 +1,15 @@ +package com.gis.xian.mapper.dzxx; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gis.xian.config.DataSource; +import com.gis.xian.entity.dzxx.DZXXCenter; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author zzw + * @description: 地震事件 + * @date 2026/5/25 下午5:21 + */ +@Mapper +public interface DZXXCenterMapper extends BaseMapper { +} diff --git a/src/main/java/com/gis/xian/mapper/dzxx/DZXXDistanceMapper.java b/src/main/java/com/gis/xian/mapper/dzxx/DZXXDistanceMapper.java new file mode 100644 index 0000000..9275556 --- /dev/null +++ b/src/main/java/com/gis/xian/mapper/dzxx/DZXXDistanceMapper.java @@ -0,0 +1,15 @@ +package com.gis.xian.mapper.dzxx; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gis.xian.config.DataSource; +import com.gis.xian.entity.dzxx.DZXXDistance; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author zzw + * @description: 震中到省市县乡距离表 + * @date 2026/5/25 下午6:20 + */ +@Mapper +public interface DZXXDistanceMapper extends BaseMapper { +} diff --git a/src/main/java/com/gis/xian/mapper/dzxx/DZXXInfluenceMapper.java b/src/main/java/com/gis/xian/mapper/dzxx/DZXXInfluenceMapper.java new file mode 100644 index 0000000..752e7a8 --- /dev/null +++ b/src/main/java/com/gis/xian/mapper/dzxx/DZXXInfluenceMapper.java @@ -0,0 +1,15 @@ +package com.gis.xian.mapper.dzxx; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gis.xian.config.DataSource; +import com.gis.xian.entity.dzxx.DZXXInfluence; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author zzw + * @description: 震中到省市县乡距离表 + * @date 2026/5/25 下午6:20 + */ +@Mapper +public interface DZXXInfluenceMapper extends BaseMapper { +} diff --git a/src/main/java/com/gis/xian/mapper/pub/DZEqEventMapper.java b/src/main/java/com/gis/xian/mapper/pub/DZEqEventMapper.java new file mode 100644 index 0000000..40655fa --- /dev/null +++ b/src/main/java/com/gis/xian/mapper/pub/DZEqEventMapper.java @@ -0,0 +1,15 @@ +package com.gis.xian.mapper.pub; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gis.xian.config.DataSource; +import com.gis.xian.entity.pub.DZEqEvent; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author zzw + * @description: 地震事件表 + * @date 2026/5/25 下午5:01 + */ +@Mapper +public interface DZEqEventMapper extends BaseMapper { +} diff --git a/src/main/java/com/gis/xian/mapper/pub/DZEqQueueMapper.java b/src/main/java/com/gis/xian/mapper/pub/DZEqQueueMapper.java new file mode 100644 index 0000000..7ffe9f5 --- /dev/null +++ b/src/main/java/com/gis/xian/mapper/pub/DZEqQueueMapper.java @@ -0,0 +1,15 @@ +package com.gis.xian.mapper.pub; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gis.xian.config.DataSource; +import com.gis.xian.entity.pub.DZEqQueue; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author zzw + * @description: 地震评估表 + * @date 2026/5/25 下午6:01 + */ +@Mapper +public interface DZEqQueueMapper extends BaseMapper { +} diff --git a/src/main/java/com/gis/xian/mapper/pub/DZInfluenceMapper.java b/src/main/java/com/gis/xian/mapper/pub/DZInfluenceMapper.java new file mode 100644 index 0000000..4d7809d --- /dev/null +++ b/src/main/java/com/gis/xian/mapper/pub/DZInfluenceMapper.java @@ -0,0 +1,15 @@ +package com.gis.xian.mapper.pub; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gis.xian.config.DataSource; +import com.gis.xian.entity.pub.DZInfluence; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author zzw + * @description: DZInfluenceMapper + * @date 2026/5/25 下午6:01 + */ +@Mapper +public interface DZInfluenceMapper extends BaseMapper { +} diff --git a/src/main/java/com/gis/xian/mapper/pub/DZProductMapper.java b/src/main/java/com/gis/xian/mapper/pub/DZProductMapper.java new file mode 100644 index 0000000..d739455 --- /dev/null +++ b/src/main/java/com/gis/xian/mapper/pub/DZProductMapper.java @@ -0,0 +1,15 @@ +package com.gis.xian.mapper.pub; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gis.xian.config.DataSource; +import com.gis.xian.entity.pub.DZProduct; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author zzw + * @description: DZInfluenceMapper + * @date 2026/5/25 下午6:01 + */ +@Mapper +public interface DZProductMapper extends BaseMapper { +} diff --git a/src/main/java/com/gis/xian/params/QgisArgs.java b/src/main/java/com/gis/xian/params/QgisArgs.java new file mode 100644 index 0000000..122c60c --- /dev/null +++ b/src/main/java/com/gis/xian/params/QgisArgs.java @@ -0,0 +1,32 @@ +package com.gis.xian.params; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @author zzw + * @description: Qgis出图参数 + * @date 2026/5/26 上午11:32 + */ +@Data +public class QgisArgs implements Serializable { + + private Integer Id; // 记录进度 + private double centerX; + private double centerY; + private String info; // 三要素 + private String event; + private String mapLayout; // 画幅(A3、A4) + private String mapTime; // 制图时间 + private String mapTitle; // 专题图标题 + private String mapUint; // 制图单位 + private String name; // 专题图文件名称 + private String outFile; // 专题图输出路径 + private String path; // qgis模板路径 + private String queueId; // 批次编码 + private String zoomRule; // 缩放规则 + private String zoomValue; // 缩放值 + private String disaster; // 灾害类型 + +} diff --git a/src/main/java/com/gis/xian/query/EqQuery.java b/src/main/java/com/gis/xian/query/EqQuery.java new file mode 100644 index 0000000..99cf4b1 --- /dev/null +++ b/src/main/java/com/gis/xian/query/EqQuery.java @@ -0,0 +1,20 @@ +package com.gis.xian.query; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author zzw + * @description: 地震请求参数 + * @date 2026/5/25 下午4:48 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class EqQuery { + + private String event; + private String eqQueueId; + +} diff --git a/src/main/java/com/gis/xian/query/IntensityQuery.java b/src/main/java/com/gis/xian/query/IntensityQuery.java new file mode 100644 index 0000000..81479d9 --- /dev/null +++ b/src/main/java/com/gis/xian/query/IntensityQuery.java @@ -0,0 +1,20 @@ +package com.gis.xian.query; + +import lombok.Data; + +/** + * @author zzw + * @description: 烈度参数 + * @date 2026/5/26 上午10:33 + */ +@Data +public class IntensityQuery { + + private double centerLon; // 中心点经度 + private double centerLat; // 中心点纬度 + private double semiMajor; // 长半轴(米) + private double semiMinor; // 短半轴(米) + private double rotation; // 旋转角度(度,顺时针为正,以北为0度) + private int numVertices; // 生成的顶点数,越多越接近椭圆 + +} diff --git a/src/main/java/com/gis/xian/query/ProductQuery.java b/src/main/java/com/gis/xian/query/ProductQuery.java new file mode 100644 index 0000000..1fcf9f1 --- /dev/null +++ b/src/main/java/com/gis/xian/query/ProductQuery.java @@ -0,0 +1,22 @@ +package com.gis.xian.query; + +import lombok.Data; + +/** + * @author zzw + * @description: 产品查询参数 + * @date 2026/5/26 上午11:00 + */ +@Data +public class ProductQuery { + + private String queueId; // 产品Id,必填项 + + private String code; // A3 A4 专题图尺寸,选填项 + + private String fileType; // 图片 文档 产品类型(图片/文档),选填 + + private String fileName; // 产品名称(模糊查询),选填 + + private String proType; // 暴雨/地震 灾害专题图 暴雨/地震 灾害文档 +} diff --git a/src/main/java/com/gis/xian/service/base/IActiveFaultService.java b/src/main/java/com/gis/xian/service/base/IActiveFaultService.java new file mode 100644 index 0000000..3dee44f --- /dev/null +++ b/src/main/java/com/gis/xian/service/base/IActiveFaultService.java @@ -0,0 +1,19 @@ +package com.gis.xian.service.base; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gis.xian.config.DataSource; +import com.gis.xian.dto.base.ActiveFaultDTO; +import com.gis.xian.entity.base.ActiveFault; + +/** + * @author zzw + * @description: 活动断层服务 + * @date 2026/5/26 上午8:31 + */ +@DataSource("slave1") +public interface IActiveFaultService extends IService { + + // 查找距离震中最近的一条断层数据 + public ActiveFaultDTO getShortlyFault(double lon, double lat); + +} diff --git a/src/main/java/com/gis/xian/service/base/IShanXiCitiesService.java b/src/main/java/com/gis/xian/service/base/IShanXiCitiesService.java new file mode 100644 index 0000000..0b866fb --- /dev/null +++ b/src/main/java/com/gis/xian/service/base/IShanXiCitiesService.java @@ -0,0 +1,21 @@ +package com.gis.xian.service.base; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gis.xian.config.DataSource; +import com.gis.xian.dto.base.ShanXiCitiesDTO; +import com.gis.xian.entity.base.SXCities; + +import java.util.List; + +/** + * @author zzw + * @description: 陕西省市区 + * @date 2026/5/26 上午8:31 + */ +@DataSource("slave1") +public interface IShanXiCitiesService extends IService { + + // 查询距离震中最近的市州 + public List getMostIntensityAreaCities(double lon, double lat); + +} diff --git a/src/main/java/com/gis/xian/service/base/IShanXiCountyService.java b/src/main/java/com/gis/xian/service/base/IShanXiCountyService.java new file mode 100644 index 0000000..54d8f1c --- /dev/null +++ b/src/main/java/com/gis/xian/service/base/IShanXiCountyService.java @@ -0,0 +1,26 @@ +package com.gis.xian.service.base; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gis.xian.config.DataSource; +import com.gis.xian.dto.base.ShanXiCountyDTO; +import com.gis.xian.entity.base.SXCounty; + +import java.util.List; + +/** + * @author zzw + * @description: 陕西省区县 + * @date 2026/5/26 上午9:46 + */ +@DataSource("slave1") +public interface IShanXiCountyService extends IService { + + /** + * 根据距离来查询附近公里的承载体数量 + * + * @param dis 距离(km) + * @return 返回极震区县区 + */ + public List getMostIntensityAreaCounty(double dis, double lon, double lat); + +} diff --git a/src/main/java/com/gis/xian/service/base/IShanXiTownsService.java b/src/main/java/com/gis/xian/service/base/IShanXiTownsService.java new file mode 100644 index 0000000..e6a4208 --- /dev/null +++ b/src/main/java/com/gis/xian/service/base/IShanXiTownsService.java @@ -0,0 +1,25 @@ +package com.gis.xian.service.base; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gis.xian.config.DataSource; +import com.gis.xian.dto.base.ShanXiTownsDTO; +import com.gis.xian.entity.base.SXTowns; + +import java.util.List; + +/** + * @author zzw + * @description: 陕西省乡镇 + * @date 2026/5/26 上午9:56 + */ +@DataSource("slave1") +public interface IShanXiTownsService extends IService { + + /** + * 根据来查询附近公里的承载体数量 + * @param dis 距离(km) + * @return 返回极震区乡镇 + */ + public List getMostIntensityAreaTowns(double dis, double lon, double lat); + +} diff --git a/src/main/java/com/gis/xian/service/base/impl/ActiveFaultServiceImpl.java b/src/main/java/com/gis/xian/service/base/impl/ActiveFaultServiceImpl.java new file mode 100644 index 0000000..705536d --- /dev/null +++ b/src/main/java/com/gis/xian/service/base/impl/ActiveFaultServiceImpl.java @@ -0,0 +1,145 @@ +package com.gis.xian.service.base.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gis.xian.config.DataSource; +import com.gis.xian.constant.BaseConstants; +import com.gis.xian.dto.base.ActiveFaultDTO; +import com.gis.xian.entity.base.ActiveFault; +import com.gis.xian.handler.GeoDistanceHandler; +import com.gis.xian.mapper.base.ActiveFaultMapper; +import com.gis.xian.service.base.IActiveFaultService; +import com.gis.xian.service.ex.ParmaException; +import com.gis.xian.utils.StringUtils; +import lombok.extern.slf4j.Slf4j; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.io.WKTWriter; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author zzw + * @description: 活断层业务层 + * @date 2026/5/26 上午10:21 + */ +@Slf4j +@Service +@DataSource("slave1") +public class ActiveFaultServiceImpl extends ServiceImpl implements IActiveFaultService { + private static final WKTWriter WKT_WRITER = new WKTWriter(); + + /** + * 根据震中点获取距离最近的断层数据 + * + * @param lon 震中经度 + * @param lat 震中纬度 + * @return 返回距离震中点最近的断层数据 + */ + @Override + public ActiveFaultDTO getShortlyFault(double lon, double lat) { + if (lon < -180 || lon > 180 || lat < -90 || lat > 90) { + throw new ParmaException(BaseConstants.PARAMS_ERROR); + } + // 获取所有断层数据 + List faults = this.baseMapper.selectList(null); + if (faults == null || faults.isEmpty()) { + throw new ParmaException(BaseConstants.RESULT_ERROR); + } + // 查找最近的一条 + ActiveFaultDTO fault = handle(faults, lon, lat); + + if (fault == null) { + throw new ParmaException(BaseConstants.RESULT_ERROR); + } + // 避难断层走向为空 + if (fault.getStrike() == null) { + fault.setStrike(0); + } + + // 返回 + return fault; + } + + /** + * 处理断层数据 + * + * @param lon 震中经度 + * @param lat 震中纬度 + * @return 返回实DTO断层实体 + */ + private ActiveFaultDTO handle(List faults, double lon, double lat) { + + // 记录最近断层、最小距离 + ActiveFault nearest = null; + // 所有断层中的最小距离 + double minTotalDistance = Double.MAX_VALUE; + // 计算距离并筛选最近 + for (ActiveFault fault : faults) { + try { + // 获取Geometry对象,并转换为标准WKT字符串 + Geometry geometry = fault.getGeometry(); + if (geometry == null) { + log.warn("断层名称:{} 无有效Geometry对象,跳过", fault.getName()); + continue; + } + + // 使用WKTWriter将Geometry对象转换为标准WKT字符串 + String lineStringWkt = WKT_WRITER.write(geometry); + + if (StringUtils.isBlank(lineStringWkt)) { + log.warn("断层名称:{} 转换后无有效WKT数据,跳过", fault.getName()); + continue; + } + + // 解析LINESTRING为端点坐标数组 + double[][] coordinates = GeoDistanceHandler.parseLineStringCoordinates(lineStringWkt); + if (coordinates.length < 2) { + log.warn("断层名称:{} 的LINESTRING无有效线段(端点数量<2),跳过", fault.getName()); + continue; + } + + // 计算该断层所有子线段的最短距离 + double minFaultDistance = Double.MAX_VALUE; // 单个断层内的最小子线段距离 + for (int i = 0; i < coordinates.length - 1; i++) { + // 提取子线段的两个端点(A和B) + double lonA = coordinates[i][0]; + double latA = coordinates[i][1]; + double lonB = coordinates[i + 1][0]; + double latB = coordinates[i + 1][1]; + + // 计算震中到该子线段的最短距离 + double segmentDistance = GeoDistanceHandler.calculateDistanceFromPointToLineString( + lon, lat, lonA, latA, lonB, latB + ); + + // 更新单个断层内的最小距离 + if (segmentDistance < minFaultDistance) { + minFaultDistance = segmentDistance; + } + } + + // 更新所有断层中的最近断层 + if (minFaultDistance < minTotalDistance) { + minTotalDistance = minFaultDistance; + nearest = fault; + } + } catch (Exception e) { + log.warn("处理断层名称:{} 失败,异常信息:{}", fault.getName(), e.getMessage(), e); + continue; + } + } + + // 转换 + ActiveFaultDTO activeFaultDTO = new ActiveFaultDTO(); + activeFaultDTO.setName(nearest.getName()); + activeFaultDTO.setDirection(nearest.getDirection()); + activeFaultDTO.setClination(nearest.getClination()); + activeFaultDTO.setShapeLen(nearest.getShape_Leng()); + activeFaultDTO.setGeometry(nearest.getGeometry()); + activeFaultDTO.setDistance(minTotalDistance); + + return activeFaultDTO; + } + + +} diff --git a/src/main/java/com/gis/xian/service/base/impl/ShanXiCitiesServiceImpl.java b/src/main/java/com/gis/xian/service/base/impl/ShanXiCitiesServiceImpl.java new file mode 100644 index 0000000..64b6ef1 --- /dev/null +++ b/src/main/java/com/gis/xian/service/base/impl/ShanXiCitiesServiceImpl.java @@ -0,0 +1,136 @@ +package com.gis.xian.service.base.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gis.xian.config.DataSource; +import com.gis.xian.constant.BaseConstants; +import com.gis.xian.dto.base.ShanXiCitiesDTO; +import com.gis.xian.entity.base.SXCities; +import com.gis.xian.handler.GeoDistanceHandler; +import com.gis.xian.mapper.base.ShanXiCitiesMapper; +import com.gis.xian.service.base.IShanXiCitiesService; +import com.gis.xian.service.ex.ParmaException; +import com.gis.xian.utils.StringUtils; +import lombok.extern.slf4j.Slf4j; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.io.WKTWriter; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; + +/** + * @author zzw + * @description: ShanXiCitiesServiceImpl + * @date 2026/5/26 上午8:38 + */ +@Slf4j +@Service +@DataSource("slave1") +public class ShanXiCitiesServiceImpl extends ServiceImpl implements IShanXiCitiesService { + + + private static final WKTWriter WKT_WRITER = new WKTWriter(); + + // 查询距离震中最近的市州 + @Override + public List getMostIntensityAreaCities(double lon, double lat) { + // 边界判断 + if (lon < -180 || lon > 180 || lat < -90 || lat > 90) { + throw new ParmaException(BaseConstants.PARAMS_ERROR); + } + // 获取所有市州 + List cities = this.baseMapper.selectList(null); + if (cities == null || cities.isEmpty()) { + throw new ParmaException(BaseConstants.RESULT_ERROR); + } + + // 获取附近震中 最近的市州(本地和外地) + List citiesDto = handle(cities, lon, lat); + if (citiesDto == null) { + throw new ParmaException(BaseConstants.RESULT_ERROR); + } + // 城市数据 + return citiesDto; + } + + /** + * 处理最近距离震中最近 + * + * @param cities + * @param lon + * @param lat + */ + private List handle(List cities, double lon, double lat) { + // 记录距离最近的市州 + List citiesdots = new ArrayList<>(); + // 记录最近市州、最小距离 + SXCities nearest = null; + // 所有市州中的最小距离 + double minTotalDistance = Double.MAX_VALUE; + // 保留两位小数 + DecimalFormat df = new DecimalFormat("#.00"); + df.setRoundingMode(java.math.RoundingMode.HALF_UP); + + // 计算距离并筛选最近 + for (SXCities city : cities) { + try { + // 获取Geometry对象,并转换为标准WKT字符串 + Geometry geometry = city.getGeometry(); + if (geometry == null) { + log.warn("市州名称:{} 无有效Geometry对象,无法解析该空间类型", city.getNAME()); + continue; + } + // 使用WKTWriter将Geometry对象转换为标准WKT字符串 + String pointStringWkt = WKT_WRITER.write(geometry); + if (StringUtils.isBlank(pointStringWkt)) { + log.warn("市州名称:{} 转换后无有效WKT数据,无法解析该空间类型", city.getNAME()); + continue; + } + // 计算震中到当前点的距离 + double distance = GeoDistanceHandler.calculateDistanceFromEpicenterToRegionPoint(lon, lat, pointStringWkt); + // 计算该断层所有市州段的最短距离 + double minCityDistance = Double.MAX_VALUE; + if (distance < minCityDistance) { + minCityDistance = distance; + } + + // 更新市州距离 + if (minCityDistance < minTotalDistance) { + minTotalDistance = minCityDistance; + nearest = city; + } + + } catch (Exception e) { + log.warn("处理市州名称:{} 失败,异常信息:{}", city.getNAME(), e.getMessage(), e); + continue; + } + } + log.info("震中距{}市中{}km!", nearest.getNAME(), minTotalDistance); + ShanXiCitiesDTO citiesdto = new ShanXiCitiesDTO(); + // 是否西安,不是的话需要返回临市和本市 + if (!nearest.getNAME().equals("西安市")) { + + // 计算震中到西安的距离 + double distance = GeoDistanceHandler.calculateDistanceFromEpicenterToRegionPoint(lon, lat, "POINT (108.935124 34.343595)"); + // citiesdto.setGeometry(); + citiesdto.setDistance(Double.parseDouble(df.format(distance))); + citiesdto.setX(108.935124); + citiesdto.setY(34.343595); + citiesdto.setNAME("西安市"); + + citiesdots.add(citiesdto); + return citiesdots; + } + // 西安属地 + BeanUtils.copyProperties(nearest,citiesdto); + // 保留两位小数 + citiesdto.setDistance(Double.parseDouble(df.format(minTotalDistance))); + + citiesdots.add(citiesdto); + // 距离最近的市州 + return citiesdots; + } + +} diff --git a/src/main/java/com/gis/xian/service/base/impl/ShanXiCountyServiceImpl.java b/src/main/java/com/gis/xian/service/base/impl/ShanXiCountyServiceImpl.java new file mode 100644 index 0000000..5d82f9a --- /dev/null +++ b/src/main/java/com/gis/xian/service/base/impl/ShanXiCountyServiceImpl.java @@ -0,0 +1,109 @@ +package com.gis.xian.service.base.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gis.xian.config.DataSource; +import com.gis.xian.constant.BaseConstants; +import com.gis.xian.dto.base.ShanXiCountyDTO; +import com.gis.xian.entity.base.SXCounty; +import com.gis.xian.handler.GeoDistanceHandler; +import com.gis.xian.mapper.base.ShanXiCountyMapper; +import com.gis.xian.service.base.IShanXiCountyService; +import com.gis.xian.service.ex.ParmaException; +import com.gis.xian.utils.StringUtils; +import lombok.extern.slf4j.Slf4j; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.io.WKTWriter; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author zzw + * @description: ShanXiCountyServiceImpl + * @date 2026/5/26 上午9:49 + */ +@Slf4j +@Service +@DataSource("slave1") +public class ShanXiCountyServiceImpl extends ServiceImpl implements IShanXiCountyService { + + private static final WKTWriter WKT_WRITER = new WKTWriter(); + + // 查询距离震中最近的市州 + @Override + public List getMostIntensityAreaCounty(double dis, double lon, double lat) { + // 边界判断 + if (lon < -180 || lon > 180 || lat < -90 || lat > 90) { + throw new ParmaException(BaseConstants.PARAMS_ERROR); + } + // 距离值判断 + if (dis < 0) { + throw new ParmaException(BaseConstants.PARAMS_ERROR); + } + + // 获取所有区县 + List counties = this.baseMapper.selectList(null); + if (counties == null || counties.isEmpty()) { + throw new ParmaException(BaseConstants.RESULT_ERROR); + } + + // 获取附近震中 区县 + List countiesDto = handle(counties, lon, lat, dis); + if (countiesDto == null) { + throw new ParmaException(BaseConstants.RESULT_ERROR); + } + // 区县数据 + return countiesDto; + } + + /** + * 筛选指定距离下的所有区县 + * @param counties + * @param lon + * @param lat + */ + private List handle(List counties, double lon, double lat, double dis) { + // 区县距离表 + List countiesdots = new ArrayList<>(); + + // 计算距离并筛选最近 + for (SXCounty county : counties) { + try { + // 获取Geometry对象,并转换为标准WKT字符串 + Geometry geometry = county.getGeometry(); + if (geometry == null) { + log.warn("市州名称:{} 无有效Geometry对象,无法解析该空间类型", county.getNAME()); + continue; + } + // 使用WKTWriter将Geometry对象转换为标准WKT字符串 + String pointStringWkt = WKT_WRITER.write(geometry); + if (StringUtils.isBlank(pointStringWkt)) { + log.warn("市州名称:{} 转换后无有效WKT数据,无法解析该空间类型", county.getNAME()); + continue; + } + // 计算震中到当前点的距离 + double distance = GeoDistanceHandler.calculateDistanceFromEpicenterToRegionPoint(lon, lat, pointStringWkt); + + // 判断是否在指定范围内 + if (distance < dis) { + ShanXiCountyDTO countydto = new ShanXiCountyDTO(); + BeanUtils.copyProperties(county, countydto); + countydto.setDistance(distance); + // 指定范围内的所有县区 + countiesdots.add(countydto); + } + + } catch (Exception e) { + log.warn("处理区县名称:{} 失败,异常信息:{}", county.getNAME(), e.getMessage(), e); + continue; + } + } + log.info("震中{}km范围内共有{}个县区!", dis, countiesdots.size()); + + // 距离最近的市州 + return countiesdots; + } + +} diff --git a/src/main/java/com/gis/xian/service/base/impl/ShanXiTownsServiceImpl.java b/src/main/java/com/gis/xian/service/base/impl/ShanXiTownsServiceImpl.java new file mode 100644 index 0000000..807f58e --- /dev/null +++ b/src/main/java/com/gis/xian/service/base/impl/ShanXiTownsServiceImpl.java @@ -0,0 +1,109 @@ +package com.gis.xian.service.base.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gis.xian.config.DataSource; +import com.gis.xian.constant.BaseConstants; +import com.gis.xian.dto.base.ShanXiTownsDTO; +import com.gis.xian.entity.base.SXTowns; +import com.gis.xian.handler.GeoDistanceHandler; +import com.gis.xian.mapper.base.ShanXiTownsMapper; +import com.gis.xian.service.base.IShanXiTownsService; +import com.gis.xian.service.ex.ParmaException; +import com.gis.xian.utils.StringUtils; +import lombok.extern.slf4j.Slf4j; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.io.WKTWriter; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author zzw + * @description: ShanXiTownsServiceImpl + * @date 2026/5/26 上午9:59 + */ +@Slf4j +@Service +@DataSource("slave1") +public class ShanXiTownsServiceImpl extends ServiceImpl implements IShanXiTownsService { + + private static final WKTWriter WKT_WRITER = new WKTWriter(); + + // 查询距离震中最近的市州 + @Override + public List getMostIntensityAreaTowns(double dis, double lon, double lat) { + // 边界判断 + if (lon < -180 || lon > 180 || lat < -90 || lat > 90) { + throw new ParmaException(BaseConstants.PARAMS_ERROR); + } + // 距离值判断 + if (dis < 0) { + throw new ParmaException(BaseConstants.PARAMS_ERROR); + } + + // 获取所有乡镇 + List towns = this.baseMapper.selectList(null); + if (towns == null || towns.isEmpty()) { + throw new ParmaException(BaseConstants.RESULT_ERROR); + } + + // 获取附近震中 乡镇 + List townsDto = handle(towns, lon, lat, dis); + if (townsDto == null) { + throw new ParmaException(BaseConstants.RESULT_ERROR); + } + // 乡镇数据 + return townsDto; + } + + /** + * 筛选指定距离下的所有乡镇 + * @param towns + * @param lon + * @param lat + */ + private List handle(List towns, double lon, double lat, double dis) { + // 乡镇距离表 + List townsdots = new ArrayList<>(); + + // 计算距离并筛选最近 + for (SXTowns town : towns) { + try { + // 获取Geometry对象,并转换为标准WKT字符串 + Geometry geometry = town.getGeometry(); + if (geometry == null) { + log.warn("乡镇名称:{} 无有效Geometry对象,无法解析该空间类型", town.getNAME()); + continue; + } + // 使用WKTWriter将Geometry对象转换为标准WKT字符串 + String pointStringWkt = WKT_WRITER.write(geometry); + if (StringUtils.isBlank(pointStringWkt)) { + log.warn("乡镇名称:{} 转换后无有效WKT数据,无法解析该空间类型", town.getNAME()); + continue; + } + // 计算震中到当前点的距离 + double distance = GeoDistanceHandler.calculateDistanceFromEpicenterToRegionPoint(lon, lat, pointStringWkt); + + // 判断是否在指定范围内 + if (distance < dis) { + ShanXiTownsDTO towndto = new ShanXiTownsDTO(); + BeanUtils.copyProperties(town, towndto); + towndto.setDistance(distance); + // 指定范围内的所有乡镇 + townsdots.add(towndto); + } + + } catch (Exception e) { + log.warn("处理乡镇名称:{} 失败,异常信息:{}", town.getNAME(), e.getMessage(), e); + continue; + } + } + log.info("震中{}km范围内共有{}个乡镇!", dis, townsdots.size()); + + // 距离最近的市州 + return townsdots; + } + +} diff --git a/src/main/java/com/gis/xian/service/dzxx/IDZXXCenterService.java b/src/main/java/com/gis/xian/service/dzxx/IDZXXCenterService.java new file mode 100644 index 0000000..a545552 --- /dev/null +++ b/src/main/java/com/gis/xian/service/dzxx/IDZXXCenterService.java @@ -0,0 +1,19 @@ +package com.gis.xian.service.dzxx; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gis.xian.config.DataSource; +import com.gis.xian.dto.dzxx.DZXXCenterDTO; +import com.gis.xian.entity.dzxx.DZXXCenter; + +/** + * @author zzw + * @description: 地震信息 + * @date 2026/5/25 下午5:01 + */ +@DataSource("slave1") +public interface IDZXXCenterService extends IService { + + // 地震触发 + public void handle(DZXXCenterDTO trigger); + +} diff --git a/src/main/java/com/gis/xian/service/dzxx/IDZXXDistanceService.java b/src/main/java/com/gis/xian/service/dzxx/IDZXXDistanceService.java new file mode 100644 index 0000000..5b1a015 --- /dev/null +++ b/src/main/java/com/gis/xian/service/dzxx/IDZXXDistanceService.java @@ -0,0 +1,19 @@ +package com.gis.xian.service.dzxx; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gis.xian.config.DataSource; +import com.gis.xian.entity.dzxx.DZXXDistance; + +/** + * @ClassName IDZXXDistanceService + * @Description 震中到省市县乡距离 + * @Author zzw + * @Date 2026/5/25 12:06 + */ +@DataSource("slave1") +public interface IDZXXDistanceService extends IService { + + // 处理震中到省市区镇 + public void handle(double lon, double lat, String eqQueueId); + +} diff --git a/src/main/java/com/gis/xian/service/dzxx/IDZXXInfluenceService.java b/src/main/java/com/gis/xian/service/dzxx/IDZXXInfluenceService.java new file mode 100644 index 0000000..fd80ac6 --- /dev/null +++ b/src/main/java/com/gis/xian/service/dzxx/IDZXXInfluenceService.java @@ -0,0 +1,29 @@ +package com.gis.xian.service.dzxx; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gis.xian.config.DataSource; +import com.gis.xian.dto.dzxx.DZXXInfluenceDTO; +import com.gis.xian.dto.pub.EqAssessmentDTO; +import com.gis.xian.entity.dzxx.DZXXInfluence; +import com.gis.xian.query.EqQuery; + +import java.util.List; + +/** + * @author zzw + * @description: 地震影响场接口 + * @date 2026/5/25 下午6:09 + */ +@DataSource("slave1") +public interface IDZXXInfluenceService extends IService { + + // 处理地震影响场数据 + public void handle(EqAssessmentDTO trigger); + + // 根据地震编码查询影响场范围 + public List findInfluenceById(EqQuery query); + + // 获取最大烈度影响场 + public DZXXInfluenceDTO findInfluenceMaxIntyById(EqQuery query); + +} diff --git a/src/main/java/com/gis/xian/service/dzxx/impl/DZXXCenterServiceImpl.java b/src/main/java/com/gis/xian/service/dzxx/impl/DZXXCenterServiceImpl.java new file mode 100644 index 0000000..e486f5c --- /dev/null +++ b/src/main/java/com/gis/xian/service/dzxx/impl/DZXXCenterServiceImpl.java @@ -0,0 +1,56 @@ +package com.gis.xian.service.dzxx.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gis.xian.config.DataSource; +import com.gis.xian.constant.BaseConstants; +import com.gis.xian.dto.dzxx.DZXXCenterDTO; +import com.gis.xian.entity.dzxx.DZXXCenter; +import com.gis.xian.mapper.dzxx.DZXXCenterMapper; +import com.gis.xian.service.dzxx.IDZXXCenterService; +import com.gis.xian.service.ex.ParmaException; +import com.gis.xian.service.ex.ServiceException; +import lombok.extern.slf4j.Slf4j; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.Point; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +/** + * @author zzw + * @description: 地震事件 + * @date 2026/5/25 下午5:21 + */ +@Slf4j +@Service +@DataSource("slave1") +public class DZXXCenterServiceImpl extends ServiceImpl implements IDZXXCenterService { + + // 地震触发 + @Override + public void handle(DZXXCenterDTO dzxxdto) { + // 抛出异常 + if (dzxxdto == null) { + throw new ParmaException(BaseConstants.PARAMS_ERROR); + } + + try { + DZXXCenter dzxx = new DZXXCenter(); + BeanUtils.copyProperties(dzxxdto, dzxx); + // 处理空间数据 + GeometryFactory geometryFactory = new GeometryFactory(); + Point point = geometryFactory.createPoint(new Coordinate( + dzxxdto.getLongitude(), dzxxdto.getLatitude() + )); + dzxx.setGeom(point); + dzxx.getGeom().setSRID(4490); + // 存库 + save(dzxx); + log.info("震中位置信息已存库..."); + } catch (Exception ex) { + log.error("地震触发:震中位置信息保存失败!", ex.getMessage()); + ex.printStackTrace(); + throw new ServiceException(BaseConstants.EQ_SERVER_ERROR); + } + } +} diff --git a/src/main/java/com/gis/xian/service/dzxx/impl/DZXXDistanceServiceImpl.java b/src/main/java/com/gis/xian/service/dzxx/impl/DZXXDistanceServiceImpl.java new file mode 100644 index 0000000..6d9da21 --- /dev/null +++ b/src/main/java/com/gis/xian/service/dzxx/impl/DZXXDistanceServiceImpl.java @@ -0,0 +1,157 @@ +package com.gis.xian.service.dzxx.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gis.xian.config.DataSource; +import com.gis.xian.constant.BaseConstants; +import com.gis.xian.dto.base.ShanXiCitiesDTO; +import com.gis.xian.dto.base.ShanXiCountyDTO; +import com.gis.xian.dto.base.ShanXiTownsDTO; +import com.gis.xian.dto.dzxx.DZXXDistanceDTO; +import com.gis.xian.entity.dzxx.DZXXDistance; +import com.gis.xian.mapper.dzxx.DZXXDistanceMapper; +import com.gis.xian.service.base.IShanXiCitiesService; +import com.gis.xian.service.base.IShanXiCountyService; +import com.gis.xian.service.base.IShanXiTownsService; +import com.gis.xian.service.dzxx.IDZXXDistanceService; +import com.gis.xian.service.ex.ParmaException; +import lombok.extern.slf4j.Slf4j; +import org.locationtech.jts.geom.*; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author zzw + * @description: 震中到省市县乡距离 + * @date 2026/5/25 下午6:20 + */ +@Slf4j +@Service +@DataSource("slave1") +public class DZXXDistanceServiceImpl extends ServiceImpl implements IDZXXDistanceService { + private static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING), 4326); + + @Autowired + private IShanXiCitiesService iShanXiCitiesService; + @Autowired + private IShanXiCountyService iShanXiCountyService; + @Autowired + private IShanXiTownsService iShanXiTownsService; + + // 处理所有乡镇表 + @Override + public void handle(double lon, double lat, String eqQueueId) { + + // 查询距震中最近市州 + List cities = iShanXiCitiesService.getMostIntensityAreaCities(lon, lat); + // 查询距震中50km县区 + List counties50km = iShanXiCountyService.getMostIntensityAreaCounty(50, lon, lat); + // 查询距震中20km乡镇 + List towns20km = iShanXiTownsService.getMostIntensityAreaTowns(20, lon, lat); + // 所有行政区划数 + List combined = combine(cities, counties50km, towns20km, eqQueueId, lon, lat); + // 存库 + asyncSave(combined); + } + + // 将行政区划组合 + private List combine(List cities, + List counties20km, + List towns10km, + String eqQueueId, double lon, double lat) { + // 震中到行政区划距离 + List distancedtos = new ArrayList<>(); + + // 处理市州 + for (ShanXiCitiesDTO city : cities) { + DZXXDistanceDTO dzxx = new DZXXDistanceDTO(); + // 处理震中到市州的线段 + dzxx.setGeom(p2pLines(lon, lat, city.getX(), city.getY())); + + dzxx.setEqQueueId(eqQueueId); + dzxx.setDistanceId(1); + dzxx.setPId(""); + dzxx.setPname(city.getNAME()); + dzxx.setBgmc("市州"); + dzxx.setDistance(city.getDistance()); + + distancedtos.add(dzxx); + } + + // 处理县区 + for (ShanXiCountyDTO county : counties20km) { + DZXXDistanceDTO dzxx = new DZXXDistanceDTO(); + // 处理震中到县区的线段 + dzxx.setGeom(p2pLines(lon, lat, county.getX(), county.getY())); + + dzxx.setEqQueueId(eqQueueId); + dzxx.setDistanceId(2); + dzxx.setPId(""); + dzxx.setPname(county.getNAME()); + dzxx.setBgmc("县区"); + dzxx.setDistance(county.getDistance()); + + distancedtos.add(dzxx); + } + + // 处理乡镇 + for (ShanXiTownsDTO town : towns10km) { + DZXXDistanceDTO dzxx = new DZXXDistanceDTO(); + // 处理震中到乡镇的线段 + dzxx.setGeom(p2pLines(lon, lat, town.getX(), town.getY())); + + dzxx.setEqQueueId(eqQueueId); + dzxx.setDistanceId(3); + dzxx.setPId(""); + dzxx.setPname(town.getNAME()); + dzxx.setBgmc("乡镇"); + dzxx.setDistance(town.getDistance()); + + distancedtos.add(dzxx); + } + + // 各级别行政区划距离 + return distancedtos; + } + + // 将震中点与区划点进行组合 形成一条牵引线 + private Geometry p2pLines(double x1, double y1, double x2, double y2) { + // 边界值判断 + if (x1 < -180 || x1 > 180 || x2 < -180 || x2 > 180) { + throw new ParmaException(BaseConstants.POM_ERROR); + } + + if (y1 < -90 || y1 > 90 || y2 < -90 || y2 > 90) { + throw new ParmaException(BaseConstants.POM_ERROR); + } + + // 创建坐标点 + Coordinate startPoint = new Coordinate(x1, y1); + Coordinate endPoint = new Coordinate(x2, y2); + Coordinate[] coordinates = new Coordinate[]{startPoint, endPoint}; + // 牵引线 + LineString lineString = GEOMETRY_FACTORY.createLineString(coordinates); + + return lineString; + } + + @Async("xianPool") + protected void asyncSave(List data) { + // 批量存储 + List dzxxs = new ArrayList<>(); + //处理数据 + for (DZXXDistanceDTO datum : data) { + DZXXDistance dzxx = new DZXXDistance(); + BeanUtils.copyProperties(datum, dzxx); + dzxx.getGeom().setSRID(4490); + dzxxs.add(dzxx); + } + // 批量保存 + saveBatch(dzxxs); + log.info("震中到行政区划距离表已计算保存!"); + } +} diff --git a/src/main/java/com/gis/xian/service/dzxx/impl/DZXXInfluenceServiceImpl.java b/src/main/java/com/gis/xian/service/dzxx/impl/DZXXInfluenceServiceImpl.java new file mode 100644 index 0000000..a609a62 --- /dev/null +++ b/src/main/java/com/gis/xian/service/dzxx/impl/DZXXInfluenceServiceImpl.java @@ -0,0 +1,206 @@ +package com.gis.xian.service.dzxx.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gis.xian.config.DataSource; +import com.gis.xian.constant.BaseConstants; +import com.gis.xian.dto.base.ActiveFaultDTO; +import com.gis.xian.dto.dzxx.DZXXInfluenceDTO; +import com.gis.xian.dto.pub.EqAssessmentDTO; +import com.gis.xian.entity.dzxx.DZXXInfluence; +import com.gis.xian.handler.EarthquakeHandler; +import com.gis.xian.handler.EllipseToWktHandler; +import com.gis.xian.mapper.dzxx.DZXXInfluenceMapper; +import com.gis.xian.query.EqQuery; +import com.gis.xian.query.IntensityQuery; +import com.gis.xian.service.base.IActiveFaultService; +import com.gis.xian.service.dzxx.IDZXXInfluenceService; +import com.gis.xian.service.ex.ParmaException; +import com.gis.xian.service.ex.ServiceException; +import com.gis.xian.service.pub.IDZInfluenceService; +import lombok.extern.slf4j.Slf4j; +import org.locationtech.jts.geom.Polygon; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author zzw + * @description: 地震影响场业务 + * @date 2026/5/26 上午10:13 + */ +@Slf4j +@Service +@DataSource("slave1") +public class DZXXInfluenceServiceImpl extends ServiceImpl implements IDZXXInfluenceService { + + + @Autowired + private IActiveFaultService faultService; + @Autowired + private EllipseToWktHandler ellipseToWktHandler; + @Autowired + private IDZInfluenceService idzInfluenceService; + + // 处理地震影响场数据 + @Override + public void handle(EqAssessmentDTO assess) { + // 异常处理 + if (assess == null) { + throw new ParmaException(BaseConstants.PARAMS_ERROR); + } + // 处理地震影响场数据 + try { + // 获取烈度值 + int[] intensities = gainIntensityLevels(assess.getEqMagnitude()); + // 根据烈度值和震级生成影响场 + for (int intensity : intensities) { + // 根据烈度和震级计算长轴 + double longUranium = EarthquakeHandler.calculateRa(assess.getEqMagnitude(), intensity); + // 根据烈度和震级计算短轴 + double shortUranium = EarthquakeHandler.calculateRb(assess.getEqMagnitude(), intensity); + // 根据长短轴计算面积 + double area = EarthquakeHandler.calculateArea(longUranium, shortUranium); + + // 获取断层走向 角度 + ActiveFaultDTO shortlyFault = faultService.getShortlyFault(assess.getLongitude(), assess.getLatitude()); + // 根据烈度长短轴、走向、面积计算生成影响场 + IntensityQuery query = compute(longUranium, shortUranium, shortlyFault, assess); + // 影响场范围 + Polygon polygon = ellipseToWktHandler.ellipseToPolygonWkt(query); + + // 转换存库 + convert(longUranium, shortUranium, area, intensity, polygon, shortlyFault, assess); + log.info("地震影响场已生成!"); + } + + } catch (Exception ex) { + log.error("处理影响场数据时出错:" + ex.getMessage()); + ex.printStackTrace(); + throw new ServiceException(BaseConstants.EQ_SERVER_ERROR); + } + + // 获取地震影响场数据 + List influences = findInfluenceById(new EqQuery(assess.getEvent(), assess.getEqQueueId())); + // 输出geojson文件 + idzInfluenceService.handle(influences); + + } + + // 查询地震影响场 + @Override + public List findInfluenceById(EqQuery query) { + // 查询条件 + LambdaQueryWrapper lambdaQuery = Wrappers.lambdaQuery(DZXXInfluence.class); + lambdaQuery.eq(DZXXInfluence::getEvent, query.getEvent()); + lambdaQuery.eq(DZXXInfluence::getEqQueueId, query.getEqQueueId()); + + // 该场地震影响场 + List influences = this.baseMapper.selectList(lambdaQuery); + + if (influences == null || influences.size() == 0) { + log.error("查询地震影响场结果为空!"); + throw new ParmaException(BaseConstants.RESULT_ERROR); + } + // 处理 + List dzxxs = new ArrayList<>(); + for (DZXXInfluence influence : influences) { + DZXXInfluenceDTO dzxx = new DZXXInfluenceDTO(); + BeanUtils.copyProperties(influence, dzxx); + dzxxs.add(dzxx); + } + + return dzxxs; + } + + + // 获取最大烈度影响场 + @Override + public DZXXInfluenceDTO findInfluenceMaxIntyById(EqQuery query) { + + LambdaQueryWrapper lambdaQuery = Wrappers.lambdaQuery(DZXXInfluence.class); + lambdaQuery + .eq(DZXXInfluence::getEvent, query.getEvent()) + .eq(DZXXInfluence::getEqQueueId, query.getEqQueueId()) + .orderByDesc(DZXXInfluence::getInty) + .last("limit 1"); // 最大烈度 + + // 获取单条数据 + DZXXInfluence influence = this.baseMapper.selectOne(lambdaQuery); + + if (influence == null) { + log.error("查询地震影响场结果为空!"); + throw new ParmaException(BaseConstants.RESULT_ERROR); + } + DZXXInfluenceDTO dzxx = new DZXXInfluenceDTO(); + BeanUtils.copyProperties(influence, dzxx); + + return dzxx; + } + + + // 根据震级获取对应的烈度值数组 + private int[] gainIntensityLevels(double magnitude) { + // 对震级进行四舍五入处理,取整数级别 + int magLevel = (int) Math.round(magnitude); + // 根据震级范围返回对应的烈度值数组 + if (magLevel >= 5.5 && magLevel < 7.0) { + return new int[]{6, 7, 8}; + } else if (magLevel >= 7.0 && magLevel < 8.0) { + return new int[]{6, 7, 8, 9}; + } else if (magLevel >= 8.0 && magLevel < 9.0) { + return new int[]{6, 7, 8, 9, 10}; + } else if (magLevel >= 9.0) { + // 9级及以上都返回9-12级烈度 + return new int[]{6, 7, 8, 9, 10, 11, 12}; + } else { + // 对于6级以下的震级,默认返回低烈度值 + return new int[]{6}; + } + } + + // 根据烈度长短轴、走向、面积计算生成影响场 + private IntensityQuery compute(double longUranium, double shortUranium, + ActiveFaultDTO shortlyFault, EqAssessmentDTO assess) { + + IntensityQuery query = new IntensityQuery(); + query.setCenterLon(assess.getLongitude()); + query.setCenterLat(assess.getLatitude()); + query.setSemiMajor(longUranium); + query.setSemiMinor(shortUranium); + query.setRotation(shortlyFault.getStrike()); + query.setNumVertices(BaseConstants.NUM_VERTICES); + + return query; + } + + // 转换存库 + private void convert(double longUranium, double shortUranium, double area, int intensity, + Polygon polygon, ActiveFaultDTO shortlyFault, EqAssessmentDTO assess) { + DZXXInfluenceDTO dzxxDto = new DZXXInfluenceDTO(); + dzxxDto.setArea(area); + dzxxDto.setGeom(polygon); + dzxxDto.setDirection(Double.valueOf(shortlyFault.getDirection())); + dzxxDto.setLongitude(assess.getLongitude()); + dzxxDto.setLatitude(assess.getLatitude()); + dzxxDto.setEqName(assess.getEqName()); + dzxxDto.setEqQueueId(assess.getEqQueueId()); + dzxxDto.setEvent(assess.getEvent()); + dzxxDto.setInty(intensity); + dzxxDto.setSInty(BaseConstants.SEISMIC_INTENSITY_MAPPING.get(intensity)); + dzxxDto.setLongUranium(longUranium); + dzxxDto.setShortUranium(shortUranium); + + // 存库 + DZXXInfluence dzxxInfluence = new DZXXInfluence(); + BeanUtils.copyProperties(dzxxDto, dzxxInfluence); + dzxxInfluence.getGeom().setSRID(4490); + save(dzxxInfluence); + log.info("地震影响场已保存!"); + } + +} diff --git a/src/main/java/com/gis/xian/service/ex/ServeException.java b/src/main/java/com/gis/xian/service/ex/ServeException.java new file mode 100644 index 0000000..94793f1 --- /dev/null +++ b/src/main/java/com/gis/xian/service/ex/ServeException.java @@ -0,0 +1,27 @@ +package com.gis.xian.service.ex; + +/** + * @author zzw + * @description: 服务异常 + * @date 2026/5/25 下午5:41 + */ +public class ServeException extends ServiceException { + public ServeException() { + } + + public ServeException(String message) { + super(message); + } + + public ServeException(String message, Throwable cause) { + super(message, cause); + } + + public ServeException(Throwable cause) { + super(cause); + } + + public ServeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/src/main/java/com/gis/xian/service/pub/IDZEqEventService.java b/src/main/java/com/gis/xian/service/pub/IDZEqEventService.java new file mode 100644 index 0000000..658d61e --- /dev/null +++ b/src/main/java/com/gis/xian/service/pub/IDZEqEventService.java @@ -0,0 +1,22 @@ +package com.gis.xian.service.pub; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gis.xian.config.DataSource; +import com.gis.xian.dto.pub.EqTriggerDTO; +import com.gis.xian.entity.pub.DZEqEvent; +import com.gis.xian.query.EqQuery; + +/** + * @author zzw + * @description: QGIS地震事件触发 + * @date 2026/5/25 下午3:23 + */ +@DataSource("slave1") +public interface IDZEqEventService extends IService { + + // 地震触发 + public EqQuery trigger(EqTriggerDTO trigger); + + // 删除地震事件 + public Boolean deletedById(Long Id); +} diff --git a/src/main/java/com/gis/xian/service/pub/IDZEqQueueService.java b/src/main/java/com/gis/xian/service/pub/IDZEqQueueService.java new file mode 100644 index 0000000..94c0163 --- /dev/null +++ b/src/main/java/com/gis/xian/service/pub/IDZEqQueueService.java @@ -0,0 +1,21 @@ +package com.gis.xian.service.pub; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gis.xian.config.DataSource; +import com.gis.xian.dto.pub.EqAssessmentDTO; +import com.gis.xian.entity.pub.DZEqQueue; + +/** + * @author zzw + * @description: 地震评估 + * @date 2026/5/25 下午6:01 + */ +@DataSource("slave1") +public interface IDZEqQueueService extends IService { + + // 地震评估 + public void assess(EqAssessmentDTO assess); + + // 更新评估进度、状态 + public void updated(String event, String queueId, double progress, int state); +} diff --git a/src/main/java/com/gis/xian/service/pub/IDZInfluenceService.java b/src/main/java/com/gis/xian/service/pub/IDZInfluenceService.java new file mode 100644 index 0000000..a01c3d2 --- /dev/null +++ b/src/main/java/com/gis/xian/service/pub/IDZInfluenceService.java @@ -0,0 +1,25 @@ +package com.gis.xian.service.pub; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gis.xian.config.DataSource; +import com.gis.xian.dto.dzxx.DZXXInfluenceDTO; +import com.gis.xian.entity.pub.DZInfluence; +import com.gis.xian.query.EqQuery; +import java.util.List; +import java.util.Map; + +/** + * @author zzw + * @description: 地震影响场 + * @date 2026/5/25 下午6:01 + */ +@DataSource("slave1") +public interface IDZInfluenceService extends IService { + + // 以文件形式 保存影响场 + public void handle(List dzxx); + + // 获取影响场文件 + public Map getInfluence(EqQuery query); + +} diff --git a/src/main/java/com/gis/xian/service/pub/IDZProductService.java b/src/main/java/com/gis/xian/service/pub/IDZProductService.java new file mode 100644 index 0000000..d84d9b5 --- /dev/null +++ b/src/main/java/com/gis/xian/service/pub/IDZProductService.java @@ -0,0 +1,25 @@ +package com.gis.xian.service.pub; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gis.xian.config.DataSource; +import com.gis.xian.dto.pub.DZProductDTO; +import com.gis.xian.dto.pub.EqAssessmentDTO; +import com.gis.xian.entity.pub.DZProduct; +import com.gis.xian.query.ProductQuery; + +import java.util.List; + +/** + * @author zzw + * @description: IDZProductService + * @date 2026/5/25 下午6:01 + */ +@DataSource("slave1") +public interface IDZProductService extends IService { + + // qgis 地震制图服务 + public void makeEarthquakeMaps(EqAssessmentDTO assess); + + // 获取产品 + public List getProducts(ProductQuery query); +} diff --git a/src/main/java/com/gis/xian/service/pub/IFeignService.java b/src/main/java/com/gis/xian/service/pub/IFeignService.java new file mode 100644 index 0000000..e17a36e --- /dev/null +++ b/src/main/java/com/gis/xian/service/pub/IFeignService.java @@ -0,0 +1,18 @@ +package com.gis.xian.service.pub; + +import com.gis.xian.config.DataSource; +import com.gis.xian.params.QgisArgs; + +import java.util.List; + +/** + * @author zzw + * @description: 三方服务接口 + * @date 2026/5/25 下午6:01 + */ +@DataSource("slave1") +public interface IFeignService { + + // 调用专题图 + public void invoke(List args); +} diff --git a/src/main/java/com/gis/xian/service/pub/impl/DZEqEventServiceImpl.java b/src/main/java/com/gis/xian/service/pub/impl/DZEqEventServiceImpl.java new file mode 100644 index 0000000..9c8b360 --- /dev/null +++ b/src/main/java/com/gis/xian/service/pub/impl/DZEqEventServiceImpl.java @@ -0,0 +1,104 @@ +package com.gis.xian.service.pub.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gis.xian.config.DataSource; +import com.gis.xian.constant.BaseConstants; +import com.gis.xian.dto.dzxx.DZXXCenterDTO; +import com.gis.xian.dto.pub.EqAssessmentDTO; +import com.gis.xian.dto.pub.EqTriggerDTO; +import com.gis.xian.entity.pub.DZEqEvent; +import com.gis.xian.mapper.pub.DZEqEventMapper; +import com.gis.xian.query.EqQuery; +import com.gis.xian.service.dzxx.IDZXXCenterService; +import com.gis.xian.service.ex.ParmaException; +import com.gis.xian.service.ex.ServeException; +import com.gis.xian.service.pub.IDZEqEventService; +import com.gis.xian.service.pub.IDZEqQueueService; +import com.gis.xian.utils.BaseUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * @author zzw + * @description: 地震事件实现 + * @date 2026/5/25 下午5:01 + */ +@Slf4j +@Service +@DataSource("slave1") +public class DZEqEventServiceImpl extends ServiceImpl implements IDZEqEventService { + + @Autowired + private IDZXXCenterService idzxxCenterService; + @Autowired + private IDZEqQueueService idzEqQueueService; + + // 地震业务触发 + @Transactional + @Override + public EqQuery trigger(EqTriggerDTO trigger) { + log.info("地震参数:{}", trigger); + // 异常值 + if (trigger == null) { + throw new ParmaException(BaseConstants.PARAMS_ERROR); + } + // 专题图命名代码 + String code = BaseUtils.generationCode(trigger.getEqTime()); + // 地震业务 + try { + DZXXCenterDTO dzxx = new DZXXCenterDTO(); + BeanUtils.copyProperties(trigger, dzxx); + dzxx.setEvent(code); + log.info("地震专题图编码:{}", code); + // 震中位置存储 + idzxxCenterService.handle(dzxx); + // 地震基本信息存储 + DZEqEvent dzeq = new DZEqEvent(); + BeanUtils.copyProperties(dzxx, dzeq); + save(dzeq); + log.info("地震基本信息已存库..."); + } catch (Exception ex) { + log.error(ex.getMessage()); + ex.printStackTrace(); + throw new ServeException(BaseConstants.EQ_SERVER_ERROR); + } + + String batch = BaseUtils.generationBatchCode(code); + // 评估业务 + try { + EqAssessmentDTO assess = new EqAssessmentDTO(); + BeanUtils.copyProperties(trigger, assess); + assess.setEvent(code); + assess.setEqQueueId(batch); + + // 开始评估 + idzEqQueueService.assess(assess); + } catch (Exception ex) { + log.error(ex.getMessage()); + ex.printStackTrace(); + throw new ServeException(BaseConstants.ASSESS_SERVER_ERROR); + } + // 地震编码 + return new EqQuery(code, batch); + } + + // 删除地震 + @Override + public Boolean deletedById(Long Id) { + // 空值 + if (Id == null) { + throw new ParmaException(BaseConstants.PARAMS_ERROR); + } + // 条件构造 + LambdaQueryWrapper lambdaQuery = Wrappers.lambdaQuery(DZEqEvent.class); + lambdaQuery.eq(DZEqEvent::getId, Id); + int flag = this.baseMapper.delete(lambdaQuery); + return flag > 0 ? true : false; + } + +} diff --git a/src/main/java/com/gis/xian/service/pub/impl/DZEqQueueServiceImpl.java b/src/main/java/com/gis/xian/service/pub/impl/DZEqQueueServiceImpl.java new file mode 100644 index 0000000..780c774 --- /dev/null +++ b/src/main/java/com/gis/xian/service/pub/impl/DZEqQueueServiceImpl.java @@ -0,0 +1,170 @@ +package com.gis.xian.service.pub.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gis.xian.config.DataSource; +import com.gis.xian.constant.BaseConstants; +import com.gis.xian.dto.pub.EqAssessmentDTO; +import com.gis.xian.dto.pub.RAssessmentDTO; +import com.gis.xian.entity.pub.DZEqQueue; +import com.gis.xian.enums.BaseEnums; +import com.gis.xian.mapper.pub.DZEqQueueMapper; +import com.gis.xian.service.dzxx.IDZXXDistanceService; +import com.gis.xian.service.dzxx.IDZXXInfluenceService; +import com.gis.xian.service.ex.ParmaException; +import com.gis.xian.service.ex.ServeException; +import com.gis.xian.service.pub.IDZEqQueueService; +import com.gis.xian.service.pub.IDZProductService; +import com.gis.xian.utils.BaseUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; + +/** + * @author zzw + * @description: 地震评估业务 + * @date 2026/5/25 下午6:09 + */ +@Slf4j +@Service +@DataSource("slave1") +public class DZEqQueueServiceImpl extends ServiceImpl implements IDZEqQueueService { + + @Autowired + private IDZXXDistanceService idzxxDistanceService; + @Autowired + private IDZXXInfluenceService idzxxInfluenceService; + @Autowired + private IDZProductService idzProductService; + + // 地震评估 + @Transactional + @Override + public void assess(EqAssessmentDTO assess) { + log.info("开始评估,评估参数:{}", assess); + // 异常值 + if (assess == null) { + throw new ParmaException(BaseConstants.PARAMS_ERROR); + } + // 评估业务 + try { + // 初始化评估 + initial(assess, BaseConstants.MANUAL); + // 地震影响场评估 5s + idzxxInfluenceService.handle(assess); + updated(assess.getEvent(), assess.getEqQueueId(), BaseUtils.compute(1, 0), BaseEnums.CALCULATING.getCode()); + // 震中距评估 + idzxxDistanceService.handle(assess.getLongitude(), assess.getLatitude(), assess.getEqQueueId()); + // 专题图产出 + idzProductService.makeEarthquakeMaps(assess); + } catch (Exception ex) { + log.error(ex.getMessage()); + throw new ServeException(BaseConstants.ASSESS_SERVER_ERROR); + } + } + + // 地震初始化评估进度和评估状态 + private void initial(EqAssessmentDTO assess, int type) { + + DZEqQueue dzqueue = new DZEqQueue(); + BeanUtils.copyProperties(assess, dzqueue); + dzqueue.setId(assess.getEqQueueId()); + dzqueue.setBatch(1); + dzqueue.setType(type); // 手动 + dzqueue.setState(BaseEnums.NOT_STARTED.getCode()); + dzqueue.setMode(1); // 0 地震参数 1 影响场 + dzqueue.setBeginTime(LocalDateTime.now()); + dzqueue.setProgress(0.0); // 评估进度 + dzqueue.setRemark(BaseEnums.NOT_STARTED.getDesc()); + + save(dzqueue); + log.info("地震评估业务初始化完成!"); + } + + // 暴雨初始化评估进度和评估状态 + private void initial(RAssessmentDTO assess, int type) { + + DZEqQueue dzqueue = new DZEqQueue(); + BeanUtils.copyProperties(assess, dzqueue); + dzqueue.setId(assess.getRainQueueId()); + dzqueue.setBatch(1); + dzqueue.setType(type); // 手动 + dzqueue.setState(BaseEnums.NOT_STARTED.getCode()); + dzqueue.setMode(null); // 0 地震参数 1 影响场 + dzqueue.setBeginTime(LocalDateTime.now()); + dzqueue.setProgress(0.0); // 评估进度 + dzqueue.setRemark(BaseEnums.NOT_STARTED.getDesc()); + + save(dzqueue); + log.info("暴雨评估业务初始化完成!"); + } + + + // 更新评估进度和评估状态 + public void updated(String event, String queueId, double progress, int state) { + + DZEqQueue dzqueue = new DZEqQueue(); + // 条件 + LambdaQueryWrapper lambdaQuery = Wrappers.lambdaQuery(DZEqQueue.class) + .eq(DZEqQueue::getEvent, event) + .eq(DZEqQueue::getId, queueId); + + // 评估异常终止 + if (state == BaseEnums.TIMEOUT_OR_EXCEPTION.getCode()) { + dzqueue.setState(BaseEnums.TIMEOUT_OR_EXCEPTION.getCode()); + dzqueue.setEndTime(LocalDateTime.now()); + dzqueue.setProgress(progress); // 评估进度 + dzqueue.setRemark(BaseEnums.TIMEOUT_OR_EXCEPTION.getDesc()); + // 更新状态 + update(dzqueue, lambdaQuery); + log.info("评估异常结束!"); + return; + } + // 人工停止 + if (state == BaseEnums.MANUAL_STOPPED.getCode()) { + dzqueue.setState(BaseEnums.MANUAL_STOPPED.getCode()); + dzqueue.setEndTime(LocalDateTime.now()); + dzqueue.setProgress(progress); // 评估进度 + dzqueue.setRemark(BaseEnums.MANUAL_STOPPED.getDesc()); + // 更新状态 + update(dzqueue, lambdaQuery); + log.info("评估人工停止!"); + return; + } + // 不计算 + if (state == BaseEnums.NOT_CALCULATE.getCode()) { + dzqueue.setState(BaseEnums.NOT_CALCULATE.getCode()); + dzqueue.setEndTime(LocalDateTime.now()); + dzqueue.setProgress(progress); // 评估进度 + dzqueue.setRemark(BaseEnums.NOT_CALCULATE.getDesc()); + // 更新状态 + update(dzqueue, lambdaQuery); + log.info("本次事件不参与评估计算!"); + return; + } + // 正常继续评估 + if (state == BaseEnums.CALCULATING.getCode()) { + if (progress < 100) { + dzqueue.setProgress(progress); + // 更新进度 + update(dzqueue, lambdaQuery); + log.info("评估业务进度:{}%", progress); + return; + } + // 评估完成 + dzqueue.setState(BaseEnums.NORMAL_COMPLETED.getCode()); + dzqueue.setEndTime(LocalDateTime.now()); + dzqueue.setProgress(progress); // 评估进度 + dzqueue.setRemark(BaseEnums.NORMAL_COMPLETED.getDesc()); + update(dzqueue, lambdaQuery); + log.info("评估工作结束!"); + } + + } + +} diff --git a/src/main/java/com/gis/xian/service/pub/impl/DZInfluenceServiceImpl.java b/src/main/java/com/gis/xian/service/pub/impl/DZInfluenceServiceImpl.java new file mode 100644 index 0000000..5c554a3 --- /dev/null +++ b/src/main/java/com/gis/xian/service/pub/impl/DZInfluenceServiceImpl.java @@ -0,0 +1,120 @@ +package com.gis.xian.service.pub.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gis.xian.config.DataSource; +import com.gis.xian.constant.BaseConstants; +import com.gis.xian.dto.dzxx.DZXXInfluenceDTO; +import com.gis.xian.dto.pub.DZInfluenceDTO; +import com.gis.xian.dto.pub.IntyGeoJsonDTO; +import com.gis.xian.entity.pub.DZInfluence; +import com.gis.xian.handler.GeoFilesHandler; +import com.gis.xian.mapper.pub.DZInfluenceMapper; +import com.gis.xian.query.EqQuery; +import com.gis.xian.service.ex.ParmaException; +import com.gis.xian.service.ex.ServiceException; +import com.gis.xian.service.pub.IDZInfluenceService; +import lombok.extern.slf4j.Slf4j; +import org.locationtech.jts.geom.Polygon; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author zzw + * @description: 地震影响场实现 + * @date 2026/5/26 上午10:39 + */ +@Slf4j +@Service +@DataSource("slave1") +public class DZInfluenceServiceImpl extends ServiceImpl implements IDZInfluenceService { + + @Autowired + private GeoFilesHandler handler; + + + // 将影响场以文件形式保存 + @Async("xianPool") + @Override + public void handle(List dzxxs) { + // 异常 + if (dzxxs == null || dzxxs.isEmpty()) { + throw new ParmaException(BaseConstants.PARAMS_ERROR); + } + try { + // 影响场名称 + String fineName = ""; + IntyGeoJsonDTO features = new IntyGeoJsonDTO(); + DZInfluenceDTO influence = new DZInfluenceDTO(); + // 处理影响场数据 + for (DZXXInfluenceDTO dzxx : dzxxs) { + // 接收面数据 + Polygon polygon = (Polygon) dzxx.getGeom(); + // 转换Polygon为GeoJSON Geometry结构 + IntyGeoJsonDTO.GeoJsonFeature feature = handler.convertPolygonToGeoJsonFeature(polygon, dzxx); + features.getFeatures().add(feature); + // 根据批次编码拼接目录和文件名 + fineName = dzxx.getEqQueueId() + "/" + dzxx.getEqName(); + // 获取地震影响场信息 + influence.setEqQueueId(dzxx.getEqQueueId()); + influence.setEvent(dzxx.getEvent()); + influence.setName(dzxx.getEqName()); + } + + if (features.getFeatures() == null || features.getFeatures().isEmpty()) { + throw new ServiceException(BaseConstants.INFLUENCE_CONVERT_ERROR); + } + + // 保存GeoJSON文件 + handler.writeGeoJsonToFile(features, fineName); + log.info("地震影响场GeoJson文件已生成成功!"); + + influence.setPath(BaseConstants.INTENSITY_GEOJSON_PATH + fineName + ".geojson"); + handleDzxxData(influence); + + } catch (Exception ex) { + log.error("影响场保存为geojson失败!:", ex.getMessage()); + throw new ServiceException(BaseConstants.INFLUENCE_CONVERT_ERROR); + } + } + + // 获取影响场文件 + @Override + public Map getInfluence(EqQuery query) { + // 异常 + if (query == null) { + throw new ParmaException(BaseConstants.PARAMS_ERROR); + } + // 条件 + LambdaQueryWrapper lambdaQuery = Wrappers.lambdaQuery(DZInfluence.class); + lambdaQuery.select(DZInfluence::getPath); + lambdaQuery.eq(DZInfluence::getEvent, query.getEvent()); + lambdaQuery.eq(DZInfluence::getEqQueueId, query.getEqQueueId()); + lambdaQuery.orderByDesc(DZInfluence::getCreateTime); // 防止多条记录 + lambdaQuery.last("limit 1"); + // 查询 + DZInfluence influence = (DZInfluence) this.baseMapper.selectList(lambdaQuery); + if (influence == null) { + throw new ParmaException(BaseConstants.RESULT_ERROR); + } + Map hashmap = new HashMap<>(); + hashmap.put("file", influence.getPath()); + return hashmap; + } + + + // 处理地震信息数据 + private void handleDzxxData(DZInfluenceDTO dto) { + DZInfluence influence = new DZInfluence(); + BeanUtils.copyProperties(dto, influence); + // 存库 + save(influence); + } +} diff --git a/src/main/java/com/gis/xian/service/pub/impl/DZProductServiceImpl.java b/src/main/java/com/gis/xian/service/pub/impl/DZProductServiceImpl.java new file mode 100644 index 0000000..913500c --- /dev/null +++ b/src/main/java/com/gis/xian/service/pub/impl/DZProductServiceImpl.java @@ -0,0 +1,209 @@ +package com.gis.xian.service.pub.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gis.xian.config.DataSource; +import com.gis.xian.constant.BaseConstants; +import com.gis.xian.dto.pub.DZProductDTO; +import com.gis.xian.dto.pub.EqAssessmentDTO; +import com.gis.xian.entity.pub.DZProduct; +import com.gis.xian.enums.BaseEnums; +import com.gis.xian.enums.EqMapsEnums; +import com.gis.xian.handler.EarthquakeHandler; +import com.gis.xian.mapper.pub.DZProductMapper; +import com.gis.xian.query.ProductQuery; +import com.gis.xian.service.base.IActiveFaultService; +import com.gis.xian.service.dzxx.IDZXXInfluenceService; +import com.gis.xian.service.ex.ParmaException; +import com.gis.xian.service.ex.ServeException; +import com.gis.xian.service.pub.IDZProductService; +import com.gis.xian.service.pub.IFeignService; +import com.gis.xian.utils.BaseUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.security.SecureRandom; +import java.time.LocalDateTime; +import java.util.*; + +import com.gis.xian.params.QgisArgs; +import org.springframework.util.StringUtils; + +/** + * @author zzw + * @description: 地震产品类 + * @date 2026/5/26 上午11:26 + */ +@Slf4j +@Service +@DataSource("slave1") +public class DZProductServiceImpl extends ServiceImpl implements IDZProductService { + + private static final SecureRandom secureRandom = new SecureRandom(); + + @Autowired + private IFeignService iFeignService; + @Autowired + private IActiveFaultService iActiveFaultService; + @Autowired + private IDZXXInfluenceService idzxxInfluenceService; + + // qgis 地震制图服务 + @Override + @Async("xianPool") + public void makeEarthquakeMaps(EqAssessmentDTO assess) { + // 待产专题图集 + List maps = Arrays.asList(EqMapsEnums.values()); + // 设置制图参数 + List args = setMakeEqMapsArgs(assess, maps); + // 调用出图服务 + iFeignService.invoke(args); + } + + // 获取产品 + @Override + public List getProducts(ProductQuery query) { + try { + log.info("查询产品参数:{}", query); + // 空值 + if (query.getQueueId() == null || query.getQueueId().trim().isEmpty()) { + throw new ParmaException(BaseConstants.QUEUE_ID_ERROR); + } + // 构造条件 + LambdaQueryWrapper lambdaQuery = Wrappers.lambdaQuery(DZProduct.class); + // 必填项 + lambdaQuery.eq(DZProduct::getEqQueueId, query.getQueueId()); + // 选填项 + lambdaQuery.or().eq(StringUtils.hasText(query.getCode()), DZProduct::getCode, query.getCode()); + lambdaQuery.or().eq(StringUtils.hasText(query.getFileType()), DZProduct::getFileType, query.getFileType()); + lambdaQuery.or().like(StringUtils.hasText(query.getFileName()), DZProduct::getFileName, query.getFileName()); + lambdaQuery.or().eq(StringUtils.hasText(query.getProType()), DZProduct::getProType, query.getProType()); + // 获取产品服务 + List productList = this.baseMapper.selectList(lambdaQuery); + List dtos = new ArrayList<>(); + for (DZProduct product : productList) { + DZProductDTO dto = new DZProductDTO(); + BeanUtils.copyProperties(product, dto); + dto.setTempletId(null); + + dtos.add(dto); + } + return dtos; + } catch (Exception ex) { + log.error(ex.getMessage()); + throw new ServeException(BaseConstants.PRODUCTS_ERROR); + } + } + + // 地震 制图参数 + private List setMakeEqMapsArgs(EqAssessmentDTO assess, List maps) { + // 专题图集参数 + List args = new ArrayList<>(); + + // A4 画幅 + for (EqMapsEnums map : maps) { + // qgis参数 + QgisArgs arg = new QgisArgs(); + arg.setId(map.getNum()); + arg.setEvent(assess.getEvent()); + arg.setQueueId(assess.getEqQueueId()); + arg.setCenterX(assess.getLongitude()); + arg.setCenterY(assess.getLatitude()); + arg.setInfo(EarthquakeHandler.parseInfo(assess.getEqTime(), assess.getEqMagnitude(), assess.getEqAddr())); + arg.setMapTitle(EarthquakeHandler.combine(assess.getEqName(), assess.getEqType(), map)); + arg.setMapTime(BaseUtils.formatTime(LocalDateTime.now(), false)); + arg.setMapLayout(BaseConstants.MAP_LAYOUT_A4); // A4 + arg.setMapUint(BaseConstants.MAP_UNIT); // 单位 + // 死信队列中获取单张图片 + arg.setName(map.getName()); + arg.setOutFile(EarthquakeHandler.getPath(assess.getEvent(), assess.getEqQueueId(), BaseConstants.MAP_LAYOUT_A4, map)); + arg.setPath(BaseConstants.EQ_MAPS_TEMPLATE_PATH + map.getName() + ".qgz"); + arg.setDisaster(BaseConstants.EQ_DISASTER_MAP); // 地震灾害 + + // 缩放规则 + Map changed = change(assess, "A4", map.getName()); + arg.setZoomRule(changed.get("k")); // 默认不缩放 + arg.setZoomValue(changed.get("v")); // 默认缩放值 + + args.add(arg); + } + + // 增加 A3 画幅 + for (EqMapsEnums map : maps) { + // qgis参数 + QgisArgs arg = new QgisArgs(); + arg.setId(map.getNum()); + arg.setEvent(assess.getEvent()); + arg.setQueueId(assess.getEqQueueId()); + arg.setCenterX(assess.getLongitude()); + arg.setCenterY(assess.getLatitude()); + arg.setInfo(EarthquakeHandler.parseInfo(assess.getEqTime(), assess.getEqMagnitude(), assess.getEqAddr())); + arg.setMapTitle(EarthquakeHandler.combine(assess.getEqName(), assess.getEqType(), map)); + arg.setMapTime(BaseUtils.formatTime(LocalDateTime.now(), false)); + arg.setMapLayout(BaseConstants.MAP_LAYOUT_A3); // A3 + arg.setMapUint(BaseConstants.MAP_UNIT); // 单位 + // 死信队列中获取单张图片 + arg.setName(map.getName()); + arg.setOutFile(EarthquakeHandler.getPath(assess.getEvent(), assess.getEqQueueId(), BaseConstants.MAP_LAYOUT_A3, map)); + arg.setPath(BaseConstants.EQ_MAPS_TEMPLATE_PATH + map.getName() + ".qgz"); + arg.setDisaster(BaseConstants.EQ_DISASTER_MAP); // 地震灾害 + + // 缩放规则 + Map changed = change(assess, "A3", map.getName()); + arg.setZoomRule(changed.get("k")); // 默认不缩放 + arg.setZoomValue(changed.get("v")); // 默认缩放值 + + args.add(arg); + } + log.info("制图参数设置完成!"); + + return args; + } + + + /** + * 专题图缩放变化: + * A3: + * 4级地震:不放缩 + * 5-6级地震:所有A3都放缩到intensity + * 6级以上,除了影响场intensity,其他不变 + *

+ * A4: + * 所有都不变 + */ + public Map change(EqAssessmentDTO assess, String size, String name) { + Map map = new HashMap<>(); + + if (size.equals("A3")) { + if (assess.getEqMagnitude() >= 4 && assess.getEqMagnitude() < 5) { + map.put("k", BaseEnums.NO.getCode().toString()); + map.put("v", ""); + return map; + } + if (assess.getEqMagnitude() >= 5 && assess.getEqMagnitude() < 6) { + map.put("k", BaseEnums.M_LAYER2.getCode().toString()); + map.put("v", "intensity"); + return map; + } + if (assess.getEqMagnitude() >= 6) { + if (name.equals("地震影响估计范围分布图")) { + map.put("k", BaseEnums.M_LAYER2.getCode().toString()); + map.put("v", "intensity"); + return map; + } else { + map.put("k", BaseEnums.NO.getCode().toString()); + map.put("v", ""); + return map; + } + } + } + map.put("k", BaseEnums.NO.getCode().toString()); + map.put("v", ""); + return map; + } + +} diff --git a/src/main/java/com/gis/xian/service/pub/impl/FeignServiceImpl.java b/src/main/java/com/gis/xian/service/pub/impl/FeignServiceImpl.java new file mode 100644 index 0000000..7308d78 --- /dev/null +++ b/src/main/java/com/gis/xian/service/pub/impl/FeignServiceImpl.java @@ -0,0 +1,97 @@ +package com.gis.xian.service.pub.impl; + +import com.alibaba.fastjson2.JSON; +import com.gis.xian.config.DataSource; +import com.gis.xian.constant.BaseConstants; +import com.gis.xian.core.rabbitmq.DlqOperate; +import com.gis.xian.enums.BaseEnums; +import com.gis.xian.params.QgisArgs; +import com.gis.xian.service.ex.ParmaException; +import com.gis.xian.service.pub.IDZEqQueueService; +import com.gis.xian.service.pub.IFeignService; +import com.gis.xian.utils.BaseUtils; +import com.gis.xian.utils.http.HttpRestClient; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Lazy; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author zzw + * @description: 三方服务接口 + * @date 2026/5/26 上午11:33 + */ +@Slf4j +@Service +@DataSource("slave1") +public class FeignServiceImpl implements IFeignService { + + + @Resource + private HttpRestClient restclient; + @Resource + private RabbitTemplate rabbitTemplate; + @Autowired + @Lazy + private IDZEqQueueService idzEqQueueService; + @Autowired + private DlqOperate dlqOperate; + + // 调用制图服务 + @Override + public void invoke(List args) { + // 进度 + double p = 0; + // 异常参数 + if (args == null || args.size() == 0) { + throw new ParmaException(BaseConstants.PARAMS_ERROR); + } + // 保证尽可能的多产, 这里不要进行任何异常抛出, 只能记录失败的图层 + try { + log.info("开始调用pyqgis服务"); + for (QgisArgs arg : args) { + try { // 处理单个图件 + // 返回数据格式 + ParameterizedTypeReference res = new ParameterizedTypeReference() { + }; + // 制图 + String mapName = restclient.post(BaseConstants.HTTP_QGIS_THEMATIC, JSON.toJSON(arg), res); + // 专题图名称 + if (mapName == null || mapName.equals("")) { + log.error("产出图件失败!"); + // 进入死信队列 + dlqOperate.sendToDlq(arg, "产出图件返回空", null); + } + log.info("图件产品:{}-产出成功", mapName); + // 这里可能会出现线程抢占, 需要加入乐观锁 + if (arg.getDisaster() == BaseConstants.EQ_DISASTER_MAP) { + // 更新状态 专题图是第二部分产品 保证进度同步 所以需要 num+1 处理 + p = BaseUtils.compute(arg.getId() + 1, 0); + } + if (arg.getDisaster() == BaseConstants.RAIN_DISASTER_MAP) { + p = BaseUtils.compute(arg.getId() + 1, 1); + } + idzEqQueueService.updated(arg.getEvent(), arg.getQueueId(), p, BaseEnums.CALCULATING.getCode()); + // 推送消息 + rabbitTemplate.convertAndSend(BaseConstants.ASSESS_EXCHANGE, BaseConstants.MAPS_QUEUE, arg); + } catch (Exception ex) { + log.error("制图服务出现错误,请检查服务问题! {}", ex.getMessage()); + // 进入死信队列 + dlqOperate.sendToDlq(arg, "图层处理异常", ex); + } + } + } catch (Exception e) { + log.error("制图服务出现错误,请检查服务问题! {}", e.getMessage(), e); + // 批量失败时,将所有未处理的参数投递到死信 + for (QgisArgs arg : args) { + // 进入死信队列 + dlqOperate.sendToDlq(arg, "制图服务整体异常", e); + } + } + } +} diff --git a/src/main/java/com/gis/xian/task/InitializeData.java b/src/main/java/com/gis/xian/task/InitializeData.java index d7b6554..3ac5107 100644 --- a/src/main/java/com/gis/xian/task/InitializeData.java +++ b/src/main/java/com/gis/xian/task/InitializeData.java @@ -17,7 +17,7 @@ import java.util.concurrent.CompletableFuture; /** * 初始化数据 */ -@Component +//@Component @Slf4j public class InitializeData { @@ -107,7 +107,7 @@ public class InitializeData { public void init() { log.info("开始初始化数据"); // 并行执行所有数据库查询和Redis写入 - + // 隐患点 - 总体 CompletableFuture allFuture = CompletableFuture.runAsync(() -> { redisTemplate.opsForValue().set(allBasePointsKey, JSON.toJSONString( @@ -117,7 +117,7 @@ public class InitializeData { ); log.info("加载隐患点信息(总体)并写入redis完成"); }); - + // 隐患点 - 滑坡 CompletableFuture landslideFuture = CompletableFuture.runAsync(() -> { redisTemplate.opsForValue().set(landslideKey, JSON.toJSONString( @@ -127,7 +127,7 @@ public class InitializeData { ); log.info("加载隐患点信息(滑坡)并写入redis完成"); }); - + // 隐患点 - 泥石流 CompletableFuture debrisFlowFuture = CompletableFuture.runAsync(() -> { redisTemplate.opsForValue().set(debrisFlowKey, JSON.toJSONString( @@ -137,7 +137,7 @@ public class InitializeData { ); log.info("加载隐患点信息(泥石流)并写入redis完成"); }); - + // 隐患点 - 山洪 CompletableFuture flashFloodFuture = CompletableFuture.runAsync(() -> { redisTemplate.opsForValue().set(flashFloodKey, JSON.toJSONString( @@ -147,7 +147,7 @@ public class InitializeData { ); log.info("加载隐患点信息(山洪)并写入redis完成"); }); - + // 隐患点 - 内涝 CompletableFuture waterLoggingFuture = CompletableFuture.runAsync(() -> { redisTemplate.opsForValue().set(waterLoggingKey, JSON.toJSONString( diff --git a/src/main/java/com/gis/xian/utils/BaseUtils.java b/src/main/java/com/gis/xian/utils/BaseUtils.java new file mode 100644 index 0000000..077107f --- /dev/null +++ b/src/main/java/com/gis/xian/utils/BaseUtils.java @@ -0,0 +1,70 @@ +package com.gis.xian.utils; + +import com.gis.xian.constant.BaseConstants; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +/** + * @author zzw + * @description: 基本工具类 + * @date 2026/5/25 下午6:06 + */ +public class BaseUtils { + // 生成一个带时间戳的地震编码 + public static String generationCode(LocalDateTime time) { + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + String timestamp = time.format(formatter); + String code = "T" + timestamp + BaseConstants.CITY_CODE; + + return code; + } + + // 格式化时间 + public static String formatTime(LocalDateTime time, boolean top) { + // true 三要素 false 落款) + if (top) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时 mm分"); + String timestamp = time.format(formatter); + return timestamp; + } + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日"); + String timestamp = time.format(formatter); + return timestamp; + + } + + // 首次生成批次编码 + public static String generationBatchCode(String code) { + return code + "01"; + } + + // 修改地震批次编码 + public static String editBatchCode(String code) { + + String prefix = code.substring(0, code.length() - 2); + String last = code.substring(code.length() - 2); + return prefix + Integer.parseInt(last) + 1; + } + + // 生成一个带时间戳的暴雨编码 + public static String generationRainCode(LocalDateTime time) { + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + String timestamp = time.format(formatter); + String code = "R" + timestamp + BaseConstants.CITY_CODE; + + return code; + } + + // 计算评估进度 0:地震、1:暴雨 + public static double compute(int finish, int type) { + if (type == 0) { + return (double) finish / BaseConstants.EQ_TOTAL_FILES * 100; + } + return (double) finish / BaseConstants.RAIN_TOTAL_FILES * 100; + } + +} diff --git a/src/main/java/com/gis/xian/utils/StringUtils.java b/src/main/java/com/gis/xian/utils/StringUtils.java new file mode 100644 index 0000000..0f14964 --- /dev/null +++ b/src/main/java/com/gis/xian/utils/StringUtils.java @@ -0,0 +1,682 @@ +package com.gis.xian.utils; + +import org.springframework.util.AntPathMatcher; + +import java.util.*; + +/** + * @author zzw + * @description: 字符串工具类 (基于RuoYi风格扩展) + * @date 2026/5/26 上午9:25 + */ +public class StringUtils extends org.apache.commons.lang3.StringUtils { + /** 空字符串 */ + private static final String NULLSTR = ""; + + /** 下划线 */ + private static final char SEPARATOR = '_'; + + /** 星号 */ + private static final char ASTERISK = '*'; + + /** + * 获取参数不为空值 + * + * @param value defaultValue 要判断的value + * @return value 返回值 + */ + public static T nvl(T value, T defaultValue) + { + return value != null ? value : defaultValue; + } + + /** + * * 判断一个Collection是否为空, 包含List,Set,Queue + * + * @param coll 要判断的Collection + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Collection coll) + { + return isNull(coll) || coll.isEmpty(); + } + + /** + * * 判断一个Collection是否非空,包含List,Set,Queue + * + * @param coll 要判断的Collection + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Collection coll) + { + return !isEmpty(coll); + } + + /** + * * 判断一个对象数组是否为空 + * + * @param objects 要判断的对象数组 + ** @return true:为空 false:非空 + */ + public static boolean isEmpty(Object[] objects) + { + return isNull(objects) || (objects.length == 0); + } + + /** + * * 判断一个对象数组是否非空 + * + * @param objects 要判断的对象数组 + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Object[] objects) + { + return !isEmpty(objects); + } + + /** + * * 判断一个Map是否为空 + * + * @param map 要判断的Map + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Map map) + { + return isNull(map) || map.isEmpty(); + } + + /** + * * 判断一个Map是否为空 + * + * @param map 要判断的Map + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Map map) + { + return !isEmpty(map); + } + + /** + * * 判断一个字符串是否为空串 + * + * @param str String + * @return true:为空 false:非空 + */ + public static boolean isEmpty(String str) + { + return isNull(str) || NULLSTR.equals(str.trim()); + } + + /** + * * 判断一个字符串是否为非空串 + * + * @param str String + * @return true:非空串 false:空串 + */ + public static boolean isNotEmpty(String str) + { + return !isEmpty(str); + } + + /** + * * 判断一个对象是否为空 + * + * @param object Object + * @return true:为空 false:非空 + */ + public static boolean isNull(Object object) + { + return object == null; + } + + /** + * * 判断一个对象是否非空 + * + * @param object Object + * @return true:非空 false:空 + */ + public static boolean isNotNull(Object object) + { + return !isNull(object); + } + + /** + * * 判断一个对象是否是数组类型(Java基本型别的数组) + * + * @param object 对象 + * @return true:是数组 false:不是数组 + */ + public static boolean isArray(Object object) + { + return isNotNull(object) && object.getClass().isArray(); + } + + /** + * 去空格 + */ + public static String trim(String str) + { + return (str == null ? "" : str.trim()); + } + + /** + * 替换指定字符串的指定区间内字符为"*" + * + * @param str 字符串 + * @param startInclude 开始位置(包含) + * @param endExclude 结束位置(不包含) + * @return 替换后的字符串 + */ + public static String hide(CharSequence str, int startInclude, int endExclude) + { + if (isEmpty(str)) + { + return NULLSTR; + } + final int strLength = str.length(); + if (startInclude > strLength) + { + return NULLSTR; + } + if (endExclude > strLength) + { + endExclude = strLength; + } + if (startInclude > endExclude) + { + // 如果起始位置大于结束位置,不替换 + return NULLSTR; + } + final char[] chars = new char[strLength]; + for (int i = 0; i < strLength; i++) + { + if (i >= startInclude && i < endExclude) + { + chars[i] = ASTERISK; + } + else + { + chars[i] = str.charAt(i); + } + } + return new String(chars); + } + + /** + * 截取字符串 + * + * @param str 字符串 + * @param start 开始 + * @return 结果 + */ + public static String substring(final String str, int start) + { + if (str == null) + { + return NULLSTR; + } + + if (start < 0) + { + start = str.length() + start; + } + + if (start < 0) + { + start = 0; + } + if (start > str.length()) + { + return NULLSTR; + } + + return str.substring(start); + } + + /** + * 截取字符串 + * + * @param str 字符串 + * @param start 开始 + * @param end 结束 + * @return 结果 + */ + public static String substring(final String str, int start, int end) + { + if (str == null) + { + return NULLSTR; + } + + if (end < 0) + { + end = str.length() + end; + } + if (start < 0) + { + start = str.length() + start; + } + + if (end > str.length()) + { + end = str.length(); + } + + if (start > end) + { + return NULLSTR; + } + + if (start < 0) + { + start = 0; + } + if (end < 0) + { + end = 0; + } + + return str.substring(start, end); + } + + /** + * 在字符串中查找第一个出现的 `open` 和最后一个出现的 `close` 之间的子字符串 + * + * @param str 要截取的字符串 + * @param open 起始字符串 + * @param close 结束字符串 + * @return 截取结果 + */ + public static String substringBetweenLast(final String str, final String open, final String close) + { + if (isEmpty(str) || isEmpty(open) || isEmpty(close)) + { + return NULLSTR; + } + final int start = str.indexOf(open); + if (start != INDEX_NOT_FOUND) + { + final int end = str.lastIndexOf(close); + if (end != INDEX_NOT_FOUND) + { + return str.substring(start + open.length(), end); + } + } + return NULLSTR; + } + + /** + * 判断是否为空,并且不是空白字符 + * + * @param str 要判断的value + * @return 结果 + */ + public static boolean hasText(String str) + { + return (str != null && !str.isEmpty() && containsText(str)); + } + + private static boolean containsText(CharSequence str) + { + int strLen = str.length(); + for (int i = 0; i < strLen; i++) + { + if (!Character.isWhitespace(str.charAt(i))) + { + return true; + } + } + return false; + } + + /** + * 字符串转set + * + * @param str 字符串 + * @param sep 分隔符 + * @return set集合 + */ + public static final Set str2Set(String str, String sep) + { + return new HashSet(str2List(str, sep, true, false)); + } + + /** + * 字符串转list + * + * @param str 字符串 + * @param sep 分隔符 + * @return list集合 + */ + public static final List str2List(String str, String sep) + { + return str2List(str, sep, true, false); + } + + /** + * 字符串转list + * + * @param str 字符串 + * @param sep 分隔符 + * @param filterBlank 过滤纯空白 + * @param trim 去掉首尾空白 + * @return list集合 + */ + public static final List str2List(String str, String sep, boolean filterBlank, boolean trim) + { + List list = new ArrayList(); + if (StringUtils.isEmpty(str)) + { + return list; + } + + // 过滤空白字符串 + if (filterBlank && StringUtils.isBlank(str)) + { + return list; + } + String[] split = str.split(sep); + for (String string : split) + { + if (filterBlank && StringUtils.isBlank(string)) + { + continue; + } + if (trim) + { + string = string.trim(); + } + list.add(string); + } + + return list; + } + + /** + * 判断给定的collection列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value + * + * @param collection 给定的集合 + * @param array 给定的数组 + * @return boolean 结果 + */ + public static boolean containsAny(Collection collection, String... array) + { + if (isEmpty(collection) || isEmpty(array)) + { + return false; + } + else + { + for (String str : array) + { + if (collection.contains(str)) + { + return true; + } + } + return false; + } + } + + /** + * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写 + * + * @param cs 指定字符串 + * @param searchCharSequences 需要检查的字符串数组 + * @return 是否包含任意一个字符串 + */ + public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) + { + if (isEmpty(cs) || isEmpty(searchCharSequences)) + { + return false; + } + for (CharSequence testStr : searchCharSequences) + { + if (containsIgnoreCase(cs, testStr)) + { + return true; + } + } + return false; + } + + /** + * 驼峰转下划线命名 + */ + public static String toUnderScoreCase(String str) + { + if (str == null) + { + return null; + } + StringBuilder sb = new StringBuilder(); + // 前置字符是否大写 + boolean preCharIsUpperCase = true; + // 当前字符是否大写 + boolean curreCharIsUpperCase = true; + // 下一字符是否大写 + boolean nexteCharIsUpperCase = true; + for (int i = 0; i < str.length(); i++) + { + char c = str.charAt(i); + if (i > 0) + { + preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1)); + } + else + { + preCharIsUpperCase = false; + } + + curreCharIsUpperCase = Character.isUpperCase(c); + + if (i < (str.length() - 1)) + { + nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1)); + } + + if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) + { + sb.append(SEPARATOR); + } + else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) + { + sb.append(SEPARATOR); + } + sb.append(Character.toLowerCase(c)); + } + + return sb.toString(); + } + + /** + * 是否包含字符串 + * + * @param str 验证字符串 + * @param strs 字符串组 + * @return 包含返回true + */ + public static boolean inStringIgnoreCase(String str, String... strs) + { + if (str != null && strs != null) + { + for (String s : strs) + { + if (str.equalsIgnoreCase(trim(s))) + { + return true; + } + } + } + return false; + } + + /** + * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld + * + * @param name 转换前的下划线大写方式命名的字符串 + * @return 转换后的驼峰式命名的字符串 + */ + public static String convertToCamelCase(String name) + { + StringBuilder result = new StringBuilder(); + // 快速检查 + if (name == null || name.isEmpty()) + { + // 没必要转换 + return ""; + } + else if (!name.contains("_")) + { + // 不含下划线,仅将首字母大写 + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + // 用下划线将原始字符串分割 + String[] camels = name.split("_"); + for (String camel : camels) + { + // 跳过原始字符串中开头、结尾的下换线或双重下划线 + if (camel.isEmpty()) + { + continue; + } + // 首字母大写 + result.append(camel.substring(0, 1).toUpperCase()); + result.append(camel.substring(1).toLowerCase()); + } + return result.toString(); + } + + /** + * 驼峰式命名法 + * 例如:user_name->userName + */ + public static String toCamelCase(String s) + { + if (s == null) + { + return null; + } + if (s.indexOf(SEPARATOR) == -1) + { + return s; + } + s = s.toLowerCase(); + StringBuilder sb = new StringBuilder(s.length()); + boolean upperCase = false; + for (int i = 0; i < s.length(); i++) + { + char c = s.charAt(i); + + if (c == SEPARATOR) + { + upperCase = true; + } + else if (upperCase) + { + sb.append(Character.toUpperCase(c)); + upperCase = false; + } + else + { + sb.append(c); + } + } + return sb.toString(); + } + + /** + * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串 + * + * @param str 指定字符串 + * @param strs 需要检查的字符串数组 + * @return 是否匹配 + */ + public static boolean matches(String str, List strs) + { + if (isEmpty(str) || isEmpty(strs)) + { + return false; + } + for (String pattern : strs) + { + if (isMatch(pattern, str)) + { + return true; + } + } + return false; + } + + /** + * 判断url是否与规则配置: + * ? 表示单个字符; + * * 表示一层路径内的任意字符串,不可跨层级; + * ** 表示任意层路径; + * + * @param pattern 匹配规则 + * @param url 需要匹配的url + * @return + */ + public static boolean isMatch(String pattern, String url) + { + AntPathMatcher matcher = new AntPathMatcher(); + return matcher.match(pattern, url); + } + + @SuppressWarnings("unchecked") + public static T cast(Object obj) + { + return (T) obj; + } + + /** + * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。 + * + * @param num 数字对象 + * @param size 字符串指定长度 + * @return 返回数字的字符串格式,该字符串为指定长度。 + */ + public static final String padl(final Number num, final int size) + { + return padl(num.toString(), size, '0'); + } + + /** + * 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。 + * + * @param s 原始字符串 + * @param size 字符串指定长度 + * @param c 用于补齐的字符 + * @return 返回指定长度的字符串,由原字符串左补齐或截取得到。 + */ + public static final String padl(final String s, final int size, final char c) + { + final StringBuilder sb = new StringBuilder(size); + if (s != null) + { + final int len = s.length(); + if (s.length() <= size) + { + for (int i = size - len; i > 0; i--) + { + sb.append(c); + } + sb.append(s); + } + else + { + return s.substring(len - size, len); + } + } + else + { + for (int i = size; i > 0; i--) + { + sb.append(c); + } + } + return sb.toString(); + } +} diff --git a/src/main/java/com/gis/xian/utils/http/HttpRestClient.java b/src/main/java/com/gis/xian/utils/http/HttpRestClient.java new file mode 100644 index 0000000..522f8fe --- /dev/null +++ b/src/main/java/com/gis/xian/utils/http/HttpRestClient.java @@ -0,0 +1,198 @@ +package com.gis.xian.utils.http; + +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.*; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import java.util.Map; + +/** + * @author zzw + * @description: 第三方请求工具类 + * @date 2026/5/26 下午4:27 + */ +public class HttpRestClient { + + private final RestTemplate restTemplate; + + // 默认的请求头设置 + private static final HttpHeaders defaultHeaders; + + static { + defaultHeaders = new HttpHeaders(); + defaultHeaders.setContentType(MediaType.APPLICATION_JSON); + defaultHeaders.add("Accept", "application/json"); + } + + /** + * 构造方法,注入RestTemplate + * @param restTemplate RestTemplate实例 + */ + public HttpRestClient(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + /** + * 不带Token的GET请求 + * @param url 请求URL + * @param responseType 响应数据类型 + * @param 响应数据泛型 + * @return 响应结果 + */ + public T get(String url, ParameterizedTypeReference responseType) { + return get(url, null, responseType); + } + + /** + * 带Token的GET请求 + * @param url 请求URL + * @param token 认证Token + * @param responseType 响应数据类型 + * @param 响应数据泛型 + * @return 响应结果 + */ + public T get(String url, String token, ParameterizedTypeReference responseType) { + HttpEntity entity = createHttpEntity(token, null); + ResponseEntity response = restTemplate.exchange( + url, + HttpMethod.GET, + entity, + responseType + ); + return response.getBody(); + } + + /** + * 带路径参数和Token的GET请求 + * @param url 请求URL,包含路径参数占位符,如"/user/{id}" + * @param token 认证Token + * @param uriVariables 路径参数键值对 + * @param responseType 响应数据类型 + * @param 响应数据泛型 + * @return 响应结果 + */ + public T get(String url, String token, Map uriVariables, ParameterizedTypeReference responseType) { + HttpEntity entity = createHttpEntity(token, null); + ResponseEntity response = restTemplate.exchange( + url, + HttpMethod.GET, + entity, + responseType, + uriVariables + ); + return response.getBody(); + } + + /** + * 不带Token的POST请求 + * @param url 请求URL + * @param requestBody 请求体 + * @param responseType 响应数据类型 + * @param 响应数据泛型 + * @param 请求体泛型 + * @return 响应结果 + */ + public T post(String url, R requestBody, ParameterizedTypeReference responseType) { + return post(url, null, requestBody, responseType); + } + + /** + * 带Token的POST请求 + * @param url 请求URL + * @param token 认证Token + * @param requestBody 请求体 + * @param responseType 响应数据类型 + * @param 响应数据泛型 + * @param 请求体泛型 + * @return 响应结果 + */ + public T post(String url, String token, R requestBody, ParameterizedTypeReference responseType) { + HttpEntity entity = createHttpEntity(token, requestBody); + ResponseEntity response = restTemplate.exchange( + url, + HttpMethod.POST, + entity, + responseType + ); + return response.getBody(); + } + + /** + * 带Token的PUT请求 + * @param url 请求URL + * @param token 认证Token + * @param requestBody 请求体 + * @param responseType 响应数据类型 + * @param 响应数据泛型 + * @param 请求体泛型 + * @return 响应结果 + */ + public T put(String url, String token, R requestBody, ParameterizedTypeReference responseType) { + HttpEntity entity = createHttpEntity(token, requestBody); + ResponseEntity response = restTemplate.exchange( + url, + HttpMethod.PUT, + entity, + responseType + ); + return response.getBody(); + } + + /** + * 带Token的DELETE请求 + * @param url 请求URL + * @param token 认证Token + * @param responseType 响应数据类型 + * @param 响应数据泛型 + * @return 响应结果 + */ + public T delete(String url, String token, ParameterizedTypeReference responseType) { + HttpEntity entity = createHttpEntity(token, null); + ResponseEntity response = restTemplate.exchange( + url, + HttpMethod.DELETE, + entity, + responseType + ); + return response.getBody(); + } + + /** + * 创建HTTP请求实体,包含 headers 和 body + * @param token 认证Token,可为null + * @param body 请求体,可为null + * @param 请求体泛型 + * @return HttpEntity实例 + */ + private HttpEntity createHttpEntity(String token, R body) { + HttpHeaders headers = new HttpHeaders(); + // 复制默认请求头 + headers.putAll(defaultHeaders); + + // 如果有token,添加到请求头 + if (token != null && !token.trim().isEmpty()) { + headers.add("Authorization", "Bearer " + token); + } + + return new HttpEntity<>(body, headers); + } + + /** + * 添加默认请求头 + * @param name 头名称 + * @param value 头值 + */ + public void addDefaultHeader(String name, String value) { + defaultHeaders.add(name, value); + } + + /** + * 移除默认请求头 + * @param name 头名称 + */ + public void removeDefaultHeader(String name) { + defaultHeaders.remove(name); + } +} + diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index debe341..3e0c421 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -7,6 +7,7 @@ spring: config: import: classpath:config/database/application-database-dev.yml + # redis data: redis: @@ -15,7 +16,31 @@ spring: password: zhangsan database: 0 connect-timeout: 3000ms - + # rabbitmq 配置 + rabbitmq: + host: localhost + port: 5672 + # username: xiaodemo + # password: 1234 + username: zzw + password: zzw0401 + #虚拟host 可以不设置,使用server默认host + # virtual-host: /xiaodemos + #消息确认配置项 + publisher-returns: true #确认消息已发送到队列(Queue) + publisher-confirm-type: correlated + listener: # 手动确认消息配置 + simple: + acknowledge-mode: manual # 全局开启消费者手动确认 + # 优化配置 + concurrency: 1 # 最小消费者数 + max-concurrency: 5 # 最大消费者数 + prefetch: 1 # 每次从队列取1条消息,处理完再取(避免消息堆积) + retry: + enabled: true # 开启消费者重试(建议结合业务幂等性使用) + max-attempts: 3 # 最大重试次数 + initial-interval: 1000ms # 第一次重试间隔 + multiplier: 2 # 重试间隔倍数(第二次2s,第三次4s) # 日志配置 logging: level: @@ -43,15 +68,17 @@ safety: - /druid - /websocket/info - /websocket/** + - /open/** # 请求无需解密的路径 no-decrypt-paths: - /crypto/sm2/public-key - /druid - /websocket/info - /websocket/** + - /open/** # 算法服务器配置 algorithm: server: # 开发环境算法服务器地址 - url: http://localhost:8082 \ No newline at end of file + url: http://localhost:8082 diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index c0d816b..ae5c61f 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -15,6 +15,31 @@ spring: password: XAYJ@gis2603 database: 0 connect-timeout: 3000ms + # rabbitmq 配置 + rabbitmq: + host: localhost + port: 5672 + # username: xiaodemo + # password: 1234 + username: zzw + password: zzw0401 + #虚拟host 可以不设置,使用server默认host + # virtual-host: /xiaodemos + #消息确认配置项 + publisher-returns: true #确认消息已发送到队列(Queue) + publisher-confirm-type: correlated + listener: # 手动确认消息配置 + simple: + acknowledge-mode: manual # 全局开启消费者手动确认 + # 优化配置 + concurrency: 1 # 最小消费者数 + max-concurrency: 5 # 最大消费者数 + prefetch: 1 # 每次从队列取1条消息,处理完再取(避免消息堆积) + retry: + enabled: true # 开启消费者重试(建议结合业务幂等性使用) + max-attempts: 3 # 最大重试次数 + initial-interval: 1000ms # 第一次重试间隔 + multiplier: 2 # 重试间隔倍数(第二次2s,第三次4s) # 日志配置 logging: @@ -51,4 +76,4 @@ safety: algorithm: server: # 生产环境算法服务器地址 - url: http://localhost:8081 \ No newline at end of file + url: http://localhost:8081 diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 802ba4d..6e8e31a 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -5,9 +5,11 @@ spring: config: import: classpath:config/redis/redis-key.yml -# MyBatis 配置 -mybatis: +#mybatis-plus 配置 +mybatis-plus: mapper-locations: classpath:mapper/*.xml - type-aliases-package: com.gis.basic_template_not_login_back.entity + type-aliases-package: com.gis.xian.entity configuration: - map-underscore-to-camel-case: true \ No newline at end of file + map-underscore-to-camel-case: true + # 添加 TypeHandler 扫描包路径 + type-handlers-package: com.gis.xian.handler diff --git a/src/main/resources/config/database/application-database-dev.yml b/src/main/resources/config/database/application-database-dev.yml index 06f319f..1bbbaa7 100644 --- a/src/main/resources/config/database/application-database-dev.yml +++ b/src/main/resources/config/database/application-database-dev.yml @@ -35,4 +35,10 @@ spring: url: jdbc:postgresql://47.92.216.173:7654/assess_disaster?characterEncoding=utf8&TimeZone=Asia/Shanghai username: postgres password: zhangsan - driver-class-name: org.postgresql.Driver \ No newline at end of file + driver-class-name: org.postgresql.Driver + + slave1: + url: jdbc:postgresql://localhost:5432/yjzyk_xian?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai&postgis=true + username: postgres + password: Zzw.0401 + driver-class-name: org.postgresql.Driver diff --git a/src/main/resources/config/database/application-database-prod.yml b/src/main/resources/config/database/application-database-prod.yml index 04c4a33..bdc9c4b 100644 --- a/src/main/resources/config/database/application-database-prod.yml +++ b/src/main/resources/config/database/application-database-prod.yml @@ -32,4 +32,10 @@ spring: url: jdbc:postgresql://10.22.245.138:54321/xianDCAccess?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai username: zaihailian password: XAYJ@gis2603 - driver-class-name: org.postgresql.Driver \ No newline at end of file + driver-class-name: org.postgresql.Driver + + slave1: + url: jdbc:postgresql://localhost:5432/yjzyk_xian?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai&postgis=true + username: postgres + password: Zzw.0401 + driver-class-name: org.postgresql.Driver