feat(测试计划): 手动生成报告查询及富文本内容编辑

This commit is contained in:
song-cc-rock 2024-07-05 16:00:54 +08:00 committed by 刘瑞斌
parent e1c24fa53f
commit 2ab3faff7e
8 changed files with 106 additions and 16 deletions

View File

@ -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;
}

View File

@ -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<TestPlanReportComponent> 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)

View File

@ -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<TestPlanReportComponent> 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) {

View File

@ -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<String> richTextTmpFileIds;

View File

@ -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 {
}

View File

@ -79,4 +79,10 @@ public class TestPlanReportDetailResponse {
private boolean deleted;
@Schema(description = "报告状态")
private String resultStatus;
/**
* 报告布局
*/
@Schema(description = "报告是否默认布局")
private Boolean defaultLayout;
}

View File

@ -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<String, String> 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<TestPlanReportComponent> 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());

View File

@ -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();
}
}