diff --git a/lib/proj.db b/lib/proj.db
new file mode 100644
index 0000000..9f42388
Binary files /dev/null and b/lib/proj.db differ
diff --git a/license/yjearth.lic b/license/yjearth.lic
new file mode 100644
index 0000000..deff4c5
--- /dev/null
+++ b/license/yjearth.lic
@@ -0,0 +1 @@
+41b/ujShRZRf9Aa433FD3uyIZuxWSSqXWXlc2dyQfJ75ED0HNbadcdsPF5CaMuJ6K2c3U/eBcWiXXw090/O7M5mJze/MavZ4dhk4dZIukMik2Jrufq9vkpQW+3/LWMFurfFWnFDZIf7Ptuoj4BvuX9h/qJ3oYUDCj14JFAR6ge7ZUtqT1yBvSl/eVexWpCiXfpNSm79whbkkpQjgjWts5/bgQ9cOYdBaVOBJnQkRxNzb4fKh3jkuyEADR+VZg2sRnjLJChAg7DYvIou8Zy16Ag==
diff --git a/pom.xml b/pom.xml
index 8c30725..ccf03c3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -175,6 +175,12 @@
+
+
+ org.yaml
+ snakeyaml
+
+
org.gdal
diff --git a/src/main/java/com/yj/earth/auth/AuthGenerator.java b/src/main/java/com/yj/earth/auth/AuthGenerator.java
index 3f35815..29b537e 100644
--- a/src/main/java/com/yj/earth/auth/AuthGenerator.java
+++ b/src/main/java/com/yj/earth/auth/AuthGenerator.java
@@ -72,6 +72,6 @@ public class AuthGenerator {
}
public static void main(String[] args) {
- System.out.println(generateAuth("标准版", 1000, 30, "25F429FDA965007B72BB7A6B2C03535A"));
+ System.out.println(generateAuth("标准版", 1000, 365, "8661A5D7040288C20E17A1D117E20045"));
}
}
diff --git a/src/main/java/com/yj/earth/business/controller/AuthController.java b/src/main/java/com/yj/earth/business/controller/AuthController.java
index 5aa213c..21f27c0 100644
--- a/src/main/java/com/yj/earth/business/controller/AuthController.java
+++ b/src/main/java/com/yj/earth/business/controller/AuthController.java
@@ -21,7 +21,7 @@ import java.nio.file.Paths;
@RequestMapping("/auth")
public class AuthController {
- // 授权文件存储路径、项目根目录下的license目录
+ // 授权文件存储路径、项目根目录下的 license 目录
private static final String AUTH_FILE_PATH = "license/yjearth.lic";
@GetMapping("/info")
diff --git a/src/main/java/com/yj/earth/business/controller/GdalController.java b/src/main/java/com/yj/earth/business/controller/GdalController.java
new file mode 100644
index 0000000..ac41022
--- /dev/null
+++ b/src/main/java/com/yj/earth/business/controller/GdalController.java
@@ -0,0 +1,47 @@
+package com.yj.earth.business.controller;
+
+import com.yj.earth.common.util.GdalUtil;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+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 java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.zip.GZIPOutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+@Tag(name = "矢量数据管理")
+@RestController
+@RequestMapping("/gdal")
+public class GdalController {
+
+ @Operation(summary = "导入矢量数据")
+ @PostMapping("/import")
+ public void importDataStreamGzip(@Parameter(description = "矢量文件路径", required = true) @RequestParam("path") String path, HttpServletResponse response) throws IOException {
+
+ // 解析矢量文件、得到JSON数据
+ String jsonData = GdalUtil.readVectorToJson(path);
+
+ // 设置响应头
+ String filename = URLEncoder.encode("data.gz", StandardCharsets.UTF_8);
+ response.setContentType("application/gzip");
+ response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
+ response.setCharacterEncoding("UTF-8");
+
+ // 使用GZIP压缩并输出
+ try (OutputStream outputStream = response.getOutputStream();
+ GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream)) {
+ gzipOutputStream.write(jsonData.getBytes(StandardCharsets.UTF_8));
+ gzipOutputStream.finish();
+ }
+ }
+}
diff --git a/src/main/java/com/yj/earth/business/controller/GraphHopperController.java b/src/main/java/com/yj/earth/business/controller/GraphHopperController.java
index 0124e58..b403055 100644
--- a/src/main/java/com/yj/earth/business/controller/GraphHopperController.java
+++ b/src/main/java/com/yj/earth/business/controller/GraphHopperController.java
@@ -10,7 +10,9 @@ import com.graphhopper.config.Profile;
import com.graphhopper.util.shapes.GHPoint;
import com.yj.earth.annotation.CheckAuth;
import com.yj.earth.business.domain.FileInfo;
+import com.yj.earth.business.domain.WebSource;
import com.yj.earth.business.service.FileInfoService;
+import com.yj.earth.business.service.WebSourceService;
import com.yj.earth.common.config.GraphHopperProperties;
import com.yj.earth.common.util.ApiResponse;
import com.yj.earth.model.Point;
@@ -40,6 +42,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
@RestController
@RequestMapping("/graphhopper")
public class GraphHopperController {
+ @Resource
+ private WebSourceService webSourceService;
@Resource
private FileInfoService fileInfoService;
@Resource
@@ -61,6 +65,15 @@ public class GraphHopperController {
return ApiResponse.success(fileInfoService.list(queryWrapper));
}
+ @Operation(summary = "获取地图列表(网页版)")
+ @CheckAuth
+ @GetMapping("/web/list")
+ public ApiResponse webList() {
+ LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
+ queryWrapper.eq(WebSource::getType, "pbf");
+ return ApiResponse.success(webSourceService.list(queryWrapper));
+ }
+
@Operation(summary = "加载地图数据")
@PostMapping("/loadMap")
@CheckAuth
@@ -120,6 +133,57 @@ public class GraphHopperController {
return ApiResponse.success(null);
}
+ @Operation(summary = "加载地图数据(网页版)")
+ @PostMapping("/web/loadMap")
+ @CheckAuth
+ public ApiResponse webLoadMap(@Parameter(description = "文件路径") @RequestParam String path) {
+ File osmFile = new File(path);
+ if (!osmFile.exists()) {
+ return ApiResponse.failure("地图文件不存在: " + path);
+ }
+ if (!osmFile.isFile() || !osmFile.getName().endsWith(".pbf")) {
+ return ApiResponse.failure("仅支持有效的.pbf格式OSM文件");
+ }
+ // 防止并发加载
+ if (isLoading.get()) {
+ return ApiResponse.failure("地图正在加载中、请稍后查询状态");
+ }
+
+ // 标记加载状态
+ isLoading.set(true);
+ isLoaded.set(false);
+
+ // 异步执行: 删除旧数据 → 创建新实例 → 加载新地图
+ new Thread(() -> {
+ GraphHopper newHopper = null;
+ try {
+ // 关键步骤1: 彻底删除旧地图数据目录
+ deleteOldGraphDir();
+ // 关键步骤2: 创建全新的GraphHopper实例
+ newHopper = createNewGraphHopperInstance(path);
+ // 关键步骤3: 加载新地图
+ newHopper.importOrLoad();
+ // 关键步骤4: 加载成功 → 替换当前实例 + 更新状态
+ currentHopper = newHopper;
+ isLoaded.set(true);
+ log.info("地图加载成功");
+ } catch (Exception e) {
+ // 加载失败 → 清理新实例资源
+ if (newHopper != null) {
+ newHopper.close();
+ }
+ isLoaded.set(false);
+ e.printStackTrace();
+ log.error("地图加载失败: " + e.getMessage());
+
+ } finally {
+ // 无论成功/失败、释放加载锁
+ isLoading.set(false);
+ }
+ }).start();
+ return ApiResponse.success(null);
+ }
+
@Operation(summary = "路径规划")
@PostMapping("/route")
@CheckAuth
diff --git a/src/main/java/com/yj/earth/business/controller/IconLibraryController.java b/src/main/java/com/yj/earth/business/controller/IconLibraryController.java
index e350475..b19e50f 100644
--- a/src/main/java/com/yj/earth/business/controller/IconLibraryController.java
+++ b/src/main/java/com/yj/earth/business/controller/IconLibraryController.java
@@ -265,6 +265,7 @@ public class IconLibraryController {
icon.icon_name as iconName,
icon.icon_type as iconType,
icon.data,
+
icon.view,
icon.created_at as createdAt,
icon.updated_at as updatedAt,
diff --git a/src/main/java/com/yj/earth/business/controller/ModelLibraryController.java b/src/main/java/com/yj/earth/business/controller/ModelLibraryController.java
index 71d3c97..70b63e6 100644
--- a/src/main/java/com/yj/earth/business/controller/ModelLibraryController.java
+++ b/src/main/java/com/yj/earth/business/controller/ModelLibraryController.java
@@ -9,18 +9,24 @@ import com.yj.earth.business.domain.ModelType;
import com.yj.earth.business.service.FileInfoService;
import com.yj.earth.business.service.ModelLibraryService;
import com.yj.earth.common.util.ApiResponse;
+import com.yj.earth.common.util.FileCommonUtil;
import com.yj.earth.common.util.SQLiteUtil;
import com.yj.earth.dto.militaryLibrary.DragMilitaryTypeDto;
import com.yj.earth.dto.modelLibrary.AddModelTypeDto;
import com.yj.earth.dto.modelLibrary.CreateModelLibraryDto;
import com.yj.earth.dto.modelLibrary.DragModelTypeDto;
import com.yj.earth.dto.modelLibrary.UpdateModelTypeNameDto;
+import com.yj.earth.vo.ModelDataVo;
import com.yj.earth.vo.ModelTypeVo;
import com.yj.earth.vo.ModelVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.jetbrains.annotations.NotNull;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@@ -28,11 +34,11 @@ import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.stream.Collectors;
@Tag(name = "模型库管理")
@@ -157,37 +163,6 @@ public class ModelLibraryController {
return ApiResponse.success(modelTypeList());
}
- @Operation(summary = "拖动模型类型树")
- @PostMapping("/dragModelType")
- public ApiResponse dragMilitaryType(@RequestBody DragModelTypeDto dragModelTypeDto) throws SQLException {
- String militaryPath = getModelLibrary();
- if (militaryPath == null) {
- return ApiResponse.failure("请先创建或导入模型库");
- }
-
- // 动态构建SQL和参数
- List updateFields = new ArrayList<>();
- List