diff --git a/src/main/java/com/yj/earth/auth/AuthGenerator.java b/src/main/java/com/yj/earth/auth/AuthGenerator.java index 1269ba7..13336f6 100644 --- a/src/main/java/com/yj/earth/auth/AuthGenerator.java +++ b/src/main/java/com/yj/earth/auth/AuthGenerator.java @@ -77,7 +77,7 @@ public class AuthGenerator { public static void main(String[] args) { try { // 生成加密的授权字符串 - String authContent = generateAuth("标准版", 1000, 365, "8B1FB12E9F8E80109724989E0B25773B"); + String authContent = generateAuth("标准版", 1000, 1, "25F429FDA965007B72BB7A6B2C03535A"); // 定义授权文件路径(当前目录下的 yjearth.YJ) Path licPath = Paths.get("yjearth.YJ"); @@ -92,3 +92,4 @@ public class AuthGenerator { } } } + 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 e7da2af..e3796e8 100644 --- a/src/main/java/com/yj/earth/business/controller/AuthController.java +++ b/src/main/java/com/yj/earth/business/controller/AuthController.java @@ -10,18 +10,25 @@ import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; @Tag(name = "系统设置管理") @RestController @RequestMapping("/auth") public class AuthController { - // 授权文件存储路径、项目根目录下的 license 目录 - private static final String AUTH_FILE_PATH = "license/yjearth.YJ"; + // 授权文件存储目录(项目根目录下的 license 目录) + private static final String LICENSE_DIR = "license"; + // 授权文件后缀(固定为.YJ) + private static final String AUTH_FILE_SUFFIX = ".YJ"; @GetMapping("/info") @Operation(summary = "获取系统授权码") @@ -37,28 +44,34 @@ public class AuthController { return ApiResponse.failure("请选择授权文件"); } - // 验证文件名是否为 yjearth.YJ String fileName = file.getOriginalFilename(); - if (fileName == null || !fileName.equals("yjearth.YJ")) { - return ApiResponse.failure("请上传 yjearth.YJ"); + // 验证文件名不为空且后缀为.YJ + if (fileName == null || !fileName.endsWith(AUTH_FILE_SUFFIX)) { + return ApiResponse.failure("授权码错误、请联系管理员提供正确的授权文件"); } try { - // 读取文件内容 + // 读取文件内容并验证有效性 String authContent = new String(file.getBytes(), StandardCharsets.UTF_8).trim(); - // 验证授权内容有效性 String serverHardwareMd5 = ServerUniqueIdUtil.getServerUniqueId(); boolean isValid = AuthValidator.validateAuth(authContent, serverHardwareMd5); if (!isValid) { - return ApiResponse.failure("授权文件无效或已过期"); + return ApiResponse.failure("授权码错误、请联系管理员提供正确的授权文件"); } - // 创建目录(如果不存在) - Path path = Paths.get(AUTH_FILE_PATH); - if (!Files.exists(path.getParent())) { - Files.createDirectories(path.getParent()); + + // 处理license目录(不存在则创建) + Path licenseDirPath = Paths.get(LICENSE_DIR); + if (!Files.exists(licenseDirPath)) { + Files.createDirectories(licenseDirPath); } - // 保存授权文件 - Files.write(path, authContent.getBytes(StandardCharsets.UTF_8)); + + // 删除目录下已存在的所有.YJ文件(确保仅保留一个) + deleteAllYjFilesInLicenseDir(); + + // 保存新的授权文件(使用原文件名) + Path newAuthFilePath = licenseDirPath.resolve(fileName); + Files.write(newAuthFilePath, authContent.getBytes(StandardCharsets.UTF_8)); + return ApiResponse.success(null); } catch (Exception e) { return ApiResponse.failure("导入授权文件失败: " + e.getMessage()); @@ -69,18 +82,60 @@ public class AuthController { @Operation(summary = "查看授权信息") public ApiResponse showAuth() { try { - // 检查授权文件是否存在 - Path path = Paths.get(AUTH_FILE_PATH); - if (!Files.exists(path)) { - return ApiResponse.failure("请先导入授权"); + // 查找license目录下的所有.YJ文件 + List yjFileList = findAllYjFilesInLicenseDir(); + + // 处理文件数量异常 + if (yjFileList.isEmpty()) { + return ApiResponse.successWithMessage("未找到授权文件"); } - // 读取授权文件内容 - String authContent = new String(Files.readAllBytes(path), StandardCharsets.UTF_8); - // 获取授权详情 + if (yjFileList.size() > 1) { + return ApiResponse.successWithMessage("授权目录下存在多个" + AUTH_FILE_SUFFIX + "文件,请删除多余文件后重试"); + } + + // 读取唯一的.YJ文件内容 + Path authFilePath = yjFileList.get(0); + String authContent = new String(Files.readAllBytes(authFilePath), StandardCharsets.UTF_8); + + // 解析并返回授权信息 AuthInfo authInfo = AuthValidator.getAuthInfo(authContent); return ApiResponse.success(authInfo); } catch (Exception e) { - return ApiResponse.failure("获取授权信息失败: " + e.getMessage()); + return ApiResponse.successWithMessage("授权码错误、请联系管理员提供正确的授权文件"); + } + } + + /** + * 查找 license 目录下所有后缀为 .YJ 的文件 + */ + private List findAllYjFilesInLicenseDir() throws IOException { + Path licenseDirPath = Paths.get(LICENSE_DIR); + if (!Files.exists(licenseDirPath)) { + return Collections.emptyList(); + } + if (!Files.isDirectory(licenseDirPath)) { + throw new IOException("license路径不是合法目录"); + } + + // 遍历目录、筛选后缀为 .YJ的文件(不区分大小写) + try (var directoryStream = Files.list(licenseDirPath)) { + return directoryStream + .filter(Files::isRegularFile) + .filter(path -> { + String fileName = path.getFileName().toString().toLowerCase(); + return fileName.endsWith(AUTH_FILE_SUFFIX.toLowerCase()); + }) + .collect(Collectors.toList()); + } + } + + /** + * 删除 license 目录下所有后缀为 .YJ 的文件 + */ + private void deleteAllYjFilesInLicenseDir() throws IOException { + List yjFileList = findAllYjFilesInLicenseDir(); + for (Path yjFile : yjFileList) { + Files.delete(yjFile); } } } diff --git a/src/main/java/com/yj/earth/business/controller/FileInfoController.java b/src/main/java/com/yj/earth/business/controller/FileInfoController.java index 5a8f9ad..1eb8db8 100644 --- a/src/main/java/com/yj/earth/business/controller/FileInfoController.java +++ b/src/main/java/com/yj/earth/business/controller/FileInfoController.java @@ -193,7 +193,7 @@ public class FileInfoController { // 标准化路径 targetFilePath = Paths.get(fileAbsolutePath).toRealPath(); - // 校验文件合法性: 是否存在、是否为普通文件 + // 是否存在、是否为普通文件 BasicFileAttributes fileAttr = Files.readAttributes(targetFilePath, BasicFileAttributes.class); if (!fileAttr.isRegularFile()) { response.setStatus(HttpServletResponse.SC_BAD_REQUEST); @@ -204,21 +204,27 @@ public class FileInfoController { // 设置预览响应头 String fileName = targetFilePath.getFileName().toString(); String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name()); + + // 手动映射常见图片格式的 MIME 类型 String contentType = Files.probeContentType(targetFilePath); + String fileExtension = getFileExtension(fileName).toLowerCase(); + // 覆盖默认探测结果 + contentType = mapImageContentType(fileExtension, contentType); // 对于文本类型文件、指定字符编码 if (contentType != null && contentType.startsWith("text/")) { response.setContentType(contentType + "; charset=UTF-8"); } else { - response.setContentType(contentType != null ? contentType : "application/octet-stream"); + // 确保 Content-Type 不为空 + response.setContentType(contentType != null ? contentType : "image/png"); } response.setContentLengthLong(fileAttr.size()); - // 关键修改: 将attachment改为inline实现预览 + // inline 已正确设置、无需修改 response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName); - // 写入文件流 + // 写入文件流(无需修改) try (InputStream inputStream = Files.newInputStream(targetFilePath); OutputStream outputStream = response.getOutputStream()) { byte[] buffer = new byte[1024 * 8]; @@ -240,4 +246,32 @@ public class FileInfoController { fileInfoService.writeResponseMessage(response, "预览失败: " + e.getMessage()); } } + + /** + * 获取文件后缀 + */ + private String getFileExtension(String fileName) { + int lastDotIndex = fileName.lastIndexOf('.'); + return lastDotIndex == -1 ? "" : fileName.substring(lastDotIndex + 1); + } + + /** + * 映射图片格式到标准 MIME 类型 + */ + private String mapImageContentType(String fileExtension, String probeContentType) { + Map imageMimeMap = new HashMap<>(); + imageMimeMap.put("webp", "image/webp"); + imageMimeMap.put("png", "image/png"); + imageMimeMap.put("jpg", "image/jpeg"); + imageMimeMap.put("jpeg", "image/jpeg"); + imageMimeMap.put("gif", "image/gif"); + imageMimeMap.put("bmp", "image/bmp"); + imageMimeMap.put("svg", "image/svg+xml"); + + // 如果探针结果已存在且是图片类型 + if (probeContentType != null && probeContentType.startsWith("image/")) { + return probeContentType; + } + return imageMimeMap.getOrDefault(fileExtension, probeContentType); + } } 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 8b322b6..8b49cdb 100644 --- a/src/main/java/com/yj/earth/business/controller/GraphHopperController.java +++ b/src/main/java/com/yj/earth/business/controller/GraphHopperController.java @@ -29,16 +29,18 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; @Data @Slf4j @Tag(name = "路径规划管理") - @RestController @RequestMapping("/graphhopper") public class GraphHopperController { @@ -56,20 +58,44 @@ public class GraphHopperController { private final AtomicBoolean isLoading = new AtomicBoolean(false); private final AtomicBoolean isLoaded = new AtomicBoolean(false); - @Operation(summary = "加载地图数据") + @Operation(summary = "加载地图数据(启用路网文件)") @PostMapping("/loadMap") - public ApiResponse loadMap(@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 (!osmFile.isFile()) { + return ApiResponse.failure("请提供有效的文件路径"); } + + String fileName = osmFile.getName(); + File tempPbfFile = null; + + // 判断文件后缀 + if (fileName.endsWith(".pbf")) { + // 直接使用原文件 + } else if (fileName.endsWith(".pbfl")) { + try { + // 创建临时文件,后缀改为 .pbf + String tempFileName = UUID.randomUUID().toString() + ".pbf"; + tempPbfFile = new File(osmFile.getParent(), tempFileName); + + // 复制文件内容 + Files.copy(osmFile.toPath(), tempPbfFile.toPath()); + + // 将路径指向临时文件 + path = tempPbfFile.getAbsolutePath(); + } catch (IOException e) { + return ApiResponse.failure("创建临时文件失败: " + e.getMessage()); + } + } else { + return ApiResponse.failure("仅支持有效的.pbf或.pbfl格式OSM文件"); + } + // 防止并发加载 if (isLoading.get()) { - return ApiResponse.failure("地图正在加载中、请稍后查询状态"); + return ApiResponse.failure("对应区域的路网文件正在启用中、请稍后查询状态"); } // 标记加载状态 @@ -77,19 +103,21 @@ public class GraphHopperController { isLoaded.set(false); // 异步执行: 删除旧数据 → 创建新实例 → 加载新地图 + String finalPath = path; + File finalTempPbfFile = tempPbfFile; new Thread(() -> { GraphHopper newHopper = null; try { // 关键步骤1: 彻底删除旧地图数据目录 deleteOldGraphDir(); // 关键步骤2: 创建全新的GraphHopper实例 - newHopper = createNewGraphHopperInstance(path); + newHopper = createNewGraphHopperInstance(finalPath); // 关键步骤3: 加载新地图 newHopper.importOrLoad(); // 关键步骤4: 加载成功 → 替换当前实例 + 更新状态 currentHopper = newHopper; isLoaded.set(true); - log.info("地图加载成功"); + log.info("对应区域的路网文件启用成功"); } catch (Exception e) { // 加载失败 → 清理新实例资源 if (newHopper != null) { @@ -97,22 +125,31 @@ public class GraphHopperController { } isLoaded.set(false); e.printStackTrace(); - log.error("地图加载失败: " + e.getMessage()); + log.error("对应区域的路网文件启用失败: " + e.getMessage()); } finally { // 无论成功/失败、释放加载锁 isLoading.set(false); + + // 删除临时文件 + if (finalTempPbfFile != null && finalTempPbfFile.exists()) { + if (finalTempPbfFile.delete()) { + log.info("临时文件已删除: " + finalTempPbfFile.getAbsolutePath()); + } else { + log.warn("临时文件删除失败: " + finalTempPbfFile.getAbsolutePath()); + } + } } }).start(); + return ApiResponse.success(null); } - @Operation(summary = "清除地图服务") + @Operation(summary = "清除地图服务(停用路网文件)") @PostMapping("/clearMap") - public ApiResponse clearMap() { // 防止并发操作(与加载操作互斥) if (isLoading.get()) { - return ApiResponse.failure("地图正在加载中、无法清除、请稍后再试"); + return ApiResponse.failure("对应区域的路网文件正在启用中、无法清除、请稍后再试"); } // 标记正在处理清除操作 @@ -120,24 +157,24 @@ public class GraphHopperController { try { // 1. 关闭当前GraphHopper实例 if (currentHopper != null) { - log.info("开始关闭当前地图服务实例"); + log.info("开始关闭当前路网服务实例"); currentHopper.close(); currentHopper = null; - log.info("地图服务实例已关闭"); + log.info("路网服务实例已关闭"); } // 2. 删除地图数据目录 - log.info("开始删除地图数据目录"); + log.info("开始删除路网数据目录"); deleteOldGraphDir(); - log.info("地图数据目录已删除"); + log.info("路网数据目录已删除"); // 3. 重置状态变量 isLoaded.set(false); - return ApiResponse.success("地图服务已成功清除"); + return ApiResponse.success("对应区域的路网文件已成功停用并清除"); } catch (Exception e) { - log.error("清除地图服务失败", e); - return ApiResponse.failure("清除地图服务失败: " + e.getMessage()); + log.error("清除路网服务失败", e); + return ApiResponse.failure("清除路网服务失败: " + e.getMessage()); } finally { // 释放操作锁 isLoading.set(false); @@ -146,15 +183,17 @@ public class GraphHopperController { @Operation(summary = "路径规划") @PostMapping("/route") - public ApiResponse calculateRoute(@RequestBody RouteRequest request) { - // 区分未加载地图和加载中两种状态 + // 区分三种核心状态提示 if (isLoading.get()) { - return ApiResponse.failure("地图正在加载中、请稍后再试"); + // 场景1: 导入了路网文件但未启用(加载中) + return ApiResponse.failure("请启用对应区域的路网文件"); } if (!isLoaded.get() || currentHopper == null) { - return ApiResponse.failure("地图未加载、请先加载地图"); + // 场景2: 未导入路网文件 + return ApiResponse.failure("请导入并启用对应区域的路网文件"); } + try { // 构建路径点列表 List ghPoints = new ArrayList<>(); @@ -182,9 +221,10 @@ public class GraphHopperController { boolean hasPointNotFoundError = response.getErrors().stream() .anyMatch(e -> e instanceof com.graphhopper.util.exceptions.PointNotFoundException); if (hasOutOfBoundsError) { - return ApiResponse.failure("路径超出地图范围"); + // 场景3: 已启用但路径超出路网范围 + return ApiResponse.failure("绘制路径超出有效路网范围"); } else if (hasPointNotFoundError) { - return ApiResponse.failure("未超地图范围但找不到路径点"); + return ApiResponse.failure("未超路网范围但找不到有效路径点"); } else { return ApiResponse.failure("路径计算异常: " + response.getErrors().get(0).getMessage()); } @@ -199,27 +239,26 @@ public class GraphHopperController { RouteResponse routeResponse = new RouteResponse(bestPath.getDistance() / 1000, (double) (bestPath.getTime() / 60000), pathPoints); return ApiResponse.success(routeResponse); } catch (com.graphhopper.util.exceptions.PointOutOfBoundsException e) { - // 捕获单点超出范围的异常 - return ApiResponse.failure("路径超出地图范围"); + // 捕获单点超出范围的异常(场景3) + return ApiResponse.failure("绘制路径超出有效路网范围"); } catch (Exception e) { return ApiResponse.failure("路径计算异常: " + e.getMessage()); } } - @Operation(summary = "获取地图加载状态") + @Operation(summary = "获取路网文件加载状态") @GetMapping("/status") public ApiResponse getMapStatus() { if (isLoading.get()) { - return ApiResponse.success("地图正在加载中"); + return ApiResponse.success("对应区域的路网文件正在启用中"); } else if (isLoaded.get() && currentHopper != null) { - return ApiResponse.success("地图已加载完成"); + return ApiResponse.success("对应区域的路网文件已启用"); } else { - return ApiResponse.success("地图未加载"); + return ApiResponse.success("未导入对应区域的路网文件"); } } @Operation(summary = "获取交通方式") - @PostMapping("/profiles") public ApiResponse profiles() { return ApiResponse.success(graphHopperProperties.getProfiles()); @@ -252,7 +291,7 @@ public class GraphHopperController { private void deleteOldGraphDir() { File graphDir = new File(graphHopperProperties.getGraphLocation()); if (!graphDir.exists()) { - log.info("旧地图目录不存在、无需删除: " + graphHopperProperties.getGraphLocation()); + log.info("旧路网目录不存在、无需删除: " + graphHopperProperties.getGraphLocation()); return; } @@ -264,14 +303,14 @@ public class GraphHopperController { deleteOldGraphDir(file); } else { boolean deleted = file.delete(); - log.info("删除旧地图文件: " + file.getAbsolutePath() + " → " + (deleted ? "成功" : "失败")); + log.info("删除旧路网文件: " + file.getAbsolutePath() + " → " + (deleted ? "成功" : "失败")); } } } // 删除空目录 boolean dirDeleted = graphDir.delete(); - System.out.println("删除旧地图目录: " + graphDir.getAbsolutePath() + " → " + (dirDeleted ? "成功" : "失败")); + log.info("删除旧路网目录: " + graphDir.getAbsolutePath() + " → " + (dirDeleted ? "成功" : "失败")); } // 重载:递归删除子目录 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 d6f9a93..4bec362 100644 --- a/src/main/java/com/yj/earth/business/controller/IconLibraryController.java +++ b/src/main/java/com/yj/earth/business/controller/IconLibraryController.java @@ -193,6 +193,9 @@ public class IconLibraryController { @GetMapping("/iconTypeTree") public ApiResponse iconTypeTree(@Parameter(description = "图标名称") @RequestParam(value = "iconName", required = false) String iconName) throws SQLException, IllegalAccessException, InstantiationException { List treeList = iconTypeList(iconName); + if(treeList == null){ + return ApiResponse.successWithMessage("请先创建或导入图标库"); + } return ApiResponse.success(treeList); } @@ -392,7 +395,7 @@ public class IconLibraryController { queryWrapper.eq(IconLibrary::getIsEnable, 1); IconLibrary library = iconLibraryService.getOne(queryWrapper); if(library == null){ - throw new RuntimeException("请先创建或导入图标库"); + return null; } return library.getPath(); } diff --git a/src/main/java/com/yj/earth/business/controller/MilitaryLibraryController.java b/src/main/java/com/yj/earth/business/controller/MilitaryLibraryController.java index b65b313..a881bca 100644 --- a/src/main/java/com/yj/earth/business/controller/MilitaryLibraryController.java +++ b/src/main/java/com/yj/earth/business/controller/MilitaryLibraryController.java @@ -206,6 +206,9 @@ public class MilitaryLibraryController { @GetMapping("/militaryTypeTree") public ApiResponse militaryTypeTree(@Parameter(description = "军标名称") @RequestParam(value = "militaryName", required = false) String militaryName) throws SQLException, IllegalAccessException, InstantiationException { List treeList = militaryTypeList(militaryName); + if (treeList == null) { + return ApiResponse.successWithMessage("请先创建或导入军标库"); + } return ApiResponse.success(treeList); } @@ -430,7 +433,7 @@ public class MilitaryLibraryController { queryWrapper.eq(MilitaryLibrary::getIsEnable, 1); // 1=启用、0=未启用 MilitaryLibrary library = militaryLibraryService.getOne(queryWrapper); if (library == null) { - throw new RuntimeException("请先创建或导入军标库"); + return null; } return library.getPath(); } 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 f2d67fc..b27e0f1 100644 --- a/src/main/java/com/yj/earth/business/controller/ModelLibraryController.java +++ b/src/main/java/com/yj/earth/business/controller/ModelLibraryController.java @@ -175,7 +175,11 @@ public class ModelLibraryController { @Operation(summary = "模型类型列表") @GetMapping("/modelTypeList") public ApiResponse modelTypeTree(@Parameter(description = "模型名称") @RequestParam(value = "modelName", required = false) String modelName) throws SQLException, IllegalAccessException, InstantiationException { - return ApiResponse.success(modelTypeList(modelName)); + List modelTypeVos = modelTypeList(modelName); + if (modelTypeVos == null) { + return ApiResponse.successWithMessage("请先创建或导入模型库"); + } + return ApiResponse.success(modelTypeVos); } @Operation(summary = "添加模型文件") @@ -547,7 +551,7 @@ public class ModelLibraryController { queryWrapper.eq(ModelLibrary::getIsEnable, 1); ModelLibrary modelLibrary = modelLibraryService.getOne(queryWrapper); if (modelLibrary == null) { - throw new RuntimeException("请先创建或导入模型库"); + return null; } return modelLibrary.getPath(); } diff --git a/src/main/java/com/yj/earth/business/controller/PbfInfoController.java b/src/main/java/com/yj/earth/business/controller/PbfInfoController.java index 6079216..98d7245 100644 --- a/src/main/java/com/yj/earth/business/controller/PbfInfoController.java +++ b/src/main/java/com/yj/earth/business/controller/PbfInfoController.java @@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.List; +import java.util.stream.Collectors; @Tag(name = "地图文件管理") @RestController @@ -27,12 +28,22 @@ public class PbfInfoController { @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); + public ApiResponse add(@Parameter(description = "地图文件路径列表") @RequestParam(required = true) List paths) { + // 批量转换为PbfInfo对象 + List pbfInfoList = paths.stream() + .map(path -> { + PbfInfo pbfInfo = new PbfInfo(); + pbfInfo.setPath(path); + pbfInfo.setName(FileUtil.mainName(path)); + pbfInfo.setIsEnable(0); + return pbfInfo; + }) + .collect(Collectors.toList()); + + // 批量保存 + pbfInfoService.saveBatch(pbfInfoList); + + // 返回成功结果 return ApiResponse.success(null); } @@ -83,6 +94,4 @@ public class PbfInfoController { graphHopperController.clearMap(); return ApiResponse.success(null); } - - } diff --git a/src/main/java/com/yj/earth/business/controller/PoiInfoController.java b/src/main/java/com/yj/earth/business/controller/PoiInfoController.java index c4461ca..c052475 100644 --- a/src/main/java/com/yj/earth/business/controller/PoiInfoController.java +++ b/src/main/java/com/yj/earth/business/controller/PoiInfoController.java @@ -19,6 +19,7 @@ import java.io.File; import java.sql.*; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; @RestController @Tag(name = "POI文件管理") @@ -27,14 +28,22 @@ public class PoiInfoController { @Resource private PoiInfoService poiInfoService; - @Operation(summary = "添加POI文件") + @Operation(summary = "批量添加POI文件") @PostMapping("/add") - public ApiResponse add(@Parameter(description = "POI文件路径") @RequestParam(required = true) String path) { - PoiInfo poiInfo = new PoiInfo(); - poiInfo.setPath(path); - poiInfo.setName(FileUtil.mainName(path)); - poiInfo.setIsEnable(0); - poiInfoService.save(poiInfo); + public ApiResponse add(@Parameter(description = "POI文件路径列表") @RequestParam(required = true) List paths) { + // 批量转换为PoiInfo对象 + List poiInfoList = paths.stream() + .map(path -> { + PoiInfo poiInfo = new PoiInfo(); + poiInfo.setPath(path); + poiInfo.setName(FileUtil.mainName(path)); + poiInfo.setIsEnable(0); + return poiInfo; + }) + .collect(Collectors.toList()); + + // 批量保存 + poiInfoService.saveBatch(poiInfoList); return ApiResponse.success(null); } @@ -57,7 +66,7 @@ public class PoiInfoController { @Operation(summary = "启用POI文件") @PostMapping("/enable") - public ApiResponse enable(@Parameter(description = "地图文件ID") @RequestParam(required = true) String id) { + public ApiResponse enable(@Parameter(description = "POI文件ID") @RequestParam(required = true) String id) { PoiInfo poiInfo = poiInfoService.getById(id); poiInfo.setIsEnable(1); poiInfoService.updateById(poiInfo); @@ -74,7 +83,7 @@ public class PoiInfoController { @Operation(summary = "禁用POI文件") @PostMapping("/disable") - public ApiResponse disable(@Parameter(description = "地图文件ID") @RequestParam(required = true) String id) { + public ApiResponse disable(@Parameter(description = "POI文件ID") @RequestParam(required = true) String id) { PoiInfo poiInfo = new PoiInfo(); poiInfo.setId(id); poiInfo.setIsEnable(0); @@ -84,10 +93,7 @@ public class PoiInfoController { @Operation(summary = "POI搜索") @GetMapping("/search") - public ApiResponse search( - @Parameter(description = "分页页码") Integer pageNum, - @Parameter(description = "分页大小") Integer pageSize, - @Parameter(description = "名称搜索") String name) { + public ApiResponse search(@Parameter(description = "分页页码") Integer pageNum, @Parameter(description = "分页大小") Integer pageSize, @Parameter(description = "名称搜索") String name) { int offset = (pageNum - 1) * pageSize; // 查询启用的POI文件 PoiInfo poiInfo = poiInfoService.getOne(new QueryWrapper().lambda().eq(PoiInfo::getIsEnable, 1)); diff --git a/src/main/java/com/yj/earth/business/controller/SourceController.java b/src/main/java/com/yj/earth/business/controller/SourceController.java index 98aa392..7fadc18 100644 --- a/src/main/java/com/yj/earth/business/controller/SourceController.java +++ b/src/main/java/com/yj/earth/business/controller/SourceController.java @@ -26,6 +26,8 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; +import java.io.File; +import java.nio.file.Paths; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; @@ -186,10 +188,20 @@ public class SourceController { queryWrapper.eq(Source::getId, updateLevelDto.getId()); Source source = sourceService.getOne(queryWrapper); String params = source.getParams(); - // 修改这个 JSON 的值 - params = JsonUtil.modifyJsonValue(params, "layerIndex", updateLevelDto.getLayerIndex()); - source.setParams(params); - sourceService.updateById(source); + if (params != null) { + // 修改这个 JSON 的值 + params = JsonUtil.modifyJsonValue(params, "layerIndex", updateLevelDto.getLayerIndex()); + source.setParams(params); + sourceService.updateById(source); + } + // 否则是新增 + if (params == null) { + Map paramsMap = new HashMap<>(); + paramsMap.put("layerIndex", updateLevelDto.getLayerIndex()); + paramsMap.put("id", updateLevelDto.getId()); + source.setParams(MapUtil.mapToString(paramsMap)); + sourceService.updateById(source); + } } return ApiResponse.success(null); } @@ -250,76 +262,92 @@ public class SourceController { @PostMapping("/uploadLocationImage") @Operation(summary = "新增定位图片") - public ApiResponse uploadLocationImage(@RequestParam("ids") @Parameter(description = "上传定位图片ID列表") List ids, - @RequestParam(value = "parentId", required = false) @Parameter(description = "父节点ID") String parentId, - @RequestParam(value = "treeIndex", required = false) @Parameter(description = "树状索引") Integer treeIndex, - @RequestParam(value = "params", required = false) @Parameter(description = "参数") String params, - @RequestParam(value = "sourceType", required = false) @Parameter(description = "资源类型") String sourceType, - @RequestParam("files") @Parameter(description = "带有定位的图片文件", required = true) MultipartFile[] files) { - // 验证并转换参数 + public ApiResponse uploadLocationImage( + @RequestParam("ids") @Parameter(description = "上传定位图片ID列表") List ids, + @RequestParam(value = "parentId", required = false) @Parameter(description = "父节点ID") String parentId, + @RequestParam(value = "treeIndex", required = false) @Parameter(description = "树状索引") Integer treeIndex, + @RequestParam(value = "params", required = false) @Parameter(description = "参数") String params, + @RequestParam(value = "sourceType", required = false) @Parameter(description = "资源类型") String sourceType, + @RequestParam("filePaths") @Parameter(description = "图片文件绝对路径列表", required = true) List filePaths) { + sourceParamsValidator.validateAndConvert( sourceType, JsonUtil.jsonToMap(params) ); + // 检查是否有重复的filePath + for (String filePath : filePaths) { + // 检查数据库中是否已存在该文件路径 + boolean exists = sourceService.lambdaQuery() + .eq(Source::getSourcePath, filePath) + .eq(Source::getIsShow, SHOW) + .exists(); + + if (exists) { + return ApiResponse.failure("数据库存在参数中部分文件路径、不允许重复上传:" + filePath); + } + } + List sources = new ArrayList<>(); - for (int i = 0; i < files.length; i++) { - Map dataMap = fileInfoService.handleLocationImageUpload(files[i]); - // 构建并保存资源对象 - Source source = new Source(); - source.setId(ids.get(i)); - source.setSourceName(files[i].getOriginalFilename()); - source.setParentId(parentId); - source.setSourceType(sourceType); - source.setTreeIndex(treeIndex); + for (int i = 0; i < filePaths.size(); i++) { + String filePath = filePaths.get(i); + File file = new File(filePath); - // 转换为对象 - Point point = JsonUtil.mapToObject(JsonUtil.jsonToMap(params), Point.class); - point.setId(ids.get(i)); - Point.Position position = new Point.Position(); - point.setName(files[i].getOriginalFilename()); - point.getLabel().setText(files[i].getOriginalFilename()); - Object lonObj = dataMap.get("lon"); - if (lonObj != null && lonObj instanceof Double) { - position.setLng((Double) lonObj); + try { + Map dataMap = fileInfoService.handleLocationImageUpload(file); + Source source = new Source(); + source.setSourcePath(filePath); + source.setId(ids.get(i)); + source.setSourceName(Paths.get(filePath).getFileName().toString()); + source.setParentId(parentId); + source.setSourceType(sourceType); + source.setTreeIndex(treeIndex); + Point point = JsonUtil.mapToObject(JsonUtil.jsonToMap(params), Point.class); + point.setId(ids.get(i)); + Point.Position position = new Point.Position(); + point.setName(Paths.get(filePath).getFileName().toString()); + point.getLabel().setText(Paths.get(filePath).getFileName().toString()); + // 解析经纬度、海拔 + Object lonObj = dataMap.get("lon"); + if (lonObj != null && lonObj instanceof Double) { + position.setLng((Double) lonObj); + } + Object latObj = dataMap.get("lat"); + if (latObj != null && latObj instanceof Double) { + position.setLat((Double) latObj); + } + Object altObj = dataMap.get("alt"); + if (altObj != null && altObj instanceof Double) { + position.setAlt((Double) altObj); + } + point.setPosition(position); + // 根据资源类型设置链接/VR内容 + if ("linkImage".equals(sourceType)) { + List list = new ArrayList<>(); + Point.Attribute.Link.LinkContent linkContent = new Point.Attribute.Link.LinkContent(); + linkContent.setName("带定位照片"); + linkContent.setUrl(dataMap.get("url").toString()); + list.add(linkContent); + point.getAttribute().getLink().setContent(list); + } else { + List list = new ArrayList<>(); + Point.Attribute.Vr.VrContent vrContent = new Point.Attribute.Vr.VrContent(); + vrContent.setName("带全景照片"); + vrContent.setUrl(dataMap.get("url").toString()); + list.add(vrContent); + point.getAttribute().getVr().setContent(list); + } + // 保存资源参数 + source.setParams(JsonUtil.toJson(point)); + source.setIsShow(SHOW); + sourceService.save(source); + // 添加角色关联 + roleSourceService.addRoleSource(userService.getById(StpUtil.getLoginIdAsString()).getRoleId(), source.getId()); + + sources.add(source); + } catch (Exception e) { + return ApiResponse.failure("处理文件失败:" + filePath + ",原因:" + e.getMessage()); } - - Object latObj = dataMap.get("lat"); - if (latObj != null && latObj instanceof Double) { - position.setLat((Double) latObj); - } - - Object altObj = dataMap.get("alt"); - if (altObj != null && altObj instanceof Double) { - position.setAlt((Double) altObj); - } - point.setPosition(position); - - if ("linkImage".equals(sourceType)) { - // 设置地址 - List list = new ArrayList<>(); - Point.Attribute.Link.LinkContent linkContent = new Point.Attribute.Link.LinkContent(); - linkContent.setName("带定位照片"); - linkContent.setUrl(dataMap.get("url").toString()); - list.add(linkContent); - point.getAttribute().getLink().setContent(list); - } else { - List list = new ArrayList<>(); - Point.Attribute.Vr.VrContent vrContent = new Point.Attribute.Vr.VrContent(); - vrContent.setName("带全景照片"); - vrContent.setUrl(dataMap.get("url").toString()); - list.add(vrContent); - point.getAttribute().getVr().setContent(list); - } - - // 将 vrImage 转化为 JSON - source.setParams(JsonUtil.toJson(point)); - source.setIsShow(SHOW); - sourceService.save(source); - // 添加资源到该用户的角色下 - roleSourceService.addRoleSource(userService.getById(StpUtil.getLoginIdAsString()).getRoleId(), source.getId()); - - sources.add(source); } return ApiResponse.success(sources); } diff --git a/src/main/java/com/yj/earth/business/controller/TsPlanController.java b/src/main/java/com/yj/earth/business/controller/TsPlanController.java index f178909..8734042 100644 --- a/src/main/java/com/yj/earth/business/controller/TsPlanController.java +++ b/src/main/java/com/yj/earth/business/controller/TsPlanController.java @@ -71,10 +71,11 @@ public class TsPlanController { } private TsSource createSourceIfNotExists(String sourceName, String sourceType, String parentId, int treeIndex, int isShow, String tsPlanId) { - // 检查资源是否已存在(通过名称和父ID组合判断唯一性) + // 检查资源是否已存在(通过名称和父ID和计划ID组合判断唯一性) TsSource existingSource = tsSourceService.getOne(new LambdaQueryWrapper() .eq(TsSource::getSourceName, sourceName) .eq(parentId != null, TsSource::getParentId, parentId) + .eq(TsSource::getPlanId, tsPlanId) .isNull(parentId == null, TsSource::getParentId)); if (existingSource != null) { return existingSource; @@ -128,21 +129,24 @@ public class TsPlanController { @Parameter(description = "开始时间") @RequestParam(required = false) String startTime, @Parameter(description = "结束时间") @RequestParam(required = false) String endTime) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + // 创建人昵称模糊查询 + if (StringUtils.isNotBlank(nickname)) { + LambdaQueryWrapper userQueryWrapper = new LambdaQueryWrapper() + .select(User::getId) + .like(User::getNickname, nickname); + List userIds = userService.list(userQueryWrapper).stream() + .map(User::getId) + .collect(Collectors.toList()); + if (userIds.isEmpty()) { + // 返回空数据 + return ApiResponse.success(new Page()); + } + } // 方案名称模糊查询 if (StringUtils.isNotBlank(name)) { queryWrapper.like(TsPlan::getName, name); } - - // 创建人昵称模糊查询 - if (StringUtils.isNotBlank(nickname)) { - queryWrapper.in(TsPlan::getCreatedBy, - new LambdaQueryWrapper() - .select(User::getId) - .like(User::getNickname, nickname) - ); - } - // 时间范围查询 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); try { @@ -154,36 +158,17 @@ public class TsPlanController { LocalDateTime end = LocalDateTime.parse(endTime, formatter); queryWrapper.le(TsPlan::getCreatedAt, end); } - } catch (DateTimeParseException e) { + } catch ( + DateTimeParseException e) { return ApiResponse.failure("时间格式错误、需为 yyyy-MM-dd HH:mm:ss"); } // 执行分页查询 Page page = tsPlanService.page(new Page<>(pageNum, pageSize), queryWrapper); - - // 关联查询用户信息并封装结果 - if (!page.getRecords().isEmpty()) { - List creatorIds = page.getRecords().stream() - .map(TsPlan::getCreatedBy) - .filter(Objects::nonNull) - .distinct() - .collect(Collectors.toList()); - - if (!creatorIds.isEmpty()) { - List creators = userService.listByIds(creatorIds); - Map creatorNicknameMap = creators.stream() - .collect(Collectors.toMap( - User::getId, - user -> user.getNickname() != null ? user.getNickname() : "未知昵称", - (k1, k2) -> k1 - )); - - page.getRecords().forEach(plan -> { - plan.setCreatedBy(creatorNicknameMap.getOrDefault(plan.getCreatedBy(), "未知用户")); - }); - } + List records = page.getRecords(); + for (TsPlan record : records) { + record.setCreatedBy(userService.getById(record.getCreatedBy()).getNickname()); } - return ApiResponse.success(page); } diff --git a/src/main/java/com/yj/earth/business/controller/TsSourceController.java b/src/main/java/com/yj/earth/business/controller/TsSourceController.java index 84c2056..cadd49c 100644 --- a/src/main/java/com/yj/earth/business/controller/TsSourceController.java +++ b/src/main/java/com/yj/earth/business/controller/TsSourceController.java @@ -2,14 +2,17 @@ package com.yj.earth.business.controller; import cn.hutool.core.io.FileUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.yj.earth.business.domain.Source; import com.yj.earth.business.domain.TsSource; import com.yj.earth.business.service.TsSourceService; import com.yj.earth.common.util.ApiResponse; import com.yj.earth.common.util.JsonUtil; import com.yj.earth.common.util.MapUtil; +import com.yj.earth.dto.source.DragSourceDto; import com.yj.earth.dto.tsPlan.BatchUpdateShowStatusDto; import com.yj.earth.dto.tsSource.AddTsModelSourceDto; import com.yj.earth.dto.tsSource.AddTsSourceDto; +import com.yj.earth.dto.tsSource.DragTsSourceDto; import com.yj.earth.dto.tsSource.UpdateTsSourceDto; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -68,6 +71,20 @@ public class TsSourceController { return ApiResponse.success(null); } + @Operation(summary = "拖动资源") + @PostMapping("/dragSource") + public ApiResponse drag(@RequestBody List dragTsSourceDtoList) { + for (DragTsSourceDto dragTsSourceDto : dragTsSourceDtoList) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TsSource::getId, dragTsSourceDto.getId()); + TsSource tsSource = tsSourceService.getOne(queryWrapper); + tsSource.setTreeIndex(dragTsSourceDto.getTreeIndex()); + tsSource.setParentId(dragTsSourceDto.getParentId()); + tsSourceService.updateById(tsSource); + } + return ApiResponse.success(null); + } + @Operation(summary = "查询某个方案下的态势资源") @PostMapping("/query") public ApiResponse query(@Parameter(description = "态势方案ID") @RequestParam(required = true) String id) { diff --git a/src/main/java/com/yj/earth/business/domain/TsPlan.java b/src/main/java/com/yj/earth/business/domain/TsPlan.java index 24cd13b..e9c6d49 100644 --- a/src/main/java/com/yj/earth/business/domain/TsPlan.java +++ b/src/main/java/com/yj/earth/business/domain/TsPlan.java @@ -32,6 +32,9 @@ public class TsPlan implements Serializable { @Schema(description = "创建人") private String createdBy; + @Schema(description = "滑轮") + private Integer wheel; + @Schema(description = "仿真开始时间") private LocalDateTime simulationStartTime; diff --git a/src/main/java/com/yj/earth/business/service/FileInfoService.java b/src/main/java/com/yj/earth/business/service/FileInfoService.java index 4cfce7f..364c5e2 100644 --- a/src/main/java/com/yj/earth/business/service/FileInfoService.java +++ b/src/main/java/com/yj/earth/business/service/FileInfoService.java @@ -5,12 +5,14 @@ import com.baomidou.mybatisplus.extension.service.IService; import jakarta.servlet.http.HttpServletResponse; import org.springframework.web.multipart.MultipartFile; +import java.io.File; import java.util.Map; public interface FileInfoService extends IService { // 根据文件ID获取文件绝对路径 String getFileAbsolutePath(String id); Map handleLocationImageUpload(MultipartFile file); + Map handleLocationImageUpload(File file); String uploadWithPreview(MultipartFile file); void writeResponseMessage(HttpServletResponse response, String message); String getFullUploadPath(); diff --git a/src/main/java/com/yj/earth/business/service/impl/FileInfoServiceImpl.java b/src/main/java/com/yj/earth/business/service/impl/FileInfoServiceImpl.java index 22fce39..25bd391 100644 --- a/src/main/java/com/yj/earth/business/service/impl/FileInfoServiceImpl.java +++ b/src/main/java/com/yj/earth/business/service/impl/FileInfoServiceImpl.java @@ -104,6 +104,62 @@ public class FileInfoServiceImpl extends ServiceImpl i return result; } + public Map handleLocationImageUpload(File file) { + // 构建并返回结果 + Map result = new HashMap<>(); + try { + if (file == null || !file.exists()) { + throw new IllegalArgumentException("文件不存在"); + } + if (file.length() == 0) { + throw new IllegalArgumentException("上传文件不能为空(空文件)"); + } + + // 原始文件名 + String originalFilename = file.getName(); + // 文件后缀 + String fileSuffix = FileUtil.extName(originalFilename); + // 文件MIME类型 + String contentType = Files.probeContentType(file.toPath()); + + if (contentType == null || !contentType.startsWith("image/")) { + throw new IllegalArgumentException("请上传图片文件,当前文件类型:" + contentType); + } + + // 获取完整的上传目录路径 + Path fullUploadPath = Paths.get(getFullUploadPath()); + // 生成唯一文件名 + String uniqueFileName = UUID.randomUUID().toString().replaceAll("-", "") + "." + fileSuffix; + // 创建文件存储目录(不存在则创建) + Files.createDirectories(fullUploadPath); + // 构建目标文件路径 + Path destFilePath = fullUploadPath.resolve(uniqueFileName); + // 覆盖已存在的文件 + Files.copy(file.toPath(), destFilePath, java.nio.file.StandardCopyOption.REPLACE_EXISTING); + String fileMd5 = calculateFileMd5(destFilePath.toFile()); + Map metadata; + try (InputStream is = Files.newInputStream(destFilePath)) { + metadata = extractImageMetadata(is); + } + FileInfo fileInfo = new FileInfo(); + fileInfo.setFileName(originalFilename); + fileInfo.setFileSuffix(fileSuffix); + fileInfo.setContentType(contentType); + fileInfo.setFileSize(file.length()); + fileInfo.setFilePath(uniqueFileName); + fileInfo.setFileMd5(fileMd5); + this.save(fileInfo); + result.put("url", "/fileInfo/preview/" + fileInfo.getId()); + result.put("lon", metadata.get("lon")); + result.put("lat", metadata.get("lat")); + result.put("alt", metadata.get("alt")); + + } catch (IOException e) { + throw new RuntimeException("文件处理失败: " + e.getMessage(), e); + } + return result; + } + public String uploadWithPreview(MultipartFile file) { FileInfo fileInfo = new FileInfo(); try { diff --git a/src/main/java/com/yj/earth/business/service/impl/SourceServiceImpl.java b/src/main/java/com/yj/earth/business/service/impl/SourceServiceImpl.java index 48dd85e..35d5452 100644 --- a/src/main/java/com/yj/earth/business/service/impl/SourceServiceImpl.java +++ b/src/main/java/com/yj/earth/business/service/impl/SourceServiceImpl.java @@ -95,12 +95,19 @@ public class SourceServiceImpl extends ServiceImpl impleme public Source addModelSource(AddModelSourceDto addModelSourceDto) { // 获取资源绝对路径 String sourcePath = addModelSourceDto.getSourcePath(); + // 判断数据是否在数据库存在 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(Source::getSourcePath, sourcePath); + if (sourceService.count(queryWrapper) > 0) { + throw new RuntimeException("资源已存在"); + } + // 获取资源名称 String sourceName = FileUtil.mainName(sourcePath); // 校验是否通过 String message = sourceService.checkIsPass(addModelSourceDto.getParentId(), sourceName); if (message != null) { - return null; + throw new RuntimeException("父节点不存在"); } // 调用SDK加载资源 String sourceId = sourceService.addAndGetSourceId(sourcePath); diff --git a/src/main/java/com/yj/earth/common/config/SaTokenConfig.java b/src/main/java/com/yj/earth/common/config/SaTokenConfig.java index 49f0239..3387755 100644 --- a/src/main/java/com/yj/earth/common/config/SaTokenConfig.java +++ b/src/main/java/com/yj/earth/common/config/SaTokenConfig.java @@ -31,7 +31,9 @@ public class SaTokenConfig implements WebMvcConfigurer { excludePathPatterns.add("/iconLibrary/data/icon/**"); excludePathPatterns.add("/militaryLibrary/data/military/**"); excludePathPatterns.add("/modelLibrary/data/**"); - excludePathPatterns.add("/**"); + excludePathPatterns.add("/auth/show"); + excludePathPatterns.add("/auth/info"); + excludePathPatterns.add("/auth/import"); // 注册 Sa-Token 拦截器 registry.addInterceptor(new SaInterceptor(handle -> { diff --git a/src/main/java/com/yj/earth/common/service/ServerInitService.java b/src/main/java/com/yj/earth/common/service/ServerInitService.java index 868c3d5..ef081d8 100644 --- a/src/main/java/com/yj/earth/common/service/ServerInitService.java +++ b/src/main/java/com/yj/earth/common/service/ServerInitService.java @@ -39,7 +39,7 @@ public class ServerInitService { for (Source source : list) { // 同步资源 sourceService.getDetail(source.getSourcePath(), sourceService.addAndGetSourceId(source.getSourcePath())); - log.info("初始化资源<--{}-->完成", source.getSourceName()); + log.info("初始化资源 <--{}--> 完成", source.getSourceName()); } } diff --git a/src/main/java/com/yj/earth/design/TsPlan.java b/src/main/java/com/yj/earth/design/TsPlan.java index e903893..7b5bc57 100644 --- a/src/main/java/com/yj/earth/design/TsPlan.java +++ b/src/main/java/com/yj/earth/design/TsPlan.java @@ -13,6 +13,8 @@ public class TsPlan { private String name; @Schema(description = "方案描述") private String desc; + @Schema(description = "滑轮") + private Integer wheel; @Schema(description = "创建人") private String createdBy; @Schema(description = "仿真开始时间") diff --git a/src/main/java/com/yj/earth/dto/tsPlan/AddTsPlanDto.java b/src/main/java/com/yj/earth/dto/tsPlan/AddTsPlanDto.java index 3118343..102e4aa 100644 --- a/src/main/java/com/yj/earth/dto/tsPlan/AddTsPlanDto.java +++ b/src/main/java/com/yj/earth/dto/tsPlan/AddTsPlanDto.java @@ -11,6 +11,8 @@ public class AddTsPlanDto { private String name; @Schema(description = "方案描述") private String desc; + @Schema(description = "滑轮") + private Integer wheel; @Schema(description = "仿真开始时间") private LocalDateTime simulationStartTime; } diff --git a/src/main/java/com/yj/earth/dto/tsPlan/UpdateTsPlanDto.java b/src/main/java/com/yj/earth/dto/tsPlan/UpdateTsPlanDto.java index 943aa58..f1d06b3 100644 --- a/src/main/java/com/yj/earth/dto/tsPlan/UpdateTsPlanDto.java +++ b/src/main/java/com/yj/earth/dto/tsPlan/UpdateTsPlanDto.java @@ -13,6 +13,8 @@ public class UpdateTsPlanDto { private String name; @Schema(description = "方案描述") private String desc; + @Schema(description = "滑轮") + private Integer wheel; @Schema(description = "仿真开始时间") private LocalDateTime simulationStartTime; } diff --git a/src/main/java/com/yj/earth/dto/tsSource/DragTsSourceDto.java b/src/main/java/com/yj/earth/dto/tsSource/DragTsSourceDto.java new file mode 100644 index 0000000..f90e5de --- /dev/null +++ b/src/main/java/com/yj/earth/dto/tsSource/DragTsSourceDto.java @@ -0,0 +1,16 @@ +package com.yj.earth.dto.tsSource; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class DragTsSourceDto { + @Schema(description = "主键") + private String id; + + @Schema(description = "父级ID") + private String parentId; + + @Schema(description = "树形索引") + private Integer treeIndex; +} diff --git a/src/main/java/com/yj/earth/params/MilitaryParam.java b/src/main/java/com/yj/earth/params/MilitaryParam.java index 238125d..abe6cbe 100644 --- a/src/main/java/com/yj/earth/params/MilitaryParam.java +++ b/src/main/java/com/yj/earth/params/MilitaryParam.java @@ -2,6 +2,7 @@ package com.yj.earth.params; import com.yj.earth.annotation.SourceType; import lombok.Data; +import lombok.NoArgsConstructor; import java.util.List; @@ -22,6 +23,7 @@ public class MilitaryParam { private Attribute attribute; private String attributeType; private Text text; + private CustomView customView; @Data public static class Position { @@ -63,4 +65,26 @@ public class MilitaryParam { private int far; private Position position; } + + @Data + @NoArgsConstructor + public static class CustomView { + private LinkImage.CustomView.Orientation orientation; + private LinkImage.CustomView.RelativePosition relativePosition; + @Data + @NoArgsConstructor + public static class Orientation { + private double heading; + private double pitch; + private double roll; + } + + @Data + @NoArgsConstructor + public static class RelativePosition { + private double lng; + private double lat; + private double alt; + } + } } diff --git a/src/main/java/com/yj/earth/params/Vector.java b/src/main/java/com/yj/earth/params/Vector.java index 3f12c4a..a12c149 100644 --- a/src/main/java/com/yj/earth/params/Vector.java +++ b/src/main/java/com/yj/earth/params/Vector.java @@ -17,6 +17,6 @@ public class Vector { private List headTables; private boolean show; private String color; - private double opacity; + private Double opacity; private Object customView; } diff --git a/src/main/java/com/yj/earth/vo/IconVo.java b/src/main/java/com/yj/earth/vo/IconVo.java index edb7f1c..5818b26 100644 --- a/src/main/java/com/yj/earth/vo/IconVo.java +++ b/src/main/java/com/yj/earth/vo/IconVo.java @@ -1,7 +1,5 @@ package com.yj.earth.vo; -import com.yj.earth.business.domain.Icon; -import com.yj.earth.business.domain.Military; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data;