diff --git a/java/src/main/java/com/yfd/platform/modules/experimentalData/controller/TsFilesController.java b/java/src/main/java/com/yfd/platform/modules/experimentalData/controller/TsFilesController.java index 18ea73f..42185bf 100644 --- a/java/src/main/java/com/yfd/platform/modules/experimentalData/controller/TsFilesController.java +++ b/java/src/main/java/com/yfd/platform/modules/experimentalData/controller/TsFilesController.java @@ -686,17 +686,18 @@ public class TsFilesController { * 参数说明 id 文件的ID * 参数说明 samTimes 时间 * 参数说明 token SSE连接的token + * 参数说明 config 配置文件的ID * 返回值说明: com.yfd.platform.config.ResponseResult ***********************************/ @Log(module = "实验数据管理", value = "实时获取轨迹数据!") @PostMapping("/startSimpleNavi") @ApiOperation("实时获取轨迹数据") - public ResponseResult startSimpleNavi(String id, int samTimes, String token, String taskId) { + public ResponseResult startSimpleNavi(String id, int samTimes, String token, String taskId,String configId) { try { // 使用线程池异步执行任务 CompletableFuture.runAsync(() -> { try { - tsFilesService.batchSendNaviOutDataJob(id, samTimes, token, taskId); + tsFilesService.batchSendNaviOutDataJob(id, samTimes, token, taskId,configId); } catch (Exception e) { e.printStackTrace(); } @@ -794,4 +795,24 @@ public class TsFilesController { FileItemResult fileItemResult = tsFilesService.obtainUrl(id, type, taskId); return ResponseResult.successData(fileItemResult); } + + /********************************** + * 用途说明: 通过文件ID获取对应的txt集合和png集合 + * 参数说明 id 文件夹ID + * 参数说明 taskId 任务ID + * 参数说明 nodeId 节点ID + * 返回值说明: com.yfd.platform.config.ResponseResult 返回文件集合列表 + ***********************************/ + @Log(module = "实验数据管理", value = "通过文件ID获取对应的txt集合和png集合!") + @PostMapping("/listTsFilesById") + @ApiOperation("通过文件ID获取对应的txt集合和png集合") + public ResponseResult listTsFilesById(String id, String taskId,String nodeId) { + if (StrUtil.isBlank(id) && StrUtil.isBlank(taskId)&& StrUtil.isBlank(nodeId)) { + return ResponseResult.error("参数为空"); + } + //通过ID查询集合 + return ResponseResult.successData(tsFilesService.listTsFilesById(id, taskId,nodeId)); + } + + } diff --git a/java/src/main/java/com/yfd/platform/modules/experimentalData/domain/TrajectoriesDto.java b/java/src/main/java/com/yfd/platform/modules/experimentalData/domain/TrajectoriesDto.java new file mode 100644 index 0000000..1a33689 --- /dev/null +++ b/java/src/main/java/com/yfd/platform/modules/experimentalData/domain/TrajectoriesDto.java @@ -0,0 +1,30 @@ +package com.yfd.platform.modules.experimentalData.domain; + +import com.baomidou.mybatisplus.annotation.TableField; +import lombok.Data; + +import java.util.List; + +@Data +public class TrajectoriesDto { + + /** + * 获取底图集合 + */ + @TableField(exist = false) + private List tsFilesListPng; + + /** + * 获取地理信息集合 + */ + @TableField(exist = false) + private List tsFilesListTxt; + + + /** + * 获取配置文件信息 + */ + @TableField(exist = false) + private List tsFilesListConfig; + +} diff --git a/java/src/main/java/com/yfd/platform/modules/experimentalData/domain/TsFiles.java b/java/src/main/java/com/yfd/platform/modules/experimentalData/domain/TsFiles.java index 47f4bf5..e620d4a 100644 --- a/java/src/main/java/com/yfd/platform/modules/experimentalData/domain/TsFiles.java +++ b/java/src/main/java/com/yfd/platform/modules/experimentalData/domain/TsFiles.java @@ -191,4 +191,13 @@ public class TsFiles implements Serializable { @TableField(exist = false) private String minioMd5; + + + /** + * 文件内容 + */ + @TableField(exist = false) + private String fileContent; + + } diff --git a/java/src/main/java/com/yfd/platform/modules/experimentalData/service/ITsFilesService.java b/java/src/main/java/com/yfd/platform/modules/experimentalData/service/ITsFilesService.java index 310cfc6..b797e8e 100644 --- a/java/src/main/java/com/yfd/platform/modules/experimentalData/service/ITsFilesService.java +++ b/java/src/main/java/com/yfd/platform/modules/experimentalData/service/ITsFilesService.java @@ -144,7 +144,7 @@ public interface ITsFilesService extends IService { * 参数说明 token SSE连接的token * 返回值说明: com.yfd.platform.config.ResponseResult ***********************************/ - void batchSendNaviOutDataJob(String id, int samTimes, String token,String taskId); + void batchSendNaviOutDataJob(String id, int samTimes, String token,String taskId,String configId); /** * 查询文件内容接口 @@ -256,4 +256,12 @@ public interface ITsFilesService extends IService { void decompressionFolderAsync(String id, String decompressionPath, String parentId, String path, String taskId) throws IOException; Object decompressionFolderData(String taskId); + /********************************** + * 用途说明: 通过文件ID获取对应的txt集合和png集合 + * 参数说明 id 文件夹ID + * 参数说明 taskId 任务ID + * 参数说明 nodeId 节点ID + * 返回值说明: com.yfd.platform.config.ResponseResult 返回文件集合列表 + ***********************************/ + Object listTsFilesById(String id, String taskId, String nodeId); } diff --git a/java/src/main/java/com/yfd/platform/modules/experimentalData/service/impl/TsFilesServiceImpl.java b/java/src/main/java/com/yfd/platform/modules/experimentalData/service/impl/TsFilesServiceImpl.java index 04ef7bb..ffdf559 100644 --- a/java/src/main/java/com/yfd/platform/modules/experimentalData/service/impl/TsFilesServiceImpl.java +++ b/java/src/main/java/com/yfd/platform/modules/experimentalData/service/impl/TsFilesServiceImpl.java @@ -89,6 +89,8 @@ import java.util.zip.*; import org.apache.commons.codec.binary.Hex; +import static java.lang.Float.parseFloat; + /** *

@@ -333,7 +335,6 @@ public class TsFilesServiceImpl extends ServiceImpl impl } - private boolean isValidPage(IPage page) { return page.getRecords() != null && !page.getRecords().isEmpty() @@ -576,7 +577,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl Timestamp currentTime = Timestamp.valueOf(now); if (tsFiles.getIsFile().equals("FILE")) { - StorageSourceConfig config = getStorageSourceConfig("filePath", "local",tsTask.getLocalStorageId()); + StorageSourceConfig config = getStorageSourceConfig("filePath", "local", tsTask.getLocalStorageId()); String basePath = config.getValue() + tsFiles.getWorkPath(); // 拼接完整的文件路径 Path filePath = Paths.get(basePath, tsFiles.getFileName() + ".txt"); @@ -1274,7 +1275,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl TableNameContextHolder.setTaskCode(tsTask.getTaskCode()); //获取本地根路径 - StorageSourceConfig storageSourceConfig = getStorageSourceConfig("filePath", "local",tsTask.getLocalStorageId()); + StorageSourceConfig storageSourceConfig = getStorageSourceConfig("filePath", "local", tsTask.getLocalStorageId()); compressedPath = normalizePath(compressedPath); @@ -1930,7 +1931,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl } // 如果拼接了文件名,返回结果 if (decompressionFolder.length() > 0) { - return (decompressionFolder+"解压任务正在进行中!"); + return (decompressionFolder + "解压任务正在进行中!"); } } @@ -1940,7 +1941,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl decompressionFolder.append("没有解压任务!"); } return decompressionFolder; - }finally { + } finally { TableNameContextHolder.clear(); } } @@ -1961,7 +1962,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl TsTask tsTask = tsTaskMapper.selectById(taskId); TableNameContextHolder.setTaskCode(tsTask.getTaskCode()); // 查询本地文件路径根目录(如 E:\yun) - StorageSourceConfig storageSourceConfig = getStorageSourceConfig("filePath", "local",tsTask.getLocalStorageId()); + StorageSourceConfig storageSourceConfig = getStorageSourceConfig("filePath", "local", tsTask.getLocalStorageId()); decompressionPath = normalizePath(decompressionPath); TsFiles zipFileRecord = tsFilesMapper.selectById(id); try { @@ -2118,16 +2119,16 @@ public class TsFilesServiceImpl extends ServiceImpl impl // return fileRecord; // } TsFiles fileRecord = new TsFiles(); - fileRecord.setNodeId(nodeId); - fileRecord.setTaskId(taskId); - fileRecord.setParentId(parentId); - fileRecord.setFileName(fileName); - fileRecord.setWorkPath(workPath); - fileRecord.setIsFile("FILE"); - fileRecord.setFileSize(fileSize); - fileRecord.setUploadTime(new Timestamp(System.currentTimeMillis())); - operateTsfeiles(fileRecord); // 插入或更新记录 - return fileRecord; + fileRecord.setNodeId(nodeId); + fileRecord.setTaskId(taskId); + fileRecord.setParentId(parentId); + fileRecord.setFileName(fileName); + fileRecord.setWorkPath(workPath); + fileRecord.setIsFile("FILE"); + fileRecord.setFileSize(fileSize); + fileRecord.setUploadTime(new Timestamp(System.currentTimeMillis())); + operateTsfeiles(fileRecord); // 插入或更新记录 + return fileRecord; } /** @@ -3218,7 +3219,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl long endIndex = Math.min(startIndex + pageSize, total); // 获取当前页数据 - List pagedRecords = filteredRecords.subList((int) startIndex,(int) endIndex); + List pagedRecords = filteredRecords.subList((int) startIndex, (int) endIndex); // ================ 5. 构建分页结果 ================ Page resultPage = new Page<>(currentPage, pageSize, total); @@ -3327,36 +3328,37 @@ public class TsFilesServiceImpl extends ServiceImpl impl // }) // .collect(Collectors.toList()); // -//// List filteredRecords = tsFilesPage.getRecords().stream() -//// .filter(tsFile -> { -//// try { -//// if("FOLDER".equals(tsFile.getIsFile())){ -//// return false; -//// } -//// // 计算本地文件MD5 -//// File localFile = new File(filePathConfig.getValue() + tsFile.getWorkPath(), tsFile.getFileName()); -//// String localMD5 = calculateMD5Data(new FileInputStream(localFile)); -//// -//// // 计算MinIO文件MD5 -//// -//// String minioMD5 = getMinioMD5Data(bucketConfig.getValue(), tsFile.getBackupPath(), tsFile.getFileName(),storageSource); -//// -//// // 路径处理 -//// //tsFile.setWorkPath(processingPath(tsFile.getWorkPath(), tsFile.getNodeId())); -//// // tsFile.setBackupPath(processingPath(tsFile.getBackupPath(), tsFile.getNodeId())); -//// -//// // 设置MD5字段(即使不满足条件也保留字段) -//// tsFile.setLocatMd5(localMD5); -//// tsFile.setMinioMd5(minioMD5); -//// -//// // 返回是否满足过滤条件 -//// return StringUtils.isNoneEmpty(localMD5, minioMD5) && !localMD5.equals(minioMD5); -//// } catch (Exception e) { -//// LOGGER.error("MD5计算失败: {}", tsFile.getFileName(), e); -//// return false; -//// } -//// }) -//// .collect(Collectors.toList()); + + /// / List filteredRecords = tsFilesPage.getRecords().stream() + /// / .filter(tsFile -> { + /// / try { + /// / if("FOLDER".equals(tsFile.getIsFile())){ + /// / return false; + /// / } + /// / // 计算本地文件MD5 + /// / File localFile = new File(filePathConfig.getValue() + tsFile.getWorkPath(), tsFile.getFileName()); + /// / String localMD5 = calculateMD5Data(new FileInputStream(localFile)); + /// / + /// / // 计算MinIO文件MD5 + /// / + /// / String minioMD5 = getMinioMD5Data(bucketConfig.getValue(), tsFile.getBackupPath(), tsFile.getFileName(),storageSource); + /// / + /// / // 路径处理 + /// / //tsFile.setWorkPath(processingPath(tsFile.getWorkPath(), tsFile.getNodeId())); + /// / // tsFile.setBackupPath(processingPath(tsFile.getBackupPath(), tsFile.getNodeId())); + /// / + /// / // 设置MD5字段(即使不满足条件也保留字段) + /// / tsFile.setLocatMd5(localMD5); + /// / tsFile.setMinioMd5(minioMD5); + /// / + /// / // 返回是否满足过滤条件 + /// / return StringUtils.isNoneEmpty(localMD5, minioMD5) && !localMD5.equals(minioMD5); + /// / } catch (Exception e) { + /// / LOGGER.error("MD5计算失败: {}", tsFile.getFileName(), e); + /// / return false; + /// / } + /// / }) + /// / .collect(Collectors.toList()); // // // // ================ 3. 构建新的分页结果 ================ @@ -3377,8 +3379,6 @@ public class TsFilesServiceImpl extends ServiceImpl impl // TableNameContextHolder.clear(); // } // } - - @Override public List compareMd5List(List dataset, String nodeId, String taskId) { @@ -3389,8 +3389,8 @@ public class TsFilesServiceImpl extends ServiceImpl impl StorageSource storageSource = getStorageConfig(tsTask.getBackupStorageId()); // 获取本地文件路径根目录和存储空间名称 - StorageSourceConfig filePathConfig = getStorageSourceConfig("filePath", "local",tsTask.getLocalStorageId()); - StorageSourceConfig bucketConfig = getStorageSourceConfig("bucketName", "minio",tsTask.getBackupStorageId()); + StorageSourceConfig filePathConfig = getStorageSourceConfig("filePath", "local", tsTask.getLocalStorageId()); + StorageSourceConfig bucketConfig = getStorageSourceConfig("bucketName", "minio", tsTask.getBackupStorageId()); // ================ 1. 执行原始分页查询 ================ QueryWrapper queryWrapper = buildQueryWrapper(dataset, nodeId, taskId); @@ -3552,7 +3552,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl } // 辅助方法:获取 MinIO 文件 MD5 - private String getMinioMD5Data(String bucketName, String path, String name,StorageSource storageSource) { + private String getMinioMD5Data(String bucketName, String path, String name, StorageSource storageSource) { AbstractBaseFileService minioService = storageSourceContext.getByStorageKey(storageSource.getKey()); String key = normalizePath(path) + name; @@ -3627,8 +3627,8 @@ public class TsFilesServiceImpl extends ServiceImpl impl TableNameContextHolder.setTaskCode(tsTask.getTaskCode()); StorageSource storageSourceLocal = getStorageConfig(tsTask.getLocalStorageId()); StorageSource storageSourceMinio = getStorageConfig(tsTask.getBackupStorageId()); - StorageSourceConfig storageSourceConfig = getStorageSourceConfig("filePath", "local",tsTask.getLocalStorageId()); - StorageSourceConfig storageSourceConfig1 = getStorageSourceConfig("bucketName", "minio",tsTask.getBackupStorageId()); + StorageSourceConfig storageSourceConfig = getStorageSourceConfig("filePath", "local", tsTask.getLocalStorageId()); + StorageSourceConfig storageSourceConfig1 = getStorageSourceConfig("bucketName", "minio", tsTask.getBackupStorageId()); List parameterLists = parameter.getParameterLists(); // 设置当前时间 LocalDateTime now = LocalDateTime.now(); @@ -3668,14 +3668,14 @@ public class TsFilesServiceImpl extends ServiceImpl impl //如果文件夹创建成功 if (flag) { value = true; - currentFile.setUpdateTime(currentTime); - currentFile.setBackupPath(minioPath); - int valueAdded = tsFilesMapper.updateById(currentFile); - if (valueAdded == 1) { - value = true; - } else { - value = false; - } + currentFile.setUpdateTime(currentTime); + currentFile.setBackupPath(minioPath); + int valueAdded = tsFilesMapper.updateById(currentFile); + if (valueAdded == 1) { + value = true; + } else { + value = false; + } } else { value = false; @@ -3714,14 +3714,14 @@ public class TsFilesServiceImpl extends ServiceImpl impl if (flag1) { value = true; - currentFile.setUpdateTime(currentTime); - currentFile.setBackupPath(minioPath); - int valueAdded = tsFilesMapper.updateById(currentFile); - if (valueAdded == 1) { - value = true; - } else { - value = false; - } + currentFile.setUpdateTime(currentTime); + currentFile.setBackupPath(minioPath); + int valueAdded = tsFilesMapper.updateById(currentFile); + if (valueAdded == 1) { + value = true; + } else { + value = false; + } } else { value = false; } @@ -3742,7 +3742,6 @@ public class TsFilesServiceImpl extends ServiceImpl impl } - /********************************** * 用途说明: 将文件上传到备份空间 其他接口使用 * 参数说明 parameter 数据集合 @@ -3755,8 +3754,8 @@ public class TsFilesServiceImpl extends ServiceImpl impl TableNameContextHolder.setTaskCode(tsTask.getTaskCode()); StorageSource storageSourceLocal = getStorageConfig(tsTask.getLocalStorageId()); StorageSource storageSourceMinio = getStorageConfig(tsTask.getBackupStorageId()); - StorageSourceConfig storageSourceConfig = getStorageSourceConfig("filePath", "local",tsTask.getLocalStorageId()); - StorageSourceConfig storageSourceConfig1 = getStorageSourceConfig("bucketName", "minio",tsTask.getBackupStorageId()); + StorageSourceConfig storageSourceConfig = getStorageSourceConfig("filePath", "local", tsTask.getLocalStorageId()); + StorageSourceConfig storageSourceConfig1 = getStorageSourceConfig("bucketName", "minio", tsTask.getBackupStorageId()); List parameterLists = parameter.getParameterLists(); // 在循环前记录开始时间 @@ -4068,7 +4067,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl LOGGER.info("总处理: {}文件/{}文件夹 | 成功: {}文件/{}文件夹 | 总耗时: {}秒", fileCount.get(), folderCount.get(), backupsFileCount.get(), backupsFolderCount.get(), - totalTime/1000.0); + totalTime / 1000.0); return String.format("本地有新增文件 %d 个, 文件夹 %d 个, 备份成功 %d 文件/%d 文件夹", fileCount.get(), folderCount.get(), @@ -4170,7 +4169,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl .eq("task_id", taskId) .and(wrapper -> wrapper.isNull("backup_path").or().eq("backup_path", "")); tsFilesMapper.update(null, updateWrapper); - }finally { + } finally { TableNameContextHolder.clear(); } @@ -4273,7 +4272,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl .and(wrapper -> wrapper.isNull("backup_path").or().eq("backup_path", "")); // 执行更新 tsFilesMapper.update(null, updateWrapper); - }finally { + } finally { TableNameContextHolder.clear(); } @@ -4302,9 +4301,9 @@ public class TsFilesServiceImpl extends ServiceImpl impl UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); LoginUser loginuser = (LoginUser) authentication.getPrincipal(); - StorageSourceConfig storageSourceConfig = getStorageSourceConfig("filePath", "local",tsTask.getLocalStorageId()); + StorageSourceConfig storageSourceConfig = getStorageSourceConfig("filePath", "local", tsTask.getLocalStorageId()); - StorageSourceConfig storageSourceConfig1 = getStorageSourceConfig("bucketName", "minio",tsTask.getBackupStorageId()); + StorageSourceConfig storageSourceConfig1 = getStorageSourceConfig("bucketName", "minio", tsTask.getBackupStorageId()); List parameterLists = parameter.getParameterLists(); @@ -4525,7 +4524,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl TsTask tsTask = tsTaskMapper.selectById(reques.getTaskId()); TableNameContextHolder.setTaskCode(tsTask.getTaskCode()); // 1. 获取存储根路径 - StorageSourceConfig config = getStorageSourceConfig("filePath", "local",tsTask.getLocalStorageId()); + StorageSourceConfig config = getStorageSourceConfig("filePath", "local", tsTask.getLocalStorageId()); Path rootPath = Paths.get(config.getValue()); String newPath = reques.getNewPath(); String oldpaths = reques.getOldpaths(); @@ -4574,7 +4573,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl moveFile(sourcePath, targetPath, type); // 更新数据库记录 - updateDatabase(parentId, oldpaths, fileName, newPath, targetFileName, type,nodeId); + updateDatabase(parentId, oldpaths, fileName, newPath, targetFileName, type, nodeId); } return "移动成功"; } catch (NoSuchFileException e) { @@ -4670,7 +4669,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl * 更新数据库中的父ID和路径 */ private void updateDatabase(String parentId, String oldpaths, String fileName, - String newPath, String targetFileName, String type,String nodeId) { + String newPath, String targetFileName, String type, String nodeId) { TsFiles tsFilesData = tsFilesMapper.selectById(parentId); LOGGER.info("移动的时候删除Redis"); @@ -4731,7 +4730,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl // 如果是文件夹,递归删除子项 if ("FOLDER".equals(fileRecord.getIsFile())) { // 先移动子项再删除原记录 - moveChildrenRecords(oldWorkPath, newWorkPath + targetFileName + "/", newRecord.getId(), type, fileRecord.getId(),nodeId); + moveChildrenRecords(oldWorkPath, newWorkPath + targetFileName + "/", newRecord.getId(), type, fileRecord.getId(), nodeId); } // 删除原记录 tsFilesMapper.deleteById(fileRecord.getId()); @@ -4762,7 +4761,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl /** * 递归移动子项记录(覆盖模式下先移动后删除) */ - private void moveChildrenRecords(String oldPrefix, String newPrefix, String parentId, String type, String oldparentId,String nodeId) { + private void moveChildrenRecords(String oldPrefix, String newPrefix, String parentId, String type, String oldparentId, String nodeId) { //查询原来的 List children = tsFilesMapper.selectList( new QueryWrapper().eq("parent_id", oldparentId)); @@ -4801,7 +4800,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl tsFilesMapper.insert(newChild); // 递归处理子文件夹 if ("FOLDER".equals(child.getIsFile())) { - moveChildrenRecords(oldPrefix, newPrefix + newChild.getFileName() + "/", newChild.getId(), type, child.getId(),nodeId); + moveChildrenRecords(oldPrefix, newPrefix + newChild.getFileName() + "/", newChild.getId(), type, child.getId(), nodeId); } // 删除原记录 tsFilesMapper.deleteById(child.getId()); @@ -4839,7 +4838,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl TsTask tsTask = tsTaskMapper.selectById(reques.getTaskId()); TableNameContextHolder.setTaskCode(tsTask.getTaskCode()); // 1. 获取存储根路径 - StorageSourceConfig config = getStorageSourceConfig("filePath", "local",tsTask.getLocalStorageId()); + StorageSourceConfig config = getStorageSourceConfig("filePath", "local", tsTask.getLocalStorageId()); Path rootPath = Paths.get(config.getValue()); String newPath = reques.getNewPath(); @@ -4886,7 +4885,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl copyPhysicalFile(sourcePath, targetPath, type); // 5. 插入新记录到数据库 - insertDatabaseRecord(parentId, oldpaths, fileName, newPath, targetFileName, type,nodeId); + insertDatabaseRecord(parentId, oldpaths, fileName, newPath, targetFileName, type, nodeId); } return "复制成功"; } catch (IllegalArgumentException e) { @@ -4934,7 +4933,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl * 插入数据库记录(主记录) */ private void insertDatabaseRecord(String parentId, String oldpaths, String fileName, - String newPath, String targetFileName, String type,String nodeId) { + String newPath, String targetFileName, String type, String nodeId) { TsFiles tsFilesData = tsFilesMapper.selectById(parentId); LOGGER.info("复制的时候删除Redis"); @@ -5018,7 +5017,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl * 递归复制子项数据库记录(关键优化点) */ private void copyChildrenRecords(String oldPrefix, String newPrefix, - String originalParentId, String newParentId, String type,String nodeId) { + String originalParentId, String newParentId, String type, String nodeId) { List children = tsFilesMapper.selectList( new QueryWrapper().eq("parent_id", originalParentId) ); @@ -5052,7 +5051,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl * 处理单个子项记录 */ private TsFiles processChildRecord(TsFiles child, String newParentId, String newPrefix, - String oldPrefix, String type, LoginUser user, Timestamp now,String nodeId) { + String oldPrefix, String type, LoginUser user, Timestamp now, String nodeId) { if ("0".equals(type)) { // 覆盖模式 TsFiles existing = tsFilesMapper.selectOne( new QueryWrapper() @@ -5060,7 +5059,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl .eq("file_name", child.getFileName()) ); if (existing != null) { - updateExisting(existing, child, now, user,nodeId); + updateExisting(existing, child, now, user, nodeId); return existing; } else { return insertNewChild(child, newParentId, newPrefix, @@ -5075,7 +5074,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl /** * 更新现有记录(覆盖模式) */ - private void updateExisting(TsFiles existing, TsFiles source, Timestamp time, LoginUser user,String nodeId) { + private void updateExisting(TsFiles existing, TsFiles source, Timestamp time, LoginUser user, String nodeId) { existing.setFileSize(source.getFileSize()); existing.setNodeId(nodeId); existing.setDescription(source.getDescription()); @@ -5088,7 +5087,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl * 插入新子项记录 */ private TsFiles insertNewChild(TsFiles source, String parentId, String newWorkPath, - LoginUser user, Timestamp time, String customName,String nodeId) { + LoginUser user, Timestamp time, String customName, String nodeId) { TsFiles newChild = new TsFiles(); newChild.setNodeId(nodeId); newChild.setTaskId(source.getTaskId()); @@ -5308,7 +5307,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl storageSourceLocal = getStorageConfig(tsTask.getLocalStorageId()); String workPath = tsFiles.getWorkPath(); path = workPath + fileNameData; - }else { + } else { storageSourceLocal = getStorageConfig(tsTask.getBackupStorageId()); String backupPath = tsFiles.getBackupPath(); path = backupPath + fileNameData; @@ -5407,8 +5406,6 @@ public class TsFilesServiceImpl extends ServiceImpl impl } - - /*******************************************读取文件内容经纬度**************************************************************/ /********************************** * 用途说明: 实时获取轨迹数据 @@ -5418,87 +5415,168 @@ public class TsFilesServiceImpl extends ServiceImpl impl * 返回值说明: com.yfd.platform.config.ResponseResult ***********************************/ @Override - public void batchSendNaviOutDataJob(String id, int samTimes, String token, String taskId) { + public void batchSendNaviOutDataJob(String id, int samTimes, String token, String taskId,String configId) { try { TsTask tsTask = tsTaskMapper.selectById(taskId); TableNameContextHolder.setTaskCode(tsTask.getTaskCode()); TsFiles tsFiles = tsFilesMapper.selectById(id); - if (currentTaskFuture != null && !currentTaskFuture.isDone()) { - currentTaskFuture.cancel(true); // 中断之前的任务 - } - currentTaskFuture = executorService.submit(() -> { - StorageSourceConfig config = getStorageSourceConfig("filePath", "local",tsTask.getLocalStorageId()); + + //判断文件后缀是.txt还是.csv + String fileName = tsFiles.getFileName(); + String suffix = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase(); + if ("txt".equals(suffix)) { + if (currentTaskFuture != null && !currentTaskFuture.isDone()) { + currentTaskFuture.cancel(true); // 中断之前的任务 + } + currentTaskFuture = executorService.submit(() -> { + StorageSourceConfig config = getStorageSourceConfig("filePath", "local", tsTask.getLocalStorageId()); - Path filePath = Paths.get(config.getValue() + tsFiles.getWorkPath() + tsFiles.getFileName()); + Path filePath = Paths.get(config.getValue() + tsFiles.getWorkPath() + tsFiles.getFileName()); - try (BufferedReader reader = new BufferedReader(new FileReader(filePath.toFile()))) { - reader.readLine(); // 跳过标题行 + try (BufferedReader reader = new BufferedReader(new FileReader(filePath.toFile()))) { + reader.readLine(); // 跳过标题行 + + + + SimpleNaviData data1 = null; + int result = 0; + // 读取第二行数据 + String secondLine = reader.readLine(); + if (secondLine != null) { + secondLine = secondLine.trim(); + String[] valuesSecond = secondLine.split("\t"); + data1 = parseLine(valuesSecond); - // 不管 samTimes 如何,先读取第一行数据 - String firstLine = reader.readLine(); - if (firstLine != null) { - firstLine = firstLine.trim(); - String[] values = firstLine.split("\t"); - if (values.length >= 40) { - // 发送第一行数据 - sendData(token, values, 1); - } else { - System.err.println("忽略不完整行: " + firstLine); } - } - //todo 这个地方该从一下 换成200 - int step = samTimes * 200; // 计算行号间隔 - int lineCount = 1; // 从第一行开始 - while (!Thread.currentThread().isInterrupted()) { - lineCount += step; // 直接跳到下一个需要读取的行 - String line = null; + // 读取第三行数据 + String thirdLine = reader.readLine(); + if (thirdLine != null) { + thirdLine = thirdLine.trim(); + String[] valuesThird = thirdLine.split("\t"); + SimpleNaviData data2 = parseLine(valuesThird); - // 读取指定行 - for (int i = 0; i < step; i++) { - line = reader.readLine(); - if (line == null) { - break; // 文件结束 + // 假设 UtcTime 是 String 类型,首先转换为 double 类型 + double time1 = Double.parseDouble(data1.getUtcTime()); // 如果 getUtcTime() 返回 String 类型 + double time2 = Double.parseDouble(data2.getUtcTime()); // 如果 getUtcTime() 返回 String 类型 + // 计算差值 + double diff = time2 - time1; + // 确保差值不为零,以避免除以零错误 + if (diff != 0) { + result = (int) Math.floor(1 / diff); + } else { + result = 1; } } - if (line == null) { - break; // 文件结束 + + // 不管 samTimes 如何,先读取第一行数据 + String firstLine = reader.readLine(); + if (firstLine != null) { + firstLine = firstLine.trim(); + String[] values = firstLine.split("\t"); + if (values.length >= 40) { + // 发送第一行数据 + sendData(token, values, 1); + } else { + System.err.println("忽略不完整行: " + firstLine); + } + } + //todo 这个地方该从一下 换成200 + int step = samTimes * result; // 计算行号间隔 + int lineCount = 1; // 从第一行开始 + + + + while (!Thread.currentThread().isInterrupted()) { + lineCount += step; // 直接跳到下一个需要读取的行 + String line = null; + + // 读取指定行 + for (int i = 0; i < step; i++) { + line = reader.readLine(); + if (line == null) { + break; // 文件结束 + } + } + + if (line == null) { + break; // 文件结束 + } + + line = line.trim(); + String[] values = line.split("\t"); + if (values.length < 40) { + LOGGER.info("忽略不完整行: " + line); + continue; + } + + // 发送数据 + sendData(token, values, lineCount); + + // 固定休眠 3 秒 + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + // 如果休眠期间被中断,则退出循环 + Thread.currentThread().interrupt(); + break; + } } - line = line.trim(); - String[] values = line.split("\t"); - if (values.length < 40) { - LOGGER.info("忽略不完整行: " + line); - continue; + // 发送完成信号(如果需要) + if (!Thread.currentThread().isInterrupted()) { + // ServerSendEventServer.sendMessage(token, "COMPLETED"); } - // 发送数据 - sendData(token, values, lineCount); - - // 固定休眠 3 秒 - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - // 如果休眠期间被中断,则退出循环 - Thread.currentThread().interrupt(); - break; - } + } catch (Exception e) { + // 捕获异常并记录日志 + LOGGER.error("任务执行失败: " + e.getMessage()); + e.printStackTrace(); } + }); + }else{ - // 发送完成信号(如果需要) - if (!Thread.currentThread().isInterrupted()) { - // ServerSendEventServer.sendMessage(token, "COMPLETED"); - } - - } catch (Exception e) { - // 捕获异常并记录日志 - LOGGER.error("任务执行失败: " + e.getMessage()); - e.printStackTrace(); + TsFiles tsFilesData = tsFilesMapper.selectById(configId); + if (currentTaskFuture != null && !currentTaskFuture.isDone()) { + currentTaskFuture.cancel(true); } - }); + + currentTaskFuture = executorService.submit(() -> { + try { + // 1. 获取配置文件路径 + StorageSourceConfig config = getStorageSourceConfig("filePath", "local", tsTask.getLocalStorageId()); + Path basePath = Paths.get(config.getValue() + tsFilesData.getWorkPath()); + + // 2. 读取配置文件(假设配置文件名为 trj_config.txt) + Path configPath = basePath.resolve("trj_config.txt"); + Map columnMapping = parseConfigFile(configPath); + + String timeColumn = columnMapping.get("time"); + String lonColumn = columnMapping.get("lon"); + String latColumn = columnMapping.get("lat"); + String hgtColumn = columnMapping.get("hgt"); + + LOGGER.info("列映射: time={}, lon={}, lat={}, hgt={}", + timeColumn, lonColumn, latColumn, hgtColumn); + + // 3. 获取数据文件路径 + Path dataPath = basePath.resolve("VINS.csv"); + + // 4. 处理数据文件 + processDataFile(dataPath, samTimes, token, timeColumn, lonColumn, latColumn, hgtColumn); + + } catch (Exception e) { + LOGGER.error("任务执行失败: {}", e.getMessage(), e); + } + }); + } + + + + } catch (Exception e) { LOGGER.error("未知异常:{}", e.getMessage(), e); throw new RuntimeException("系统错误,请联系管理员"); @@ -5544,6 +5622,232 @@ public class TsFilesServiceImpl extends ServiceImpl impl } + + + + /** + * 读取配置文件并解析为列名映射 + * + * @param configFilePath 配置文件路径 + * @return 列名映射Map(time, lon, lat, hgt) + * @throws IOException 文件读取错误 + */ + public Map parseConfigFile(Path configFilePath) throws IOException { + Map columnMapping = new HashMap<>(); + + try (BufferedReader reader = Files.newBufferedReader(configFilePath, StandardCharsets.UTF_8)) { + String line; + while ((line = reader.readLine()) != null) { + line = line.trim(); + if (line.isEmpty()) continue; + + // 分割键值对 + String[] parts = line.split(":"); + if (parts.length < 2) { + LOGGER.warn("忽略无效行: {}", line); + continue; + } + + String key = parts[0].trim().toLowerCase(); + String value = parts[1].trim(); + + // 只处理需要的键 + if (key.equals("time") || key.equals("lon") || + key.equals("lat") || key.equals("hgt")) { + columnMapping.put(key, value); + } + } + } + + // 验证是否获取到所有必需的列 + if (columnMapping.size() < 4) { + throw new IOException("配置文件缺少必需的列定义"); + } + + return columnMapping; + } + + + /** + * 处理数据文件 + */ + private void processDataFile(Path dataPath, int samTimes, String token, + String timeColumn, String lonColumn, + String latColumn, String hgtColumn) + throws IOException { + + try (BufferedReader reader = Files.newBufferedReader(dataPath, StandardCharsets.UTF_8)) { + // 1. 读取标题行 + String headerLine = reader.readLine(); + if (headerLine == null) { + LOGGER.error("数据文件为空: {}", dataPath); + return; + } + + // 2. 解析标题行 - 使用逗号分隔 + String[] headers = headerLine.split(","); // 改为逗号分隔 + + // 添加标题行调试日志 + LOGGER.info("数据文件标题行包含 {} 列", headers.length); + LOGGER.debug("完整标题行: {}", String.join("|", headers)); + + Map columnIndices = new HashMap<>(); + + // 3. 查找列索引(修复后的逻辑) + for (int i = 0; i < headers.length; i++) { + String header = headers[i].trim(); + + // 使用 equalsIgnoreCase 进行不区分大小写的匹配 + if (header.equalsIgnoreCase(timeColumn)) { + columnIndices.put("time", i); + LOGGER.info("找到 time 列 '{}' 在位置 {}", header, i); + } + if (header.equalsIgnoreCase(lonColumn)) { + columnIndices.put("lon", i); + LOGGER.info("找到 lon 列 '{}' 在位置 {}", header, i); + } + if (header.equalsIgnoreCase(latColumn)) { + columnIndices.put("lat", i); + LOGGER.info("找到 lat 列 '{}' 在位置 {}", header, i); + } + if (header.equalsIgnoreCase(hgtColumn)) { + columnIndices.put("hgt", i); + LOGGER.info("找到 hgt 列 '{}' 在位置 {}", header, i); + } + } + + // 4. 验证列是否存在 + List missingColumns = new ArrayList<>(); + if (!columnIndices.containsKey("time")) missingColumns.add(timeColumn); + if (!columnIndices.containsKey("lon")) missingColumns.add(lonColumn); + if (!columnIndices.containsKey("lat")) missingColumns.add(latColumn); + if (!columnIndices.containsKey("hgt")) missingColumns.add(hgtColumn); + + if (!missingColumns.isEmpty()) { + LOGGER.error("以下列在数据文件中不存在: {}", String.join(", ", missingColumns)); + LOGGER.error("数据文件标题行: {}", headerLine); + return; + } + + int timeIndex = columnIndices.get("time"); + int lonIndex = columnIndices.get("lon"); + int latIndex = columnIndices.get("lat"); + int hgtIndex = columnIndices.get("hgt"); + + LOGGER.info("列索引: time={}, lon={}, lat={}, hgt={}", + timeIndex, lonIndex, latIndex, hgtIndex); + + // 5. 读取并处理数据行 + String line; + int lineCount = 0; + + int lineCountData = 0; + + float timeValue0 = 0; + float timeValue1 = 0; + int result = 0; // + + while (!Thread.currentThread().isInterrupted() && (line = reader.readLine()) != null) { + lineCountData++; + if (lineCountData > 2) { + break; // 跳出循环,停止读取数据 + } + // 使用逗号分隔数据行 + String[] values = line.split(","); // 改为逗号分隔 + if (lineCountData == 1) { + // 读取第一行的时间值 + timeValue0 = Float.parseFloat(getValueSafely(values, timeIndex, "0.0")); // 将字符串转换为数字 + } else if (lineCountData == 2) { + // 读取第二行的时间值 + timeValue1 = Float.parseFloat(getValueSafely(values, timeIndex, "0.0")); // 将字符串转换为数字 + // 计算 timeValue1 - timeValue0 + float data = timeValue1 - timeValue0; + // 计算 1 / data + if (data != 0) { // 确保避免除以零 + result = (int) Math.floor(1 / data); + } else { + result = 1; + } + } + } + + + + + while (!Thread.currentThread().isInterrupted() && (line = reader.readLine()) != null) { + lineCount++; + // 使用逗号分隔数据行 + String[] values = line.split(","); // 改为逗号分隔 + + if (lineCount > 1 && (lineCount - 1) % (samTimes * result) != 0) { + continue; + } + + + + // 检查数据完整性 + int maxIndex = getMaxIndex(timeIndex, lonIndex, latIndex, hgtIndex); + if (values.length <= maxIndex) { + LOGGER.warn("行 {} 数据不完整: {}", lineCount, line); + continue; + } + + // 发送数据 + sendDataCsv(token, values, lineCount, timeIndex, lonIndex, latIndex, hgtIndex); + + // 每次发送后都休眠3秒 + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + break; + } + } + + if (!Thread.currentThread().isInterrupted()) { + LOGGER.info("文件处理完成,共处理 {} 行", lineCount); + } + } + } + + // 辅助方法:获取最大索引 + private int getMaxIndex(int... indices) { + int max = -1; + for (int index : indices) { + if (index > max) max = index; + } + return max; + } + + + private void sendDataCsv(String token, String[] values, int lineCount, + int timeIndex, int lonIndex, int latIndex, int hgtIndex) { + if (Thread.currentThread().isInterrupted()) { + return; + } + + try { + SimpleNaviData data = new SimpleNaviData(); + data.setUtcTime(getValueSafely(values, timeIndex, "0.0")); + data.setLon(getValueSafely(values, lonIndex, "0.0")); + data.setLat(getValueSafely(values, latIndex, "0.0")); + data.setAlt(getValueSafely(values, hgtIndex, "0.0")); + + String jsonData = JSONUtil.toJsonStr(data); + ServerSendEventServer.sendMessageById(token, jsonData); + LOGGER.info("Line {} sent at: {}", lineCount, System.currentTimeMillis()); + } catch (Exception e) { + LOGGER.error("发送数据失败: {}", e.getMessage()); + if (e.getCause() instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } + } + } + + + + + /** * 查询文件内容接口 * @@ -5556,7 +5860,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl TsTask tsTask = tsTaskMapper.selectById(taskId); TableNameContextHolder.setTaskCode(tsTask.getTaskCode()); - StorageSourceConfig config = getStorageSourceConfig("filePath", "local",tsTask.getLocalStorageId()); + StorageSourceConfig config = getStorageSourceConfig("filePath", "local", tsTask.getLocalStorageId()); TsFiles tsFiles = tsFilesMapper.selectById(id); // 1. 路径标准化与安全校验 Path targetPath = validateAndNormalizePath(config.getValue() + tsFiles.getWorkPath() + tsFiles.getFileName(), tsTask); @@ -5585,7 +5889,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl * 验证路径是否合法并转换为标准化路径 */ private Path validateAndNormalizePath(String filePath, TsTask tsTask) throws SecurityException { - StorageSourceConfig config = getStorageSourceConfig("filePath", "local",tsTask.getLocalStorageId()); + StorageSourceConfig config = getStorageSourceConfig("filePath", "local", tsTask.getLocalStorageId()); Path targetPath = Paths.get(filePath).normalize(); Path baseDirPath = Paths.get(config.getValue()); @@ -5617,10 +5921,10 @@ public class TsFilesServiceImpl extends ServiceImpl impl TsTask tsTask = tsTaskMapper.selectById(taskId); TableNameContextHolder.setTaskCode(tsTask.getTaskCode()); TsFiles tsFiles = tsFilesMapper.selectById(id); - StorageSourceConfig config = getStorageSourceConfig("filePath", "local",tsTask.getLocalStorageId()); + StorageSourceConfig config = getStorageSourceConfig("filePath", "local", tsTask.getLocalStorageId()); // 1. 路径标准化与安全校验 - Path targetPath = validateAndNormalizePath(config.getValue() + tsFiles.getWorkPath() + tsFiles.getFileName(),tsTask); + Path targetPath = validateAndNormalizePath(config.getValue() + tsFiles.getWorkPath() + tsFiles.getFileName(), tsTask); // 2. 确保父目录存在 Path parentDir = targetPath.getParent(); if (parentDir != null && !Files.exists(parentDir)) { @@ -5650,7 +5954,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl TsTask tsTask = tsTaskMapper.selectById(taskId); TableNameContextHolder.setTaskCode(tsTask.getTaskCode()); TsFiles tsFile = tsFilesMapper.selectById(id); - StorageSourceConfig config = getStorageSourceConfig("filePath", "local",tsTask.getLocalStorageId()); + StorageSourceConfig config = getStorageSourceConfig("filePath", "local", tsTask.getLocalStorageId()); if (tsFile == null) { throw new IllegalArgumentException("文件ID不存在: " + id); } @@ -5871,19 +6175,175 @@ public class TsFilesServiceImpl extends ServiceImpl impl } ServerSendEventServer.removeUser(token); } + // 辅助方法:获取存储配置 - private StorageSource getStorageConfig( Integer id) { + private StorageSource getStorageConfig(Integer id) { return storageSourceMapper.selectOne(new LambdaQueryWrapper().eq(StorageSource::getId, id) ); } // 辅助方法:获取存储配置 - private StorageSourceConfig getStorageSourceConfig(String name, String type,Integer id) { + private StorageSourceConfig getStorageSourceConfig(String name, String type, Integer id) { return storageSourceConfigMapper.selectOne( - new LambdaQueryWrapper().eq(StorageSourceConfig::getName, name).eq(StorageSourceConfig::getType, type).eq(StorageSourceConfig::getStorageId,id) + new LambdaQueryWrapper().eq(StorageSourceConfig::getName, name).eq(StorageSourceConfig::getType, type).eq(StorageSourceConfig::getStorageId, id) ); } + /********************************** + * 用途说明: 通过文件ID获取对应的txt集合和png集合 + * 参数说明 id 文件夹ID + * 参数说明 taskId 任务ID + * 参数说明 nodeId 节点ID + * 返回值说明: com.yfd.platform.config.ResponseResult 返回文件集合列表 + ***********************************/ + @Override + public Object listTsFilesById(String id, String taskId, String nodeId) { + + try { + TrajectoriesDto trajectoriesDto = new TrajectoriesDto(); + + //图片集合 + List tsFilesListPng = new ArrayList<>(); + //txt集合 + List tsFilesListTxt = new ArrayList<>(); + //config集合 + List tsFilesListConfig = new ArrayList<>(); + + //1:动态表名 以及通过ID查询tsfiles 然后根据id path taskId nodeid 等等条件查询所欲的集合 + TsTask tsTask = tsTaskMapper.selectById(taskId); + TableNameContextHolder.setTaskCode(tsTask.getTaskCode()); + TsFiles tsFile = tsFilesMapper.selectById(id); + if (tsFile == null) { + return new ArrayList<>(); + } + + LambdaQueryWrapper queryWrapperPng = new LambdaQueryWrapper<>(); + queryWrapperPng.eq(TsFiles::getTaskId, taskId) + .eq(TsFiles::getNodeId, nodeId) + .eq(TsFiles::getWorkPath, tsFile.getWorkPath()) + .eq(TsFiles::getParentId, tsFile.getParentId()) + .eq(TsFiles::getIsFile, "FILE") + // 图片文件类型:匹配多种图片格式 + .and(wrapper -> wrapper + .likeLeft(TsFiles::getFileName, ".png") + .or().likeLeft(TsFiles::getFileName, ".jpg") + .or().likeLeft(TsFiles::getFileName, ".jpeg") + ); + List listTsFilesPng = tsFilesMapper.selectList(queryWrapperPng); + if (listTsFilesPng == null) { + trajectoriesDto.setTsFilesListPng(new ArrayList<>()); + }else { + for (TsFiles tsFiles1 : listTsFilesPng) { + FileItemResult fileItemResult = new FileItemResult(); + //获取图片url + String fileNameData = tsFiles1.getFileName(); + String path = ""; + StorageSource storageSourceLocal = null; + storageSourceLocal = getStorageConfig(tsTask.getLocalStorageId()); + String workPath = tsFiles1.getWorkPath(); + path = workPath + fileNameData; + //准备获取文件的信息 + AbstractBaseFileService fileService = storageSourceContext.getByStorageKey(storageSourceLocal.getKey()); + fileItemResult = fileService.getFileItem(path); + tsFiles1.setUrl(fileItemResult.getUrl()); + tsFilesListPng.add(tsFiles1); + } + trajectoriesDto.setTsFilesListPng(listTsFilesPng); + } + + + LambdaQueryWrapper queryWrapperTxt = new LambdaQueryWrapper<>(); + queryWrapperTxt.eq(TsFiles::getTaskId, taskId) + .eq(TsFiles::getNodeId, nodeId) + .eq(TsFiles::getWorkPath, tsFile.getWorkPath()) + .eq(TsFiles::getParentId, tsFile.getParentId()) + .eq(TsFiles::getIsFile, "FILE") + //地图的四个角的经纬度 + .like(TsFiles::getFileName, "maps") + .likeLeft(TsFiles::getFileName, ".txt"); + List listTsFilesTxt = tsFilesMapper.selectList(queryWrapperTxt); + if (listTsFilesTxt == null) { + trajectoriesDto.setTsFilesListTxt(new ArrayList<>()); + }else{ + for (TsFiles tsFiles1 : listTsFilesTxt) { + //读物文件内容 + StorageSourceConfig config = getStorageSourceConfig("filePath", "local", tsTask.getLocalStorageId()); + // 1. 路径标准化与安全校验 + Path targetPath = validateAndNormalizePath(config.getValue() + tsFiles1.getWorkPath() + tsFiles1.getFileName(), tsTask); + try { + // 高效读取第一行 + String firstLine = readFirstLine(targetPath.toString()); + // 处理内容 + String result = processMapContent(firstLine); + tsFiles1.setFileContent(result); + System.out.println("拼接结果: " + result); + } catch (IOException e) { + System.err.println("文件错误: " + e.getMessage()); + } catch (IllegalArgumentException e) { + System.err.println("内容错误: " + e.getMessage()); + } + tsFilesListTxt.add(tsFiles1); + } + trajectoriesDto.setTsFilesListTxt(listTsFilesTxt); + } + + LambdaQueryWrapper queryWrapperConfig = new LambdaQueryWrapper<>(); + queryWrapperConfig.eq(TsFiles::getTaskId, taskId) + .eq(TsFiles::getNodeId, nodeId) + .eq(TsFiles::getWorkPath, tsFile.getWorkPath()) + .eq(TsFiles::getParentId, tsFile.getParentId()) + .eq(TsFiles::getIsFile, "FILE") + //配置文件 + .like(TsFiles::getFileName, "config") + .likeLeft(TsFiles::getFileName, ".txt"); + List listTsFilesConfig = tsFilesMapper.selectList(queryWrapperConfig); + if (listTsFilesConfig == null) { + trajectoriesDto.setTsFilesListConfig(new ArrayList<>()); + }else { + for (TsFiles tsFiles1 : listTsFilesConfig) { + tsFilesListConfig.add(tsFiles1); + } + trajectoriesDto.setTsFilesListConfig(listTsFilesConfig); + } + + //3:返回对应的数据 + return trajectoriesDto; + } catch (Exception e) { + LOGGER.error("未知异常:{}", e.getMessage(), e); + throw new RuntimeException("系统错误,请联系管理员"); + } finally { + TableNameContextHolder.clear(); + } + } + + private static String readFirstLine(String filePath) throws IOException { + Path path = Paths.get(filePath); + if (!Files.exists(path)) { + throw new IOException("文件不存在: " + filePath); + } + + try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) { + return reader.readLine(); // 可能返回 null + } + } + + private static String processMapContent(String content) { + if (content == null || content.trim().isEmpty()) { + throw new IllegalArgumentException("内容为空"); + } + // 分割字符串(处理任意空白) + String[] parts = content.trim().split("\\s+"); + + if (parts.length < 4) { + throw new IllegalArgumentException("需要至少4个坐标值"); + } + // 高效拼接 + return String.format("%s,%s,%s,%s", parts[0], parts[1], parts[2], parts[3]); + } + + + + }