diff --git a/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java b/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java index ccea652c..3f7f4e1f 100644 --- a/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java +++ b/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java @@ -87,6 +87,7 @@ import java.nio.file.StandardCopyOption; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.stream.Collectors; @@ -1832,126 +1833,218 @@ public class SimulationRunServiceImpl extends ServiceImpl reportResponse = reportFeignClient.queryReportTemplateInfo(req.getReportTemplate()); - if (reportResponse.isSuccess()) { - Long reportTemplateFileId = reportResponse.getData().getFileId(); - // 获取报告模板名称 - GetFileBaseInfoReq getFileBaseInfoReq = new GetFileBaseInfoReq(); - getFileBaseInfoReq.setFileId(reportTemplateFileId); - SdmResponse fileBaseInfoResp = dataFeignClient.getFileBaseInfo(getFileBaseInfoReq); - String originalName = fileBaseInfoResp.getData().getOriginalName(); - // 下载到本地临时目录 - dataFeignClient.downloadFileToLocal(reportTemplateFileId, TEMP_REPORT_PATH + randomId); + /** + * 准备报告模板(获取模板信息并下载到临时目录) + */ + private String prepareReportTemplate(String reportTemplateId, String randomId) { + SdmResponse reportResponse = reportFeignClient.queryReportTemplateInfo(reportTemplateId); + if (!reportResponse.isSuccess()) { + return null; + } + Long reportTemplateFileId = reportResponse.getData().getFileId(); + GetFileBaseInfoReq getFileBaseInfoReq = new GetFileBaseInfoReq(); + getFileBaseInfoReq.setFileId(reportTemplateFileId); + SdmResponse fileBaseInfoResp = dataFeignClient.getFileBaseInfo(getFileBaseInfoReq); + String originalName = fileBaseInfoResp.getData().getOriginalName(); + dataFeignClient.downloadFileToLocal(reportTemplateFileId, TEMP_REPORT_PATH + randomId); + return originalName; + } - String reportName = "report_" + - LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + - ".docx"; + /** + * 生成报告文件名 + * @param taskName 任务名称,用作报告文件名前缀 + */ + private String generateReportName(String taskName) { + String prefix = StringUtils.isNotEmpty(taskName) ? taskName : "report"; + return prefix + "_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + ".docx"; + } - // 构建python命令 - List command = new ArrayList<>(); - command.add("python"); - command.add("/opt/script/modifyReport.py"); -// command.add(TEMP_REPORT_PATH + File.separator +"modifyReport.py"); - command.add(TEMP_REPORT_PATH + randomId); - command.add(TEMP_REPORT_PATH + randomId + File.separator + originalName); - command.add(reportName); - String commands = String.join(" ", command); + /** + * 构建修改报告的Python命令 + */ + private String buildModifyReportCommand(String randomId, String originalName, String reportName) { + List command = new ArrayList<>(); + command.add("python"); + command.add("/opt/script/modifyReport.py"); + command.add(TEMP_REPORT_PATH + randomId); + command.add(TEMP_REPORT_PATH + randomId + File.separator + originalName); + command.add(reportName); + return String.join(" ", command); + } - // 前端参数写入临时目录 - FileOutputStream projectInfoOutputStream = null; - try { - projectInfoOutputStream = new FileOutputStream(TEMP_REPORT_PATH + randomId + File.separator + "reportContent.json"); - projectInfoOutputStream.write(reportContent.getBytes(StandardCharsets.UTF_8)); - projectInfoOutputStream.flush(); - projectInfoOutputStream.close(); - } catch (Exception e) { - throw new RuntimeException(e); - } - - // 调用脚本 - log.info("执行 Python 命令: {}", commands); - int runningStatus = -1; - try { - log.info("开始同步执行脚本"); - Process process = Runtime.getRuntime().exec(commands); - log.info("开始获取脚本输出"); - BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - String line; - while ((line = reader.readLine()) != null) { - log.info("executePython:" + line); - } - log.info("脚本执行完成"); - runningStatus = process.waitFor(); - log.info("脚本运行状态:" + runningStatus); - } catch (IOException | InterruptedException e) { - log.error("执行脚本失败:" + e); - return SdmResponse.failed("执行脚本失败"); + /** + * 写入报告内容JSON到临时目录 + */ + private void writeReportContentJson(String randomId, String reportContent) { + try (FileOutputStream outputStream = new FileOutputStream(TEMP_REPORT_PATH + randomId + File.separator + "reportContent.json")) { + outputStream.write(reportContent.getBytes(StandardCharsets.UTF_8)); + outputStream.flush(); + } catch (Exception e) { + throw new RuntimeException("写入报告内容失败", e); + } + } + + /** + * 执行Python脚本(带5秒超时) + */ + private SdmResponse executePythonScriptWithTimeout(String commands) { + log.info("执行 Python 命令: {}", commands); + Process process = null; + try { + log.info("开始同步执行脚本"); + process = Runtime.getRuntime().exec(commands); + boolean finished = process.waitFor(5, TimeUnit.SECONDS); + if (!finished) { + log.error("脚本执行超时,超过5秒未完成"); + process.destroyForcibly(); + return SdmResponse.failed("脚本执行超时,请稍后重试"); } + int runningStatus = process.exitValue(); + log.info("脚本运行状态:" + runningStatus); if (runningStatus != 0) { log.error("执行脚本失败"); return SdmResponse.failed("执行脚本失败"); - } else { - log.info(commands + "执行脚本完成!"); - } - - // 读取脚本生成的报告并归档 - archiveReportAndImage(reportName, req.getTaskId(), req.getRunId(), randomId, FileBizTypeEnum.REPORT_FILE, null, null); - - // 读取脚本生成的图片并按顺序归档 - List imageNames = extractPicNames(reportContent); - if (CollectionUtils.isNotEmpty(imageNames)) { - int sortOrder = 1; - for (String imageName : imageNames) { - archiveReportAndImage(null, req.getTaskId(), req.getRunId(), randomId, FileBizTypeEnum.CLOUD_FILE, imageName, sortOrder++); - } } + log.info(commands + " 执行脚本完成!"); return SdmResponse.success(); - // 删除临时路径 -// log.info("删除临时路径:{},中。。。。。。", randomId); -// deleteFolder(new File(TEMP_REPORT_PATH + randomId)); + } catch (IOException e) { + log.error("执行脚本失败:" + e); + return SdmResponse.failed("执行脚本失败"); + } catch (InterruptedException e) { + log.error("脚本执行被中断:" + e); + Thread.currentThread().interrupt(); + return SdmResponse.failed("脚本执行被中断"); + } finally { + if (process != null) { + process.destroy(); + } } - return SdmResponse.failed("生成自动化报告失败"); } + /** + * 归档生成的报告和图片 + */ + private void archiveGeneratedReport(String reportName, String taskId, String runId, String randomId, String reportContent) { + // 归档报告文件 + archiveReportAndImage(reportName, taskId, runId, randomId, FileBizTypeEnum.REPORT_FILE, null, null); + + // 归档图片 + List imageNames = extractPicNames(reportContent); + if (CollectionUtils.isNotEmpty(imageNames)) { + int sortOrder = 1; + for (String imageName : imageNames) { + archiveReportAndImage(null, taskId, runId, randomId, FileBizTypeEnum.CLOUD_FILE, imageName, sortOrder++); + } + } + } + + /** + * 下载报告文件到响应流 + */ + private void downloadReportFile(String reportName, String randomId, HttpServletResponse response) { + try (FileInputStream fileInputStream = new FileInputStream(TEMP_REPORT_PATH + randomId + File.separator + reportName)) { + byte[] fileData = fileInputStream.readAllBytes(); + + response.reset(); + response.setContentType("application/octet-stream;charset=UTF-8"); + response.addHeader("Content-Length", String.valueOf(fileData.length)); + + OutputStream outputStream = response.getOutputStream(); + outputStream.write(fileData); + outputStream.flush(); + } catch (Exception ex) { + log.error("下载报告文件失败:{}", ex.getMessage()); + throw new RuntimeException("下载报告文件失败"); + } + } + + // ==================== 原有私有方法 ==================== + private void archiveReportAndImage(String reportName, String taskId, String runId, String randomId, FileBizTypeEnum fileBizTypeEnum, String imageName, Integer sortOrder) { byte[] fileData = null; try { @@ -2161,144 +2254,40 @@ public class SimulationRunServiceImpl extends ServiceImpl reportResponse = reportFeignClient.queryReportTemplateInfo(req.getReportTemplate()); - if (reportResponse.isSuccess()) { - Long reportTemplateFileId = reportResponse.getData().getFileId(); - // 获取报告模板名称 - GetFileBaseInfoReq getFileBaseInfoReq = new GetFileBaseInfoReq(); - getFileBaseInfoReq.setFileId(reportTemplateFileId); - SdmResponse fileBaseInfoResp = dataFeignClient.getFileBaseInfo(getFileBaseInfoReq); - String originalName = fileBaseInfoResp.getData().getOriginalName(); - // 下载到本地临时目录 - dataFeignClient.downloadFileToLocal(reportTemplateFileId, TEMP_REPORT_PATH + randomId); - - String reportName = "report_" + - LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + - ".docx"; - - // 构建python命令 - List command = new ArrayList<>(); - command.add("python"); - command.add("/opt/script/modifyReport.py"); -// command.add(TEMP_REPORT_PATH + File.separator +"modifyReport.py"); - command.add(TEMP_REPORT_PATH + randomId); - command.add(TEMP_REPORT_PATH + randomId + File.separator + originalName); - command.add(reportName); - String commands = String.join(" ", command); - - // 前端参数写入临时目录 - FileOutputStream projectInfoOutputStream = null; - try { - projectInfoOutputStream = new FileOutputStream(TEMP_REPORT_PATH + randomId + File.separator + "reportContent.json"); - projectInfoOutputStream.write(reportContent.getBytes(StandardCharsets.UTF_8)); - projectInfoOutputStream.flush(); - projectInfoOutputStream.close(); - } catch (Exception e) { - throw new RuntimeException(e); - } - - // 调用脚本 - log.info("执行 Python 命令: {}", commands); - int runningStatus = -1; - try { - log.info("开始同步执行脚本"); - Process process = Runtime.getRuntime().exec(commands); - log.info("开始获取脚本输出"); - BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - String line; - while ((line = reader.readLine()) != null) { - log.info("executePython:" + line); - } - log.info("脚本执行完成"); - runningStatus = process.waitFor(); - log.info("脚本运行状态:" + runningStatus); - } catch (IOException | InterruptedException e) { - log.error("执行脚本失败:" + e); - return; - } - if (runningStatus != 0) { - log.error("执行脚本失败"); - return; - } else { - log.info(commands + "执行脚本完成!"); - } - byte[] fileData = null; - if (response != null) { - try { - // 读取脚本生成的报告并归档 - archiveReportAndImage(reportName, req.getTaskId(), req.getRunId(), randomId, FileBizTypeEnum.REPORT_FILE, null, null); - - // 读取脚本生成的图片并按顺序归档 - List imageNames = extractPicNames(reportContent); - if (CollectionUtils.isNotEmpty(imageNames)) { - int sortOrder = 1; - for (String imageName : imageNames) { - archiveReportAndImage(null, req.getTaskId(), req.getRunId(), randomId, FileBizTypeEnum.CLOUD_FILE, imageName, sortOrder++); - } - } - - FileInputStream fileInputStream = new FileInputStream(TEMP_REPORT_PATH + randomId + File.separator + reportName); - fileData = fileInputStream.readAllBytes(); - - // 下载到本地 - // 设置响应头 - response.reset(); - response.setContentType("application/octet-stream;charset=UTF-8"); - response.addHeader("Content-Length", String.valueOf(fileData.length)); - // 写入响应流 - OutputStream outputStream = response.getOutputStream(); - outputStream.write(fileData); - outputStream.flush(); - outputStream.close(); - fileInputStream.close(); - } catch (Exception ex) { - log.error("生成自动化报告失败:{}", ex.getMessage()); - throw new RuntimeException("生成自动化报告失败"); - } - } - // 删除临时路径 -// log.info("删除临时路径:{},中。。。。。。", randomId); -// deleteFolder(new File(TEMP_REPORT_PATH + randomId)); + // 3. 准备报告模板 + String originalName = prepareReportTemplate(req.getReportTemplate(), randomId); + if (originalName == null) { + throw new RuntimeException("获取报告模板失败"); } + + // 4. 生成报告名称(使用任务名称作为前缀) + String reportName = generateReportName(taskName); + + // 5. 构建并执行Python脚本 + String commands = buildModifyReportCommand(randomId, originalName, reportName); + writeReportContentJson(randomId, reportContent); + + SdmResponse executeResult = executePythonScriptWithTimeout(commands); + if (!executeResult.isSuccess()) { + throw new RuntimeException(executeResult.getMessage()); + } + + // 6. 归档报告和图片 + archiveGeneratedReport(reportName, req.getTaskId(), req.getRunId(), randomId, reportContent); + + // 7. 下载报告文件 + downloadReportFile(reportName, randomId, response); } @Override diff --git a/project/src/main/java/com/sdm/project/service/impl/TaskServiceImpl.java b/project/src/main/java/com/sdm/project/service/impl/TaskServiceImpl.java index 00cf0250..efd0aa42 100644 --- a/project/src/main/java/com/sdm/project/service/impl/TaskServiceImpl.java +++ b/project/src/main/java/com/sdm/project/service/impl/TaskServiceImpl.java @@ -3166,6 +3166,7 @@ public class TaskServiceImpl implements ITaskService { } taskVo.setNodeName(taskVo.getTaskName()); taskVo.setNodeType("task"); + taskVo.setNodeCode(taskVo.getTaskCode()); List memberList = mapper.getMemberList(Collections.singletonList(taskVo.getUuid()), null); if (CollectionUtils.isNotEmpty(memberList)) { List userIdList = memberList.stream().map(SpdmTaskMemberVo::getUserId).toList();