最新产品
This commit is contained in:
		| @ -0,0 +1,86 @@ | ||||
| package com.yj.earth.business.controller; | ||||
|  | ||||
| import com.yj.earth.auth.AuthInfo; | ||||
| import com.yj.earth.auth.AuthValidator; | ||||
| import com.yj.earth.common.util.ApiResponse; | ||||
| import com.yj.earth.common.util.ServerUniqueIdUtil; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.Parameter; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
| import org.springframework.web.multipart.MultipartFile; | ||||
|  | ||||
| import java.nio.charset.StandardCharsets; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.nio.file.Paths; | ||||
|  | ||||
| @Tag(name = "系统设置管理") | ||||
| @RestController | ||||
| @RequestMapping("/auth") | ||||
| public class AuthController { | ||||
|  | ||||
|     // 授权文件存储路径、项目根目录下的license目录 | ||||
|     private static final String AUTH_FILE_PATH = "license/yjearth.lic"; | ||||
|  | ||||
|     @GetMapping("/info") | ||||
|     @Operation(summary = "获取系统授权码") | ||||
|     public ApiResponse info() { | ||||
|         return ApiResponse.success(ServerUniqueIdUtil.getServerUniqueId()); | ||||
|     } | ||||
|  | ||||
|     @PostMapping("/import") | ||||
|     @Operation(summary = "导入授权信息") | ||||
|     public ApiResponse importAuth(@Parameter(description = "授权文件", required = true) @RequestParam("file") MultipartFile file) { | ||||
|         // 验证文件是否为空 | ||||
|         if (file.isEmpty()) { | ||||
|             return ApiResponse.failure("请选择授权文件"); | ||||
|         } | ||||
|  | ||||
|         // 验证文件名是否为 yjearth.lic | ||||
|         String fileName = file.getOriginalFilename(); | ||||
|         if (fileName == null || !fileName.equals("yjearth.lic")) { | ||||
|             return ApiResponse.failure("请上传 yjearth.lic"); | ||||
|         } | ||||
|  | ||||
|         try { | ||||
|             // 读取文件内容 | ||||
|             String authContent = new String(file.getBytes(), StandardCharsets.UTF_8).trim(); | ||||
|             // 验证授权内容有效性 | ||||
|             String serverHardwareMd5 = ServerUniqueIdUtil.getServerUniqueId(); | ||||
|             boolean isValid = AuthValidator.validateAuth(authContent, serverHardwareMd5); | ||||
|             if (!isValid) { | ||||
|                 return ApiResponse.failure("授权文件无效或已过期"); | ||||
|             } | ||||
|             // 创建目录(如果不存在) | ||||
|             Path path = Paths.get(AUTH_FILE_PATH); | ||||
|             if (!Files.exists(path.getParent())) { | ||||
|                 Files.createDirectories(path.getParent()); | ||||
|             } | ||||
|             // 保存授权文件 | ||||
|             Files.write(path, authContent.getBytes(StandardCharsets.UTF_8)); | ||||
|             return ApiResponse.success(null); | ||||
|         } catch (Exception e) { | ||||
|             return ApiResponse.failure("导入授权文件失败:" + e.getMessage()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/show") | ||||
|     @Operation(summary = "查看授权信息") | ||||
|     public ApiResponse showAuth() { | ||||
|         try { | ||||
|             // 检查授权文件是否存在 | ||||
|             Path path = Paths.get(AUTH_FILE_PATH); | ||||
|             if (!Files.exists(path)) { | ||||
|                 return ApiResponse.failure("请先导入授权"); | ||||
|             } | ||||
|             // 读取授权文件内容 | ||||
|             String authContent = new String(Files.readAllBytes(path), StandardCharsets.UTF_8); | ||||
|             // 获取授权详情 | ||||
|             AuthInfo authInfo = AuthValidator.getAuthInfo(authContent); | ||||
|             return ApiResponse.success(authInfo); | ||||
|         } catch (Exception e) { | ||||
|             return ApiResponse.failure("获取授权信息失败:" + e.getMessage()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,241 @@ | ||||
| package com.yj.earth.business.controller; | ||||
|  | ||||
| import cn.hutool.core.io.FileUtil; | ||||
| 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.metadata.IPage; | ||||
| import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | ||||
| import com.yj.earth.business.domain.FileInfo; | ||||
| import com.yj.earth.business.service.FileInfoService; | ||||
| import com.yj.earth.common.util.ApiResponse; | ||||
| import com.yj.earth.vo.FileInfoVo; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.Parameter; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import jakarta.servlet.http.HttpServletResponse; | ||||
| import org.springframework.beans.BeanUtils; | ||||
| import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.http.HttpHeaders; | ||||
| 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.OutputStream; | ||||
| import java.net.URLEncoder; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| @Tag(name = "文件数据管理") | ||||
| @RestController | ||||
| @RequestMapping("/fileInfo") | ||||
| 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(); | ||||
|  | ||||
|         List<FileInfoVo> fileInfoVoList = new ArrayList<>(); | ||||
|  | ||||
|         // 遍历处理每个文件 | ||||
|         for (MultipartFile file : files) { | ||||
|             // 跳过空文件 | ||||
|             if (file.isEmpty()) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // 获取原始文件名和后缀 | ||||
|             String originalFilename = file.getOriginalFilename(); | ||||
|             String fileSuffix = FileUtil.extName(originalFilename); | ||||
|             String contentType = file.getContentType(); | ||||
|  | ||||
|             // 生成唯一文件名、避免重复 | ||||
|             String uniqueFileName = IdUtil.simpleUUID() + "." + fileSuffix; | ||||
|  | ||||
|             // 创建文件存储目录(如果不存在则自动创建) | ||||
|             File uploadDir = new File(fullUploadPath); | ||||
|             FileUtil.mkdir(uploadDir); | ||||
|  | ||||
|             // 构建完整文件路径 | ||||
|             String filePath = fullUploadPath + File.separator + uniqueFileName; | ||||
|             File destFile = new File(filePath); | ||||
|  | ||||
|             // 使用Hutool工具类保存文件 | ||||
|             FileUtil.writeBytes(file.getBytes(), destFile); | ||||
|  | ||||
|             // 计算文件MD5(用于校验文件完整性) | ||||
|             String fileMd5 = DigestUtil.md5Hex(destFile); | ||||
|  | ||||
|             // 查询有没有文件名一样并且 MD5 也一样的数据 | ||||
|             LambdaQueryWrapper<FileInfo> queryWrapper = new LambdaQueryWrapper<>(); | ||||
|             queryWrapper.eq(FileInfo::getFileName, originalFilename).eq(FileInfo::getFileMd5, fileMd5); | ||||
|             if (fileInfoService.count(queryWrapper) > 0) {  // 修复了此处的bug、添加了queryWrapper参数 | ||||
|                 return ApiResponse.failure("已存在文件名相同且内容完全一致的文件"); | ||||
|             } | ||||
|  | ||||
|             // 保存文件信息到数据库 | ||||
|             FileInfo fileInfo = new FileInfo(); | ||||
|             fileInfo.setFileName(originalFilename); | ||||
|             fileInfo.setFileSuffix(fileSuffix); | ||||
|             fileInfo.setContentType(contentType); | ||||
|             fileInfo.setFileSize(file.getSize()); | ||||
|             fileInfo.setFilePath(uniqueFileName);  // 只保存相对文件名、不保存完整路径 | ||||
|             fileInfo.setFileMd5(fileMd5); | ||||
|  | ||||
|             // 保存文件信息并获取ID | ||||
|             fileInfoService.save(fileInfo); | ||||
|  | ||||
|             // 构建并设置预览URL和下载URL | ||||
|             String previewUrl = "/fileInfo/preview/" + fileInfo.getId(); | ||||
|             String downloadUrl = "/fileInfo/download/" + fileInfo.getId(); | ||||
|  | ||||
|             FileInfoVo fileInfoVo = new FileInfoVo(); | ||||
|             BeanUtils.copyProperties(fileInfo, fileInfoVo); | ||||
|             fileInfoVo.setPreviewUrl(previewUrl); | ||||
|             fileInfoVo.setDownloadUrl(downloadUrl); | ||||
|  | ||||
|             fileInfoVoList.add(fileInfoVo); | ||||
|         } | ||||
|  | ||||
|         if (fileInfoVoList.isEmpty()) { | ||||
|             return ApiResponse.failure("未成功上传任何文件"); | ||||
|         } | ||||
|  | ||||
|         return ApiResponse.success(fileInfoVoList); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "文件下载") | ||||
|     @GetMapping("/download/{id}") | ||||
|     public void downloadFile(@Parameter(description = "文件ID", required = true) @PathVariable String id, HttpServletResponse response) throws IOException { | ||||
|         // 根据ID查询文件信息 | ||||
|         FileInfo fileInfo = fileInfoService.getById(id); | ||||
|         if (fileInfo == null) { | ||||
|             response.setStatus(HttpServletResponse.SC_NOT_FOUND); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // 构建完整文件路径 | ||||
|         String fullPath = getFullUploadPath() + File.separator + fileInfo.getFilePath(); | ||||
|         File file = new File(fullPath); | ||||
|  | ||||
|         // 校验文件是否存在 | ||||
|         if (!file.exists()) { | ||||
|             response.setStatus(HttpServletResponse.SC_NOT_FOUND); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // 设置响应头 | ||||
|         response.setContentType(fileInfo.getContentType()); | ||||
|         response.setContentLengthLong(fileInfo.getFileSize()); | ||||
|         String encodedFileName = URLEncoder.encode(fileInfo.getFileName(), StandardCharsets.UTF_8.name()); | ||||
|         response.setHeader(HttpHeaders.CONTENT_DISPOSITION, | ||||
|                 "attachment; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName); | ||||
|  | ||||
|         // 使用 Hutool 工具类复制文件流到响应输出流 | ||||
|         try (OutputStream os = response.getOutputStream()) { | ||||
|             FileUtil.writeToStream(file, os); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "文件预览") | ||||
|     @GetMapping("/preview/{id}") | ||||
|     public void previewFile( | ||||
|             @Parameter(description = "文件ID", required = true) | ||||
|             @PathVariable String id, | ||||
|             HttpServletResponse response) throws IOException { | ||||
|  | ||||
|         // 根据ID查询文件信息 | ||||
|         FileInfo fileInfo = fileInfoService.getById(id); | ||||
|         if (fileInfo == null) { | ||||
|             response.setStatus(HttpServletResponse.SC_NOT_FOUND); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // 构建完整文件路径 | ||||
|         String fullPath = getFullUploadPath() + File.separator + fileInfo.getFilePath(); | ||||
|         File file = new File(fullPath); | ||||
|  | ||||
|         // 校验文件是否存在 | ||||
|         if (!file.exists()) { | ||||
|             response.setStatus(HttpServletResponse.SC_NOT_FOUND); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // 设置响应头(不设置 attachment、让浏览器直接显示) | ||||
|         response.setContentType(fileInfo.getContentType()); | ||||
|         response.setContentLengthLong(fileInfo.getFileSize()); | ||||
|  | ||||
|         // 使用 Hutool 工具类复制文件流到响应输出流 | ||||
|         try (OutputStream os = response.getOutputStream()) { | ||||
|             FileUtil.writeToStream(file, os); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "文件列表") | ||||
|     @GetMapping("/list") | ||||
|     public ApiResponse getFileList( | ||||
|             @Parameter(description = "页码", required = true) Integer pageNum, | ||||
|             @Parameter(description = "每页条数", required = true) Integer pageSize, | ||||
|             @Parameter(description = "文件名称") String fileName) { | ||||
|  | ||||
|         // 创建分页对象 | ||||
|         Page<FileInfo> page = new Page<>(pageNum, pageSize); | ||||
|         // 构建查询条件 | ||||
|         LambdaQueryWrapper<FileInfo> queryWrapper = new LambdaQueryWrapper<>(); | ||||
|         if (fileName != null && !fileName.isEmpty()) { | ||||
|             queryWrapper.like(FileInfo::getFileName, fileName); | ||||
|         } | ||||
|         // 按创建时间倒序排列、最新上传的文件在前 | ||||
|         queryWrapper.orderByDesc(FileInfo::getCreatedAt); | ||||
|  | ||||
|         // 执行分页查询 | ||||
|         IPage<FileInfo> fileInfoPage = fileInfoService.page(page, queryWrapper); | ||||
|  | ||||
|         // 转换为VO对象并设置URL | ||||
|         List<FileInfoVo> records = fileInfoPage.getRecords().stream().map(fileInfo -> { | ||||
|             FileInfoVo vo = new FileInfoVo(); | ||||
|             BeanUtils.copyProperties(fileInfo, vo); | ||||
|             vo.setPreviewUrl("/fileInfo/preview/" + fileInfo.getId()); | ||||
|             vo.setDownloadUrl("/fileInfo/download/" + fileInfo.getId()); | ||||
|             return vo; | ||||
|         }).collect(Collectors.toList()); | ||||
|  | ||||
|         // 构建分页结果 | ||||
|         Page<FileInfoVo> resultPage = new Page<>(); | ||||
|         resultPage.setRecords(records); | ||||
|         resultPage.setTotal(fileInfoPage.getTotal()); | ||||
|         resultPage.setSize(fileInfoPage.getSize()); | ||||
|         resultPage.setCurrent(fileInfoPage.getCurrent()); | ||||
|         resultPage.setPages(fileInfoPage.getPages()); | ||||
|         return ApiResponse.success(resultPage); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,237 @@ | ||||
| package com.yj.earth.business.controller; | ||||
|  | ||||
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | ||||
| import com.graphhopper.GHRequest; | ||||
| import com.graphhopper.GHResponse; | ||||
| import com.graphhopper.GraphHopper; | ||||
| import com.graphhopper.ResponsePath; | ||||
| import com.graphhopper.config.Profile; | ||||
| import com.graphhopper.util.shapes.GHPoint; | ||||
| import com.yj.earth.business.domain.FileInfo; | ||||
| import com.yj.earth.business.service.FileInfoService; | ||||
| import com.yj.earth.common.config.GraphHopperProperties; | ||||
| import com.yj.earth.common.util.ApiResponse; | ||||
| import com.yj.earth.model.Point; | ||||
| import com.yj.earth.model.RouteRequest; | ||||
| import com.yj.earth.model.RouteResponse; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.Parameter; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import lombok.Data; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
|  | ||||
| import javax.annotation.PostConstruct; | ||||
| import javax.annotation.Resource; | ||||
| import java.io.File; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.List; | ||||
| import java.util.concurrent.atomic.AtomicBoolean; | ||||
|  | ||||
|  | ||||
| @Data | ||||
| @Slf4j | ||||
| @Tag(name = "路径规划管理") | ||||
| @RestController | ||||
| @RequestMapping("/graphhopper") | ||||
| public class GraphHopperController { | ||||
|     @Resource | ||||
|     private FileInfoService fileInfoService; | ||||
|     @Resource | ||||
|     private GraphHopperProperties graphHopperProperties; | ||||
|  | ||||
|     // 存储当前可用的 GraphHopper 实例 | ||||
|     private volatile GraphHopper currentHopper; | ||||
|  | ||||
|     // 状态控制: 线程安全 | ||||
|     private final AtomicBoolean isLoading = new AtomicBoolean(false); | ||||
|     private final AtomicBoolean isLoaded = new AtomicBoolean(false); | ||||
|  | ||||
|     @Operation(summary = "获取地图列表") | ||||
|     @GetMapping("/list") | ||||
|     public ApiResponse list() { | ||||
|         LambdaQueryWrapper<FileInfo> queryWrapper = new LambdaQueryWrapper<>(); | ||||
|         queryWrapper.eq(FileInfo::getFileSuffix, "pbf"); | ||||
|         return ApiResponse.success(fileInfoService.list(queryWrapper)); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "加载地图数据") | ||||
|     @PostMapping("/loadMap") | ||||
|     public ApiResponse loadMap(@Parameter(description = "文件ID") @RequestParam String fileId) { | ||||
|         // 参数校验 | ||||
|         if (fileId == null) { | ||||
|             return ApiResponse.failure("文件ID不能为空"); | ||||
|         } | ||||
|  | ||||
|         // 获取并校验OSM文件 | ||||
|         String osmFilePath = fileInfoService.getFileAbsolutePath(fileId); | ||||
|         File osmFile = new File(osmFilePath); | ||||
|         if (!osmFile.exists()) { | ||||
|             return ApiResponse.failure("地图文件不存在: " + osmFilePath); | ||||
|         } | ||||
|         if (!osmFile.isFile() || !osmFile.getName().endsWith(".pbf")) { | ||||
|             return ApiResponse.failure("仅支持有效的.pbf格式OSM文件"); | ||||
|         } | ||||
|         // 防止并发加载 | ||||
|         if (isLoading.get()) { | ||||
|             return ApiResponse.failure("地图正在加载中、请稍后查询状态"); | ||||
|         } | ||||
|  | ||||
|         // 标记加载状态 | ||||
|         isLoading.set(true); | ||||
|         isLoaded.set(false); | ||||
|  | ||||
|         // 异步执行: 删除旧数据 → 创建新实例 → 加载新地图 | ||||
|         new Thread(() -> { | ||||
|             GraphHopper newHopper = null; | ||||
|             try { | ||||
|                 // 关键步骤1: 彻底删除旧地图数据目录 | ||||
|                 deleteOldGraphDir(); | ||||
|                 // 关键步骤2: 创建全新的GraphHopper实例 | ||||
|                 newHopper = createNewGraphHopperInstance(osmFilePath); | ||||
|                 // 关键步骤3: 加载新地图 | ||||
|                 newHopper.importOrLoad(); | ||||
|                 // 关键步骤4: 加载成功 → 替换当前实例 + 更新状态 | ||||
|                 currentHopper = newHopper; | ||||
|                 isLoaded.set(true); | ||||
|                 log.info("地图加载成功"); | ||||
|             } catch (Exception e) { | ||||
|                 // 加载失败 → 清理新实例资源 | ||||
|                 if (newHopper != null) { | ||||
|                     newHopper.close(); | ||||
|                 } | ||||
|                 isLoaded.set(false); | ||||
|                 e.printStackTrace(); | ||||
|                 log.error("地图加载失败: " + e.getMessage()); | ||||
|  | ||||
|             } finally { | ||||
|                 // 无论成功/失败、释放加载锁 | ||||
|                 isLoading.set(false); | ||||
|             } | ||||
|         }).start(); | ||||
|  | ||||
|         return ApiResponse.success(null); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "路径规划") | ||||
|     @PostMapping("/route") | ||||
|     public ApiResponse calculateRoute(@RequestBody RouteRequest request) { | ||||
|         // 校验地图是否加载完成 + 实例是否可用 | ||||
|         if (!isLoaded.get() || currentHopper == null) { | ||||
|             return ApiResponse.failure("地图未加载完成"); | ||||
|         } | ||||
|         try { | ||||
|             // 构建路径点列表 | ||||
|             List<GHPoint> ghPoints = new ArrayList<>(); | ||||
|             ghPoints.add(new GHPoint(request.getStartLat(), request.getStartLng())); // 起点 | ||||
|             // 添加途经点 | ||||
|             if (request.getWaypoints() != null && !request.getWaypoints().isEmpty()) { | ||||
|                 for (Point waypoint : request.getWaypoints()) { | ||||
|                     ghPoints.add(new GHPoint(waypoint.getLat(), waypoint.getLng())); | ||||
|                 } | ||||
|             } | ||||
|             ghPoints.add(new GHPoint(request.getEndLat(), request.getEndLng())); // 终点 | ||||
|  | ||||
|             // 构建请求(仅指定Profile、无setWeighting) | ||||
|             String targetProfile = request.getProfile() != null ? request.getProfile() : "car"; | ||||
|             GHRequest ghRequest = new GHRequest(ghPoints) | ||||
|                     .setProfile(targetProfile); | ||||
|  | ||||
|             // 用新实例计算路径 | ||||
|             GHResponse response = currentHopper.route(ghRequest); | ||||
|  | ||||
|             // 处理错误 | ||||
|             if (response.hasErrors()) { | ||||
|                 return ApiResponse.failure("路径计算失败: " + response.getErrors().toString()); | ||||
|             } | ||||
|  | ||||
|             // 解析结果 | ||||
|             ResponsePath bestPath = response.getBest(); | ||||
|             List<Point> pathPoints = new ArrayList<>(); | ||||
|             bestPath.getPoints().forEach(ghPoint -> | ||||
|                     pathPoints.add(new Point(ghPoint.getLat(), ghPoint.getLon())) | ||||
|             ); | ||||
|  | ||||
|             // 封装返回 | ||||
|             RouteResponse routeResponse = new RouteResponse(bestPath.getDistance() / 1000, (double) (bestPath.getTime() / 60000), pathPoints); | ||||
|             return ApiResponse.success(routeResponse); | ||||
|  | ||||
|         } catch (Exception e) { | ||||
|             return ApiResponse.failure("路径计算异常: " + e.getMessage()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "获取交通方式") | ||||
|     @PostMapping("/profiles") | ||||
|     public ApiResponse profiles() { | ||||
|         return ApiResponse.success(graphHopperProperties.getProfiles()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 创建全新的 GraphHopper 实例 | ||||
|      */ | ||||
|     private GraphHopper createNewGraphHopperInstance(String osmFilePath) { | ||||
|         GraphHopper hopper = new GraphHopper(); | ||||
|         // 配置基础参数 | ||||
|         hopper.setOSMFile(osmFilePath); | ||||
|         hopper.setGraphHopperLocation(graphHopperProperties.getGraphLocation()); | ||||
|  | ||||
|         // 配置交通方式 + 权重策略 | ||||
|         List<Profile> profileList = new ArrayList<>(); | ||||
|         for (String profileName : graphHopperProperties.getProfiles()) { | ||||
|             Profile profile = new Profile(profileName); | ||||
|             profile.setVehicle(profileName); | ||||
|             profile.setWeighting("fastest"); | ||||
|             profileList.add(profile); | ||||
|         } | ||||
|         hopper.setProfiles(profileList); | ||||
|  | ||||
|         return hopper; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 递归删除旧地图数据目录 | ||||
|      */ | ||||
|     private void deleteOldGraphDir() { | ||||
|         File graphDir = new File(graphHopperProperties.getGraphLocation()); | ||||
|         if (!graphDir.exists()) { | ||||
|             log.info("旧地图目录不存在、无需删除: " + graphHopperProperties.getGraphLocation()); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // 递归删除所有文件和子目录 | ||||
|         File[] files = graphDir.listFiles(); | ||||
|         if (files != null) { | ||||
|             for (File file : files) { | ||||
|                 if (file.isDirectory()) { | ||||
|                     deleteOldGraphDir(file); | ||||
|                 } else { | ||||
|                     boolean deleted = file.delete(); | ||||
|                     log.info("删除旧地图文件: " + file.getAbsolutePath() + " → " + (deleted ? "成功" : "失败")); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // 删除空目录 | ||||
|         boolean dirDeleted = graphDir.delete(); | ||||
|         System.out.println("删除旧地图目录: " + graphDir.getAbsolutePath() + " → " + (dirDeleted ? "成功" : "失败")); | ||||
|     } | ||||
|  | ||||
|     // 重载: 递归删除子目录 | ||||
|     private void deleteOldGraphDir(File subDir) { | ||||
|         File[] files = subDir.listFiles(); | ||||
|         if (files != null) { | ||||
|             for (File file : files) { | ||||
|                 if (file.isDirectory()) { | ||||
|                     deleteOldGraphDir(file); | ||||
|                 } else { | ||||
|                     file.delete(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         subDir.delete(); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,62 @@ | ||||
| package com.yj.earth.business.controller; | ||||
|  | ||||
| import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | ||||
| import com.yj.earth.business.domain.Role; | ||||
| import com.yj.earth.business.service.RoleService; | ||||
| import com.yj.earth.common.util.ApiResponse; | ||||
| import com.yj.earth.dto.role.AddRoleDto; | ||||
| import com.yj.earth.dto.role.UpdateRoleDto; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.Parameter; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import org.springframework.beans.BeanUtils; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
|  | ||||
| @Tag(name = "角色数据管理") | ||||
| @RestController | ||||
| @RequestMapping("/role") | ||||
| public class RoleController { | ||||
|     @Resource | ||||
|     private RoleService roleService; | ||||
|  | ||||
|     @Operation(summary = "新增角色") | ||||
|     @PostMapping("/add") | ||||
|     public ApiResponse save(@RequestBody AddRoleDto addRoleDto) { | ||||
|         Role role = new Role(); | ||||
|         BeanUtils.copyProperties(addRoleDto, role); | ||||
|         roleService.save(role); | ||||
|         return ApiResponse.success(null); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "删除角色") | ||||
|     @PostMapping("/delete") | ||||
|     public ApiResponse delete(@Parameter(description = "角色ID") String id) { | ||||
|         roleService.removeById(id); | ||||
|         return ApiResponse.success(null); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "更新角色") | ||||
|     @PostMapping("/update") | ||||
|     public ApiResponse update(@RequestBody UpdateRoleDto updateRoleDto) { | ||||
|         Role role = new Role(); | ||||
|         BeanUtils.copyProperties(updateRoleDto, role); | ||||
|         roleService.updateById(role); | ||||
|         return ApiResponse.success(null); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "角色详情") | ||||
|     @GetMapping("/getById") | ||||
|     public ApiResponse get(@Parameter(description = "角色ID") String id) { | ||||
|         Role role = roleService.getById(id); | ||||
|         return ApiResponse.success(role); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "角色列表") | ||||
|     @GetMapping("/list") | ||||
|     public ApiResponse list(@Parameter(description = "分页数量") Integer pageNum, @Parameter(description = "分页大小") Integer pageSize) { | ||||
|         Page<Role> rolePage = roleService.page(new Page<>(pageNum, pageSize)); | ||||
|         return ApiResponse.success(rolePage); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,44 @@ | ||||
| package com.yj.earth.business.controller; | ||||
|  | ||||
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||
| import com.yj.earth.business.domain.RoleSource; | ||||
| import com.yj.earth.business.service.RoleService; | ||||
| import com.yj.earth.business.service.RoleSourceService; | ||||
| import com.yj.earth.business.service.SourceService; | ||||
| import com.yj.earth.common.util.ApiResponse; | ||||
| import com.yj.earth.dto.relation.RoleBindOrUnBindSourceDto; | ||||
| import com.yj.earth.dto.relation.SourceBindOrUnBindRoleDto; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.Parameter; | ||||
| 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.util.List; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| @Tag(name = "角色资源管理") | ||||
| @RestController | ||||
| @RequestMapping("/roleSource") | ||||
| public class RoleSourceController { | ||||
|     @Resource | ||||
|     private RoleSourceService roleSourceService; | ||||
|  | ||||
|     @Operation(summary = "角色绑定资源") | ||||
|     @PostMapping("/roleBindSource") | ||||
|     public ApiResponse roleBindSource(@RequestBody RoleBindOrUnBindSourceDto roleBindOrUnBindSourceDto) { | ||||
|         // 先删除该角色下的所有资源 | ||||
|         roleSourceService.remove(new LambdaQueryWrapper<RoleSource>().eq(RoleSource::getRoleId, roleBindOrUnBindSourceDto.getRoleId())); | ||||
|         // 再设置新的资源 | ||||
|         for (String sourceId : roleBindOrUnBindSourceDto.getSourceIdList()) { | ||||
|             RoleSource roleSource = new RoleSource(); | ||||
|             roleSource.setRoleId(roleBindOrUnBindSourceDto.getRoleId()); | ||||
|             roleSource.setSourceId(sourceId); | ||||
|             roleSourceService.save(roleSource); | ||||
|         } | ||||
|         return ApiResponse.success(null); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,168 @@ | ||||
| package com.yj.earth.business.controller; | ||||
|  | ||||
| import cn.dev33.satoken.stp.StpUtil; | ||||
| import cn.hutool.core.io.FileUtil; | ||||
| import com.fasterxml.jackson.core.JsonProcessingException; | ||||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||||
| import com.yj.earth.business.domain.Source; | ||||
| import com.yj.earth.business.service.RoleSourceService; | ||||
| import com.yj.earth.business.service.SourceService; | ||||
| import com.yj.earth.business.service.UserService; | ||||
| import com.yj.earth.common.service.SourceParamsValidator; | ||||
| import com.yj.earth.common.util.ApiResponse; | ||||
| import com.yj.earth.common.util.MapUtil; | ||||
| import com.yj.earth.dto.source.AddDirectoryDto; | ||||
| import com.yj.earth.dto.source.AddModelSourceDto; | ||||
| import com.yj.earth.dto.source.AddOtherSourceDto; | ||||
| import com.yj.earth.dto.source.UpdateSourceDto; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import org.springframework.beans.BeanUtils; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
| import java.util.Map; | ||||
| import java.util.Set; | ||||
|  | ||||
| import static com.yj.earth.common.constant.GlobalConstant.DIRECTORY; | ||||
| import static com.yj.earth.common.constant.GlobalConstant.SHOW; | ||||
|  | ||||
| @Slf4j | ||||
| @Tag(name = "树形结构管理") | ||||
| @RestController | ||||
| @RequestMapping("/source") | ||||
| public class SourceController { | ||||
|     @Resource | ||||
|     private SourceService sourceService; | ||||
|     @Resource | ||||
|     private UserService userService; | ||||
|     @Resource | ||||
|     private RoleSourceService roleSourceService; | ||||
|     @Resource | ||||
|     private SourceParamsValidator sourceParamsValidator; | ||||
|  | ||||
|     @PostMapping("/addDirectory") | ||||
|     @Operation(summary = "新增目录资源") | ||||
|     public ApiResponse addDirectory(@RequestBody AddDirectoryDto addDirectoryDto) { | ||||
|         // 校验是否通过 | ||||
|         String message = sourceService.checkIsPass(addDirectoryDto.getParentId(), addDirectoryDto.getSourceName()); | ||||
|         if (message != null) { | ||||
|             return ApiResponse.failure(message); | ||||
|         } | ||||
|         // 通过之后保存资源 | ||||
|         Source source = new Source(); | ||||
|         BeanUtils.copyProperties(addDirectoryDto, source); | ||||
|         source.setSourceType(DIRECTORY); | ||||
|         source.setIsShow(SHOW); | ||||
|         sourceService.save(source); | ||||
|         // 添加资源到该用户的角色下 | ||||
|         roleSourceService.addRoleSource(userService.getById(StpUtil.getLoginIdAsString()).getRoleId(), source.getId()); | ||||
|         return ApiResponse.success(source); | ||||
|     } | ||||
|  | ||||
|     @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.setSourcePath(sourcePath); | ||||
|         source.setSourceName(sourceName); | ||||
|         source.setParentId(addModelSourceDto.getParentId()); | ||||
|         source.setTreeIndex(addModelSourceDto.getTreeIndex()); | ||||
|         source.setDetail(detail); | ||||
|         source.setSourceType(MapUtil.getString(MapUtil.jsonToMap(detail), "fileType")); | ||||
|         source.setIsShow(SHOW); | ||||
|         source.setParams(addModelSourceDto.getParams()); | ||||
|         sourceService.save(source); | ||||
|         // 添加资源到该用户的角色下 | ||||
|         roleSourceService.addRoleSource(userService.getById(StpUtil.getLoginIdAsString()).getRoleId(), source.getId()); | ||||
|         return ApiResponse.success(source); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     @Operation(summary = "新增其他资源") | ||||
|     @PostMapping("/addOtherSource") | ||||
|     public ApiResponse addOtherSource(@RequestBody AddOtherSourceDto addOtherSourceDto) throws JsonProcessingException { | ||||
|         // 校验是否通过 | ||||
|         String message = sourceService.checkIsPass(addOtherSourceDto.getParentId(), addOtherSourceDto.getSourceName()); | ||||
|         if (message != null) { | ||||
|             return ApiResponse.failure(message); | ||||
|         } | ||||
|         // 验证并转换参数 | ||||
|         Object validatedParams = sourceParamsValidator.validateAndConvert( | ||||
|                 addOtherSourceDto.getSourceType(), | ||||
|                 addOtherSourceDto.getParams() | ||||
|         ); | ||||
|         System.out.println(validatedParams); | ||||
|         Source source = new Source(); | ||||
|         BeanUtils.copyProperties(addOtherSourceDto, source); | ||||
|         source.setIsShow(SHOW); | ||||
|         source.setParams(MapUtil.objectToJson(validatedParams)); | ||||
|         sourceService.save(source); | ||||
|         // 添加资源到该用户的角色下 | ||||
|         roleSourceService.addRoleSource(userService.getById(StpUtil.getLoginIdAsString()).getRoleId(), source.getId()); | ||||
|         return ApiResponse.success(source); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     @Operation(summary = "更新资源信息及参数") | ||||
|     @PostMapping("/update") | ||||
|     public ApiResponse updateSource(@RequestBody UpdateSourceDto updateSourceDto) { | ||||
|         // 查询资源 | ||||
|         Source source = sourceService.getById(updateSourceDto.getId()); | ||||
|         if (source == null) { | ||||
|             return ApiResponse.failure("资源不存在"); | ||||
|         } | ||||
|  | ||||
|         // 更新基本信息 | ||||
|         BeanUtils.copyProperties(updateSourceDto, source); | ||||
|  | ||||
|         // 处理参数更新 | ||||
|         if (updateSourceDto.getParams() != null && !updateSourceDto.getParams().isEmpty()) { | ||||
|             // 获取类型 | ||||
|             String sourceType = source.getSourceType(); | ||||
|             // 验证参数 | ||||
|             Object validatedParams = sourceParamsValidator.validateAndConvert( | ||||
|                     sourceType, | ||||
|                     updateSourceDto.getParams() | ||||
|             ); | ||||
|  | ||||
|             // 获取原始数据的 Map 并合并新参数 | ||||
|             Map<String, Object> dataMap = MapUtil.jsonToMap(source.getParams()); | ||||
|             MapUtil.mergeMaps(dataMap, updateSourceDto.getParams()); | ||||
|             source.setParams(MapUtil.mapToString(dataMap)); | ||||
|         } | ||||
|  | ||||
|         // 保存更新 | ||||
|         sourceService.updateById(source); | ||||
|         return ApiResponse.success(source); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/type") | ||||
|     @Operation(summary = "获取支持的资源类型") | ||||
|     public ApiResponse getSupportedSourceTypes() { | ||||
|         Set<String> supportedTypes = sourceParamsValidator.getSupportedSourceTypes(); | ||||
|         return ApiResponse.success(supportedTypes); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     @Operation(summary = "获取资源列表") | ||||
|     @GetMapping("/list") | ||||
|     public ApiResponse list() { | ||||
|         return ApiResponse.success(sourceService.getSourceListByUserId(StpUtil.getLoginIdAsString())); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,140 @@ | ||||
| package com.yj.earth.business.controller; | ||||
|  | ||||
| import cn.dev33.satoken.stp.SaTokenInfo; | ||||
| import cn.dev33.satoken.stp.StpUtil; | ||||
| import cn.hutool.crypto.digest.BCrypt; | ||||
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||
| import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | ||||
| import com.yj.earth.annotation.EncryptResponse; | ||||
| import com.yj.earth.annotation.ExcludeField; | ||||
| import com.yj.earth.annotation.RoleAccess; | ||||
| import com.yj.earth.business.domain.Role; | ||||
| import com.yj.earth.business.domain.User; | ||||
| import com.yj.earth.business.service.RoleService; | ||||
| import com.yj.earth.dto.relation.UserBindOrUnBindRoleDto; | ||||
| import com.yj.earth.dto.user.AddUserDto; | ||||
| import com.yj.earth.dto.user.UpdatePasswordDto; | ||||
| import com.yj.earth.dto.user.UpdateUserDto; | ||||
| import com.yj.earth.dto.user.UserLoginDto; | ||||
| import com.yj.earth.business.service.UserService; | ||||
| import com.yj.earth.common.util.ApiResponse; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.Parameter; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import org.springframework.beans.BeanUtils; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
|  | ||||
| @Tag(name = "用户数据管理") | ||||
| @RestController | ||||
| @RequestMapping("/user") | ||||
| public class UserController { | ||||
|     @Resource | ||||
|     private UserService userService; | ||||
|     @Resource | ||||
|     private RoleService roleService; | ||||
|  | ||||
|     @Operation(summary = "新增用户") | ||||
|     @PostMapping("/add") | ||||
|     @RoleAccess(roleNames = "管理员") | ||||
|     public ApiResponse save(@RequestBody AddUserDto addUserDto) { | ||||
|         User user = new User(); | ||||
|         BeanUtils.copyProperties(addUserDto, user); | ||||
|         if (userService.getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, user.getUsername())) != null) { | ||||
|             return ApiResponse.failure("用户已存在"); | ||||
|         } | ||||
|         String password = user.getPassword(); | ||||
|         user.setPassword(BCrypt.hashpw(password, BCrypt.gensalt())); | ||||
|         if (addUserDto.getRoleId() == null) { | ||||
|             // 查询系统名字为默认角色的角色ID | ||||
|             user.setRoleId(roleService.getOne(new LambdaQueryWrapper<Role>().eq(Role::getRoleName, "默认角色")).getId()); | ||||
|         } | ||||
|         userService.save(user); | ||||
|         return ApiResponse.success(null); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "删除用户") | ||||
|     @PostMapping("/delete") | ||||
|     @RoleAccess(roleNames = "管理员") | ||||
|     public ApiResponse delete(@Parameter(description = "用户ID") String id) { | ||||
|         userService.removeById(id); | ||||
|         return ApiResponse.success(null); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "更新信息") | ||||
|     @PostMapping("/update") | ||||
|     public ApiResponse update(@RequestBody UpdateUserDto updateUserDto) { | ||||
|         User user = new User(); | ||||
|         BeanUtils.copyProperties(updateUserDto, user); | ||||
|         userService.updateById(user); | ||||
|         return ApiResponse.success(null); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "更新密码") | ||||
|     @PostMapping("/updatePassword") | ||||
|     public ApiResponse updatePassword(@RequestBody UpdatePasswordDto updatePasswordDto) { | ||||
|         User user = userService.getById(updatePasswordDto.getId()); | ||||
|         if (user == null) { | ||||
|             return ApiResponse.failure("用户不存在"); | ||||
|         } | ||||
|         if (!BCrypt.checkpw(updatePasswordDto.getOldPassword(), user.getPassword())) { | ||||
|             return ApiResponse.failure("旧密码错误"); | ||||
|         } | ||||
|         user.setPassword(BCrypt.hashpw(updatePasswordDto.getNewPassword(), BCrypt.gensalt())); | ||||
|         userService.updateById(user); | ||||
|         return ApiResponse.success(null); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "用户详情") | ||||
|     @GetMapping("/getById") | ||||
|     public ApiResponse get(@Parameter(description = "用户ID") String id) { | ||||
|         return ApiResponse.success(userService.getById(id)); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "用户列表") | ||||
|     @GetMapping("/list") | ||||
|     @RoleAccess(roleNames = "管理员") | ||||
|     public ApiResponse list(@Parameter(description = "分页数量") Integer pageNum, @Parameter(description = "分页大小") Integer pageSize) { | ||||
|         Page<User> userPage = userService.page(new Page<>(pageNum, pageSize)); | ||||
|         return ApiResponse.success(userPage); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "用户登录") | ||||
|     @PostMapping("/login") | ||||
|     public ApiResponse login(@RequestBody UserLoginDto userLoginDto) { | ||||
|         User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, userLoginDto.getUsername())); | ||||
|         if (user == null) { | ||||
|             return ApiResponse.failure("用户名不存在"); | ||||
|         } | ||||
|         if (!BCrypt.checkpw(userLoginDto.getPassword(), user.getPassword())) { | ||||
|             return ApiResponse.failure("密码错误"); | ||||
|         } | ||||
|         StpUtil.login(user.getId()); | ||||
|         SaTokenInfo tokenInfo = StpUtil.getTokenInfo(); | ||||
|         return ApiResponse.success(Map.of("header", tokenInfo.getTokenName(), "token", tokenInfo.getTokenValue())); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "用户登出") | ||||
|     @PostMapping("/logout") | ||||
|     public ApiResponse logout() { | ||||
|         StpUtil.logout(); | ||||
|         return ApiResponse.success(null); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "设置角色") | ||||
|     @PostMapping("/userBindOrUnBindRole") | ||||
|     @RoleAccess(roleNames = "管理员") | ||||
|     public ApiResponse userBindOrUnBindRole(@RequestBody UserBindOrUnBindRoleDto userBindOrUnBindRoleDto) { | ||||
|         userService.lambdaUpdate().set(User::getRoleId, userBindOrUnBindRoleDto.getRoleId()).eq(User::getId, userBindOrUnBindRoleDto.getUserId()).update(); | ||||
|         return ApiResponse.success(null); | ||||
|     } | ||||
|  | ||||
|     @Operation(summary = "获取当前用户信息") | ||||
|     @GetMapping("/getCurrentUserInfo") | ||||
|     public ApiResponse getCurrentUserInfo() { | ||||
|         return ApiResponse.success(userService.getById(StpUtil.getLoginIdAsString())); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										50
									
								
								src/main/java/com/yj/earth/business/domain/FileInfo.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/main/java/com/yj/earth/business/domain/FileInfo.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | ||||
| 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 com.baomidou.mybatisplus.annotation.TableName; | ||||
| import java.io.Serializable; | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
| import lombok.Getter; | ||||
| import lombok.Setter; | ||||
| import lombok.experimental.Accessors; | ||||
|  | ||||
| @Data | ||||
| public class FileInfo implements Serializable { | ||||
|  | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     @Schema(description = "主键") | ||||
|     @TableId(value = "id", type = IdType.ASSIGN_UUID) | ||||
|     private String id; | ||||
|  | ||||
|     @Schema(description = "文件名") | ||||
|     private String fileName; | ||||
|  | ||||
|     @Schema(description = "文件后缀") | ||||
|     private String fileSuffix; | ||||
|  | ||||
|     @Schema(description = "内容类型") | ||||
|     private String contentType; | ||||
|  | ||||
|     @Schema(description = "文件大小") | ||||
|     private Long fileSize; | ||||
|  | ||||
|     @Schema(description = "文件路径") | ||||
|     private String filePath; | ||||
|  | ||||
|     @Schema(description = "文件MD5") | ||||
|     private String fileMd5; | ||||
|  | ||||
|     @Schema(description = "创建时间") | ||||
|     @TableField(fill = FieldFill.INSERT) | ||||
|     private LocalDateTime createdAt; | ||||
|  | ||||
|     @TableField(fill = FieldFill.UPDATE) | ||||
|     private LocalDateTime updatedAt; | ||||
| } | ||||
							
								
								
									
										41
									
								
								src/main/java/com/yj/earth/business/domain/Role.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/main/java/com/yj/earth/business/domain/Role.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| 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 java.io.Serializable; | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
| import lombok.Getter; | ||||
| import lombok.Setter; | ||||
| import lombok.experimental.Accessors; | ||||
|  | ||||
| @Data | ||||
| public class Role implements Serializable { | ||||
|  | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     @Schema(description = "主键") | ||||
|     @TableId(value = "id", type = IdType.ASSIGN_UUID) | ||||
|     private String id; | ||||
|  | ||||
|     @Schema(description = "角色名称") | ||||
|     private String roleName; | ||||
|  | ||||
|     @Schema(description = "角色描述") | ||||
|     private String description; | ||||
|  | ||||
|     @Schema(description = "是否超级管理员") | ||||
|     private Integer isSuper; | ||||
|  | ||||
|     @Schema(description = "创建时间") | ||||
|     @TableField(fill = FieldFill.INSERT) | ||||
|     private LocalDateTime createdAt; | ||||
|  | ||||
|     @Schema(description = "更新时间") | ||||
|     @TableField(fill = FieldFill.UPDATE) | ||||
|     private LocalDateTime updatedAt; | ||||
| } | ||||
							
								
								
									
										39
									
								
								src/main/java/com/yj/earth/business/domain/RoleSource.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/main/java/com/yj/earth/business/domain/RoleSource.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | ||||
| 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 com.baomidou.mybatisplus.annotation.TableName; | ||||
| import java.io.Serializable; | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
| import lombok.Getter; | ||||
| import lombok.Setter; | ||||
| import lombok.experimental.Accessors; | ||||
|  | ||||
| @Data | ||||
| public class RoleSource implements Serializable { | ||||
|  | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     @Schema(description = "主键") | ||||
|     @TableId(value = "id", type = IdType.ASSIGN_UUID) | ||||
|     private String id; | ||||
|  | ||||
|     @Schema(description = "角色ID") | ||||
|     private String roleId; | ||||
|  | ||||
|     @Schema(description = "资源ID") | ||||
|     private String sourceId; | ||||
|  | ||||
|     @Schema(description = "创建时间") | ||||
|     @TableField(fill = FieldFill.INSERT) | ||||
|     private LocalDateTime createdAt; | ||||
|  | ||||
|     @Schema(description = "更新时间") | ||||
|     @TableField(fill = FieldFill.UPDATE) | ||||
|     private LocalDateTime updatedAt; | ||||
| } | ||||
							
								
								
									
										56
									
								
								src/main/java/com/yj/earth/business/domain/Source.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/main/java/com/yj/earth/business/domain/Source.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | ||||
| 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 java.io.Serializable; | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
| import lombok.Getter; | ||||
| import lombok.Setter; | ||||
| import lombok.experimental.Accessors; | ||||
|  | ||||
| @Data | ||||
| public class Source implements Serializable { | ||||
|  | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     @Schema(description = "主键") | ||||
|     @TableId(value = "id", type = IdType.INPUT) | ||||
|     private String id; | ||||
|  | ||||
|     @Schema(description = "资源名称") | ||||
|     private String sourceName; | ||||
|  | ||||
|     @Schema(description = "资源类型") | ||||
|     private String sourceType; | ||||
|  | ||||
|     @Schema(description = "资源路径") | ||||
|     private String sourcePath; | ||||
|  | ||||
|     @Schema(description = "父级ID") | ||||
|     private String parentId; | ||||
|  | ||||
|     @Schema(description = "树形索引") | ||||
|     private Integer treeIndex; | ||||
|  | ||||
|     @Schema(description = "是否显示") | ||||
|     private Integer isShow; | ||||
|  | ||||
|     @Schema (description = "其他内容") | ||||
|     private String detail; | ||||
|  | ||||
|     @Schema (description = "前端参数") | ||||
|     private String params; | ||||
|  | ||||
|     @Schema(description = "创建时间") | ||||
|     @TableField(fill = FieldFill.INSERT) | ||||
|     private LocalDateTime createdAt; | ||||
|  | ||||
|     @Schema(description = "更新时间") | ||||
|     @TableField(fill = FieldFill.UPDATE) | ||||
|     private LocalDateTime updatedAt; | ||||
| } | ||||
							
								
								
									
										51
									
								
								src/main/java/com/yj/earth/business/domain/User.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/main/java/com/yj/earth/business/domain/User.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | ||||
| 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 java.io.Serializable; | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| import com.yj.earth.annotation.ExcludeField; | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
| import lombok.Getter; | ||||
| import lombok.Setter; | ||||
| import lombok.experimental.Accessors; | ||||
|  | ||||
| @Data | ||||
| public class User implements Serializable { | ||||
|  | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     @TableId(value = "id", type = IdType.ASSIGN_UUID) | ||||
|     private String id; | ||||
|  | ||||
|     @Schema(description = "用户名") | ||||
|     private String username; | ||||
|  | ||||
|     @Schema(description = "密码") | ||||
|     @ExcludeField | ||||
|     private String password; | ||||
|  | ||||
|     @Schema(description = "头像") | ||||
|     private String avatar; | ||||
|  | ||||
|     @Schema(description = "昵称") | ||||
|     private String nickname; | ||||
|  | ||||
|     @Schema(description = "手机号") | ||||
|     private String phone; | ||||
|  | ||||
|     @Schema(description = "所属角色") | ||||
|     private String roleId; | ||||
|  | ||||
|     @Schema(description = "创建时间") | ||||
|     @TableField(fill = FieldFill.INSERT) | ||||
|     private LocalDateTime createdAt; | ||||
|  | ||||
|     @Schema(description = "更新时间") | ||||
|     @TableField(fill = FieldFill.UPDATE) | ||||
|     private LocalDateTime updatedAt; | ||||
| } | ||||
| @ -0,0 +1,18 @@ | ||||
| package com.yj.earth.business.mapper; | ||||
|  | ||||
| import com.yj.earth.business.domain.FileInfo; | ||||
| import com.baomidou.mybatisplus.core.mapper.BaseMapper; | ||||
| import org.apache.ibatis.annotations.Mapper; | ||||
|  | ||||
| /** | ||||
|  * <p> | ||||
|  *  Mapper 接口 | ||||
|  * </p> | ||||
|  * | ||||
|  * @author 周志雄 | ||||
|  * @since 2025-08-29 | ||||
|  */ | ||||
| @Mapper | ||||
| public interface FileInfoMapper extends BaseMapper<FileInfo> { | ||||
|  | ||||
| } | ||||
							
								
								
									
										18
									
								
								src/main/java/com/yj/earth/business/mapper/RoleMapper.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/main/java/com/yj/earth/business/mapper/RoleMapper.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| package com.yj.earth.business.mapper; | ||||
|  | ||||
| import com.yj.earth.business.domain.Role; | ||||
| import com.baomidou.mybatisplus.core.mapper.BaseMapper; | ||||
| import org.apache.ibatis.annotations.Mapper; | ||||
|  | ||||
| /** | ||||
|  * <p> | ||||
|  *  Mapper 接口 | ||||
|  * </p> | ||||
|  * | ||||
|  * @author 周志雄 | ||||
|  * @since 2025-08-28 | ||||
|  */ | ||||
| @Mapper | ||||
| public interface RoleMapper extends BaseMapper<Role> { | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,18 @@ | ||||
| package com.yj.earth.business.mapper; | ||||
|  | ||||
| import com.yj.earth.business.domain.RoleSource; | ||||
| import com.baomidou.mybatisplus.core.mapper.BaseMapper; | ||||
| import org.apache.ibatis.annotations.Mapper; | ||||
|  | ||||
| /** | ||||
|  * <p> | ||||
|  *  Mapper 接口 | ||||
|  * </p> | ||||
|  * | ||||
|  * @author 周志雄 | ||||
|  * @since 2025-08-27 | ||||
|  */ | ||||
| @Mapper | ||||
| public interface RoleSourceMapper extends BaseMapper<RoleSource> { | ||||
|  | ||||
| } | ||||
							
								
								
									
										18
									
								
								src/main/java/com/yj/earth/business/mapper/SourceMapper.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/main/java/com/yj/earth/business/mapper/SourceMapper.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| package com.yj.earth.business.mapper; | ||||
|  | ||||
| import com.yj.earth.business.domain.Source; | ||||
| import com.baomidou.mybatisplus.core.mapper.BaseMapper; | ||||
| import org.apache.ibatis.annotations.Mapper; | ||||
|  | ||||
| /** | ||||
|  * <p> | ||||
|  *  Mapper 接口 | ||||
|  * </p> | ||||
|  * | ||||
|  * @author 周志雄 | ||||
|  * @since 2025-08-26 | ||||
|  */ | ||||
| @Mapper | ||||
| public interface SourceMapper extends BaseMapper<Source> { | ||||
|  | ||||
| } | ||||
							
								
								
									
										18
									
								
								src/main/java/com/yj/earth/business/mapper/UserMapper.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/main/java/com/yj/earth/business/mapper/UserMapper.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| package com.yj.earth.business.mapper; | ||||
|  | ||||
| import com.yj.earth.business.domain.User; | ||||
| import com.baomidou.mybatisplus.core.mapper.BaseMapper; | ||||
| import org.apache.ibatis.annotations.Mapper; | ||||
|  | ||||
| /** | ||||
|  * <p> | ||||
|  *  Mapper 接口 | ||||
|  * </p> | ||||
|  * | ||||
|  * @author 周志雄 | ||||
|  * @since 2025-08-28 | ||||
|  */ | ||||
| @Mapper | ||||
| public interface UserMapper extends BaseMapper<User> { | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,9 @@ | ||||
| package com.yj.earth.business.service; | ||||
|  | ||||
| import com.yj.earth.business.domain.FileInfo; | ||||
| import com.baomidou.mybatisplus.extension.service.IService; | ||||
|  | ||||
| public interface FileInfoService extends IService<FileInfo> { | ||||
|     // 根据文件ID获取文件绝对路径 | ||||
|     String getFileAbsolutePath(String id); | ||||
| } | ||||
							
								
								
									
										16
									
								
								src/main/java/com/yj/earth/business/service/RoleService.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/main/java/com/yj/earth/business/service/RoleService.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| package com.yj.earth.business.service; | ||||
|  | ||||
| import com.yj.earth.business.domain.Role; | ||||
| import com.baomidou.mybatisplus.extension.service.IService; | ||||
|  | ||||
| /** | ||||
|  * <p> | ||||
|  *  服务类 | ||||
|  * </p> | ||||
|  * | ||||
|  * @author 周志雄 | ||||
|  * @since 2025-08-28 | ||||
|  */ | ||||
| public interface RoleService extends IService<Role> { | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,9 @@ | ||||
| package com.yj.earth.business.service; | ||||
|  | ||||
| import com.yj.earth.business.domain.RoleSource; | ||||
| import com.baomidou.mybatisplus.extension.service.IService; | ||||
|  | ||||
|  | ||||
| public interface RoleSourceService extends IService<RoleSource> { | ||||
|     void addRoleSource(String roleId, String sourceId); | ||||
| } | ||||
| @ -0,0 +1,25 @@ | ||||
| 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 java.util.List; | ||||
|  | ||||
| public interface SourceService extends IService<Source> { | ||||
|     String addAndGetSourceId(String sourcePath); | ||||
|  | ||||
|     String getDetail(String sourcePath, String sourceId); | ||||
|  | ||||
|     String buildSdkUrl(String path); | ||||
|  | ||||
|     String fetchCltDetail(String sourceId); | ||||
|  | ||||
|     String fetchMbtilesDetail(String sourceId); | ||||
|  | ||||
|     String fetchPakDetail(String sourceId); | ||||
|  | ||||
|     List<Source> getSourceListByUserId(String userId); | ||||
|  | ||||
|     String checkIsPass(String parentId, String sourceName); | ||||
| } | ||||
							
								
								
									
										16
									
								
								src/main/java/com/yj/earth/business/service/UserService.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/main/java/com/yj/earth/business/service/UserService.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| package com.yj.earth.business.service; | ||||
|  | ||||
| import com.yj.earth.business.domain.User; | ||||
| import com.baomidou.mybatisplus.extension.service.IService; | ||||
|  | ||||
| /** | ||||
|  * <p> | ||||
|  *  服务类 | ||||
|  * </p> | ||||
|  * | ||||
|  * @author 周志雄 | ||||
|  * @since 2025-08-28 | ||||
|  */ | ||||
| public interface UserService extends IService<User> { | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,40 @@ | ||||
| package com.yj.earth.business.service.impl; | ||||
|  | ||||
| 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 io.swagger.v3.oas.annotations.Parameter; | ||||
| import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.stereotype.Service; | ||||
| import org.springframework.web.bind.annotation.PathVariable; | ||||
|  | ||||
| import java.io.File; | ||||
|  | ||||
| @Service | ||||
| public class FileInfoServiceImpl extends ServiceImpl<FileInfoMapper, FileInfo> implements FileInfoService { | ||||
|  | ||||
|     @Value("${file.upload.path}") | ||||
|     private String uploadPath; | ||||
|  | ||||
|     public String getFileAbsolutePath(String id) { | ||||
|  | ||||
|         // 根据ID查询文件信息 | ||||
|         FileInfo fileInfo = this.getById(id); | ||||
|         if (fileInfo == null) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         // 构建完整文件路径 | ||||
|         String fullPath = uploadPath + File.separator + fileInfo.getFilePath(); | ||||
|         File file = new File(fullPath); | ||||
|  | ||||
|         // 校验文件是否存在 | ||||
|         if (!file.exists()) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         // 获取并返回绝对路径 | ||||
|         return file.getAbsolutePath(); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| package com.yj.earth.business.service.impl; | ||||
|  | ||||
| import com.yj.earth.business.domain.Role; | ||||
| import com.yj.earth.business.mapper.RoleMapper; | ||||
| import com.yj.earth.business.service.RoleService; | ||||
| import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | ||||
| import org.springframework.stereotype.Service; | ||||
|  | ||||
| /** | ||||
|  * <p> | ||||
|  *  服务实现类 | ||||
|  * </p> | ||||
|  * | ||||
|  * @author 周志雄 | ||||
|  * @since 2025-08-28 | ||||
|  */ | ||||
| @Service | ||||
| public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService { | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| package com.yj.earth.business.service.impl; | ||||
|  | ||||
| import com.yj.earth.business.domain.RoleSource; | ||||
| import com.yj.earth.business.mapper.RoleSourceMapper; | ||||
| import com.yj.earth.business.service.RoleSourceService; | ||||
| import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | ||||
| import org.springframework.stereotype.Service; | ||||
|  | ||||
|  | ||||
| @Service | ||||
| public class RoleSourceServiceImpl extends ServiceImpl<RoleSourceMapper, RoleSource> implements RoleSourceService { | ||||
|  | ||||
|     @Override | ||||
|     public void addRoleSource(String roleId, String sourceId) { | ||||
|         RoleSource roleSource = new RoleSource(); | ||||
|         roleSource.setRoleId(roleId); | ||||
|         roleSource.setSourceId(sourceId); | ||||
|         save(roleSource); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,166 @@ | ||||
| package com.yj.earth.business.service.impl; | ||||
|  | ||||
| import cn.hutool.core.io.FileUtil; | ||||
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||
| import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | ||||
| import com.yj.earth.business.domain.Role; | ||||
| import com.yj.earth.business.domain.RoleSource; | ||||
| import com.yj.earth.business.domain.Source; | ||||
| import com.yj.earth.business.domain.User; | ||||
| import com.yj.earth.business.mapper.SourceMapper; | ||||
| import com.yj.earth.business.service.RoleService; | ||||
| import com.yj.earth.business.service.RoleSourceService; | ||||
| import com.yj.earth.business.service.SourceService; | ||||
| 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 lombok.extern.slf4j.Slf4j; | ||||
| import org.springframework.stereotype.Service; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.function.Function; | ||||
|  | ||||
|  | ||||
| @Slf4j | ||||
| @Service | ||||
| public class SourceServiceImpl extends ServiceImpl<SourceMapper, Source> implements SourceService { | ||||
|  | ||||
|     @Resource | ||||
|     private ServerConfig serverConfig; | ||||
|     @Resource | ||||
|     private RoleSourceService roleSourceService; | ||||
|     @Resource | ||||
|     private UserService userService; | ||||
|     @Resource | ||||
|     private SourceService sourceService; | ||||
|     @Resource | ||||
|     private RoleService roleService; | ||||
|  | ||||
|     // 存储文件后缀与对应处理函数的映射关系 | ||||
|     public final Map<String, Function<String, String>> detailFetchers; | ||||
|  | ||||
|     // 初始化映射关系 | ||||
|     public SourceServiceImpl() { | ||||
|         detailFetchers = new HashMap<>(); | ||||
|         detailFetchers.put("clt", this::fetchCltDetail); | ||||
|         detailFetchers.put("mbtiles", this::fetchMbtilesDetail); | ||||
|         detailFetchers.put("pak", this::fetchPakDetail); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 调用SDK获取资源ID | ||||
|      */ | ||||
|     @Override | ||||
|     public String addAndGetSourceId(String sourcePath) { | ||||
|         Map<String, Object> addParams = new HashMap<>(); | ||||
|         addParams.put("filePath", sourcePath); | ||||
|         String url = buildSdkUrl("/sourceMap/add"); | ||||
|         return HttpUtil.doPostForm(url, addParams); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 检测资源是否通过审核 | ||||
|      */ | ||||
|     @Override | ||||
|     public String checkIsPass(String parentId, String sourceName) { | ||||
|         // 先查询父节点是否存在 | ||||
|         if (parentId != null) { | ||||
|             LambdaQueryWrapper<Source> queryWrapper = new LambdaQueryWrapper<>(); | ||||
|             queryWrapper.eq(Source::getId, parentId); | ||||
|             List<Source> list = sourceService.list(queryWrapper); | ||||
|             if (sourceService.count(queryWrapper) == 0) { | ||||
|                 return "父级不存在"; | ||||
|             } | ||||
|         } | ||||
| //        // 验证该目录下是否已经存在此资源名一样的 | ||||
| //        LambdaQueryWrapper<Source> queryWrapper = new LambdaQueryWrapper<>(); | ||||
| //        queryWrapper.eq(Source::getSourceName, sourceName); | ||||
| //        if (sourceService.count(queryWrapper) > 0) { | ||||
| //            return "此目录下已存在此资源"; | ||||
| //        } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 根据文件后缀获取详情信息 | ||||
|      */ | ||||
|     @Override | ||||
|     public String getDetail(String sourcePath, String sourceId) { | ||||
|         String ext = FileUtil.extName(sourcePath); | ||||
|         // 通过映射关系获取并执行对应的处理函数 | ||||
|         Function<String, String> fetcher = detailFetchers.get(ext); | ||||
|         if (fetcher != null) { | ||||
|             String detailResult = fetcher.apply(sourceId); | ||||
|             return detailResult; | ||||
|         } else { | ||||
|             log.info("未找到{}类型的处理方式", ext); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 构建SDK请求URL | ||||
|      */ | ||||
|     @Override | ||||
|     public String buildSdkUrl(String path) { | ||||
|         return "http://" + serverConfig.getHost() + ":" + serverConfig.getSdkPort() + path; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取 CLT 类型资源详情 | ||||
|      */ | ||||
|     @Override | ||||
|     public String fetchCltDetail(String sourceId) { | ||||
|         String url = buildSdkUrl("/data/clt/detail/" + sourceId); | ||||
|         return HttpUtil.doGet(url); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取 MBTiles 类型资源详情 | ||||
|      */ | ||||
|     @Override | ||||
|     public String fetchMbtilesDetail(String sourceId) { | ||||
|         String url = buildSdkUrl("/data/mbtiles/detail/" + sourceId); | ||||
|         return HttpUtil.doGet(url); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取 PAK 类型资源详情 | ||||
|      */ | ||||
|     @Override | ||||
|     public String fetchPakDetail(String sourceId) { | ||||
|         String url = buildSdkUrl("/data/pak/detail/" + sourceId); | ||||
|         return HttpUtil.doGet(url); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * 获取用户资源列表 | ||||
|      */ | ||||
|     @Override | ||||
|     public List<Source> getSourceListByUserId(String userId) { | ||||
|         // 查询该用户信息 | ||||
|         LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>(); | ||||
|         queryWrapper.eq(User::getId, userId); | ||||
|         User user = userService.getOne(queryWrapper); | ||||
|         // 查询角色信息 | ||||
|         String roleId = user.getRoleId(); | ||||
|         LambdaQueryWrapper<Role> roleQueryWrapper = new LambdaQueryWrapper<>(); | ||||
|         roleQueryWrapper.eq(Role::getId, roleId); | ||||
|         // 如果这个角色是管理员则直接返回所有资源 | ||||
|         if (roleService.getOne(roleQueryWrapper).getIsSuper() == 1) { | ||||
|             return sourceService.list(); | ||||
|         } | ||||
|         // 查询属于该角色的资源列表 | ||||
|         LambdaQueryWrapper<RoleSource> roleSourceQueryWrapper = new LambdaQueryWrapper<>(); | ||||
|         roleSourceQueryWrapper.eq(RoleSource::getRoleId, roleId); | ||||
|         List<RoleSource> roleSourceList = roleSourceService.list(roleSourceQueryWrapper); | ||||
|         // 从结果提取出资源ID列表 | ||||
|         List<String> sourceIdList = roleSourceList.stream().map(RoleSource::getSourceId).toList(); | ||||
|         return sourceService.listByIds(sourceIdList); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| package com.yj.earth.business.service.impl; | ||||
|  | ||||
| import com.yj.earth.business.domain.User; | ||||
| import com.yj.earth.business.mapper.UserMapper; | ||||
| import com.yj.earth.business.service.UserService; | ||||
| import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | ||||
| import org.springframework.stereotype.Service; | ||||
|  | ||||
| /** | ||||
|  * <p> | ||||
|  *  服务实现类 | ||||
|  * </p> | ||||
|  * | ||||
|  * @author 周志雄 | ||||
|  * @since 2025-08-28 | ||||
|  */ | ||||
| @Service | ||||
| public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { | ||||
|  | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 ZZX9599
					ZZX9599