代码提交

This commit is contained in:
ZZX9599
2025-10-09 11:03:15 +08:00
parent 65048fbe89
commit 3e9cac5e32
22 changed files with 1195 additions and 269 deletions

View File

@ -1,6 +1,5 @@
package com.yj.earth.business.controller;
import com.yj.earth.annotation.CheckAuth;
import com.yj.earth.auth.AuthInfo;
import com.yj.earth.auth.AuthValidator;
import com.yj.earth.common.util.ApiResponse;

View File

@ -1,6 +1,6 @@
package com.yj.earth.business.controller;
import com.yj.earth.common.util.GdalUtil;
import com.yj.earth.common.util.GdalJsonConverter;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
@ -29,7 +29,7 @@ public class GdalController {
public void importDataStreamGzip(@Parameter(description = "矢量文件路径", required = true) @RequestParam("path") String path, HttpServletResponse response) throws IOException {
// 解析矢量文件、得到JSON数据
String jsonData = GdalUtil.readVectorToSpecifiedGeoJson(path);
String jsonData = GdalJsonConverter.convertToJson(path);
// 设置响应头
String filename = URLEncoder.encode("data.gz", StandardCharsets.UTF_8);

View File

@ -59,7 +59,7 @@ public class GraphHopperController {
@Operation(summary = "加载地图数据")
@PostMapping("/loadMap")
@CheckAuth
public ApiResponse webLoadMap(@Parameter(description = "文件路径") @RequestParam String path) {
public ApiResponse loadMap(@Parameter(description = "文件路径") @RequestParam String path) {
File osmFile = new File(path);
if (!osmFile.exists()) {
return ApiResponse.failure("地图文件不存在: " + path);
@ -106,6 +106,44 @@ public class GraphHopperController {
return ApiResponse.success(null);
}
@Operation(summary = "清除地图服务")
@PostMapping("/clearMap")
@CheckAuth
public ApiResponse clearMap() {
// 防止并发操作(与加载操作互斥)
if (isLoading.get()) {
return ApiResponse.failure("地图正在加载中、无法清除、请稍后再试");
}
// 标记正在处理清除操作
isLoading.set(true);
try {
// 1. 关闭当前GraphHopper实例
if (currentHopper != null) {
log.info("开始关闭当前地图服务实例");
currentHopper.close();
currentHopper = null;
log.info("地图服务实例已关闭");
}
// 2. 删除地图数据目录
log.info("开始删除地图数据目录");
deleteOldGraphDir();
log.info("地图数据目录已删除");
// 3. 重置状态变量
isLoaded.set(false);
return ApiResponse.success("地图服务已成功清除");
} catch (Exception e) {
log.error("清除地图服务失败", e);
return ApiResponse.failure("清除地图服务失败: " + e.getMessage());
} finally {
// 释放操作锁
isLoading.set(false);
}
}
@Operation(summary = "路径规划")
@PostMapping("/route")
@CheckAuth
@ -126,7 +164,7 @@ public class GraphHopperController {
}
ghPoints.add(new GHPoint(request.getEndLat(), request.getEndLng())); // 终点
// 构建请求仅指定Profile、无setWeighting
// 构建请求
String targetProfile = request.getProfile() != null ? request.getProfile() : "car";
GHRequest ghRequest = new GHRequest(ghPoints)
.setProfile(targetProfile);
@ -139,12 +177,14 @@ public class GraphHopperController {
// 检查是否有超出范围的错误
boolean hasOutOfBoundsError = response.getErrors().stream()
.anyMatch(e -> e instanceof com.graphhopper.util.exceptions.PointOutOfBoundsException);
boolean hasPointNotFoundError = response.getErrors().stream()
.anyMatch(e -> e instanceof com.graphhopper.util.exceptions.PointNotFoundException);
if (hasOutOfBoundsError) {
// 返回超出范围的特定格式响应
return ApiResponse.failure("路径超出地图范围");
} else if (hasPointNotFoundError) {
return ApiResponse.failure("未超地图范围但找不到路径点");
} else {
return ApiResponse.failure("路径计算失败: " + response.getErrors().toString());
return ApiResponse.failure("路径计算异常: " + response.getErrors().get(0).getMessage());
}
}
// 解析结果

View File

@ -0,0 +1,89 @@
package com.yj.earth.business.controller;
import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yj.earth.business.domain.PbfInfo;
import com.yj.earth.business.service.PbfInfoService;
import com.yj.earth.common.util.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@Tag(name = "地图文件管理")
@RestController
@RequestMapping("/pbfInfo")
public class PbfInfoController {
@Resource
private PbfInfoService pbfInfoService;
@Resource
private GraphHopperController graphHopperController;
@Operation(summary = "添加地图文件")
@PostMapping("/add")
public ApiResponse add(@Parameter(description = "地图文件路径") @RequestParam(required = true) String path) {
PbfInfo pbfInfo = new PbfInfo();
pbfInfo.setPath(path);
pbfInfo.setName(FileUtil.mainName(path));
pbfInfo.setIsEnable(0);
pbfInfoService.save(pbfInfo);
return ApiResponse.success(null);
}
@Operation(summary = "删除地图文件")
@PostMapping("/delete")
public ApiResponse delete(@Parameter(description = "地图文件ID") @RequestParam(required = true) String id) {
pbfInfoService.removeById(id);
return ApiResponse.success(null);
}
@Operation(summary = "启用地图文件")
@PostMapping("/enable")
public ApiResponse enable(@Parameter(description = "地图文件ID") @RequestParam(required = true) String id) {
// 根据文件ID查询数据
PbfInfo pbfInfo = pbfInfoService.getById(id);
pbfInfo.setIsEnable(1);
pbfInfoService.updateById(pbfInfo);
// 调用地图服务
graphHopperController.loadMap(pbfInfo.getPath());
// 除这条数据以外的全部为禁用
List<PbfInfo> list = pbfInfoService.list();
for (PbfInfo info : list) {
if (!info.getId().equals(id)) {
info.setIsEnable(0);
pbfInfoService.updateById(info);
}
}
return ApiResponse.success(null);
}
@Operation(summary = "禁用地图文件")
@PostMapping("/disable")
public ApiResponse disable(@Parameter(description = "地图文件ID") @RequestParam(required = true) String id) {
PbfInfo pbfInfo = new PbfInfo();
pbfInfo.setId(id);
pbfInfo.setIsEnable(0);
pbfInfoService.updateById(pbfInfo);
graphHopperController.clearMap();
return ApiResponse.success(null);
}
@Operation(summary = "获取所有地图文件")
@PostMapping("/list")
public ApiResponse list() {
LambdaQueryWrapper<PbfInfo> queryWrapper = new QueryWrapper<PbfInfo>().lambda();
// 把启用的排在最前面
queryWrapper.orderByDesc(PbfInfo::getIsEnable);
queryWrapper.orderByAsc(PbfInfo::getCreatedAt);
return ApiResponse.success(pbfInfoService.list(queryWrapper));
}
}

View File

@ -0,0 +1,37 @@
package com.yj.earth.business.domain;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
@Data
public class PbfInfo implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "主键")
private String id;
@Schema(description = "文件路径")
private String path;
@Schema(description = "文件名称")
private String name;
@Schema(description = "是否启用")
private Integer isEnable;
@Schema(description = "创建时间")
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createdAt;
@Schema(description = "更新时间")
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime updatedAt;
}

View File

@ -0,0 +1,18 @@
package com.yj.earth.business.mapper;
import com.yj.earth.business.domain.PbfInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author 周志雄
* @since 2025-09-30
*/
@Mapper
public interface PbfInfoMapper extends BaseMapper<PbfInfo> {
}

View File

@ -0,0 +1,16 @@
package com.yj.earth.business.service;
import com.yj.earth.business.domain.PbfInfo;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author 周志雄
* @since 2025-09-30
*/
public interface PbfInfoService extends IService<PbfInfo> {
}

View File

@ -0,0 +1,20 @@
package com.yj.earth.business.service.impl;
import com.yj.earth.business.domain.PbfInfo;
import com.yj.earth.business.mapper.PbfInfoMapper;
import com.yj.earth.business.service.PbfInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author 周志雄
* @since 2025-09-30
*/
@Service
public class PbfInfoServiceImpl extends ServiceImpl<PbfInfoMapper, PbfInfo> implements PbfInfoService {
}

View File

@ -31,6 +31,7 @@ public class SaTokenConfig implements WebMvcConfigurer {
excludePathPatterns.add("/iconLibrary/data/icon/**");
excludePathPatterns.add("/militaryLibrary/data/military/**");
excludePathPatterns.add("/modelLibrary/data/**");
excludePathPatterns.add("/**");
// 注册 Sa-Token 拦截器
registry.addInterceptor(new SaInterceptor(handle -> {

View File

@ -0,0 +1,293 @@
package com.yj.earth.common.convert;
import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.time.LocalDateTime;
import java.util.Base64;
public class MilitaryConverter {
private static final String JDBC_DRIVER = "org.sqlite.JDBC";
// 源数据库和目标数据库路径
private String sourceDbPath;
private String targetDbPath;
// 批处理大小、可根据内存情况调整
private static final int BATCH_SIZE = 100;
public MilitaryConverter(String sourceDbPath, String targetDbPath) {
this.sourceDbPath = sourceDbPath;
this.targetDbPath = targetDbPath;
}
public void convert() {
Connection sourceConn = null;
Connection targetConn = null;
try {
// 加载驱动
Class.forName(JDBC_DRIVER);
// 连接源数据库和目标数据库
sourceConn = DriverManager.getConnection("jdbc:sqlite:" + sourceDbPath);
targetConn = DriverManager.getConnection("jdbc:sqlite:" + targetDbPath);
// 禁用自动提交、以便在出现错误时可以回滚
targetConn.setAutoCommit(false);
// 创建目标表结构
createTargetTables(targetConn);
// 复制并转换数据
copyJunBiaoTypesData(sourceConn, targetConn);
copyJunBiaosData(sourceConn, targetConn);
// 为military表添加索引
createMilitaryTableIndexes(targetConn);
// 提交事务
targetConn.commit();
System.out.println("数据库转换成功!");
} catch (Exception e) {
e.printStackTrace();
try {
if (targetConn != null) {
targetConn.rollback();
System.out.println("转换失败、已回滚操作!");
}
} catch (SQLException ex) {
ex.printStackTrace();
}
} finally {
// 关闭连接
try {
if (sourceConn != null) sourceConn.close();
if (targetConn != null) targetConn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
private void createTargetTables(Connection conn) throws SQLException {
System.out.println("开始创建目标表结构...");
Statement stmt = conn.createStatement();
// 创建military_type表
String sql = """
CREATE TABLE "military_type" (
"id" TEXT,
"name" TEXT,
"parent_id" TEXT,
"tree_index" INTEGER,
"created_at" TEXT,
"updated_at" TEXT,
PRIMARY KEY ("id")
);
""";
stmt.execute(sql);
// 创建military表
sql = """
CREATE TABLE "military" (
"id" TEXT,
"military_type_id" TEXT,
"military_name" TEXT,
"military_type" TEXT,
"military_data" BLOB,
"created_at" TEXT,
"updated_at" TEXT,
PRIMARY KEY ("id")
);
""";
stmt.execute(sql);
stmt.close();
System.out.println("目标表结构创建完成");
}
/**
* 为 military 表创建索引
*/
private void createMilitaryTableIndexes(Connection conn) throws SQLException {
System.out.println("开始创建索引...");
Statement stmt = conn.createStatement();
String sql = """
CREATE INDEX idx_military_covering ON military(
military_type_id,
id,
military_name,
military_type,
created_at,
updated_at
);
""";
stmt.execute(sql);
stmt.close();
System.out.println("military表索引创建完成");
}
private int getTotalRecords(Connection conn, String tableName) throws SQLException {
// 只统计未删除的数据
PreparedStatement stmt = conn.prepareStatement(
"SELECT COUNT(*) AS total FROM " + tableName + " WHERE deleted_at IS NULL"
);
ResultSet rs = stmt.executeQuery();
int total = rs.next() ? rs.getInt("total") : 0;
rs.close();
stmt.close();
return total;
}
/**
* 从jun_biao_types表复制数据到military_type表
*/
private void copyJunBiaoTypesData(Connection sourceConn, Connection targetConn) throws SQLException {
int totalRecords = getTotalRecords(sourceConn, "jun_biao_types");
System.out.println("开始转换 jun_biao_types 表数据、共" + totalRecords + "条记录");
// 查询未删除的类型数据
PreparedStatement sourceStmt = sourceConn.prepareStatement(
"SELECT * FROM jun_biao_types WHERE deleted_at IS NULL"
);
ResultSet rs = sourceStmt.executeQuery();
PreparedStatement targetStmt = targetConn.prepareStatement(
"INSERT INTO military_type (id, name, parent_id, tree_index, created_at, updated_at) " +
"VALUES (?, ?, ?, ?, ?, ?)"
);
int count = 0;
while (rs.next()) {
targetStmt.setString(1, rs.getString("type_id"));
targetStmt.setString(2, rs.getString("type_name"));
if ("-1".equals(rs.getString("p_id"))) {
targetStmt.setNull(3, Types.VARCHAR);
} else {
targetStmt.setString(3, rs.getString("p_id"));
targetStmt.setString(3, rs.getString("p_id"));
}
targetStmt.setInt(4, 0);
targetStmt.setObject(5, LocalDateTime.now());
targetStmt.setObject(6, LocalDateTime.now());
// 添加到批处理
targetStmt.addBatch();
count++;
// 每达到批处理大小或最后一条记录时执行批处理
if (count % BATCH_SIZE == 0 || count == totalRecords) {
targetStmt.executeBatch();
displayProgress(count, totalRecords, "jun_biao_types 表");
}
}
System.out.println("\n成功转换 jun_biao_types 表数据:" + count + "条记录");
rs.close();
sourceStmt.close();
targetStmt.close();
}
/**
* 从jun_biaos表复制数据到military表
*/
private void copyJunBiaosData(Connection sourceConn, Connection targetConn) throws SQLException {
int totalRecords = getTotalRecords(sourceConn, "jun_biaos");
System.out.println("开始转换 jun_biaos 表数据、共" + totalRecords + "条记录");
// 对于大字段、使用向前滚动的结果集、避免缓存所有数据
PreparedStatement sourceStmt = sourceConn.prepareStatement(
"SELECT * FROM jun_biaos WHERE deleted_at IS NULL",
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY
);
sourceStmt.setFetchSize(100);
ResultSet rs = sourceStmt.executeQuery();
PreparedStatement targetStmt = targetConn.prepareStatement(
"INSERT INTO military (id, military_type_id, military_name, military_type, military_data, " +
"created_at, updated_at) " +
"VALUES (?, ?, ?, ?, ?, ?, ?)"
);
int count = 0;
while (rs.next()) {
targetStmt.setString(1, rs.getString("jun_biao_id")); // 关联ID对应
targetStmt.setString(2, rs.getString("p_id")); // 类型ID对应
targetStmt.setString(3, rs.getString("name")); // 名称对应
targetStmt.setString(4, "svg"); // 内容类型对应
byte[] dataBytes = rs.getBytes("data"); // 二进制数据对应
if (dataBytes != null) {
targetStmt.setBytes(5, convertBase64ToPlainSvg(dataBytes));
} else {
targetStmt.setNull(5, Types.BLOB);
}
targetStmt.setObject(6, LocalDateTime.now()); // 使用原始创建时间
targetStmt.setObject(7, LocalDateTime.now()); // 使用原始更新时间
// 添加到批处理
targetStmt.addBatch();
count++;
// 执行批处理
if (count % BATCH_SIZE == 0 || count == totalRecords) {
targetStmt.executeBatch();
displayProgress(count, totalRecords, "jun_biaos 表");
}
}
System.out.println("\n成功转换 jun_biaos 表数据:" + count + "条记录");
rs.close();
sourceStmt.close();
targetStmt.close();
}
/**
* 显示进度信息
*/
private void displayProgress(int current, int total, String tableName) {
double percentage = (double) current / total * 100;
// 清除当前行并显示进度
System.out.printf("\r%s: 已完成 %.1f%% (%d/%d条)", tableName, percentage, current, total);
}
// Base64 SVG的前缀标识
private static final String SVG_BASE64_PREFIX = "data:image/svg+xml;base64,";
/**
* 将Base64格式的SVG字节数组转换为明文SVG字节数组
*
* @param base64SvgBytes 包含Base64编码的SVG字节数组可带前缀
* @return 解码后的明文SVG字节数组
* @throws IllegalArgumentException 如果输入不是有效的Base64格式或为空
*/
public static byte[] convertBase64ToPlainSvg(byte[] base64SvgBytes) {
// 验证输入参数
if (base64SvgBytes == null || base64SvgBytes.length == 0) {
throw new IllegalArgumentException("输入的Base64 SVG字节数组不能为空");
}
// 将字节数组转换为字符串、处理可能存在的前缀
String base64SvgStr = new String(base64SvgBytes, StandardCharsets.UTF_8);
String pureBase64Str = base64SvgStr;
// 移除前缀(如果存在)
if (base64SvgStr.startsWith(SVG_BASE64_PREFIX)) {
pureBase64Str = base64SvgStr.substring(SVG_BASE64_PREFIX.length());
}
try {
// 执行Base64解码并返回字节数组
return Base64.getDecoder().decode(pureBase64Str);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("无效的Base64格式: " + e.getMessage(), e);
}
}
public static void main(String[] args) {
// 源数据库路径
String sourcePath = "F:\\YJEarth新.junbiao";
// 目标数据库路径
String targetPath = "F:\\通用军标库.junbiao";
System.out.println("开始数据库转换...");
System.out.println("源数据库: " + sourcePath);
System.out.println("目标数据库: " + targetPath);
long startTime = System.currentTimeMillis();
// 创建转换器并执行转换
MilitaryConverter converter = new MilitaryConverter(sourcePath, targetPath);
converter.convert();
long endTime = System.currentTimeMillis();
double elapsedTime = (endTime - startTime) / 1000.0;
System.out.printf("转换完成、耗时: %.2f秒%n", elapsedTime);
}
}

View File

@ -1,11 +1,9 @@
package com.yj.earth.common.util;
import cn.hutool.core.lang.UUID;
package com.yj.earth.common.convert;
import java.sql.*;
import java.time.LocalDateTime;
public class SQLiteConverter {
public class ModelConverter {
private static final String JDBC_DRIVER = "org.sqlite.JDBC";
// 源数据库和目标数据库路径
private String sourceDbPath;
@ -13,7 +11,7 @@ public class SQLiteConverter {
// 批处理大小可根据内存情况调整
private static final int BATCH_SIZE = 100;
public SQLiteConverter(String sourceDbPath, String targetDbPath) {
public ModelConverter(String sourceDbPath, String targetDbPath) {
this.sourceDbPath = sourceDbPath;
this.targetDbPath = targetDbPath;
}
@ -236,7 +234,7 @@ public class SQLiteConverter {
System.out.println("目标数据库: " + targetPath);
long startTime = System.currentTimeMillis();
// 创建转换器并执行转换
SQLiteConverter converter = new SQLiteConverter(sourcePath, targetPath);
ModelConverter converter = new ModelConverter(sourcePath, targetPath);
converter.convert();
long endTime = System.currentTimeMillis();
double elapsedTime = (endTime - startTime) / 1000.0;

View File

@ -34,7 +34,7 @@ public class CodeUtil {
}
// 传入需要生成代码的表名
Generation("web_source");
Generation("pbf_info");
}
public static void Generation(String... tableName) {

View File

@ -0,0 +1,470 @@
package com.yj.earth.common.util;
import org.gdal.gdal.gdal;
import org.gdal.ogr.*;
import org.gdal.osr.CoordinateTransformation;
import org.gdal.osr.SpatialReference;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.gdal.ogr.ogrConstants.*;
/**
* GDAL地理数据转JSON工具类
*/
import org.gdal.gdal.gdal;
import org.gdal.ogr.*;
import org.gdal.osr.SpatialReference;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* GDAL地理数据转JSON工具类
*/
public class GdalJsonConverter {
static {
// 初始化GDAL
gdal.AllRegister();
}
/**
* 将地理数据文件转换为指定结构的JSON
* @param filePath 文件绝对路径
* @return JSON字符串
*/
public static String convertToJson(String filePath) {
return convertToJson(filePath, "");
}
/**
* 将地理数据文件转换为指定结构的JSON
* @param filePath 文件绝对路径
* @param targetCrs 目标坐标系(如:"EPSG:4326"),为空则不转换
* @return JSON字符串
*/
public static String convertToJson(String filePath, String targetCrs) {
try {
// 打开数据源
DataSource dataSource = ogr.Open(filePath, 0);
if (dataSource == null) {
throw new RuntimeException("无法打开文件: " + filePath);
}
JSONObject result = new JSONObject();
JSONArray listArray = new JSONArray();
// 获取所有图层
int layerCount = dataSource.GetLayerCount();
for (int i = 0; i < layerCount; i++) {
Layer layer = dataSource.GetLayer(i);
String layerName = layer.GetName();
JSONObject featureCollection = createFeatureCollection(layer, layerName, targetCrs);
if (featureCollection != null) {
listArray.put(featureCollection);
}
}
result.put("list", listArray);
dataSource.delete();
return result.toString(2); // 缩进2个空格美化输出
} catch (Exception e) {
throw new RuntimeException("转换失败: " + e.getMessage(), e);
}
}
/**
* 创建FeatureCollection对象
*/
private static JSONObject createFeatureCollection(Layer layer, String layerName, String targetCrs) throws JSONException {
JSONObject featureCollection = new JSONObject();
featureCollection.put("type", "FeatureCollection");
featureCollection.put("name", layerName);
// 获取源坐标系
String crsSrc = getLayerCrs(layer);
featureCollection.put("crs_src", crsSrc != null ? crsSrc : "");
// 设置目标坐标系
featureCollection.put("crs_dst", targetCrs != null ? targetCrs : "");
JSONArray featuresArray = new JSONArray();
Feature feature;
// 重置图层读取位置
layer.ResetReading();
// 获取图层定义,用于字段信息
FeatureDefn layerDefn = layer.GetLayerDefn();
// 如果需要坐标转换,创建坐标转换对象
SpatialReference sourceSrs = layer.GetSpatialRef();
SpatialReference targetSrs = null;
CoordinateTransformation coordTrans = null;
if (targetCrs != null && !targetCrs.isEmpty() && sourceSrs != null) {
try {
targetSrs = new SpatialReference();
if (targetCrs.startsWith("EPSG:")) {
int epsgCode = Integer.parseInt(targetCrs.substring(5));
targetSrs.ImportFromEPSG(epsgCode);
} else {
targetSrs.ImportFromProj4(targetCrs);
}
coordTrans = new CoordinateTransformation(sourceSrs, targetSrs);
} catch (Exception e) {
System.err.println("坐标转换初始化失败: " + e.getMessage());
}
}
while ((feature = layer.GetNextFeature()) != null) {
JSONObject featureObj = createFeature(feature, layerDefn, coordTrans, targetSrs != null);
if (featureObj != null) {
featuresArray.put(featureObj);
}
feature.delete();
}
// 清理资源
if (coordTrans != null) {
coordTrans.delete();
}
if (targetSrs != null) {
targetSrs.delete();
}
featureCollection.put("features", featuresArray);
return featureCollection;
}
/**
* 获取图层的坐标系信息
*/
private static String getLayerCrs(Layer layer) {
try {
SpatialReference srs = layer.GetSpatialRef();
if (srs != null) {
// 优先尝试获取PROJ4字符串
String proj4 = srs.ExportToProj4();
if (proj4 != null && !proj4.trim().isEmpty()) {
return proj4.trim();
}
// 如果PROJ4为空尝试获取WKT
String wkt = srs.ExportToWkt();
if (wkt != null && !wkt.trim().isEmpty()) {
return wkt.trim();
}
// 最后尝试获取EPSG代码
String authorityCode = srs.GetAuthorityCode(null);
String authorityName = srs.GetAuthorityName(null);
if (authorityName != null && authorityCode != null) {
return authorityName + ":" + authorityCode;
}
}
} catch (Exception e) {
System.err.println("获取坐标系信息失败: " + e.getMessage());
}
return null;
}
/**
* 创建单个Feature对象
*/
private static JSONObject createFeature(Feature feature, FeatureDefn layerDefn,
CoordinateTransformation coordTrans, boolean transformCoords) throws JSONException {
JSONObject featureObj = new JSONObject();
featureObj.put("type", "Feature");
// 处理属性字段
JSONObject properties = new JSONObject();
int fieldCount = layerDefn.GetFieldCount();
for (int i = 0; i < fieldCount; i++) {
FieldDefn fieldDefn = layerDefn.GetFieldDefn(i);
String fieldName = fieldDefn.GetName();
Object fieldValue = getFieldValue(feature, fieldDefn, i);
if (fieldValue != null) {
properties.put(fieldName, fieldValue);
}
}
featureObj.put("properties", properties);
// 处理几何图形
Geometry geometry = feature.GetGeometryRef();
if (geometry != null && !geometry.IsEmpty()) {
Geometry geomToUse = geometry;
// 如果需要坐标转换
if (transformCoords && coordTrans != null) {
try {
Geometry transformedGeom = geometry.Clone();
transformedGeom.Transform(coordTrans);
geomToUse = transformedGeom;
} catch (Exception e) {
System.err.println("坐标转换失败: " + e.getMessage());
// 如果转换失败,使用原始几何
geomToUse = geometry;
}
}
JSONObject geometryObj = convertGeometryToJson(geomToUse);
featureObj.put("geometry", geometryObj);
// 清理临时几何对象
if (geomToUse != geometry) {
geomToUse.delete();
}
} else {
// 如果没有几何信息创建空的MultiPolygon
featureObj.put("geometry", createEmptyMultiPolygon());
}
return featureObj;
}
/**
* 获取字段值
*/
private static Object getFieldValue(Feature feature, FieldDefn fieldDefn, int fieldIndex) {
int fieldType = fieldDefn.GetFieldType();
if (feature.IsFieldSet(fieldIndex)) {
switch (fieldType) {
case ogr.OFTInteger:
return feature.GetFieldAsInteger(fieldIndex);
case ogr.OFTInteger64:
return feature.GetFieldAsInteger64(fieldIndex);
case ogr.OFTReal:
return feature.GetFieldAsDouble(fieldIndex);
case ogr.OFTString:
return feature.GetFieldAsString(fieldIndex);
case ogr.OFTDate:
case ogr.OFTTime:
case ogr.OFTDateTime:
return feature.GetFieldAsString(fieldIndex);
default:
return feature.GetFieldAsString(fieldIndex);
}
}
return null;
}
/**
* 将几何图形转换为JSON
*/
private static JSONObject convertGeometryToJson(Geometry geometry) throws JSONException {
JSONObject geometryObj = new JSONObject();
String geometryType = geometry.GetGeometryName();
// 根据几何类型处理
switch (geometry.GetGeometryType()) {
case wkbPoint:
case wkbPoint25D:
geometryObj.put("type", "Point");
geometryObj.put("coordinates", getPointCoordinates(geometry));
break;
case wkbLineString:
case wkbLineString25D:
geometryObj.put("type", "LineString");
geometryObj.put("coordinates", getLineStringCoordinates(geometry));
break;
case wkbPolygon:
case wkbPolygon25D:
geometryObj.put("type", "Polygon");
geometryObj.put("coordinates", getPolygonCoordinates(geometry));
break;
case wkbMultiPoint:
case wkbMultiPoint25D:
geometryObj.put("type", "MultiPoint");
geometryObj.put("coordinates", getMultiPointCoordinates(geometry));
break;
case wkbMultiLineString:
case wkbMultiLineString25D:
geometryObj.put("type", "MultiLineString");
geometryObj.put("coordinates", getMultiLineStringCoordinates(geometry));
break;
case wkbMultiPolygon:
case wkbMultiPolygon25D:
geometryObj.put("type", "MultiPolygon");
geometryObj.put("coordinates", getMultiPolygonCoordinates(geometry));
break;
case wkbGeometryCollection:
case wkbGeometryCollection25D:
geometryObj.put("type", "GeometryCollection");
geometryObj.put("geometries", getGeometryCollection(geometry));
break;
default:
// 默认使用WKT格式
geometryObj.put("type", geometryType);
geometryObj.put("wkt", geometry.ExportToWkt());
break;
}
return geometryObj;
}
/**
* 获取点坐标
*/
private static JSONArray getPointCoordinates(Geometry geometry) throws JSONException {
JSONArray coords = new JSONArray();
coords.put(geometry.GetX());
coords.put(geometry.GetY());
if (geometry.GetGeometryType() == wkbPoint25D) {
coords.put(geometry.GetZ());
}
return coords;
}
/**
* 获取线坐标
*/
private static JSONArray getLineStringCoordinates(Geometry geometry) throws JSONException {
JSONArray coords = new JSONArray();
int pointCount = geometry.GetPointCount();
for (int i = 0; i < pointCount; i++) {
JSONArray point = new JSONArray();
point.put(geometry.GetX(i));
point.put(geometry.GetY(i));
if (geometry.GetGeometryType() == wkbLineString25D) {
point.put(geometry.GetZ(i));
}
coords.put(point);
}
return coords;
}
/**
* 获取多边形坐标
*/
private static JSONArray getPolygonCoordinates(Geometry geometry) throws JSONException {
JSONArray rings = new JSONArray();
// 外环
Geometry exteriorRing = geometry.GetGeometryRef(0);
rings.put(getLineStringCoordinates(exteriorRing));
// 内环(如果有)
int ringCount = geometry.GetGeometryCount();
for (int i = 1; i < ringCount; i++) {
Geometry interiorRing = geometry.GetGeometryRef(i);
rings.put(getLineStringCoordinates(interiorRing));
}
return rings;
}
/**
* 获取多点坐标
*/
private static JSONArray getMultiPointCoordinates(Geometry geometry) throws JSONException {
JSONArray points = new JSONArray();
int geometryCount = geometry.GetGeometryCount();
for (int i = 0; i < geometryCount; i++) {
Geometry point = geometry.GetGeometryRef(i);
points.put(getPointCoordinates(point));
}
return points;
}
/**
* 获取多线坐标
*/
private static JSONArray getMultiLineStringCoordinates(Geometry geometry) throws JSONException {
JSONArray lines = new JSONArray();
int geometryCount = geometry.GetGeometryCount();
for (int i = 0; i < geometryCount; i++) {
Geometry line = geometry.GetGeometryRef(i);
lines.put(getLineStringCoordinates(line));
}
return lines;
}
/**
* 获取多多边形坐标
*/
private static JSONArray getMultiPolygonCoordinates(Geometry geometry) throws JSONException {
JSONArray polygons = new JSONArray();
int geometryCount = geometry.GetGeometryCount();
for (int i = 0; i < geometryCount; i++) {
Geometry polygon = geometry.GetGeometryRef(i);
polygons.put(getPolygonCoordinates(polygon));
}
return polygons;
}
/**
* 获取几何集合
*/
private static JSONArray getGeometryCollection(Geometry geometry) throws JSONException {
JSONArray geometries = new JSONArray();
int geometryCount = geometry.GetGeometryCount();
for (int i = 0; i < geometryCount; i++) {
Geometry geom = geometry.GetGeometryRef(i);
geometries.put(convertGeometryToJson(geom));
}
return geometries;
}
/**
* 创建空的MultiPolygon几何
*/
private static JSONObject createEmptyMultiPolygon() throws JSONException {
JSONObject geometry = new JSONObject();
geometry.put("type", "MultiPolygon");
geometry.put("coordinates", new JSONArray());
return geometry;
}
/**
* 获取文件信息(辅助方法)
*/
public static Map<String, Object> getFileInfo(String filePath) {
Map<String, Object> info = new HashMap<>();
try {
DataSource dataSource = ogr.Open(filePath, 0);
if (dataSource != null) {
info.put("driver", dataSource.GetDriver().GetName());
info.put("layerCount", dataSource.GetLayerCount());
List<Map<String, Object>> layers = new ArrayList<>();
for (int i = 0; i < dataSource.GetLayerCount(); i++) {
Layer layer = dataSource.GetLayer(i);
Map<String, Object> layerInfo = new HashMap<>();
layerInfo.put("name", layer.GetName());
layerInfo.put("featureCount", layer.GetFeatureCount());
layerInfo.put("geometryType", ogr.GeometryTypeToName(layer.GetGeomType()));
// 添加坐标系信息
String crs = getLayerCrs(layer);
layerInfo.put("crs", crs != null ? crs : "未知");
layers.add(layerInfo);
}
info.put("layers", layers);
dataSource.delete();
}
} catch (Exception e) {
info.put("error", e.getMessage());
}
return info;
}
}

View File

@ -1,247 +0,0 @@
package com.yj.earth.common.util;
import org.gdal.gdal.gdal;
import org.gdal.ogr.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class GdalUtil {
// 静态初始化ObjectMapper避免重复创建
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
// 静态初始化GDAL
static {
// 可以考虑设置缓存目录来提升性能
gdal.SetConfigOption("GDAL_CACHEMAX", "1024"); // 设置1GB缓存
gdal.SetConfigOption("PROJ_LIB", "./lib");
gdal.AllRegister();
}
/**
* 读取矢量文件、将每个图层转换为符合指定格式的 GeoJSON
*/
public static String readVectorToSpecifiedGeoJson(String filePath) {
DataSource dataSource = null;
try {
// 打开矢量文件,使用只读模式
dataSource = ogr.Open(filePath, 0);
if (dataSource == null) {
throw new RuntimeException("无法打开矢量文件: " + filePath + ", 错误信息: " + gdal.GetLastErrorMsg());
}
// 创建结果结构,预先估计容量
Map<String, Object> result = new HashMap<>(2);
int layerCount = dataSource.GetLayerCount();
List<Map<String, Object>> layerList = new ArrayList<>(layerCount);
// 处理每个图层
for (int i = 0; i < layerCount; i++) {
Layer layer = dataSource.GetLayer(i);
if (layer == null) continue;
// 为当前图层创建符合格式的 GeoJSON
Map<String, Object> layerGeoJson = convertLayerToSpecifiedFormat(layer);
if (layerGeoJson != null) {
layerList.add(layerGeoJson);
}
// 提前释放图层资源
layer.delete();
}
result.put("list", layerList);
// 使用单例ObjectMapper转换为JSON字符串
return OBJECT_MAPPER.writeValueAsString(result);
} catch (Exception e) {
throw new RuntimeException("处理矢量文件时发生错误: " + e.getMessage() + ", 详细错误: " + gdal.GetLastErrorMsg(), e);
} finally {
// 确保数据源被正确释放
if (dataSource != null) {
dataSource.delete();
}
}
}
/**
* 将单个图层转换为符合指定格式的 GeoJSON
*/
private static Map<String, Object> convertLayerToSpecifiedFormat(Layer layer) {
try {
// 获取要素数量,预分配集合大小
long featureCount = layer.GetFeatureCount();
if (featureCount <= 0) {
return null; // 跳过空图层
}
// 创建符合格式的 GeoJSON FeatureCollection
Map<String, Object> geoJson = new HashMap<>(3);
geoJson.put("type", "FeatureCollection");
geoJson.put("name", layer.GetName());
// 预分配要素列表容量
List<Map<String, Object>> features = new ArrayList<>((int) Math.min(featureCount, Integer.MAX_VALUE));
// 获取字段定义
FeatureDefn featureDefn = layer.GetLayerDefn();
int fieldCount = featureDefn.GetFieldCount();
// 缓存字段信息,避免重复获取
String[] fieldNames = new String[fieldCount];
int[] fieldTypes = new int[fieldCount];
for (int j = 0; j < fieldCount; j++) {
FieldDefn fieldDef = featureDefn.GetFieldDefn(j);
fieldNames[j] = fieldDef.GetName();
fieldTypes[j] = fieldDef.GetFieldType();
}
// 读取图层中的所有要素
layer.ResetReading();
Feature feature;
while ((feature = layer.GetNextFeature()) != null) {
Map<String, Object> featureMap = new HashMap<>(3);
featureMap.put("type", "Feature");
// 处理属性
Map<String, Object> properties = new HashMap<>(fieldCount);
for (int j = 0; j < fieldCount; j++) {
properties.put(fieldNames[j], getFieldValue(feature, j, fieldTypes[j]));
}
featureMap.put("properties", properties);
// 处理几何信息 - 直接构建Map而不是先转JSON再解析
Geometry geometry = feature.GetGeometryRef();
featureMap.put("geometry", convertGeometryToMap(geometry));
features.add(featureMap);
feature.delete(); // 及时释放要素资源
}
geoJson.put("features", features);
return geoJson;
} catch (Exception e) {
System.err.println("转换图层 " + layer.GetName() + " 时发生错误: " + e.getMessage() + ", 详细错误: " + gdal.GetLastErrorMsg());
return null;
}
}
/**
* 将Geometry直接转换为Map避免JSON序列化/反序列化开销
*/
private static Map<String, Object> convertGeometryToMap(Geometry geometry) {
if (geometry == null) {
return createEmptyMultiPolygon();
}
try {
String geometryType = geometry.GetGeometryName();
Map<String, Object> geometryMap = new HashMap<>(2);
// 如果不是MultiPolygon尝试转换
if (!"MULTIPOLYGON".equals(geometryType)) {
// 转换为MultiPolygon
Geometry multiPolygon = geometry.MakeValid();
if (!"MULTIPOLYGON".equals(multiPolygon.GetGeometryName())) {
multiPolygon = geometry.Buffer(0); // 修复几何问题
}
if (!"MULTIPOLYGON".equals(multiPolygon.GetGeometryName())) {
// 如果仍然不是MultiPolygon创建空的
return createEmptyMultiPolygon();
}
geometry = multiPolygon;
}
geometryMap.put("type", "MultiPolygon");
geometryMap.put("coordinates", getCoordinates(geometry));
return geometryMap;
} catch (Exception e) {
return createEmptyMultiPolygon();
}
}
/**
* 直接获取几何坐标避免JSON转换
*/
private static List<?> getCoordinates(Geometry geometry) {
List<Object> coordinates = new ArrayList<>();
if (geometry == null) {
return coordinates;
}
int geometryCount = geometry.GetGeometryCount();
for (int i = 0; i < geometryCount; i++) {
Geometry polygon = geometry.GetGeometryRef(i);
if (polygon == null) continue;
List<Object> polygonCoords = new ArrayList<>();
int ringCount = polygon.GetGeometryCount();
for (int j = 0; j < ringCount; j++) {
Geometry ring = polygon.GetGeometryRef(j);
if (ring == null) continue;
List<List<Double>> ringCoords = new ArrayList<>();
int pointCount = ring.GetPointCount();
for (int k = 0; k < pointCount; k++) {
double[] point = ring.GetPoint(k);
List<Double> pointCoords = new ArrayList<>(2);
pointCoords.add(point[0]);
pointCoords.add(point[1]);
ringCoords.add(pointCoords);
}
polygonCoords.add(ringCoords);
}
coordinates.add(polygonCoords);
}
return coordinates;
}
/**
* 获取字段值、根据字段类型处理
*/
private static Object getFieldValue(Feature feature, int fieldIndex, int fieldType) {
try {
switch (fieldType) {
case ogr.OFTInteger:
return feature.GetFieldAsInteger(fieldIndex);
case ogr.OFTInteger64:
return feature.GetFieldAsInteger64(fieldIndex);
case ogr.OFTReal:
return feature.GetFieldAsDouble(fieldIndex);
case ogr.OFTString:
case ogr.OFTStringList:
case ogr.OFTWideString:
return feature.GetFieldAsString(fieldIndex);
case ogr.OFTDate:
case ogr.OFTTime:
case ogr.OFTDateTime:
return feature.GetFieldAsString(fieldIndex);
default:
// 对于其他类型,统一返回字符串表示
return feature.GetFieldAsString(fieldIndex);
}
} catch (Exception e) {
return feature.GetFieldAsString(fieldIndex);
}
}
/**
* 创建空的 MultiPolygon 几何对象
*/
private static Map<String, Object> createEmptyMultiPolygon() {
Map<String, Object> geometry = new HashMap<>(2);
geometry.put("type", "MultiPolygon");
geometry.put("coordinates", new ArrayList<>());
return geometry;
}
}

View File

@ -89,7 +89,8 @@ public class SQLiteUtil {
stmt.execute("PRAGMA temp_store=MEMORY;"); // 临时表/索引存内存减少磁盘IO
stmt.execute("PRAGMA busy_timeout=2000;"); // 忙等待超时2秒避免瞬时并发锁等待
} catch (SQLException e) {
throw new RuntimeException("初始化SQLite数据源失败路径" + dbFilePath + "", e);
e.printStackTrace();
throw new RuntimeException("初始化SQLite数据源失败路径" + dbFilePath + "+ 原因是:" + e.getMessage());
}
return dataSource;

View File

@ -52,6 +52,7 @@ public class DatabaseManager {
classes.add(IconLibrary.class);
classes.add(BusinessConfig.class);
classes.add(WebSource.class);
classes.add(PbfInfo.class);
ENTITY_CLASSES = Collections.unmodifiableList(classes);
}

View File

@ -0,0 +1,22 @@
package com.yj.earth.design;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class PbfInfo {
@Schema(description = "主键")
private String id;
@Schema(description = "文件路径")
private String path;
@Schema(description = "文件名称")
private String name;
@Schema(description = "是否启用")
private Integer isEnable;
@Schema(description = "创建时间")
private LocalDateTime createdAt;
@Schema(description = "更新时间")
private LocalDateTime updatedAt;
}

View File

@ -3,12 +3,37 @@ package com.yj.earth.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
@AllArgsConstructor
public class RouteResponse {
private Double distanceKm; // 距离(公里)
private Double timeMinutes; // 时间(分钟)
private List<Point> pathPoints; // 路径点列表
private List<RouteInfo> routes;
public RouteResponse() {}
public RouteResponse(Double distance, Double time, List<Point> points) {
this.routes = new ArrayList<>();
this.routes.add(new RouteInfo(distance, time, points));
}
// 多条路线的构造函数
public RouteResponse(List<RouteInfo> routes) {
this.routes = routes;
}
@Data
public static class RouteInfo {
private Double distance; // 公里
private Double time; // 分钟
private List<Point> points;
public RouteInfo() {}
public RouteInfo(Double distance, Double time, List<Point> points) {
this.distance = distance;
this.time = time;
this.points = points;
}
}
}

View File

@ -8,7 +8,7 @@ import lombok.Data;
import java.time.LocalDateTime;
@Data
public class MilitaryVo extends Military {
public class MilitaryVo{
@Schema(description = "军标类型名称")
private String militaryTypeName;
@Schema(description = "军标数据URL")

View File

@ -46,4 +46,4 @@ graphhopper:
- foot
sync:
folder: E:\\地理资源
folder: F:\POI

View File

@ -0,0 +1,123 @@
{
"list": [
{
"type": "FeatureCollection",
"name": "JobDetails",
"features": [
{
"type": "Feature",
"properties": {
"JobDetails": "执行(Manage Map Cache Tiles): ManageMapCacheTiles 商河电子地图:MapServer 2254.4677204803465;1127.2338602401733;563.61693012008664 3 RECREATE_ALL_TILES \"-180 -90 180 90\" # 要素集",
"JobID": "j140c6b943560494f9ac1ec04f87b9593",
"JobType": "RECREATE_ALL_TILES",
"NumThreads": 3,
"Scales": "2254.4677204803465;1127.2338602401733;563.61693012008664",
"Shape_Area": 64799.99999999998,
"Shape_Length": 1080
},
"geometry": {
"type": "MultiPolygon",
"coordinates": []
}
},
{
"type": "Feature",
"properties": {
"JobDetails": "执行(Manage Map Cache Tiles): ManageMapCacheTiles 商河电子地图:MapServer 2254.4677204803465;1127.2338602401733;563.61693012008664 3 RECREATE_ALL_TILES \"116.9772866 37.112894162 117.439131151 37.53690506\" # 要素集",
"JobID": "je0622d35aeda4b8592e766171053dbbd",
"JobType": "RECREATE_ALL_TILES",
"NumThreads": 3,
"Scales": "2254.4677204803465;1127.2338602401733;563.61693012008664",
"Shape_Area": 0.11797651104571212,
"Shape_Length": 2.9442372034773885
},
"geometry": {
"type": "MultiPolygon",
"coordinates": []
}
}
]
},
{
"type": "FeatureCollection",
"name": "JobStatus",
"features": [
{
"type": "Feature",
"properties": {
"ActualTiles": 2326528,
"CancelJobID": "j140c6b943560494f9ac1ec04f87b9593",
"DoneTasks": 142,
"EndTime": "2023/10/13 14:32:09+00",
"ExpectedTiles": 0,
"FailedTasks": 0,
"JobID": "j140c6b943560494f9ac1ec04f87b9593",
"JobStatus": "CANCELED",
"JobType": "RECREATE_ALL_TILES",
"PercentComplete": 0,
"Scale": 2254.4677204803465,
"Shape_Area": 64799.99999999998,
"Shape_Length": 1080,
"StartTime": "2023/10/13 12:31:12+00",
"TotalTasks": 2097152,
"percent": 0
},
"geometry": {
"type": "MultiPolygon",
"coordinates": []
}
},
{
"type": "Feature",
"properties": {
"ActualTiles": 0,
"CancelJobID": "j140c6b943560494f9ac1ec04f87b9593",
"DoneTasks": 0,
"EndTime": "2023/10/13 14:32:09+00",
"ExpectedTiles": 0,
"FailedTasks": 0,
"JobID": "j140c6b943560494f9ac1ec04f87b9593",
"JobStatus": "CANCELED",
"JobType": "RECREATE_ALL_TILES",
"PercentComplete": 0,
"Scale": 1127.2338602401733,
"Shape_Area": 64799.99999999998,
"Shape_Length": 1080,
"StartTime": "2023/10/13 12:31:12+00",
"TotalTasks": 8388608,
"percent": 0
},
"geometry": {
"type": "MultiPolygon",
"coordinates": []
}
},
{
"type": "Feature",
"properties": {
"ActualTiles": 0,
"CancelJobID": "j140c6b943560494f9ac1ec04f87b9593",
"DoneTasks": 0,
"EndTime": "2023/10/13 14:32:09+00",
"ExpectedTiles": 0,
"FailedTasks": 0,
"JobID": "j140c6b943560494f9ac1ec04f87b9593",
"JobStatus": "CANCELED",
"JobType": "RECREATE_ALL_TILES",
"PercentComplete": 0,
"Scale": 563.6169301200866,
"Shape_Area": 64799.99999999998,
"Shape_Length": 1080,
"StartTime": "2023/10/13 12:31:12+00",
"TotalTasks": 33554432,
"percent": 0
},
"geometry": {
"type": "MultiPolygon",
"coordinates": []
}
}
]
}
]
}

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yj.earth.business.mapper.PbfInfoMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.yj.earth.business.domain.PbfInfo">
<id column="id" property="id" />
<result column="path" property="path" />
<result column="name" property="name" />
<result column="is_enable" property="isEnable" />
<result column="created_at" property="createdAt" />
<result column="updated_at" property="updatedAt" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, path, name, is_enable, created_at, updated_at
</sql>
</mapper>