From 2ab3faff7ee6e4e32575c33279d4b7efe5c6cb8b Mon Sep 17 00:00:00 2001 From: song-cc-rock Date: Fri, 5 Jul 2024 16:00:54 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=B5=8B=E8=AF=95=E8=AE=A1=E5=88=92):=20?= =?UTF-8?q?=E6=89=8B=E5=8A=A8=E7=94=9F=E6=88=90=E6=8A=A5=E5=91=8A=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E5=8F=8A=E5=AF=8C=E6=96=87=E6=9C=AC=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E7=BC=96=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sdk/util/FilterChainUtils.java | 1 + .../controller/TestPlanReportController.java | 19 +++++++--- .../TestPlanReportShareController.java | 9 +++++ .../TestPlanReportDetailEditRequest.java | 7 ++-- .../TestPlanReportComponentResponse.java | 9 +++++ .../TestPlanReportDetailResponse.java | 6 ++++ .../plan/service/TestPlanReportService.java | 36 ++++++++++++++----- .../TestPlanReportControllerTests.java | 35 +++++++++++++++++- 8 files changed, 106 insertions(+), 16 deletions(-) create mode 100644 backend/services/test-plan/src/main/java/io/metersphere/plan/dto/response/TestPlanReportComponentResponse.java diff --git a/backend/framework/sdk/src/main/java/io/metersphere/sdk/util/FilterChainUtils.java b/backend/framework/sdk/src/main/java/io/metersphere/sdk/util/FilterChainUtils.java index 680925e6b4..66c8f2426e 100644 --- a/backend/framework/sdk/src/main/java/io/metersphere/sdk/util/FilterChainUtils.java +++ b/backend/framework/sdk/src/main/java/io/metersphere/sdk/util/FilterChainUtils.java @@ -97,6 +97,7 @@ public class FilterChainUtils { // 测试计划报告分享接口 filterChainDefinitionMap.put("/test-plan/report/share/detail/**", "anon"); filterChainDefinitionMap.put("/test-plan/report/share/get/**", "anon"); + filterChainDefinitionMap.put("/test-plan/report/share/get-layout/**", "anon"); return filterChainDefinitionMap; } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanReportController.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanReportController.java index 6b88198dfe..1a7a015752 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanReportController.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanReportController.java @@ -6,6 +6,7 @@ import io.metersphere.bug.dto.response.BugDTO; import io.metersphere.bug.service.BugAttachmentService; import io.metersphere.plan.constants.AssociateCaseType; import io.metersphere.plan.constants.TestPlanResourceConfig; +import io.metersphere.plan.domain.TestPlanReportComponent; import io.metersphere.plan.dto.ReportDetailCasePageDTO; import io.metersphere.plan.dto.request.*; import io.metersphere.plan.dto.response.TestPlanCaseExecHistoryResponse; @@ -91,18 +92,18 @@ public class TestPlanReportController { @Operation(summary = "测试计划-详情-手动生成报告") @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_EXECUTE) @CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan") - public void genReportByManual(@Validated @RequestBody TestPlanReportManualRequest request) { + public String genReportByManual(@Validated @RequestBody TestPlanReportManualRequest request) { testPlanService.checkTestPlanNotArchived(request.getTestPlanId()); - testPlanReportService.genReportByManual(request, SessionUtils.getUserId()); + return testPlanReportService.genReportByManual(request, SessionUtils.getUserId()); } @PostMapping("/auto-gen") @Operation(summary = "测试计划-详情-自动生成报告") @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_EXECUTE) @CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan") - public void genReportByAuto(@Validated @RequestBody TestPlanReportGenRequest request) { + public String genReportByAuto(@Validated @RequestBody TestPlanReportGenRequest request) { testPlanService.checkTestPlanNotArchived(request.getTestPlanId()); - testPlanReportService.genReportByAuto(request, SessionUtils.getUserId()); + return testPlanReportService.genReportByAuto(request, SessionUtils.getUserId()); } // 报告详情开始 @@ -115,6 +116,14 @@ public class TestPlanReportController { return testPlanReportService.getReport(reportId); } + @GetMapping("/get-layout/{reportId}") + @Operation(summary = "测试计划-报告-组件布局") + @RequiresPermissions(value = {PermissionConstants.TEST_PLAN_REPORT_READ, PermissionConstants.TEST_PLAN_READ_EXECUTE}, logical = Logical.OR) + @CheckOwner(resourceId = "#reportId", resourceType = "test_plan_report") + public List getLayout(@PathVariable String reportId) { + return testPlanReportService.getLayout(reportId); + } + @PostMapping("/upload/md/file") @Operation(summary = "测试计划-报告-详情-上传富文本(图片)") @RequiresPermissions(PermissionConstants.TEST_PLAN_REPORT_READ_UPDATE) @@ -123,7 +132,7 @@ public class TestPlanReportController { } @PostMapping("/detail/edit") - @Operation(summary = "测试计划-报告-详情-报告内容更新") + @Operation(summary = "测试计划-报告-详情-富文本组件内容更新") @RequiresPermissions(PermissionConstants.TEST_PLAN_REPORT_READ_UPDATE) @CheckOwner(resourceId = "#request.getId()", resourceType = "test_plan_report") @Log(type = OperationLogType.UPDATE, expression = "#msClass.updateDetailLog(#request)", msClass = TestPlanReportLogService.class) diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanReportShareController.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanReportShareController.java index 9062299ce6..c17c7fb8bf 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanReportShareController.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanReportShareController.java @@ -10,6 +10,7 @@ import io.metersphere.api.service.definition.ApiReportService; import io.metersphere.api.service.scenario.ApiScenarioReportService; import io.metersphere.bug.dto.response.BugDTO; import io.metersphere.plan.constants.AssociateCaseType; +import io.metersphere.plan.domain.TestPlanReportComponent; import io.metersphere.plan.dto.ReportDetailCasePageDTO; import io.metersphere.plan.dto.TestPlanShareInfo; import io.metersphere.plan.dto.request.TestPlanReportShareRequest; @@ -71,6 +72,14 @@ public class TestPlanReportShareController { // 分享报告详情开始 + @GetMapping("/get-layout/{shareId}/{reportId}") + @Operation(summary = "测试计划-报告-组件布局") + public List getLayout(@PathVariable String shareId, @PathVariable String reportId) { + ShareInfo shareInfo = testPlanReportShareService.checkResource(shareId); + testPlanReportShareService.validateExpired(shareInfo); + return testPlanReportService.getLayout(reportId); + } + @GetMapping("/get/detail/{shareId}/{reportId}") @Operation(summary = "测试计划-报告分享-详情查看") public TestPlanReportDetailResponse getDetail(@PathVariable String shareId, @PathVariable String reportId) { diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanReportDetailEditRequest.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanReportDetailEditRequest.java index 58d62215ea..53afad58cc 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanReportDetailEditRequest.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanReportDetailEditRequest.java @@ -13,8 +13,11 @@ public class TestPlanReportDetailEditRequest { @NotBlank(message = "{test_plan_report_id.not_blank}") private String id; - @Schema(description = "报告内容") - private String summary; + @Schema(description = "组件ID; {默认布局时使用报告总结枚举值作为ID}") + private String componentId; + + @Schema(description = "报告总结") + private String componentValue; @Schema(description = "富文本临时文件ID(图片)") private List richTextTmpFileIds; diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/response/TestPlanReportComponentResponse.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/response/TestPlanReportComponentResponse.java new file mode 100644 index 0000000000..7f642f3b39 --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/response/TestPlanReportComponentResponse.java @@ -0,0 +1,9 @@ +package io.metersphere.plan.dto.response; + +import io.metersphere.plan.domain.TestPlanReportComponent; +import lombok.Data; + +@Data +public class TestPlanReportComponentResponse extends TestPlanReportComponent { + +} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/response/TestPlanReportDetailResponse.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/response/TestPlanReportDetailResponse.java index 7346a0e9f1..82f867c084 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/response/TestPlanReportDetailResponse.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/response/TestPlanReportDetailResponse.java @@ -79,4 +79,10 @@ public class TestPlanReportDetailResponse { private boolean deleted; @Schema(description = "报告状态") private String resultStatus; + + /** + * 报告布局 + */ + @Schema(description = "报告是否默认布局") + private Boolean defaultLayout; } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanReportService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanReportService.java index 1c92009aa6..f3ae835ca9 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanReportService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanReportService.java @@ -102,6 +102,8 @@ public class TestPlanReportService { private TestPlanSendNoticeService testPlanSendNoticeService; @Resource private ExtTestPlanCaseExecuteHistoryMapper extTestPlanCaseExecuteHistoryMapper; + @Resource + private TestPlanReportComponentMapper componentMapper; /** * 分页查询报告列表 @@ -226,7 +228,7 @@ public class TestPlanReportService { * @param request 请求参数 * @param currentUser 当前用户 */ - public void genReportByManual(TestPlanReportManualRequest request, String currentUser) { + public String genReportByManual(TestPlanReportManualRequest request, String currentUser) { /* * 1. 生成报告 (全量生成; 暂不根据布局来选择生成报告预览数据, 因为影响分析汇总) * 2. 保存报告布局组件 (只对当前生成的计划/组有效, 不会对下面的子计划报告生效) @@ -257,6 +259,7 @@ public class TestPlanReportService { testPlanReportMapper.updateByPrimaryKeySelective(record); // 处理富文本文件 transferRichTextTmpFile(genReportId, request.getProjectId(), request.getRichTextTmpFileIds(), currentUser, TestPlanReportAttachmentSourceType.RICH_TEXT.name()); + return reportMap.get(request.getTestPlanId()); } /** @@ -264,8 +267,9 @@ public class TestPlanReportService { * @param request 请求参数 * @param currentUser 当前用户 */ - public void genReportByAuto(TestPlanReportGenRequest request, String currentUser) { - genReport(IDGenerator.nextStr(), request, true, currentUser, "/test-plan/report/gen"); + public String genReportByAuto(TestPlanReportGenRequest request, String currentUser) { + Map reportMap = genReport(IDGenerator.nextStr(), request, true, currentUser, "/test-plan/report/gen"); + return reportMap.get(request.getTestPlanId()); } /** @@ -595,6 +599,12 @@ public class TestPlanReportService { return planReportDetail; } + public List getLayout(String reportId) { + TestPlanReportComponentExample example = new TestPlanReportComponentExample(); + example.createCriteria().andTestPlanReportIdEqualTo(reportId); + return componentMapper.selectByExample(example); + } + /** * 更新报告详情 * @@ -603,11 +613,21 @@ public class TestPlanReportService { */ public TestPlanReportDetailResponse edit(TestPlanReportDetailEditRequest request, String currentUser) { TestPlanReport planReport = checkReport(request.getId()); - TestPlanReportSummary reportSummary = new TestPlanReportSummary(); - reportSummary.setSummary(StringUtils.isBlank(request.getSummary()) ? StringUtils.EMPTY : request.getSummary()); - TestPlanReportSummaryExample example = new TestPlanReportSummaryExample(); - example.createCriteria().andTestPlanReportIdEqualTo(planReport.getId()); - testPlanReportSummaryMapper.updateByExampleSelective(reportSummary, example); + if (planReport.getDefaultLayout()) { + // 默认布局只存在报告总结 + TestPlanReportSummary reportSummary = new TestPlanReportSummary(); + reportSummary.setSummary(StringUtils.isBlank(request.getComponentValue()) ? StringUtils.EMPTY : request.getComponentValue()); + TestPlanReportSummaryExample example = new TestPlanReportSummaryExample(); + example.createCriteria().andTestPlanReportIdEqualTo(planReport.getId()); + testPlanReportSummaryMapper.updateByExampleSelective(reportSummary, example); + } else { + // 手动生成的布局, 只更新富文本组件的内容 + TestPlanReportComponentExample componentExample = new TestPlanReportComponentExample(); + componentExample.createCriteria().andIdEqualTo(request.getComponentId()); + TestPlanReportComponent record = new TestPlanReportComponent(); + record.setValue(request.getComponentValue()); + componentMapper.updateByExample(record, componentExample); + } // 处理富文本文件 transferRichTextTmpFile(request.getId(), planReport.getProjectId(), request.getRichTextTmpFileIds(), currentUser, TestPlanReportAttachmentSourceType.RICH_TEXT.name()); return getReport(planReport.getId()); diff --git a/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanReportControllerTests.java b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanReportControllerTests.java index d3d5fdc216..c5cd407761 100644 --- a/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanReportControllerTests.java +++ b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanReportControllerTests.java @@ -46,6 +46,7 @@ public class TestPlanReportControllerTests extends BaseTest { private static final String DELETE_PLAN_REPORT = "/test-plan/report/delete"; private static final String BATCH_DELETE_PLAN_REPORT = "/test-plan/report/batch-delete"; private static final String MANUAL_GEN_PLAN_REPORT = "/test-plan/report/manual-gen"; + private static final String GET_MANUAL_PLAN_REPORT_LAYOUT = "/test-plan/report/get-layout"; private static final String AUTO_GEN_PLAN_REPORT = "/test-plan/report/auto-gen"; private static final String GET_PLAN_REPORT = "/test-plan/report/get"; private static final String EDIT_PLAN_REPORT_AND_UPLOAD_PIC = "/test-plan/report/upload/md/file"; @@ -58,6 +59,7 @@ public class TestPlanReportControllerTests extends BaseTest { private static final String GET_PLAN_REPORT_DETAIL_PLAN_PAGE = "/test-plan/report/detail/plan/report/page"; private static final String GEN_AND_SHARE = "/test-plan/report/share/gen"; private static final String GET_SHARE_INFO = "/test-plan/report/share/get"; + private static final String GET_SHARE_REPORT_LAYOUT = "/test-plan/report/share/get-layout"; private static final String GET_SHARE_TIME = "/test-plan/report/share/get-share-time"; private static final String GET_SHARE_REPORT = "/test-plan/report/share/get/detail"; private static final String GET_SHARE_REPORT_BUG_LIST = "/test-plan/report/share/detail/bug/page"; @@ -326,7 +328,7 @@ public class TestPlanReportControllerTests extends BaseTest { void testEditReportDetail() throws Exception { TestPlanReportDetailEditRequest request = new TestPlanReportDetailEditRequest(); request.setId(GEN_REPORT_ID); - request.setSummary("This is a summary for report detail"); + request.setComponentValue("This is a summary for report detail"); this.requestPostWithOk(EDIT_PLAN_REPORT, request); request.setRichTextTmpFileIds(List.of("rich-text-file-id-for-report")); this.requestPost(EDIT_PLAN_REPORT, request, status().is5xxServerError()); @@ -376,6 +378,31 @@ public class TestPlanReportControllerTests extends BaseTest { this.requestPost(MANUAL_GEN_PLAN_REPORT, genRequest); } + @Test + @Order(21) + void testShareOrEditReportByManual() throws Exception { + TestPlanReportShareRequest shareRequest = new TestPlanReportShareRequest(); + shareRequest.setReportId(getManualGenPlanReportId()); + shareRequest.setProjectId("100001100001"); + shareRequest.setShareType(ShareInfoType.TEST_PLAN_SHARE_REPORT.name()); + shareRequest.setLang(Locale.SIMPLIFIED_CHINESE.getLanguage()); + MvcResult mvcResult = this.requestPost(GEN_AND_SHARE, shareRequest).andReturn(); + String sortData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8); + ResultHolder sortHolder = JSON.parseObject(sortData, ResultHolder.class); + TestPlanShareInfo shareInfo = JSON.parseObject(JSON.toJSONString(sortHolder.getData()), TestPlanShareInfo.class); + Assertions.assertNotNull(shareInfo); + this.requestGet(GET_SHARE_INFO + "/" + shareInfo.getId()); + this.requestGet(GET_SHARE_REPORT_LAYOUT + "/" + shareInfo.getId() + "/" + getManualGenPlanReportId()); + + this.requestGet(GET_MANUAL_PLAN_REPORT_LAYOUT + "/" + getManualGenPlanReportId()); + // 编辑手动生成的报告 + TestPlanReportDetailEditRequest request = new TestPlanReportDetailEditRequest(); + request.setId(getManualGenPlanReportId()); + request.setComponentId("component-for-test"); + request.setComponentValue("This is a summary for report detail"); + this.requestPostWithOk(EDIT_PLAN_REPORT, request); + } + @Resource private TestPlanReportSummaryMapper testPlanReportSummaryMapper; @Resource @@ -439,4 +466,10 @@ public class TestPlanReportControllerTests extends BaseTest { example.createCriteria().andTestPlanIdEqualTo("plan_id_for_gen_report"); return testPlanReportMapper.selectByExample(example).getFirst().getId(); } + + private String getManualGenPlanReportId() { + TestPlanReportExample example = new TestPlanReportExample(); + example.createCriteria().andTestPlanIdEqualTo("plan_id_for_gen_report").andDefaultLayoutEqualTo(false); + return testPlanReportMapper.selectByExample(example).get(0).getId(); + } }