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