From 521efbafaccf6eab119114694ef49a637ffe1a97 Mon Sep 17 00:00:00 2001
From: ZZX9599 <536509593@qq.com>
Date: Mon, 22 Sep 2025 17:13:22 +0800
Subject: [PATCH] =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E5=BA=93?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pom.xml | 6 +
.../java/com/yj/earth/aspect/AuthAspect.java | 4 +-
.../java/com/yj/earth/auth/AuthGenerator.java | 4 +
.../controller/FileInfoController.java | 165 +++------
.../business/controller/ModelController.java | 65 ----
.../controller/ModelTypeController.java | 12 -
.../business/controller/SourceController.java | 82 +++--
.../TacticalCalculationController.java | 2 +-
.../com/yj/earth/business/domain/Model.java | 39 +-
.../yj/earth/business/domain/ModelType.java | 19 +-
.../yj/earth/business/mapper/ModelMapper.java | 18 -
.../business/mapper/ModelTypeMapper.java | 18 -
.../business/service/FileInfoService.java | 8 +
.../earth/business/service/ModelService.java | 16 -
.../business/service/ModelTypeService.java | 16 -
.../service/impl/FileInfoServiceImpl.java | 206 ++++++++++-
.../service/impl/ModelServiceImpl.java | 20 --
.../service/impl/ModelTypeServiceImpl.java | 20 --
.../common/config/GlobalExceptionHandler.java | 3 -
.../yj/earth/common/config/SaTokenConfig.java | 2 +-
.../common/service/ServerInitService.java | 95 -----
.../com/yj/earth/common/util/CodeUtil.java | 2 +-
.../com/yj/earth/common/util/FileUtil.java | 28 ++
.../com/yj/earth/common/util/JsonUtil.java | 39 ++
.../com/yj/earth/common/util/SQLiteUtil.java | 334 ++++++++++++++++++
.../yj/earth/datasource/DatabaseManager.java | 6 +-
.../com/yj/earth/design/BusinessConfig.java | 24 ++
.../com/yj/earth/design/ModelLibrary.java | 22 ++
.../businessConfig/AddBusinessConfigDto.java | 13 +
.../yj/earth/dto/model/AddModelTypeDto.java | 12 +
...ileDto.java => CreateModelLibraryDto.java} | 6 +-
.../java/com/yj/earth/params/LinkImage.java | 134 +++++++
src/main/java/com/yj/earth/params/Point.java | 18 +
.../java/com/yj/earth/params/Terrain.java | 12 +
.../java/com/yj/earth/params/VrImage.java | 134 +++++++
.../java/com/yj/earth/vo/ModelTypeVo.java | 40 +++
src/main/java/com/yj/earth/vo/ModelVo.java | 9 +
src/main/resources/application.yml | 4 -
src/main/resources/mapper/ModelMapper.xml | 24 --
src/main/resources/mapper/ModelTypeMapper.xml | 19 -
40 files changed, 1177 insertions(+), 523 deletions(-)
delete mode 100644 src/main/java/com/yj/earth/business/controller/ModelController.java
delete mode 100644 src/main/java/com/yj/earth/business/controller/ModelTypeController.java
delete mode 100644 src/main/java/com/yj/earth/business/mapper/ModelMapper.java
delete mode 100644 src/main/java/com/yj/earth/business/mapper/ModelTypeMapper.java
delete mode 100644 src/main/java/com/yj/earth/business/service/ModelService.java
delete mode 100644 src/main/java/com/yj/earth/business/service/ModelTypeService.java
delete mode 100644 src/main/java/com/yj/earth/business/service/impl/ModelServiceImpl.java
delete mode 100644 src/main/java/com/yj/earth/business/service/impl/ModelTypeServiceImpl.java
create mode 100644 src/main/java/com/yj/earth/common/util/FileUtil.java
create mode 100644 src/main/java/com/yj/earth/common/util/SQLiteUtil.java
create mode 100644 src/main/java/com/yj/earth/design/BusinessConfig.java
create mode 100644 src/main/java/com/yj/earth/design/ModelLibrary.java
create mode 100644 src/main/java/com/yj/earth/dto/businessConfig/AddBusinessConfigDto.java
create mode 100644 src/main/java/com/yj/earth/dto/model/AddModelTypeDto.java
rename src/main/java/com/yj/earth/dto/model/{CreateModelFileDto.java => CreateModelLibraryDto.java} (68%)
create mode 100644 src/main/java/com/yj/earth/params/LinkImage.java
create mode 100644 src/main/java/com/yj/earth/params/Terrain.java
create mode 100644 src/main/java/com/yj/earth/params/VrImage.java
create mode 100644 src/main/java/com/yj/earth/vo/ModelTypeVo.java
create mode 100644 src/main/java/com/yj/earth/vo/ModelVo.java
delete mode 100644 src/main/resources/mapper/ModelMapper.xml
delete mode 100644 src/main/resources/mapper/ModelTypeMapper.xml
diff --git a/pom.xml b/pom.xml
index 1ea7803..18c2c19 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,6 +29,12 @@
spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
com.baomidou
diff --git a/src/main/java/com/yj/earth/aspect/AuthAspect.java b/src/main/java/com/yj/earth/aspect/AuthAspect.java
index d459f6f..72765c3 100644
--- a/src/main/java/com/yj/earth/aspect/AuthAspect.java
+++ b/src/main/java/com/yj/earth/aspect/AuthAspect.java
@@ -61,13 +61,13 @@ public class AuthAspect {
}
}
- // 授权有效,继续执行原方法
+ // 授权有效、继续执行原方法
return point.proceed();
}
/**
* 读取授权文件内容
- * @return 授权文件内容,如果文件不存在或读取失败则返回null
+ * @return 授权文件内容、如果文件不存在或读取失败则返回null
*/
private String readLicenseFile() {
try {
diff --git a/src/main/java/com/yj/earth/auth/AuthGenerator.java b/src/main/java/com/yj/earth/auth/AuthGenerator.java
index 5539d81..2260890 100644
--- a/src/main/java/com/yj/earth/auth/AuthGenerator.java
+++ b/src/main/java/com/yj/earth/auth/AuthGenerator.java
@@ -70,4 +70,8 @@ public class AuthGenerator {
throw new RuntimeException("授权信息加密失败", e);
}
}
+
+ public static void main(String[] args) {
+ System.out.println(generateAuth("标准版", 1000, 30, "DAC653349FD15F1E6DB2F9322AD628F4"));
+ }
}
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 546ef9a..b4e3df6 100644
--- a/src/main/java/com/yj/earth/business/controller/FileInfoController.java
+++ b/src/main/java/com/yj/earth/business/controller/FileInfoController.java
@@ -4,17 +4,22 @@ import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
+import com.drew.lang.Rational;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import java.io.*;
import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.drew.metadata.MetadataException;
+import com.drew.metadata.exif.GpsDirectory;
import com.yj.earth.business.domain.FileInfo;
import com.yj.earth.business.service.FileInfoService;
import com.yj.earth.common.util.ApiResponse;
@@ -46,41 +51,22 @@ public class FileInfoController {
@Resource
private FileInfoService fileInfoService;
- @Value("${file.upload.path}")
- private String uploadPath;
-
- // 获取项目根目录
- private String getProjectRootPath() {
- return System.getProperty("user.dir");
- }
-
- // 获取完整的上传目录路径
- private String getFullUploadPath() {
- // 拼接项目根目录和配置的上传路径
- return getProjectRootPath() + File.separator + uploadPath;
- }
-
@Operation(summary = "文件上传")
@PostMapping("/upload")
public ApiResponse uploadFiles(@Parameter(description = "上传的文件数组", required = true) @RequestParam("files") MultipartFile[] files) throws IOException {
-
// 校验文件数组是否为空
if (files == null || files.length == 0) {
return ApiResponse.failure("上传文件不能为空");
}
-
// 获取完整的上传目录路径
- String fullUploadPath = getFullUploadPath();
-
+ String fullUploadPath = fileInfoService.getFullUploadPath();
List fileInfoVoList = new ArrayList<>();
-
// 遍历处理每个文件
for (MultipartFile file : files) {
// 跳过空文件
if (file.isEmpty()) {
continue;
}
-
// 获取原始文件名和后缀
String originalFilename = file.getOriginalFilename();
String fileSuffix = FileUtil.extName(originalFilename);
@@ -106,7 +92,7 @@ public class FileInfoController {
// 查询有没有文件名一样并且 MD5 也一样的数据
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(FileInfo::getFileName, originalFilename).eq(FileInfo::getFileMd5, fileMd5);
- if (fileInfoService.count(queryWrapper) > 0) { // 修复了此处的bug、添加了queryWrapper参数
+ if (fileInfoService.count(queryWrapper) > 0) {
return ApiResponse.failure("已存在文件名相同且内容完全一致的文件");
}
@@ -116,7 +102,7 @@ public class FileInfoController {
fileInfo.setFileSuffix(fileSuffix);
fileInfo.setContentType(contentType);
fileInfo.setFileSize(file.getSize());
- fileInfo.setFilePath(uniqueFileName); // 只保存相对文件名、不保存完整路径
+ fileInfo.setFilePath(uniqueFileName);
fileInfo.setFileMd5(fileMd5);
// 保存文件信息并获取ID
@@ -152,7 +138,7 @@ public class FileInfoController {
}
// 构建完整文件路径
- String fullPath = getFullUploadPath() + File.separator + fileInfo.getFilePath();
+ String fullPath = fileInfoService.getFullUploadPath() + File.separator + fileInfo.getFilePath();
File file = new File(fullPath);
// 校验文件是否存在
@@ -185,7 +171,7 @@ public class FileInfoController {
}
// 构建完整文件路径
- String fullPath = getFullUploadPath() + File.separator + fileInfo.getFilePath();
+ String fullPath = fileInfoService.getFullUploadPath() + File.separator + fileInfo.getFilePath();
File file = new File(fullPath);
// 校验文件是否存在
@@ -204,100 +190,59 @@ public class FileInfoController {
}
}
- public String handleLocationImageUpload(MultipartFile file) {
+ @Operation(summary = "本地文件预览")
+ @GetMapping("/previewLocal")
+ public void previewLocalFile(@Parameter(description = "本地文件绝对路径") @RequestParam String fileAbsolutePath, HttpServletResponse response) {
+ Path targetFilePath = null;
try {
- // 校验文件是否为空
- if (file.isEmpty()) {
- throw new IllegalArgumentException("上传文件不能为空");
- }
- // 获取文件基本信息
- String originalFilename = file.getOriginalFilename();
- String fileSuffix = FileUtil.extName(originalFilename);
- String contentType = file.getContentType();
- // 验证是否为图片文件
- if (contentType == null || !contentType.startsWith("image/")) {
- throw new IllegalArgumentException("请上传图片文件");
- }
- // 获取完整的上传目录路径
- Path fullUploadPath = Paths.get(getFullUploadPath());
- // 生成唯一文件名
- String uniqueFileName = UUID.randomUUID().toString().replaceAll("-", "") + "." + fileSuffix;
- // 创建文件存储目录
- Files.createDirectories(fullUploadPath);
- // 构建完整文件路径并保存文件
- Path destFilePath = fullUploadPath.resolve(uniqueFileName);
- // 先将文件保存到目标位置
- file.transferTo(destFilePath);
- // 计算文件MD5(使用已保存的文件)
- String fileMd5 = calculateFileMd5(destFilePath.toFile());
- // 检查文件是否已存在
- LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
- queryWrapper.eq(FileInfo::getFileName, originalFilename)
- .eq(FileInfo::getFileMd5, fileMd5);
- if (fileInfoService.count(queryWrapper) > 0) {
- throw new IllegalStateException("已存在相同的图片文件");
- }
- // 提取图片元数据(使用已保存的文件,避免使用临时文件)
- 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.getSize());
- fileInfo.setFilePath(uniqueFileName);
- fileInfo.setFileMd5(fileMd5);
- fileInfoService.save(fileInfo);
- // 构建并返回结果
- Map result = new HashMap<>();
- result.put("previewUrl", "/fileInfo/preview/" + fileInfo.getId());
- result.put("downloadUrl", "/fileInfo/download/" + fileInfo.getId());
- result.put("metadata", metadata);
- return JsonUtil.mapToJson(result);
- } catch (IOException e) {
- throw new RuntimeException("文件上传失败: " + e.getMessage(), e);
- }
- }
+ // 标准化路径
+ targetFilePath = Paths.get(fileAbsolutePath).toRealPath();
- /**
- * 计算文件的 MD5
- */
- private String calculateFileMd5(File file) throws IOException {
- try (InputStream is = new FileInputStream(file)) {
- return DigestUtils.md5DigestAsHex(is);
- }
- }
+ // 校验文件合法性:是否存在、是否为普通文件
+ BasicFileAttributes fileAttr = Files.readAttributes(targetFilePath, BasicFileAttributes.class);
+ if (!fileAttr.isRegularFile()) {
+ response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ fileInfoService.writeResponseMessage(response, "目标路径不是有效的文件");
+ return;
+ }
- /**
- * 提取图片的EXIF元数据(包括定位信息)
- */
- private Map extractImageMetadata(InputStream inputStream) {
- try {
- Map result = new HashMap<>();
- Metadata metadata = ImageMetadataReader.readMetadata(inputStream);
+ // 设置预览响应头
+ String fileName = targetFilePath.getFileName().toString();
+ String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());
+ String contentType = Files.probeContentType(targetFilePath);
- // 遍历所有元数据目录
- for (Directory directory : metadata.getDirectories()) {
- String directoryName = directory.getName();
- Map directoryTags = new HashMap<>();
+ // 对于文本类型文件、指定字符编码
+ if (contentType != null && contentType.startsWith("text/")) {
+ response.setContentType(contentType + "; charset=UTF-8");
+ } else {
+ response.setContentType(contentType != null ? contentType : "application/octet-stream");
+ }
- // 提取当前目录下的所有标签
- for (com.drew.metadata.Tag tag : directory.getTags()) {
- directoryTags.put(tag.getTagName(), tag.getDescription());
- }
-
- // 存储当前目录的所有标签
- if (!directoryTags.isEmpty()) {
- result.put(directoryName, directoryTags);
+ response.setContentLengthLong(fileAttr.size());
+ // 关键修改:将attachment改为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];
+ int len;
+ while ((len = inputStream.read(buffer)) != -1) {
+ outputStream.write(buffer, 0, len);
}
+ outputStream.flush();
}
- return result;
- } catch (ImageProcessingException | IOException e) {
- return Collections.emptyMap();
+ } catch (NoSuchFileException e) {
+ response.setStatus(HttpServletResponse.SC_NOT_FOUND);
+ fileInfoService.writeResponseMessage(response, "文件不存在:" + fileAbsolutePath);
+ } catch (SecurityException e) {
+ response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+ fileInfoService.writeResponseMessage(response, "访问拒绝:无权限读取该文件");
+ } catch (Exception e) {
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ fileInfoService.writeResponseMessage(response, "预览失败:" + e.getMessage());
}
}
}
diff --git a/src/main/java/com/yj/earth/business/controller/ModelController.java b/src/main/java/com/yj/earth/business/controller/ModelController.java
deleted file mode 100644
index 5d2b07e..0000000
--- a/src/main/java/com/yj/earth/business/controller/ModelController.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.yj.earth.business.controller;
-
-import com.yj.earth.business.service.ModelService;
-import com.yj.earth.business.service.ModelTypeService;
-import com.yj.earth.common.util.ApiResponse;
-import com.yj.earth.datasource.DatabaseManager;
-import com.yj.earth.design.Model;
-import com.yj.earth.design.ModelType;
-import com.yj.earth.dto.model.CreateModelFileDto;
-import io.swagger.v3.oas.annotations.Operation;
-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.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.annotation.Resource;
-import java.io.File;
-import java.sql.Connection;
-import java.sql.DriverManager;
-
-@Tag(name = "模型相关")
-@RestController
-@RequestMapping("/model")
-public class ModelController {
- @Resource
- private ModelService modelService;
- @Resource
- private ModelTypeService modelTypeService;
-
- @Operation(summary = "创建模型库")
- @PostMapping("/createModelFile")
- public ApiResponse createModelFile(@RequestBody CreateModelFileDto createModelFileDto) {
- try {
- // 获取参数并处理文件路径
- String folderPath = createModelFileDto.getFolderPath();
- String modelFileName = createModelFileDto.getModelFileName() + ".model";
- // 创建文件夹(如果不存在)
- File folder = new File(folderPath);
- if (!folder.exists()) {
- boolean folderCreated = folder.mkdirs();
- if (!folderCreated) {
- return ApiResponse.failure("无法创建文件夹: " + folderPath);
- }
- }
- // 构建完整文件路径
- String filePath = folderPath + File.separator + modelFileName;
- // 加载 SQLite 驱动并创建数据库文件
- Class.forName("org.sqlite.JDBC");
- // SQLite会自动创建不存在的数据库文件
- try (Connection connection = DriverManager.getConnection("jdbc:sqlite:" + filePath)) {
- if (connection != null) {
- // 初始化表结构
- DatabaseManager.createTablesForEntities(DatabaseManager.DatabaseType.SQLITE, ModelType.class, connection);
- DatabaseManager.createTablesForEntities(DatabaseManager.DatabaseType.SQLITE, Model.class, connection);
- return ApiResponse.success(null);
- }
- }
- } catch (Exception e) {
- return ApiResponse.failure("创建模型库失败: " + e.getMessage());
- }
- return ApiResponse.failure("未知错误");
- }
-}
diff --git a/src/main/java/com/yj/earth/business/controller/ModelTypeController.java b/src/main/java/com/yj/earth/business/controller/ModelTypeController.java
deleted file mode 100644
index a63cd88..0000000
--- a/src/main/java/com/yj/earth/business/controller/ModelTypeController.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.yj.earth.business.controller;
-
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-@Tag(name = "模型类型管理")
-@RestController
-@RequestMapping("/modelType")
-public class ModelTypeController {
-
-}
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 8caeeb6..ca862fc 100644
--- a/src/main/java/com/yj/earth/business/controller/SourceController.java
+++ b/src/main/java/com/yj/earth/business/controller/SourceController.java
@@ -2,20 +2,8 @@ package com.yj.earth.business.controller;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.io.FileUtil;
-import cn.hutool.core.lang.UUID;
-import cn.hutool.core.util.IdUtil;
-import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.drew.imaging.ImageMetadataReader;
-import com.drew.imaging.ImageProcessingException;
-import com.drew.metadata.Directory;
-import com.drew.metadata.Metadata;
import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.yj.earth.annotation.CheckAuth;
-import com.yj.earth.business.domain.FileInfo;
-import com.yj.earth.business.domain.Role;
import com.yj.earth.business.domain.Source;
import com.yj.earth.business.service.*;
import com.yj.earth.common.service.SourceDataGenerator;
@@ -24,6 +12,7 @@ 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.*;
+import com.yj.earth.params.Point;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -34,9 +23,6 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
import java.util.*;
import static com.yj.earth.common.constant.GlobalConstant.DIRECTORY;
@@ -62,12 +48,6 @@ public class SourceController {
@Resource
private FileInfoService fileInfoService;
- @Resource
- private FileInfoController fileInfoControllerl;
-
- @Value("${file.upload.path}")
- private String uploadPath;
-
@PostMapping("/addDirectory")
@Operation(summary = "新增目录资源")
public ApiResponse addDirectory(@RequestBody AddDirectoryDto addDirectoryDto) {
@@ -223,23 +203,75 @@ public class SourceController {
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) {
+ // 验证并转换参数
+ sourceParamsValidator.validateAndConvert(
+ sourceType,
+ JsonUtil.jsonToMap(params)
+ );
+
+ List sources = new ArrayList<>();
for (int i = 0; i < files.length; i++) {
- String detail = fileInfoControllerl.handleLocationImageUpload(files[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("locationImage");
+ source.setSourceType(sourceType);
source.setTreeIndex(treeIndex);
- source.setDetail(detail);
+
+ // 转换为对象
+ 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);
+ }
+
+ 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(null);
+ return ApiResponse.success(sources);
}
@GetMapping("/type")
diff --git a/src/main/java/com/yj/earth/business/controller/TacticalCalculationController.java b/src/main/java/com/yj/earth/business/controller/TacticalCalculationController.java
index aabf0be..3531828 100644
--- a/src/main/java/com/yj/earth/business/controller/TacticalCalculationController.java
+++ b/src/main/java/com/yj/earth/business/controller/TacticalCalculationController.java
@@ -38,7 +38,7 @@ public class TacticalCalculationController {
// 同向而行:时间 = 距离 / (速度差)
double speedDiff = Math.abs(input.getSpeed1() - input.getSpeed2());
if (speedDiff <= 0) {
- throw new IllegalArgumentException("同向而行时,速度不能相等或后方速度小于前方");
+ throw new IllegalArgumentException("同向而行时、速度不能相等或后方速度小于前方");
}
meetTimeHours = input.getInitialDistance() / speedDiff;
} else {
diff --git a/src/main/java/com/yj/earth/business/domain/Model.java b/src/main/java/com/yj/earth/business/domain/Model.java
index 4cc5e0a..d6240c9 100644
--- a/src/main/java/com/yj/earth/business/domain/Model.java
+++ b/src/main/java/com/yj/earth/business/domain/Model.java
@@ -1,49 +1,34 @@
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 io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
import lombok.Data;
+import lombok.NoArgsConstructor;
-import java.io.Serializable;
import java.time.LocalDateTime;
-
@Data
-public class Model implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
+@NoArgsConstructor
+@AllArgsConstructor
+public class Model {
@Schema(description = "主键")
- @TableId(value = "id", type = IdType.ASSIGN_UUID)
private String id;
-
@Schema(description = "模型类型ID")
private String modelTypeId;
-
@Schema(description = "模型名称")
private String modelName;
-
@Schema(description = "模型类型")
private String modelType;
-
@Schema(description = "海报类型")
private String posterType;
-
- @Schema(description = "海报")
- private byte[] poster;
-
- @Schema(description = "数据")
- private byte[] data;
-
- @Schema(description = "视图")
+ @Schema(description = "海报数据")
+ private String poster;
+ @Schema(description = "模型数据")
+ private String data;
+ @Schema(description = "模型视图")
private String view;
-
- @TableField(fill = FieldFill.INSERT)
+ @Schema(description = "创建时间")
private LocalDateTime createdAt;
-
- @TableField(fill = FieldFill.UPDATE)
+ @Schema(description = "更新时间")
private LocalDateTime updatedAt;
}
diff --git a/src/main/java/com/yj/earth/business/domain/ModelType.java b/src/main/java/com/yj/earth/business/domain/ModelType.java
index b303c8a..ca189af 100644
--- a/src/main/java/com/yj/earth/business/domain/ModelType.java
+++ b/src/main/java/com/yj/earth/business/domain/ModelType.java
@@ -1,35 +1,20 @@
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 io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
-import java.io.Serializable;
import java.time.LocalDateTime;
@Data
-public class ModelType implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
+public class ModelType {
@Schema(description = "主键")
- @TableId(value = "id", type = IdType.ASSIGN_UUID)
private String id;
-
@Schema(description = "模型类型名称")
private String name;
-
- @Schema(description = "模型类型父级ID")
+ @Schema(description = "父级节点ID")
private String parentId;
-
@Schema(description = "创建时间")
- @TableField(fill = FieldFill.INSERT)
private LocalDateTime createdAt;
-
@Schema(description = "更新时间")
- @TableField(fill = FieldFill.UPDATE)
private LocalDateTime updatedAt;
}
diff --git a/src/main/java/com/yj/earth/business/mapper/ModelMapper.java b/src/main/java/com/yj/earth/business/mapper/ModelMapper.java
deleted file mode 100644
index 9e46f96..0000000
--- a/src/main/java/com/yj/earth/business/mapper/ModelMapper.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.yj.earth.business.mapper;
-
-import com.yj.earth.business.domain.Model;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import org.apache.ibatis.annotations.Mapper;
-
-/**
- *
- * Mapper 接口
- *
- *
- * @author 周志雄
- * @since 2025-09-16
- */
-@Mapper
-public interface ModelMapper extends BaseMapper {
-
-}
diff --git a/src/main/java/com/yj/earth/business/mapper/ModelTypeMapper.java b/src/main/java/com/yj/earth/business/mapper/ModelTypeMapper.java
deleted file mode 100644
index 7c89063..0000000
--- a/src/main/java/com/yj/earth/business/mapper/ModelTypeMapper.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.yj.earth.business.mapper;
-
-import com.yj.earth.business.domain.ModelType;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import org.apache.ibatis.annotations.Mapper;
-
-/**
- *
- * Mapper 接口
- *
- *
- * @author 周志雄
- * @since 2025-09-16
- */
-@Mapper
-public interface ModelTypeMapper extends BaseMapper {
-
-}
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 d2d5de0..4cfce7f 100644
--- a/src/main/java/com/yj/earth/business/service/FileInfoService.java
+++ b/src/main/java/com/yj/earth/business/service/FileInfoService.java
@@ -2,8 +2,16 @@ package com.yj.earth.business.service;
import com.yj.earth.business.domain.FileInfo;
import com.baomidou.mybatisplus.extension.service.IService;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.Map;
public interface FileInfoService extends IService {
// 根据文件ID获取文件绝对路径
String getFileAbsolutePath(String id);
+ Map handleLocationImageUpload(MultipartFile file);
+ String uploadWithPreview(MultipartFile file);
+ void writeResponseMessage(HttpServletResponse response, String message);
+ String getFullUploadPath();
}
diff --git a/src/main/java/com/yj/earth/business/service/ModelService.java b/src/main/java/com/yj/earth/business/service/ModelService.java
deleted file mode 100644
index 53081cf..0000000
--- a/src/main/java/com/yj/earth/business/service/ModelService.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.yj.earth.business.service;
-
-import com.yj.earth.business.domain.Model;
-import com.baomidou.mybatisplus.extension.service.IService;
-
-/**
- *
- * 服务类
- *
- *
- * @author 周志雄
- * @since 2025-09-16
- */
-public interface ModelService extends IService {
-
-}
diff --git a/src/main/java/com/yj/earth/business/service/ModelTypeService.java b/src/main/java/com/yj/earth/business/service/ModelTypeService.java
deleted file mode 100644
index dbb4798..0000000
--- a/src/main/java/com/yj/earth/business/service/ModelTypeService.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.yj.earth.business.service;
-
-import com.yj.earth.business.domain.ModelType;
-import com.baomidou.mybatisplus.extension.service.IService;
-
-/**
- *
- * 服务类
- *
- *
- * @author 周志雄
- * @since 2025-09-16
- */
-public interface ModelTypeService extends IService {
-
-}
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 36d5d5b..6a2ea51 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
@@ -1,21 +1,38 @@
package com.yj.earth.business.service.impl;
+import cn.hutool.core.io.FileUtil;
+import com.drew.imaging.ImageMetadataReader;
+import com.drew.lang.Rational;
+import com.drew.metadata.Metadata;
+import com.drew.metadata.exif.GpsDirectory;
import com.yj.earth.business.domain.FileInfo;
import com.yj.earth.business.mapper.FileInfoMapper;
import com.yj.earth.business.service.FileInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.yj.earth.datasource.DatabaseManager;
import io.swagger.v3.oas.annotations.Parameter;
+import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
+import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.multipart.MultipartFile;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
@Service
public class FileInfoServiceImpl extends ServiceImpl implements FileInfoService {
- @Value("${file.upload.path}")
- private String uploadPath;
+ private static final String DEFAULT_UPLOAD_PATH = "upload";
public String getFileAbsolutePath(String id) {
@@ -26,7 +43,7 @@ public class FileInfoServiceImpl extends ServiceImpl i
}
// 构建完整文件路径
- String fullPath = uploadPath + File.separator + fileInfo.getFilePath();
+ String fullPath = DEFAULT_UPLOAD_PATH + File.separator + fileInfo.getFilePath();
File file = new File(fullPath);
// 校验文件是否存在
@@ -37,4 +54,187 @@ public class FileInfoServiceImpl extends ServiceImpl i
// 获取并返回绝对路径
return file.getAbsolutePath();
}
+
+ public Map handleLocationImageUpload(MultipartFile file) {
+ // 构建并返回结果
+ Map result = new HashMap<>();
+ try {
+ // 校验文件是否为空
+ if (file.isEmpty()) {
+ throw new IllegalArgumentException("上传文件不能为空");
+ }
+ // 获取文件基本信息
+ String originalFilename = file.getOriginalFilename();
+ String fileSuffix = FileUtil.extName(originalFilename);
+ String contentType = file.getContentType();
+ // 验证是否为图片文件
+ if (contentType == null || !contentType.startsWith("image/")) {
+ throw new IllegalArgumentException("请上传图片文件");
+ }
+ // 获取完整的上传目录路径
+ Path fullUploadPath = Paths.get(getFullUploadPath());
+ // 生成唯一文件名
+ String uniqueFileName = UUID.randomUUID().toString().replaceAll("-", "") + "." + fileSuffix;
+ // 创建文件存储目录
+ Files.createDirectories(fullUploadPath);
+ // 构建完整文件路径并保存文件
+ Path destFilePath = fullUploadPath.resolve(uniqueFileName);
+ // 先将文件保存到目标位置
+ file.transferTo(destFilePath);
+ // 计算文件MD5(使用已保存的文件)
+ 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.getSize());
+ 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();
+ // 构建并返回结果
+ Map result = new HashMap<>();
+ try {
+ // 校验文件是否为空
+ if (file.isEmpty()) {
+ throw new IllegalArgumentException("上传文件不能为空");
+ }
+ // 获取文件基本信息
+ String originalFilename = file.getOriginalFilename();
+ String fileSuffix = FileUtil.extName(originalFilename);
+ String contentType = file.getContentType();
+ // 获取完整的上传目录路径
+ Path fullUploadPath = Paths.get(getFullUploadPath());
+ // 生成唯一文件名
+ String uniqueFileName = UUID.randomUUID().toString().replaceAll("-", "") + "." + fileSuffix;
+ // 创建文件存储目录
+ Files.createDirectories(fullUploadPath);
+ // 构建完整文件路径并保存文件
+ Path destFilePath = fullUploadPath.resolve(uniqueFileName);
+ // 先将文件保存到目标位置
+ file.transferTo(destFilePath);
+ // 计算文件MD5(使用已保存的文件)
+ String fileMd5 = calculateFileMd5(destFilePath.toFile());
+ // 保存文件信息到数据库
+ fileInfo.setFileName(originalFilename);
+ fileInfo.setFileSuffix(fileSuffix);
+ fileInfo.setContentType(contentType);
+ fileInfo.setFileSize(file.getSize());
+ fileInfo.setFilePath(uniqueFileName);
+ fileInfo.setFileMd5(fileMd5);
+ this.save(fileInfo);
+ } catch (IOException e) {
+ throw new RuntimeException("文件上传失败: " + e.getMessage(), e);
+ }
+ return "/fileInfo/preview/" + fileInfo.getId();
+ }
+
+ public void writeResponseMessage(HttpServletResponse response, String message) {
+ try {
+ response.setContentType("text/plain; charset=UTF-8");
+ response.getWriter().write(message);
+ response.getWriter().flush();
+ } catch (IOException e) {
+ }
+ }
+
+ public String getFullUploadPath() {
+ // 拼接项目根目录和配置的上传路径
+ return DatabaseManager.getRecommendedCacheDirectory() + File.separator + DEFAULT_UPLOAD_PATH;
+ }
+
+ /**
+ * 提取图片的EXIF元数据
+ */
+ public Map extractImageMetadata(InputStream inputStream) {
+ Map result = new HashMap<>(3);
+ try {
+ Metadata metadata = ImageMetadataReader.readMetadata(inputStream);
+ // 获取GPS相关元数据目录(图片的经纬度和高度通常存储在GPS目录中)
+ GpsDirectory gpsDirectory = metadata.getFirstDirectoryOfType(GpsDirectory.class);
+ if (gpsDirectory == null) {
+ return result;
+ }
+
+ // 解析纬度(度分秒转十进制)
+ Double latitude = parseLatitudeOrLongitude(
+ gpsDirectory.getRationalArray(GpsDirectory.TAG_LATITUDE),
+ gpsDirectory.getString(GpsDirectory.TAG_LATITUDE_REF)
+ );
+
+ // 解析经度(度分秒转十进制)
+ Double longitude = parseLatitudeOrLongitude(
+ gpsDirectory.getRationalArray(GpsDirectory.TAG_LONGITUDE),
+ gpsDirectory.getString(GpsDirectory.TAG_LONGITUDE_REF)
+ );
+
+ // 解析高度(考虑海拔参考、0表示海平面以上、1表示以下)
+ Double altitude = null;
+ if (gpsDirectory.containsTag(GpsDirectory.TAG_ALTITUDE)) {
+ Rational altitudeRational = gpsDirectory.getRational(GpsDirectory.TAG_ALTITUDE);
+ if (altitudeRational != null) {
+ altitude = altitudeRational.doubleValue();
+ // 处理海拔参考(是否在海平面以下)
+ if (gpsDirectory.containsTag(GpsDirectory.TAG_ALTITUDE_REF) &&
+ gpsDirectory.getInt(GpsDirectory.TAG_ALTITUDE_REF) == 1) {
+ altitude = -altitude;
+ }
+ }
+ }
+
+ // 存入结果 Map
+ result.put("lat", latitude);
+ result.put("lon", longitude);
+ result.put("alt", altitude);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return result;
+ }
+
+ /**
+ * 将GPS的度分秒格式转换为十进制坐标
+ */
+ public Double parseLatitudeOrLongitude(Rational[] degreesMinutesSeconds, String ref) {
+ if (degreesMinutesSeconds == null || degreesMinutesSeconds.length != 3 || ref == null) {
+ return null;
+ }
+ // 度分秒转十进制:度 + 分/60 + 秒/3600
+ double degrees = degreesMinutesSeconds[0].doubleValue();
+ double minutes = degreesMinutesSeconds[1].doubleValue();
+ double seconds = degreesMinutesSeconds[2].doubleValue();
+ double value = degrees + (minutes / 60) + (seconds / 3600);
+ // 根据方向参考调整正负(南纬/西经为负)
+ if (ref.equalsIgnoreCase("S") || ref.equalsIgnoreCase("W")) {
+ value = -value;
+ }
+
+ return value;
+ }
+
+ /**
+ * 计算文件的 MD5
+ */
+ public String calculateFileMd5(File file) throws IOException {
+ try (InputStream is = new FileInputStream(file)) {
+ return DigestUtils.md5DigestAsHex(is);
+ }
+ }
}
diff --git a/src/main/java/com/yj/earth/business/service/impl/ModelServiceImpl.java b/src/main/java/com/yj/earth/business/service/impl/ModelServiceImpl.java
deleted file mode 100644
index 03dfe3e..0000000
--- a/src/main/java/com/yj/earth/business/service/impl/ModelServiceImpl.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.yj.earth.business.service.impl;
-
-import com.yj.earth.business.domain.Model;
-import com.yj.earth.business.mapper.ModelMapper;
-import com.yj.earth.business.service.ModelService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.stereotype.Service;
-
-/**
- *
- * 服务实现类
- *
- *
- * @author 周志雄
- * @since 2025-09-16
- */
-@Service
-public class ModelServiceImpl extends ServiceImpl implements ModelService {
-
-}
diff --git a/src/main/java/com/yj/earth/business/service/impl/ModelTypeServiceImpl.java b/src/main/java/com/yj/earth/business/service/impl/ModelTypeServiceImpl.java
deleted file mode 100644
index 8826fb9..0000000
--- a/src/main/java/com/yj/earth/business/service/impl/ModelTypeServiceImpl.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.yj.earth.business.service.impl;
-
-import com.yj.earth.business.domain.ModelType;
-import com.yj.earth.business.mapper.ModelTypeMapper;
-import com.yj.earth.business.service.ModelTypeService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.stereotype.Service;
-
-/**
- *
- * 服务实现类
- *
- *
- * @author 周志雄
- * @since 2025-09-16
- */
-@Service
-public class ModelTypeServiceImpl extends ServiceImpl implements ModelTypeService {
-
-}
diff --git a/src/main/java/com/yj/earth/common/config/GlobalExceptionHandler.java b/src/main/java/com/yj/earth/common/config/GlobalExceptionHandler.java
index 07cb141..364a530 100644
--- a/src/main/java/com/yj/earth/common/config/GlobalExceptionHandler.java
+++ b/src/main/java/com/yj/earth/common/config/GlobalExceptionHandler.java
@@ -11,9 +11,6 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ApiResponse handleException(Exception e) {
- if (!e.getMessage().contains("No static resource")) {
- log.error("全局异常处理:{}", e.getMessage());
- }
return ApiResponse.failure(e.getMessage());
}
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 9306d0c..49fdb47 100644
--- a/src/main/java/com/yj/earth/common/config/SaTokenConfig.java
+++ b/src/main/java/com/yj/earth/common/config/SaTokenConfig.java
@@ -23,10 +23,10 @@ public class SaTokenConfig implements WebMvcConfigurer {
excludePathPatterns.add("/v3/api-docs/**");
excludePathPatterns.add("/fileInfo/download/**");
excludePathPatterns.add("/fileInfo/preview/**");
+ excludePathPatterns.add("/fileInfo/previewLocal/**");
excludePathPatterns.add("/data/clt/**");
excludePathPatterns.add("/data/mbtiles/**");
excludePathPatterns.add("/data/pak/**");
- excludePathPatterns.add("/**");
// 注册 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 731574e..5d76c70 100644
--- a/src/main/java/com/yj/earth/common/service/ServerInitService.java
+++ b/src/main/java/com/yj/earth/common/service/ServerInitService.java
@@ -44,7 +44,6 @@ public class ServerInitService {
public void checkDefaultData() {
checkDefaultUserAndRole();
- checkDefaultSource();
}
public void checkDefaultUserAndRole() {
@@ -73,98 +72,4 @@ public class ServerInitService {
userService.save(user);
}
}
-
- public void checkDefaultSource() {
- if(sourceService.count() == 0) {
- // 查询管理员角色
- Role adminRole = roleService.getOne(new LambdaQueryWrapper().eq(Role::getRoleName, "管理员"));
- log.info("初始化默认资源数据");
- Source source1 = new Source();
- source1.setId(UUID.fastUUID().toString(true));
- source1.setSourceName("倾斜模型");
- source1.setSourceType("directory");
- source1.setTreeIndex(0);
- source1.setIsShow(1);
- sourceService.save(source1);
- roleSourceService.addRoleSource(adminRole.getId(), source1.getId());
-
- Source source2 = new Source();
- source2.setId(UUID.fastUUID().toString(true));
- source2.setSourceName("人工模型");
- source2.setSourceType("directory");
- source2.setTreeIndex(0);
- source2.setIsShow(1);
- sourceService.save(source2);
- roleSourceService.addRoleSource(adminRole.getId(), source2.getId());
-
- Source source3 = new Source();
- source3.setId(UUID.fastUUID().toString(true));
- source3.setSourceName("卫星底图");
- source3.setSourceType("directory");
- source3.setTreeIndex(0);
- source3.setIsShow(1);
- sourceService.save(source3);
- roleSourceService.addRoleSource(adminRole.getId(), source3.getId());
-
- Source source4 = new Source();
- source4.setId(UUID.fastUUID().toString(true));
- source4.setSourceName("地形");
- source4.setSourceType("directory");
- source4.setTreeIndex(0);
- source4.setIsShow(1);
- sourceService.save(source4);
- roleSourceService.addRoleSource(adminRole.getId(), source4.getId());
-
- Source source5 = new Source();
- source5.setId(UUID.fastUUID().toString(true));
- source5.setSourceName("在线图源");
- source5.setSourceType("directory");
- source5.setTreeIndex(0);
- source5.setIsShow(1);
- sourceService.save(source5);
- roleSourceService.addRoleSource(adminRole.getId(), source5.getId());
-
- Source source6 = new Source();
- source6.setId(UUID.fastUUID().toString(true));
- source6.setSourceName("卫星图");
- source6.setSourceType("arcgisWximagery");
- source6.setParentId(source5.getId());
- source6.setTreeIndex(0);
- source6.setIsShow(1);
- sourceService.save(source6);
- roleSourceService.addRoleSource(adminRole.getId(), source6.getId());
-
- Source source7 = new Source();
- source7.setId(UUID.fastUUID().toString(true));
- source7.setSourceName("暗黑地图");
- source7.setSourceType("arcgisBlueImagery");
- source7.setParentId(source5.getId());
- source7.setTreeIndex(0);
- source7.setIsShow(1);
- sourceService.save(source7);
- roleSourceService.addRoleSource(adminRole.getId(), source7.getId());
-
- Source source8 = new Source();
- source8.setId(UUID.fastUUID().toString(true));
- source8.setSourceName("路网图");
- source8.setSourceType("gdlwImagery");
- source8.setParentId(source5.getId());
- source8.setTreeIndex(0);
- source8.setIsShow(1);
- sourceService.save(source8);
- roleSourceService.addRoleSource(adminRole.getId(), source8.getId());
-
- Source source9 = new Source();
- source9.setId(UUID.fastUUID().toString(true));
- source9.setSourceName("矢量图");
- source9.setSourceType("gdslImagery");
- source9.setParentId(source5.getId());
- source9.setTreeIndex(0);
- source9.setIsShow(1);
- sourceService.save(source9);
- roleSourceService.addRoleSource(adminRole.getId(), source9.getId());
-
-
- }
- }
}
diff --git a/src/main/java/com/yj/earth/common/util/CodeUtil.java b/src/main/java/com/yj/earth/common/util/CodeUtil.java
index c885103..ac113dc 100644
--- a/src/main/java/com/yj/earth/common/util/CodeUtil.java
+++ b/src/main/java/com/yj/earth/common/util/CodeUtil.java
@@ -34,7 +34,7 @@ public class CodeUtil {
}
// 传入需要生成代码的表名
- Generation("model");
+ Generation("business_config");
}
public static void Generation(String... tableName) {
diff --git a/src/main/java/com/yj/earth/common/util/FileUtil.java b/src/main/java/com/yj/earth/common/util/FileUtil.java
new file mode 100644
index 0000000..63cd703
--- /dev/null
+++ b/src/main/java/com/yj/earth/common/util/FileUtil.java
@@ -0,0 +1,28 @@
+package com.yj.earth.common.util;
+
+import org.springframework.http.MediaType;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+public class FileUtil {
+
+ /**
+ * 将本地文件转换为 MultipartFile
+ */
+ public static MultipartFile convertToMultipartFile(File file) {
+ try (FileInputStream inputStream = new FileInputStream(file)) {
+ return new MockMultipartFile(
+ "files",
+ file.getName(),
+ MediaType.APPLICATION_OCTET_STREAM_VALUE,
+ inputStream
+ );
+ } catch (IOException e) {
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/com/yj/earth/common/util/JsonUtil.java b/src/main/java/com/yj/earth/common/util/JsonUtil.java
index 2b4e09c..37cdd8f 100644
--- a/src/main/java/com/yj/earth/common/util/JsonUtil.java
+++ b/src/main/java/com/yj/earth/common/util/JsonUtil.java
@@ -47,4 +47,43 @@ public class JsonUtil {
return new HashMap<>(0);
}
}
+
+ /**
+ * 将 JSON 字符串转换为指定类型的对象
+ */
+ public static T jsonToObject(String json, Class clazz) {
+ if (json == null || json.trim().isEmpty()) {
+ return null;
+ }
+ return objectMapper.convertValue(json, clazz);
+ }
+
+ /**
+ * 将 Map 转换为指定类型的对象
+ */
+ public static T mapToObject(Map map, Class clazz) {
+ if (map == null || clazz == null) {
+ return null;
+ }
+
+ try {
+ // 使用ObjectMapper将Map转换为指定类型对象
+ return objectMapper.convertValue(map, clazz);
+ } catch (IllegalArgumentException e) {
+ log.error("Map转对象失败、目标类型: {}, Map内容: {}", clazz.getName(), map, e);
+ return null;
+ }
+ }
+
+ /**
+ * 将任意 Object 转化为 JSON
+ */
+ public static String toJson(Object obj) {
+ try {
+ return objectMapper.writeValueAsString(obj);
+ } catch (JsonProcessingException e) {
+ log.error("对象转JSON失败", e);
+ return null;
+ }
+ }
}
diff --git a/src/main/java/com/yj/earth/common/util/SQLiteUtil.java b/src/main/java/com/yj/earth/common/util/SQLiteUtil.java
new file mode 100644
index 0000000..9665a0a
--- /dev/null
+++ b/src/main/java/com/yj/earth/common/util/SQLiteUtil.java
@@ -0,0 +1,334 @@
+package com.yj.earth.common.util;
+
+import java.sql.*;
+import java.util.*;
+import java.lang.reflect.*;
+import java.util.Date;
+import java.time.LocalDateTime; // 新增导入
+import java.time.format.DateTimeFormatter; // 新增导入
+import java.time.format.DateTimeParseException; // 新增导入
+
+public class SQLiteUtil {
+
+ // 加载 SQLite JDBC 驱动
+ static {
+ try {
+ Class.forName("org.sqlite.JDBC");
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("无法加载SQLite JDBC驱动", e);
+ }
+ }
+
+ // 统一日期格式(匹配数据库TEXT字段存储的格式:yyyy-MM-dd'T'HH:mm:ss.SSS)
+ private static final DateTimeFormatter LOCAL_DATE_TIME_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
+
+ /**
+ * 根据数据库文件绝对路径获取连接
+ */
+ public static Connection getConnection(String dbFilePath) throws SQLException {
+ String url = "jdbc:sqlite:" + dbFilePath;
+ return DriverManager.getConnection(url);
+ }
+
+ /**
+ * 执行查询并返回单个对象
+ */
+ public static T queryForObject(String dbFilePath, String sql, List