From dea2dbd508f672ad197baf8072a4f8605a9e09cf Mon Sep 17 00:00:00 2001 From: ZZX9599 <536509593@qq.com> Date: Sun, 28 Sep 2025 15:10:29 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A0=91=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ModelLibraryController.java | 55 ++++++--- .../business/controller/SourceController.java | 44 +++---- .../business/controller/UserController.java | 1 - .../earth/business/service/SourceService.java | 3 + .../service/impl/SourceServiceImpl.java | 44 ++++++- .../yj/earth/common/config/ServerConfig.java | 9 +- .../com/yj/earth/common/util/SdkUtil.java | 112 +++++++++++++----- .../earth/dto/source/UpdateShowHideDto.java | 12 ++ 8 files changed, 201 insertions(+), 79 deletions(-) create mode 100644 src/main/java/com/yj/earth/dto/source/UpdateShowHideDto.java diff --git a/src/main/java/com/yj/earth/business/controller/ModelLibraryController.java b/src/main/java/com/yj/earth/business/controller/ModelLibraryController.java index 99188f1..71d3c97 100644 --- a/src/main/java/com/yj/earth/business/controller/ModelLibraryController.java +++ b/src/main/java/com/yj/earth/business/controller/ModelLibraryController.java @@ -20,6 +20,7 @@ import com.yj.earth.vo.ModelVo; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import org.jetbrains.annotations.NotNull; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -153,20 +154,7 @@ public class ModelLibraryController { @Operation(summary = "模型类型列表") @GetMapping("/modelTypeList") public ApiResponse modelTypeTree() throws SQLException, IllegalAccessException, InstantiationException { - String modelPath = getModelLibrary(); - if (modelPath == null) { - return ApiResponse.failure("请先创建或导入模型库"); - } - String sql = """ - SELECT id, name, parent_id as parentId, - tree_index as treeIndex, created_at as createdAt, - updated_at as updatedAt FROM model_type ORDER BY tree_index ASC - """; - // 查询所有模型类型 - List modelTypes = SQLiteUtil.queryForList(modelPath, sql, null, ModelType.class); - // 转换为树形结构 - List treeList = buildModelTypeTree(modelTypes); - return ApiResponse.success(treeList); + return ApiResponse.success(modelTypeList()); } @Operation(summary = "拖动模型类型树") @@ -200,7 +188,6 @@ public class ModelLibraryController { return ApiResponse.success(null); } - @Operation(summary = "添加模型文件") @PostMapping("/addModelFile") public ApiResponse addModelFile(@RequestParam("files") MultipartFile[] files, @Parameter(description = "模型类型ID") @RequestParam("modelTypeId") String modelTypeId) throws IOException, SQLException { @@ -325,6 +312,44 @@ public class ModelLibraryController { return ApiResponse.success(null); } + @Operation(summary = "拖动层级") + @PostMapping("/dragModelType") + public ApiResponse dragModelType(@RequestBody List dragModelTypeDtoList) throws SQLException, IllegalAccessException, InstantiationException { + String modelPath = getModelLibrary(); + if (modelPath == null) { + return ApiResponse.failure("请先创建或导入模型库"); + } + // 遍历数据列表 + for (DragModelTypeDto dragModelTypeDto : dragModelTypeDtoList) { + String id = dragModelTypeDto.getId(); + String parentId = dragModelTypeDto.getParentId(); + String treeIndex = dragModelTypeDto.getTreeIndex(); + List params = new ArrayList<>(); + params.add(parentId); + params.add(treeIndex); + params.add(id); + SQLiteUtil.executeUpdate(modelPath, "UPDATE model_type SET parent_id = ?, tree_index = ? WHERE id = ?", params); + } + // 返回树列表 + return ApiResponse.success(modelTypeList()); + } + + private List modelTypeList() throws SQLException, IllegalAccessException, InstantiationException { + String modelPath = getModelLibrary(); + if (modelPath == null) { + return null; + } + String sql = """ + SELECT id, name, parent_id as parentId, + tree_index as treeIndex, created_at as createdAt, + updated_at as updatedAt FROM model_type ORDER BY tree_index ASC + """; + // 查询所有模型类型 + List modelTypes = SQLiteUtil.queryForList(modelPath, sql, null, ModelType.class); + // 转换为树形结构 + return buildModelTypeTree(modelTypes); + } + private List buildModelTypeTree(List modelTypes) { List treeNodes = modelTypes.stream() .map(modelType -> new ModelTypeVo(modelType)) 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 4bf996a..5f72489 100644 --- a/src/main/java/com/yj/earth/business/controller/SourceController.java +++ b/src/main/java/com/yj/earth/business/controller/SourceController.java @@ -18,6 +18,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -72,34 +73,7 @@ public class SourceController { @Operation(summary = "新增模型资源") @PostMapping("/addModelSource") public ApiResponse addModelSource(@RequestBody AddModelSourceDto addModelSourceDto) { - // 获取资源绝对路径 - String sourcePath = addModelSourceDto.getSourcePath(); - // 获取资源名称 - String sourceName = FileUtil.mainName(sourcePath); - // 校验是否通过 - String message = sourceService.checkIsPass(addModelSourceDto.getParentId(), sourceName); - if (message != null) { - return ApiResponse.failure(message); - } - // 调用SDK加载资源 - String sourceId = sourceService.addAndGetSourceId(sourcePath); - // 获取文件路径并处理详情 - String detail = sourceService.getDetail(sourcePath, sourceId); - // 构建并保存资源对象 - Source source = new Source(); - source.setId(addModelSourceDto.getId()); - source.setSourcePath(sourcePath); - source.setSourceName(sourceName); - source.setParentId(addModelSourceDto.getParentId()); - source.setTreeIndex(addModelSourceDto.getTreeIndex()); - source.setParams(JsonUtil.mapToJson(addModelSourceDto.getParams())); - source.setDetail(detail); - source.setSourceType(MapUtil.getString(MapUtil.jsonToMap(detail), "fileType")); - source.setIsShow(SHOW); - sourceService.save(source); - // 添加资源到该用户的角色下 - roleSourceService.addRoleSource(userService.getById(StpUtil.getLoginIdAsString()).getRoleId(), source.getId()); - return ApiResponse.success(source); + return ApiResponse.success(sourceService.addModelSource(addModelSourceDto)); } @Operation(summary = "新增其他资源") @@ -227,6 +201,20 @@ public class SourceController { return ApiResponse.success(null); } + @Operation(summary = "更新显示隐藏") + @PostMapping("/updateShowHide") + public ApiResponse updateShowHide(@RequestBody List updateShowHideDtoList) { + for (UpdateShowHideDto updateShowHideDto : updateShowHideDtoList) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(Source::getId, updateShowHideDto.getId()); + Source source = sourceService.getOne(queryWrapper); + source.setIsShow(updateShowHideDto.getIsShow()); + sourceService.updateById(source); + } + return ApiResponse.success(null); + } + + @PostMapping("/uploadLocationImage") @Operation(summary = "新增定位图片") public ApiResponse uploadLocationImage(@RequestParam("ids") @Parameter(description = "上传定位图片ID列表") List ids, diff --git a/src/main/java/com/yj/earth/business/controller/UserController.java b/src/main/java/com/yj/earth/business/controller/UserController.java index 2380ad7..0342f67 100644 --- a/src/main/java/com/yj/earth/business/controller/UserController.java +++ b/src/main/java/com/yj/earth/business/controller/UserController.java @@ -109,7 +109,6 @@ public class UserController { return ApiResponse.success(userPage); } - @CheckAuth @Operation(summary = "设置角色") @PostMapping("/userBindOrUnBindRole") @RoleAccess(roleNames = "管理员") diff --git a/src/main/java/com/yj/earth/business/service/SourceService.java b/src/main/java/com/yj/earth/business/service/SourceService.java index 12e7b59..e7c0b32 100644 --- a/src/main/java/com/yj/earth/business/service/SourceService.java +++ b/src/main/java/com/yj/earth/business/service/SourceService.java @@ -3,6 +3,7 @@ package com.yj.earth.business.service; import com.yj.earth.business.domain.Source; import com.baomidou.mybatisplus.extension.service.IService; import com.yj.earth.common.util.ApiResponse; +import com.yj.earth.dto.source.AddModelSourceDto; import java.util.List; @@ -22,4 +23,6 @@ public interface SourceService extends IService { List getSourceListByUserId(String userId); String checkIsPass(String parentId, String sourceName); + + Source addModelSource(AddModelSourceDto addModelSourceDto); } diff --git a/src/main/java/com/yj/earth/business/service/impl/SourceServiceImpl.java b/src/main/java/com/yj/earth/business/service/impl/SourceServiceImpl.java index ce8df84..e255c49 100644 --- a/src/main/java/com/yj/earth/business/service/impl/SourceServiceImpl.java +++ b/src/main/java/com/yj/earth/business/service/impl/SourceServiceImpl.java @@ -1,5 +1,6 @@ package com.yj.earth.business.service.impl; +import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.io.FileUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -15,6 +16,9 @@ import com.yj.earth.business.service.UserService; import com.yj.earth.common.config.ServerConfig; import com.yj.earth.common.util.ApiResponse; import com.yj.earth.common.util.HttpUtil; +import com.yj.earth.common.util.JsonUtil; +import com.yj.earth.common.util.MapUtil; +import com.yj.earth.dto.source.AddModelSourceDto; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -24,6 +28,8 @@ import java.util.List; import java.util.Map; import java.util.function.Function; +import static com.yj.earth.common.constant.GlobalConstant.SHOW; + @Slf4j @Service @@ -76,15 +82,41 @@ public class SourceServiceImpl extends ServiceImpl impleme return "父级不存在"; } } -// // 验证该目录下是否已经存在此资源名一样的 -// LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); -// queryWrapper.eq(Source::getSourceName, sourceName); -// if (sourceService.count(queryWrapper) > 0) { -// return "此目录下已存在此资源"; -// } return null; } + @Override + public Source addModelSource(AddModelSourceDto addModelSourceDto) { + // 获取资源绝对路径 + String sourcePath = addModelSourceDto.getSourcePath(); + // 获取资源名称 + String sourceName = FileUtil.mainName(sourcePath); + // 校验是否通过 + String message = sourceService.checkIsPass(addModelSourceDto.getParentId(), sourceName); + if (message != null) { + return null; + } + // 调用SDK加载资源 + String sourceId = sourceService.addAndGetSourceId(sourcePath); + // 获取文件路径并处理详情 + String detail = sourceService.getDetail(sourcePath, sourceId); + // 构建并保存资源对象 + Source source = new Source(); + source.setId(addModelSourceDto.getId()); + source.setSourcePath(sourcePath); + source.setSourceName(sourceName); + source.setParentId(addModelSourceDto.getParentId()); + source.setTreeIndex(addModelSourceDto.getTreeIndex()); + source.setParams(JsonUtil.mapToJson(addModelSourceDto.getParams())); + source.setDetail(detail); + source.setSourceType(MapUtil.getString(MapUtil.jsonToMap(detail), "fileType")); + source.setIsShow(SHOW); + sourceService.save(source); + // 添加资源到该用户的角色下 + roleSourceService.addRoleSource(userService.getById(StpUtil.getLoginIdAsString()).getRoleId(), source.getId()); + return source; + } + /** * 根据文件后缀获取详情信息 */ diff --git a/src/main/java/com/yj/earth/common/config/ServerConfig.java b/src/main/java/com/yj/earth/common/config/ServerConfig.java index f1c231b..91eca24 100644 --- a/src/main/java/com/yj/earth/common/config/ServerConfig.java +++ b/src/main/java/com/yj/earth/common/config/ServerConfig.java @@ -1,9 +1,12 @@ package com.yj.earth.common.config; +import com.yj.earth.common.util.SdkUtil; import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import javax.annotation.PostConstruct; + @Data @Component public class ServerConfig { @@ -13,6 +16,10 @@ public class ServerConfig { @Value("${server.host}") private String host; - @Value("${sdk.port}") private int sdkPort; + + @PostConstruct + public void initSdkPort() { + this.sdkPort = SdkUtil.getServerPortFromSdkConfig(); + } } diff --git a/src/main/java/com/yj/earth/common/util/SdkUtil.java b/src/main/java/com/yj/earth/common/util/SdkUtil.java index 88f0061..3849124 100644 --- a/src/main/java/com/yj/earth/common/util/SdkUtil.java +++ b/src/main/java/com/yj/earth/common/util/SdkUtil.java @@ -2,10 +2,10 @@ package com.yj.earth.common.util; import com.yj.earth.common.constant.GlobalConstant; import lombok.extern.slf4j.Slf4j; -import org.springframework.core.io.ClassPathResource; import org.yaml.snakeyaml.Yaml; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; @@ -18,24 +18,22 @@ import java.util.stream.Collectors; public class SdkUtil { // 保存SDK进程引用 private static Process sdkProcess; - // 保存SDK端口号、用于关闭时强制终止 - private static Integer sdkPort; // 对外提供的启动入口 public static void startSdkIfConfigured() throws IOException { - // 读取配置 - sdkPort = getSdkPortFromYamlConfig(); + // 读取SDK端口 + Integer serverPort = getServerPortFromSdkConfig(); // 未配置则不启动 - if (sdkPort == null) { - log.info("请先配置SDK端口"); + if (serverPort == null) { + log.info("未配置SDK端口"); return; } // 配置存在时、正常启动SDK - startSdkJar(sdkPort); + startSdkJar(serverPort); } // 接收已确认的端口、启动SDK - private static void startSdkJar(int sdkPort) throws IOException { + private static void startSdkJar(int serverPort) throws IOException { // 获取项目根目录(当前工作目录) String projectRoot = System.getProperty("user.dir"); // 获取SDK完整路径 @@ -44,20 +42,41 @@ public class SdkUtil { File sdkJarFile = new File(sdkJarPath); if (!sdkJarFile.exists() || !sdkJarFile.isFile()) { log.error("SDK不存在或不是有效文件:{}", sdkJarPath); + return; } + + // 获取SDK所在目录(sdk目录) + File sdkDir = sdkJarFile.getParentFile(); + if (sdkDir == null || !sdkDir.exists()) { + log.error("无法获取SDK所在目录:{}", sdkJarPath); + return; + } + + // 构建JDK的java可执行文件路径(适配新目录结构) + String javaExecutablePath = getJavaExecutablePath(sdkDir); + File javaExecutable = new File(javaExecutablePath); + if (!javaExecutable.exists() || !javaExecutable.canExecute()) { + log.error("JDK可执行文件不存在或不可执行:{}", javaExecutablePath); + return; + } + log.info("准备启动SDK: {}", sdkJarPath); - log.info("使用SDK端口: {}", sdkPort); + log.info("使用JDK路径: {}", javaExecutablePath); + log.info("使用SDK端口: {}", serverPort); + // 构建启动命令、添加 -Dserver.port 参数 List command = new ArrayList<>(); - command.add("java"); - command.add("-Dserver.port=" + sdkPort); + command.add(javaExecutablePath); // 使用指定路径的java + command.add("-Dserver.port=" + serverPort); command.add("-jar"); command.add(sdkJarPath); + // 构建进程启动器 ProcessBuilder processBuilder = new ProcessBuilder(command); // 打印执行的命令 String commandStr = command.stream().collect(Collectors.joining(" ")); log.info("执行命令: {}", commandStr); + // 输出SDK的控制台日志到当前应用的日志中 processBuilder.redirectErrorStream(true); // 日志文件路径建议优化: 避免与项目根目录混淆 @@ -67,9 +86,11 @@ public class SdkUtil { sdkLogFile.getParentFile().mkdirs(); } processBuilder.redirectOutput(sdkLogFile); + // 启动进程(非阻塞) sdkProcess = processBuilder.start(); log.info("SDK已在后台启动、进程ID: {}", sdkProcess.pid()); + // 注册JVM关闭钩子、在主程序退出时关闭SDK进程 Runtime.getRuntime().addShutdownHook(new Thread(() -> { if (sdkProcess != null && sdkProcess.isAlive()) { @@ -82,13 +103,13 @@ public class SdkUtil { if (terminated) { log.info("SDK进程已成功停止"); } else { - log.warn("SDK进程未能正常停止、尝试通过端口{}强制终止...", sdkPort); + log.warn("SDK进程未能正常停止、尝试通过端口{}强制终止...", serverPort); // 通过端口强制终止 - boolean killSuccess = PortKillUtil.killProcessByPort(sdkPort); + boolean killSuccess = PortKillUtil.killProcessByPort(serverPort); if (killSuccess) { - log.info("已通过端口{}强制终止SDK进程", sdkPort); + log.info("已通过端口{}强制终止SDK进程", serverPort); } else { - log.error("通过端口{}强制终止SDK进程失败", sdkPort); + log.error("通过端口{}强制终止SDK进程失败", serverPort); } } } catch (InterruptedException e) { @@ -100,26 +121,61 @@ public class SdkUtil { } /** - * 从配置文件读取SDK端口配置 + * 根据新目录结构获取JDK的java可执行文件路径 */ - private static Integer getSdkPortFromYamlConfig() { + private static String getJavaExecutablePath(File sdkDir) { + // 从sdk目录向上两级找到根目录(sdk -> app -> 根目录) + File appDir = sdkDir.getParentFile(); + if (appDir == null || !appDir.exists()) { + log.error("无法获取app目录(sdk的父目录)"); + return null; + } + + File rootDir = appDir.getParentFile(); + if (rootDir == null || !rootDir.exists()) { + log.error("无法获取根目录(app的父目录)"); + return null; + } + + // 判断操作系统类型 + boolean isWindows = System.getProperty("os.name").toLowerCase().contains("win"); + // 构建JDK路径:根目录/jdk/bin/java(或java.exe) + String javaRelativePath = "jdk" + File.separator + "bin" + File.separator + + (isWindows ? "java.exe" : "java"); + return new File(rootDir, javaRelativePath).getAbsolutePath(); + } + + /** + * 从sdk文件夹下的application.yml读取server.port配置 + */ + public static Integer getServerPortFromSdkConfig() { Yaml yaml = new Yaml(); - try (InputStream inputStream = new ClassPathResource("application.yml").getInputStream()) { + String projectRoot = System.getProperty("user.dir"); + File sdkConfigFile = new File(projectRoot, "sdk/application.yml"); + + if (!sdkConfigFile.exists() || !sdkConfigFile.isFile()) { + log.error("配置文件不存在: {}", sdkConfigFile.getAbsolutePath()); + return null; + } + + try (InputStream inputStream = new FileInputStream(sdkConfigFile)) { // 解析YAML文件为Map Map yamlMap = yaml.load(inputStream); - // 逐级获取配置 - if (yamlMap.containsKey("sdk")) { - Object sdkObj = yamlMap.get("sdk"); - if (sdkObj instanceof Map) { - Map sdkMap = (Map) sdkObj; - if (sdkMap.containsKey("port")) { - return ((Number) sdkMap.get("port")).intValue(); + // 逐级获取server.port配置 + if (yamlMap.containsKey("server")) { + Object serverObj = yamlMap.get("server"); + if (serverObj instanceof Map) { + Map serverMap = (Map) serverObj; + if (serverMap.containsKey("port")) { + return ((Number) serverMap.get("port")).intValue(); } } } - log.error("未配置SDK端口"); + log.error("sdk配置文件中未配置server.port"); } catch (IOException e) { - log.error("读取配置文件失败", e); + log.error("读取sdk配置文件失败", e); + } catch (ClassCastException e) { + log.error("sdk配置文件中server.port格式错误,应为数字类型", e); } return null; } diff --git a/src/main/java/com/yj/earth/dto/source/UpdateShowHideDto.java b/src/main/java/com/yj/earth/dto/source/UpdateShowHideDto.java new file mode 100644 index 0000000..66d7e64 --- /dev/null +++ b/src/main/java/com/yj/earth/dto/source/UpdateShowHideDto.java @@ -0,0 +1,12 @@ +package com.yj.earth.dto.source; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class UpdateShowHideDto { + @Schema(description = "主键") + private String id; + @Schema(description = "是否显示") + private Integer isShow; +}