feat(用例评审): 新增获取脑图用例的接口

This commit is contained in:
guoyuqi 2024-01-22 16:30:29 +08:00 committed by Craftsman
parent 6ee926c091
commit 362b06cd86
16 changed files with 413 additions and 132 deletions

View File

@ -0,0 +1,29 @@
package io.metersphere.functional.constants;
public enum MinderLabel {
/**
* 用例标签
*/
CASE,
/**
* 模块标签
*/
MODULE,
/**
* 前置条件标签
*/
PREREQUISITE,
/**
* 步骤描述标签
*/
TEXT_DESCRIPTION,
/**
* 预期结果标签
*/
EXPECTED_RESULT,
/**
* 备注标签
*/
DESCRIPTION
}

View File

@ -51,7 +51,7 @@ public class CaseReviewFunctionalCaseController {
@Operation(summary = "用例管理-用例评审-评审列表-评审详情-已关联用例列表")
public Pager<List<ReviewFunctionalCaseDTO>> page(@Validated @RequestBody ReviewFunctionalCasePageRequest request) {
String userId = StringUtils.EMPTY;
if (request.getViewFlag()) {
if (request.isViewFlag()) {
userId = SessionUtils.getUserId();
}
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize());
@ -74,7 +74,7 @@ public class CaseReviewFunctionalCaseController {
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
public Map<String, Long> moduleCount(@Validated @RequestBody ReviewFunctionalCasePageRequest request) {
String userId = StringUtils.EMPTY;
if (request.getViewFlag()) {
if (request.isViewFlag()) {
userId = SessionUtils.getUserId();
}
return caseReviewFunctionalCaseService.moduleCount(request, false, userId);

View File

@ -1,10 +1,13 @@
package io.metersphere.functional.controller;
import com.alibaba.excel.util.StringUtils;
import io.metersphere.functional.dto.FunctionalMinderTreeDTO;
import io.metersphere.functional.request.FunctionalCasePageRequest;
import io.metersphere.functional.request.MinderReviewFunctionalCasePageRequest;
import io.metersphere.functional.service.FunctionalCaseMinderService;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.system.security.CheckOwner;
import io.metersphere.system.utils.SessionUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
@ -34,4 +37,16 @@ public class FunctionalCaseMinderController {
return functionalCaseMinderService.getFunctionalCasePage(request, false);
}
@PostMapping("/review/list")
@Operation(summary = "用例管理-用例评审-脑图用例列表查询")
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_MINDER)
@CheckOwner(resourceId = "#request.getReviewId()", resourceType = "case_review")
public FunctionalMinderTreeDTO getFunctionalReviewCaseMinderTree(@Validated @RequestBody MinderReviewFunctionalCasePageRequest request) {
String userId = StringUtils.EMPTY;
if (request.isViewFlag()) {
userId = SessionUtils.getUserId();
}
return functionalCaseMinderService.getReviewFunctionalCasePage(request, false, userId);
}
}

View File

@ -19,6 +19,9 @@ public class FunctionalMinderTreeNodeDTO {
@Schema(description = "用例等级")
private String priority;
@Schema(description = "用例评审状态")
private String status;
@Schema(description = "节点标签")
private List<String> resource;

View File

@ -0,0 +1,20 @@
package io.metersphere.functional.dto;
import io.metersphere.functional.domain.FunctionalCaseBlob;
import io.metersphere.system.dto.sdk.BaseTreeNode;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
public class MinderSearchDTO {
private List<BaseTreeNode> baseTreeNodes;
private Map<String, List<ReviewFunctionalCaseDTO>> moduleCaseMap;
private Map<String, FunctionalCaseBlob> blobMap;
private Map<String, List<FunctionalCaseCustomFieldDTO>> customFieldMap;
private String reviewPassRule;
private boolean viewResult;
private boolean viewFlag;
private BaseTreeNode baseTreeNode;
}

View File

@ -49,4 +49,7 @@ public class ReviewFunctionalCaseDTO implements Serializable {
@Schema(description = "模块名称")
private String moduleName;
@Schema(description = "编辑模式(用于脑图的查询)")
private String caseEditType;
}

View File

@ -38,7 +38,8 @@
functional_case.version_id as versionId,
functional_case.module_id as moduleId,
functional_case.name as name,
functional_case.num as num
functional_case.num as num,
functional_case.case_edit_type as caseEditType
FROM
case_review_functional_case crfc
LEFT JOIN functional_case ON crfc.case_id = functional_case.id

View File

@ -11,7 +11,7 @@ import java.util.List;
public interface ExtFunctionalCaseModuleMapper {
List<BaseTreeNode> selectBaseByProjectId(@Param("projectId")String projectId);
List<BaseTreeNode> selectBaseByProjectIdAndReviewId(@Param("projectId")String projectId, @Param("reviewId")String reviewId);
List<String> selectBaseByProjectIdAndReviewId(@Param("projectId")String projectId, @Param("reviewId")String reviewId);
List<BaseTreeNode> selectBaseByIds(@Param("ids") List<String> ids);

View File

@ -7,8 +7,8 @@
WHERE project_id = #{projectId}
ORDER BY pos
</select>
<select id="selectBaseByProjectIdAndReviewId" resultType="io.metersphere.system.dto.sdk.BaseTreeNode">
SELECT fcm.id, fcm.name, fcm.parent_id AS parentId, 'module' AS type
<select id="selectBaseByProjectIdAndReviewId" resultType="java.lang.String">
SELECT fcm.id
FROM functional_case_module fcm
WHERE fcm.project_id = #{projectId}
AND fcm.id IN

View File

@ -0,0 +1,11 @@
package io.metersphere.functional.request;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class MinderReviewFunctionalCasePageRequest extends ReviewFunctionalCasePageRequest{
@Schema(description = "我的评审", requiredMode = Schema.RequiredMode.REQUIRED)
private boolean viewResult;
}

View File

@ -26,7 +26,7 @@ public class ReviewFunctionalCasePageRequest extends BasePageRequest implements
private String projectId;
@Schema(description = "是否只看我的", requiredMode = Schema.RequiredMode.REQUIRED)
private Boolean viewFlag;
private boolean viewFlag;
@Schema(description = "模块id")
private List<String> moduleIds;

View File

@ -16,7 +16,6 @@ import io.metersphere.project.domain.ProjectVersion;
import io.metersphere.project.dto.ModuleCountDTO;
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
import io.metersphere.project.mapper.ProjectApplicationMapper;
import io.metersphere.project.service.ModuleTreeService;
import io.metersphere.provider.BaseCaseProvider;
import io.metersphere.sdk.constants.ProjectApplicationType;
import io.metersphere.sdk.exception.MSException;
@ -47,7 +46,7 @@ import java.util.stream.Collectors;
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class CaseReviewFunctionalCaseService extends ModuleTreeService {
public class CaseReviewFunctionalCaseService {
@Resource
@ -78,6 +77,9 @@ public class CaseReviewFunctionalCaseService extends ModuleTreeService {
private ReviewSendNoticeService reviewSendNoticeService;
@Resource
private FunctionalCaseAttachmentService functionalCaseAttachmentService;
@Resource
private FunctionalCaseModuleService functionalCaseModuleService;
private static final String CASE_MODULE_COUNT_ALL = "all";
@ -531,8 +533,9 @@ public class CaseReviewFunctionalCaseService extends ModuleTreeService {
}
public List<BaseTreeNode> getTree(String projectId, String reviewId) {
List<BaseTreeNode> functionalModuleList = extFunctionalCaseModuleMapper.selectBaseByProjectIdAndReviewId(projectId, reviewId);
return super.buildTreeAndCountResource(functionalModuleList, true, Translator.get("default.module"));
List<String> functionalModuleIds = extFunctionalCaseModuleMapper.selectBaseByProjectIdAndReviewId(projectId, reviewId);
List<BaseTreeNode> nodeByNodeIds = functionalCaseModuleService.getNodeByNodeIds(functionalModuleIds);
return functionalCaseModuleService.buildTreeAndCountResource(nodeByNodeIds, true, Translator.get("default.module"));
}
public Map<String, Long> moduleCount(ReviewFunctionalCasePageRequest request, boolean deleted, String userId) {
@ -554,22 +557,13 @@ public class CaseReviewFunctionalCaseService extends ModuleTreeService {
//构建模块树并计算每个节点下的所有数量包含子节点
List<BaseTreeNode> treeNodeList = this.getTreeOnlyIdsAndResourceCount(projectId,reviewId, moduleCountDTOList);
//通过广度遍历的方式构建返回值
return super.getIdCountMapByBreadth(treeNodeList);
return functionalCaseModuleService.getIdCountMapByBreadth(treeNodeList);
}
public List<BaseTreeNode> getTreeOnlyIdsAndResourceCount(String projectId, String reviewId, List<ModuleCountDTO> moduleCountDTOList) {
//节点内容只有Id和parentId
List<BaseTreeNode> fileModuleList = extFunctionalCaseModuleMapper.selectIdAndParentIdByProjectIdAndReviewId(projectId, reviewId);
return super.buildTreeAndCountResource(fileModuleList, moduleCountDTOList, true, Translator.get("default.module"));
return functionalCaseModuleService.buildTreeAndCountResource(fileModuleList, moduleCountDTOList, true, Translator.get("default.module"));
}
@Override
public void updatePos(String id, long pos) {
}
@Override
public void refreshPos(String parentId) {
}
}

View File

@ -1,11 +1,16 @@
package io.metersphere.functional.service;
import io.metersphere.functional.constants.CaseReviewPassRule;
import io.metersphere.functional.constants.MinderLabel;
import io.metersphere.functional.domain.CaseReview;
import io.metersphere.functional.domain.FunctionalCase;
import io.metersphere.functional.domain.FunctionalCaseBlob;
import io.metersphere.functional.domain.FunctionalCaseBlobExample;
import io.metersphere.functional.dto.*;
import io.metersphere.functional.mapper.CaseReviewMapper;
import io.metersphere.functional.mapper.FunctionalCaseBlobMapper;
import io.metersphere.functional.request.FunctionalCasePageRequest;
import io.metersphere.functional.request.MinderReviewFunctionalCasePageRequest;
import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Translator;
@ -33,27 +38,31 @@ public class FunctionalCaseMinderService {
@Resource
private FunctionalCaseService functionalCaseService;
@Resource
private FunctionalCaseModuleService functionalCaseModuleService;
@Resource
private FunctionalCaseBlobMapper functionalCaseBlobMapper;
@Resource
private CaseReviewFunctionalCaseService caseReviewFunctionalCaseService;
@Resource
private CaseReviewMapper caseReviewMapper;
/**
* 功能用例-脑图用例列表查询
* @param request FunctionalCasePageRequest
* @param deleted 用例是否删除
* @return FunctionalMinderTreeDTO
*/
public FunctionalMinderTreeDTO getFunctionalCasePage(FunctionalCasePageRequest request, boolean deleted) {
//根据查询条件查询出所有符合的功能用例
List<FunctionalCasePageDTO> functionalCasePage = functionalCaseService.getFunctionalCasePage(request, deleted);
List<String> caseIds = functionalCasePage.stream().map(FunctionalCase::getId).distinct().toList();
FunctionalCaseBlobExample functionalCaseBlobExample = new FunctionalCaseBlobExample();
functionalCaseBlobExample.createCriteria().andIdIn(caseIds);
List<FunctionalCaseBlob> functionalCaseBlobs = functionalCaseBlobMapper.selectByExampleWithBLOBs(functionalCaseBlobExample);
Map<String, FunctionalCaseBlob> blobMap = functionalCaseBlobs.stream().collect(Collectors.toMap(FunctionalCaseBlob::getId, t -> t));
Map<String, FunctionalCaseBlob> blobMap = getStringFunctionalCaseBlobMap(caseIds);
//根据功能用例的模块ID查出每个模块id父级直到根节点
List<String> moduleIds = functionalCasePage.stream().map(FunctionalCase::getModuleId).distinct().toList();
Map<String, List<FunctionalCasePageDTO>> moduleCaseMap = functionalCasePage.stream().collect(Collectors.groupingBy(FunctionalCasePageDTO::getModuleId));
List<BaseTreeNode> nodeByNodeIds = functionalCaseModuleService.getNodeByNodeIds(moduleIds);
//根据模块节点构造模块树
List<BaseTreeNode> baseTreeNodes = functionalCaseModuleService.buildTreeAndCountResource(nodeByNodeIds, true, Translator.get("default.module"));
List<BaseTreeNode> baseTreeNodes = getBaseTreeNodes(moduleIds);
//判断虚拟节点有无数据
if (moduleCaseMap.get(ModuleConstants.DEFAULT_NODE_ID) == null && CollectionUtils.isEmpty(baseTreeNodes.get(0).getChildren())) {
baseTreeNodes.remove(0);
@ -61,23 +70,37 @@ public class FunctionalCaseMinderService {
//构建返回数据主层级应与模块树层级相同
List<FunctionalMinderTreeDTO> functionalMinderTreeNodeDTOs = new ArrayList<>();
buildCaseTree(baseTreeNodes, moduleCaseMap, functionalMinderTreeNodeDTOs, blobMap);
return getRoot(functionalMinderTreeNodeDTOs);
}
private static FunctionalMinderTreeDTO getRoot(List<FunctionalMinderTreeDTO> functionalMinderTreeDTOs) {
FunctionalMinderTreeDTO root = new FunctionalMinderTreeDTO();
FunctionalMinderTreeNodeDTO rootData = new FunctionalMinderTreeNodeDTO();
rootData.setResource(List.of("模块"));
rootData.setText("全部用例");
root.setChildren(functionalMinderTreeNodeDTOs);
rootData.setResource(List.of(MinderLabel.MODULE.toString()));
rootData.setText(Translator.get("case.minder.all.case"));
root.setChildren(functionalMinderTreeDTOs);
root.setData(rootData);
return root;
}
private List<BaseTreeNode> getBaseTreeNodes(List<String> moduleIds) {
List<BaseTreeNode> nodeByNodeIds = functionalCaseModuleService.getNodeByNodeIds(moduleIds);
//根据模块节点构造模块树
return functionalCaseModuleService.buildTreeAndCountResource(nodeByNodeIds, true, Translator.get("default.module"));
}
private Map<String, FunctionalCaseBlob> getStringFunctionalCaseBlobMap(List<String> caseIds) {
FunctionalCaseBlobExample functionalCaseBlobExample = new FunctionalCaseBlobExample();
functionalCaseBlobExample.createCriteria().andIdIn(caseIds);
List<FunctionalCaseBlob> functionalCaseBlobs = functionalCaseBlobMapper.selectByExampleWithBLOBs(functionalCaseBlobExample);
return functionalCaseBlobs.stream().collect(Collectors.toMap(FunctionalCaseBlob::getId, t -> t));
}
private static void buildCaseTree(List<BaseTreeNode> baseTreeNodes, Map<String, List<FunctionalCasePageDTO>> moduleCaseMap, List<FunctionalMinderTreeDTO> functionalMinderTreeNodeDTOs, Map<String, FunctionalCaseBlob> blobMap) {
baseTreeNodes.forEach(t -> {
//构建根节点
FunctionalMinderTreeDTO functionalMinderTreeDTO = new FunctionalMinderTreeDTO();
FunctionalMinderTreeNodeDTO functionalMinderTreeNodeDTO = new FunctionalMinderTreeNodeDTO();
functionalMinderTreeNodeDTO.setId(t.getId());
functionalMinderTreeNodeDTO.setText(t.getName());
functionalMinderTreeNodeDTO.setResource(List.of("模块"));
FunctionalMinderTreeNodeDTO functionalMinderTreeNodeDTO = getFunctionalMinderTreeNodeDTO(t);
functionalMinderTreeDTO.setData(functionalMinderTreeNodeDTO);
List<FunctionalMinderTreeDTO> children = new ArrayList<>();
@ -90,6 +113,14 @@ public class FunctionalCaseMinderService {
});
}
private static FunctionalMinderTreeNodeDTO getFunctionalMinderTreeNodeDTO(BaseTreeNode t) {
FunctionalMinderTreeNodeDTO functionalMinderTreeNodeDTO = new FunctionalMinderTreeNodeDTO();
functionalMinderTreeNodeDTO.setId(t.getId());
functionalMinderTreeNodeDTO.setText(t.getName());
functionalMinderTreeNodeDTO.setResource(List.of(MinderLabel.MODULE.toString()));
return functionalMinderTreeNodeDTO;
}
private static void buildCaseChild(Map<String, List<FunctionalCasePageDTO>> moduleCaseMap, Map<String, FunctionalCaseBlob> blobMap, BaseTreeNode t, List<FunctionalMinderTreeDTO> children) {
if (moduleCaseMap.get(t.getId()) != null && CollectionUtils.isNotEmpty(moduleCaseMap.get(t.getId()))) {
List<FunctionalCasePageDTO> functionalCasePageDTOS = moduleCaseMap.get(t.getId());
@ -105,10 +136,138 @@ public class FunctionalCaseMinderService {
functionalMinderTreeNodeChild.setPriority(list.get(0).getDefaultValue());
}
}
functionalMinderTreeNodeChild.setResource(List.of("用例"));
functionalMinderTreeNodeChild.setResource(List.of(MinderLabel.CASE.toString()));
functionalMinderTreeChild.setData(functionalMinderTreeNodeChild);
//将用例的blob记为Case的children
setBlobInfo(blobMap, functionalCasePageDTO.getId(), functionalCasePageDTO.getCaseEditType(), functionalMinderTreeChild);
children.add(functionalMinderTreeChild);
});
}
}
private static void buildModuleChild(Map<String, List<FunctionalCasePageDTO>> moduleCaseMap, Map<String, FunctionalCaseBlob> blobMap, BaseTreeNode t, List<FunctionalMinderTreeDTO> children) {
if (CollectionUtils.isNotEmpty(t.getChildren())) {
t.getChildren().forEach(child->{
FunctionalMinderTreeDTO functionalMinderTreeDTOChild = new FunctionalMinderTreeDTO();
FunctionalMinderTreeNodeDTO functionalMinderTreeNodeDTOChild = getFunctionalMinderTreeNodeDTO(child);
functionalMinderTreeDTOChild.setData(functionalMinderTreeNodeDTOChild);
List<FunctionalMinderTreeDTO> childChildren = new ArrayList<>();
buildCaseChild(moduleCaseMap, blobMap, child, childChildren);
functionalMinderTreeDTOChild.setChildren(childChildren);
children.add(functionalMinderTreeDTOChild);
buildModuleChild(moduleCaseMap, blobMap, child, childChildren);
});
}
}
/**
* 用例评审-脑图用例列表查询
* @param request MinderReviewFunctionalCasePageRequest
* @param deleted 用例是否删除
* @param userId userId 只看我的
* @return FunctionalMinderTreeDTO
*/
public FunctionalMinderTreeDTO getReviewFunctionalCasePage(MinderReviewFunctionalCasePageRequest request, boolean deleted, String userId) {
CaseReview caseReview = caseReviewMapper.selectByPrimaryKey(request.getReviewId());
List<ReviewFunctionalCaseDTO> page = caseReviewFunctionalCaseService.page(request, deleted, userId);
List<String> caseIds = page.stream().map(ReviewFunctionalCaseDTO::getCaseId).toList();
Map<String, FunctionalCaseBlob> blobMap = getStringFunctionalCaseBlobMap(caseIds);
List<String> moduleIds = page.stream().map(ReviewFunctionalCaseDTO::getModuleId).toList();
List<BaseTreeNode> baseTreeNodes = getBaseTreeNodes(moduleIds);
//判断虚拟节点有无数据
Map<String, List<ReviewFunctionalCaseDTO>> moduleCaseMap = page.stream().collect(Collectors.groupingBy(ReviewFunctionalCaseDTO::getModuleId));
if (moduleCaseMap.get(ModuleConstants.DEFAULT_NODE_ID) == null && CollectionUtils.isEmpty(baseTreeNodes.get(0).getChildren())) {
baseTreeNodes.remove(0);
}
//自定义字段
Map<String, List<FunctionalCaseCustomFieldDTO>> caseCustomFiledMap = functionalCaseService.getCaseCustomFiledMap(caseIds);
//构建返回数据主层级应与模块树层级相同
MinderSearchDTO minderSearchDTO = new MinderSearchDTO();
minderSearchDTO.setBaseTreeNodes(baseTreeNodes);
minderSearchDTO.setModuleCaseMap(moduleCaseMap);
minderSearchDTO.setBlobMap(blobMap);
minderSearchDTO.setCustomFieldMap(caseCustomFiledMap);
minderSearchDTO.setReviewPassRule(caseReview.getReviewPassRule());
minderSearchDTO.setViewFlag(request.isViewFlag());
minderSearchDTO.setViewResult(request.isViewResult());
List<FunctionalMinderTreeDTO> functionalMinderTreeDTOs = buildReviewCaseTree(minderSearchDTO);
return getRoot(functionalMinderTreeDTOs);
}
private List<FunctionalMinderTreeDTO> buildReviewCaseTree(MinderSearchDTO minderSearchDTO) {
List<FunctionalMinderTreeDTO> functionalMinderTreeNodeDTOs = new ArrayList<>();
minderSearchDTO.getBaseTreeNodes().forEach(t -> {
//构建根节点
FunctionalMinderTreeDTO functionalMinderTreeDTO = new FunctionalMinderTreeDTO();
FunctionalMinderTreeNodeDTO functionalMinderTreeNodeDTO = getFunctionalMinderTreeNodeDTO(t);
functionalMinderTreeDTO.setData(functionalMinderTreeNodeDTO);
List<FunctionalMinderTreeDTO> children = new ArrayList<>();
//如果当前节点有用例则用例是他的子节点
minderSearchDTO.setBaseTreeNode(t);
buildReviewCaseChild(minderSearchDTO, children);
//查询当前节点下的子模块节点
buildReviewModuleChild(minderSearchDTO, children);
functionalMinderTreeDTO.setChildren(children);
functionalMinderTreeNodeDTOs.add(functionalMinderTreeDTO);
});
return functionalMinderTreeNodeDTOs;
}
private void buildReviewModuleChild(MinderSearchDTO minderSearchDTO, List<FunctionalMinderTreeDTO> children) {
List<BaseTreeNode> baseTreeNodes = minderSearchDTO.getBaseTreeNode().getChildren();
if (CollectionUtils.isNotEmpty(baseTreeNodes)) {
baseTreeNodes.forEach(child->{
FunctionalMinderTreeDTO functionalMinderTreeDTOChild = new FunctionalMinderTreeDTO();
FunctionalMinderTreeNodeDTO functionalMinderTreeNodeDTOChild = getFunctionalMinderTreeNodeDTO(child);
functionalMinderTreeDTOChild.setData(functionalMinderTreeNodeDTOChild);
minderSearchDTO.setBaseTreeNode(child);
List<FunctionalMinderTreeDTO> childChildren = new ArrayList<>();
buildReviewCaseChild(minderSearchDTO, childChildren);
functionalMinderTreeDTOChild.setChildren(childChildren);
children.add(functionalMinderTreeDTOChild);
buildReviewModuleChild(minderSearchDTO, childChildren);
});
}
}
private void buildReviewCaseChild(MinderSearchDTO minderSearchDTO, List<FunctionalMinderTreeDTO> children) {
Map<String, List<ReviewFunctionalCaseDTO>> moduleCaseMap = minderSearchDTO.getModuleCaseMap();
BaseTreeNode baseTreeNode = minderSearchDTO.getBaseTreeNode();
String baseTreeNodeId = baseTreeNode.getId();
if (moduleCaseMap.get(baseTreeNodeId) != null && CollectionUtils.isNotEmpty(moduleCaseMap.get(baseTreeNodeId))) {
List<ReviewFunctionalCaseDTO> reviewFunctionalCaseDTOS = moduleCaseMap.get(baseTreeNodeId);
reviewFunctionalCaseDTOS.forEach(reviewFunctionalCaseDTO -> {
FunctionalMinderTreeDTO functionalMinderTreeChild = new FunctionalMinderTreeDTO();
//加载用例为children
FunctionalMinderTreeNodeDTO functionalMinderTreeNodeChild = new FunctionalMinderTreeNodeDTO();
functionalMinderTreeNodeChild.setId(reviewFunctionalCaseDTO.getCaseId());
functionalMinderTreeNodeChild.setText(reviewFunctionalCaseDTO.getName());
List<FunctionalCaseCustomFieldDTO> functionalCaseCustomFieldDTOS = minderSearchDTO.getCustomFieldMap().get(reviewFunctionalCaseDTO.getCaseId());
if (CollectionUtils.isNotEmpty(functionalCaseCustomFieldDTOS)) {
List<FunctionalCaseCustomFieldDTO> list = functionalCaseCustomFieldDTOS.stream().filter(customField -> customField.getFieldName().equals(Translator.get("custom_field.functional_priority"))).toList();
if (CollectionUtils.isNotEmpty(list)) {
functionalMinderTreeNodeChild.setPriority(list.get(0).getDefaultValue());
}
}
if (minderSearchDTO.isViewFlag()&& minderSearchDTO.isViewResult() && StringUtils.equalsIgnoreCase(minderSearchDTO.getReviewPassRule(), CaseReviewPassRule.MULTIPLE.toString()) ) {
functionalMinderTreeNodeChild.setStatus(reviewFunctionalCaseDTO.getStatus());
}
functionalMinderTreeNodeChild.setResource(List.of(MinderLabel.CASE.toString()));
functionalMinderTreeChild.setData(functionalMinderTreeNodeChild);
setBlobInfo(minderSearchDTO.getBlobMap(), reviewFunctionalCaseDTO.getCaseId(), reviewFunctionalCaseDTO.getCaseEditType(), functionalMinderTreeChild);
children.add(functionalMinderTreeChild);
});
}
}
private static void setBlobInfo(Map<String, FunctionalCaseBlob> blobMap, String caseId, String caseEditType, FunctionalMinderTreeDTO functionalMinderTreeChild) {
//将用例的blob记为Case的children
List<FunctionalMinderTreeDTO> functionalMinderTreeNodeChildChild = new ArrayList<>();
FunctionalCaseBlob functionalCaseBlob = blobMap.get(functionalCasePageDTO.getId());
FunctionalCaseBlob functionalCaseBlob = blobMap.get(caseId);
if (functionalCaseBlob != null) {
if (functionalCaseBlob.getPrerequisite() != null) {
FunctionalMinderTreeDTO functionalMinderTreeDTOPre = new FunctionalMinderTreeDTO();
@ -116,27 +275,27 @@ public class FunctionalCaseMinderService {
FunctionalMinderTreeNodeDTO functionalMinderTreeNodeChildPre = new FunctionalMinderTreeNodeDTO();
String prerequisite = new String(functionalCaseBlob.getPrerequisite(), StandardCharsets.UTF_8);
functionalMinderTreeNodeChildPre.setText(prerequisite);
functionalMinderTreeNodeChildPre.setResource(List.of("前置条件"));
functionalMinderTreeNodeChildPre.setResource(List.of(MinderLabel.PREREQUISITE.toString()));
functionalMinderTreeDTOPre.setData(functionalMinderTreeNodeChildPre);
functionalMinderTreeNodeChildChild.add(functionalMinderTreeDTOPre);
}
//步骤描述
if (StringUtils.equalsIgnoreCase(functionalCasePageDTO.getCaseEditType(),"TEXT") ) {
if (StringUtils.equalsIgnoreCase(caseEditType, "TEXT")) {
if (functionalCaseBlob.getTextDescription() != null) {
//1.文本描述(一个)
FunctionalMinderTreeDTO functionalMinderTreeDTOText = new FunctionalMinderTreeDTO();
FunctionalMinderTreeNodeDTO functionalMinderTreeNodeChildText = new FunctionalMinderTreeNodeDTO();
String textDescription = new String(functionalCaseBlob.getTextDescription(), StandardCharsets.UTF_8);
functionalMinderTreeNodeChildText.setText(textDescription);
functionalMinderTreeNodeChildText.setResource(List.of("步骤描述"));
functionalMinderTreeNodeChildText.setResource(List.of(MinderLabel.TEXT_DESCRIPTION.toString()));
functionalMinderTreeDTOText.setData(functionalMinderTreeNodeChildText);
List<FunctionalMinderTreeDTO> functionalMinderTreeNodeChildTextChildren = new ArrayList<>();
FunctionalMinderTreeDTO functionalMinderTreeNodeChildTextChild = new FunctionalMinderTreeDTO();
FunctionalMinderTreeNodeDTO functionalMinderTreeNodeDTOChildTextChild = new FunctionalMinderTreeNodeDTO();
String expectedResult = new String(functionalCaseBlob.getExpectedResult(), StandardCharsets.UTF_8);
functionalMinderTreeNodeDTOChildTextChild.setText(expectedResult);
functionalMinderTreeNodeDTOChildTextChild.setResource(List.of("预期结果"));
functionalMinderTreeNodeDTOChildTextChild.setResource(List.of(MinderLabel.EXPECTED_RESULT.toString()));
functionalMinderTreeNodeChildTextChild.setData(functionalMinderTreeNodeDTOChildTextChild);
functionalMinderTreeNodeChildTextChildren.add(functionalMinderTreeNodeChildTextChild);
functionalMinderTreeDTOText.setChildren(functionalMinderTreeNodeChildTextChildren);
@ -150,13 +309,13 @@ public class FunctionalCaseMinderService {
FunctionalMinderTreeDTO functionalMinderTreeDTOText = new FunctionalMinderTreeDTO();
FunctionalMinderTreeNodeDTO functionalMinderTreeNodeChildStep = new FunctionalMinderTreeNodeDTO();
functionalMinderTreeNodeChildStep.setText(functionalCaseStepDTO.getDesc());
functionalMinderTreeNodeChildStep.setResource(List.of("步骤描述"));
functionalMinderTreeNodeChildStep.setResource(List.of(MinderLabel.TEXT_DESCRIPTION.toString()));
List<FunctionalMinderTreeDTO> functionalMinderTreeNodeChildTextChildren = new ArrayList<>();
FunctionalMinderTreeDTO functionalMinderTreeNodeChildTextChild = new FunctionalMinderTreeDTO();
FunctionalMinderTreeNodeDTO functionalMinderTreeNodeDTOChildTextChild = new FunctionalMinderTreeNodeDTO();
functionalMinderTreeNodeDTOChildTextChild.setText(functionalCaseStepDTO.getResult());
functionalMinderTreeNodeDTOChildTextChild.setResource(List.of("预期结果"));
functionalMinderTreeNodeDTOChildTextChild.setResource(List.of(MinderLabel.EXPECTED_RESULT.toString()));
functionalMinderTreeNodeChildTextChild.setData(functionalMinderTreeNodeDTOChildTextChild);
functionalMinderTreeNodeChildTextChildren.add(functionalMinderTreeNodeChildTextChild);
@ -173,36 +332,11 @@ public class FunctionalCaseMinderService {
FunctionalMinderTreeNodeDTO functionalMinderTreeNodeChildRemark = new FunctionalMinderTreeNodeDTO();
String description = new String(functionalCaseBlob.getDescription(), StandardCharsets.UTF_8);
functionalMinderTreeNodeChildRemark.setText(description);
functionalMinderTreeNodeChildRemark.setResource(List.of("备注"));
functionalMinderTreeNodeChildRemark.setResource(List.of(MinderLabel.DESCRIPTION.toString()));
functionalMinderTreeDTORemark.setData(functionalMinderTreeNodeChildRemark);
functionalMinderTreeNodeChildChild.add(functionalMinderTreeDTORemark);
}
}
functionalMinderTreeChild.setData(functionalMinderTreeNodeChild);
functionalMinderTreeChild.setChildren(functionalMinderTreeNodeChildChild);
children.add(functionalMinderTreeChild);
});
}
}
private static void buildModuleChild(Map<String, List<FunctionalCasePageDTO>> moduleCaseMap, Map<String, FunctionalCaseBlob> blobMap, BaseTreeNode t, List<FunctionalMinderTreeDTO> children) {
if (CollectionUtils.isNotEmpty(t.getChildren())) {
t.getChildren().forEach(child->{
FunctionalMinderTreeDTO functionalMinderTreeDTOChild = new FunctionalMinderTreeDTO();
FunctionalMinderTreeNodeDTO functionalMinderTreeNodeDTOChild = new FunctionalMinderTreeNodeDTO();
functionalMinderTreeNodeDTOChild.setId(child.getId());
functionalMinderTreeNodeDTOChild.setText(child.getName());
functionalMinderTreeNodeDTOChild.setResource(List.of("模块"));
functionalMinderTreeDTOChild.setData(functionalMinderTreeNodeDTOChild);
List<FunctionalMinderTreeDTO> childChildren = new ArrayList<>();
buildCaseChild(moduleCaseMap, blobMap, child, childChildren);
functionalMinderTreeDTOChild.setChildren(childChildren);
children.add(functionalMinderTreeDTOChild);
buildModuleChild(moduleCaseMap, blobMap, child, childChildren);
});
}
}
}

View File

@ -515,6 +515,15 @@ public class FunctionalCaseService {
private List<FunctionalCasePageDTO> handleCustomFields(List<FunctionalCasePageDTO> functionalCaseLists) {
List<String> ids = functionalCaseLists.stream().map(FunctionalCasePageDTO::getId).collect(Collectors.toList());
Map<String, List<FunctionalCaseCustomFieldDTO>> collect = getCaseCustomFiledMap(ids);
functionalCaseLists.forEach(functionalCasePageDTO -> {
functionalCasePageDTO.setCustomFields(collect.get(functionalCasePageDTO.getId()));
});
return functionalCaseLists;
}
public Map<String, List<FunctionalCaseCustomFieldDTO>> getCaseCustomFiledMap(List<String> ids) {
List<FunctionalCaseCustomFieldDTO> customFields = functionalCaseCustomFieldService.getCustomFieldsByCaseIds(ids);
customFields.forEach(customField -> {
if (customField.getInternal()) {
@ -527,12 +536,7 @@ public class FunctionalCaseService {
customFields.forEach(customField -> {
customField.setOptions(customOptions.get(customField.getFieldId()));
});
Map<String, List<FunctionalCaseCustomFieldDTO>> collect = customFields.stream().collect(Collectors.groupingBy(FunctionalCaseCustomFieldDTO::getCaseId));
functionalCaseLists.forEach(functionalCasePageDTO -> {
functionalCasePageDTO.setCustomFields(collect.get(functionalCasePageDTO.getId()));
});
return functionalCaseLists;
return customFields.stream().collect(Collectors.groupingBy(FunctionalCaseCustomFieldDTO::getCaseId));
}
public void batchDeleteFunctionalCaseToGc(FunctionalCaseBatchRequest request, String userId) {

View File

@ -5,6 +5,7 @@ import io.metersphere.functional.dto.FunctionalCaseStepDTO;
import io.metersphere.functional.dto.FunctionalMinderTreeDTO;
import io.metersphere.functional.mapper.FunctionalCaseBlobMapper;
import io.metersphere.functional.request.FunctionalCasePageRequest;
import io.metersphere.functional.request.MinderReviewFunctionalCasePageRequest;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder;
@ -28,14 +29,13 @@ public class FunctionalCaseMinderControllerTest extends BaseTest {
public static final String FUNCTIONAL_CASE_LIST_URL = "/functional/mind/case/list";
public static final String REViEW_FUNCTIONAL_CASE_LIST_URL = "/functional/mind/case/review/list";
@Resource
private FunctionalCaseBlobMapper functionalCaseBlobMapper;
@Test
@Order(1)
@Sql(scripts = {"/dml/init_file_minder_test.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED))
public void testGetPageList() throws Exception {
public void initPartBlob() {
List<FunctionalCaseBlob>blobs = new ArrayList<>();
FunctionalCaseBlob blob = new FunctionalCaseBlob();
blob.setId("TEST_FUNCTIONAL_MINDER_CASE_ID_4");
@ -87,7 +87,13 @@ public class FunctionalCaseMinderControllerTest extends BaseTest {
blob6.setDescription(description6.getBytes(StandardCharsets.UTF_8));
blobs.add(blob6);
functionalCaseBlobMapper.batchInsert(blobs);
}
@Test
@Order(1)
@Sql(scripts = {"/dml/init_file_minder_test.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED))
public void testGetPageList() throws Exception {
initPartBlob();
FunctionalCasePageRequest request = new FunctionalCasePageRequest();
request.setProjectId("project-case-minder-test");
request.setCurrent(1);
@ -95,8 +101,20 @@ public class FunctionalCaseMinderControllerTest extends BaseTest {
request.setSort(new HashMap<>() {{
put("createTime", "desc");
}});
/*//自定义字段 测试
Map<String, Object> map = new HashMap<>();
MvcResult mvcResultPage = this.requestPostWithOkAndReturn(FUNCTIONAL_CASE_LIST_URL, request);
String contentAsString = mvcResultPage.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(contentAsString, ResultHolder.class);
FunctionalMinderTreeDTO baseTreeNodes = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), FunctionalMinderTreeDTO.class);
Assertions.assertNotNull(baseTreeNodes);
// String jsonString = JSON.toJSONString(baseTreeNodes);
//System.out.println(jsonString);
}
@Test
@Order(2)
public void testGetReviewPageList() throws Exception {
/* Map<String, Object> map = new HashMap<>();
map.put("customs", Arrays.asList(new LinkedHashMap() {{
put("id", "TEST_FIELD_ID");
put("operator", "in");
@ -104,13 +122,31 @@ public class FunctionalCaseMinderControllerTest extends BaseTest {
put("type", "List");
}}));
request.setCombine(map);*/
MvcResult mvcResultPage = this.requestPostWithOkAndReturn(FUNCTIONAL_CASE_LIST_URL, request);
MinderReviewFunctionalCasePageRequest request = new MinderReviewFunctionalCasePageRequest();
request.setProjectId("project-case-minder-test");
request.setCurrent(1);
request.setPageSize(10);
request.setSort(new HashMap<>() {{
put("createTime", "desc");
}});
request.setReviewId("TEST_MINDER_REVIEW_ID_GYQ");
request.setViewFlag(true);
request.setViewResult(true);
MvcResult mvcResultPage = this.requestPostWithOkAndReturn(REViEW_FUNCTIONAL_CASE_LIST_URL, request);
String contentAsString = mvcResultPage.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(contentAsString, ResultHolder.class);
FunctionalMinderTreeDTO baseTreeNodes = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), FunctionalMinderTreeDTO.class);
Assertions.assertNotNull(baseTreeNodes);
String jsonString = JSON.toJSONString(baseTreeNodes);
System.out.println(jsonString);
//String jsonString = JSON.toJSONString(baseTreeNodes);
//System.out.println(jsonString);
request.setReviewId("TEST_MINDER_REVIEW_ID_GYQ2");
mvcResultPage = this.requestPostWithOkAndReturn(REViEW_FUNCTIONAL_CASE_LIST_URL, request);
contentAsString = mvcResultPage.getResponse().getContentAsString(StandardCharsets.UTF_8);
resultHolder = JSON.parseObject(contentAsString, ResultHolder.class);
baseTreeNodes = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), FunctionalMinderTreeDTO.class);
Assertions.assertNotNull(baseTreeNodes);
//jsonString = JSON.toJSONString(baseTreeNodes);
//System.out.println(jsonString);
}
}

View File

@ -29,9 +29,40 @@ VALUES
INSERT INTO custom_field (id, name, scene, type, remark, internal, scope_type, create_time, update_time, create_user, scope_id) VALUE
('custom_field_minder_gyq_id_3', 'functional_priority', 'FUNCTIONAL', 'SELECT', '', 0, 'ORGANIZATION', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', '100001');
('custom_field_minder_gyq_id_3', '用例等级', 'FUNCTIONAL', 'SELECT', '', 0, 'ORGANIZATION', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', '100001');
INSERT INTO case_review(id, num, name, module_id, project_id, status, review_pass_rule, pos, start_time, end_time, case_count, pass_rate, tags, description, create_time, create_user, update_time, update_user)
VALUES ('TEST_MINDER_REVIEW_ID_GYQ', 100, 'TEST_MINDER_REVIEW_GYQ', 'TEST_MINDER_REVIEW_MODULE_GYQ', 'project-case-minder-test', 'UNDERWAY', 'MULTIPLE', 100,UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 6, 50.00, null, null, UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 'admin'),
('TEST_MINDER_REVIEW_ID_GYQ2', 200, 'TEST_MINDER_REVIEW_GYQ2', 'TEST_MINDER_REVIEW_MODULE_GYQ', 'project-case-minder-test', 'UNDERWAY', 'SINGLE', 200,UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 6, 50.00, null, null, UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 'admin');
INSERT INTO case_review_functional_case(id, review_id, case_id, status, create_time, create_user, update_time, pos)
VALUES ('case_review_functional_case_minder_id1', 'TEST_MINDER_REVIEW_ID_GYQ', 'TEST_FUNCTIONAL_MINDER_CASE_ID_1', 'PASS', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 100 ),
('case_review_functional_case_minder_id2', 'TEST_MINDER_REVIEW_ID_GYQ', 'TEST_FUNCTIONAL_MINDER_CASE_ID_2', 'PASS', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 100 ),
('case_review_functional_case_minder_id3', 'TEST_MINDER_REVIEW_ID_GYQ', 'TEST_FUNCTIONAL_MINDER_CASE_ID_3', 'PASS', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 100 ),
('case_review_functional_case_minder_id4', 'TEST_MINDER_REVIEW_ID_GYQ', 'TEST_FUNCTIONAL_MINDER_CASE_ID_4', 'UNDER_REVIEWED', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 100 ),
('case_review_functional_case_minder_id5', 'TEST_MINDER_REVIEW_ID_GYQ', 'TEST_FUNCTIONAL_MINDER_CASE_ID_5', 'UNDER_REVIEWED', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 100 ),
('case_review_functional_case_minder_id6', 'TEST_MINDER_REVIEW_ID_GYQ', 'TEST_FUNCTIONAL_MINDER_CASE_ID_6', 'UNDER_REVIEWED', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 100 ),
('case_review_functional_case_minder_id7', 'TEST_MINDER_REVIEW_ID_GYQ2', 'TEST_FUNCTIONAL_MINDER_CASE_ID_1', 'PASS', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 100 ),
('case_review_functional_case_minder_id8', 'TEST_MINDER_REVIEW_ID_GYQ2', 'TEST_FUNCTIONAL_MINDER_CASE_ID_2', 'PASS', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 100 ),
('case_review_functional_case_minder_id9', 'TEST_MINDER_REVIEW_ID_GYQ2', 'TEST_FUNCTIONAL_MINDER_CASE_ID_3', 'PASS', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 100 ),
('case_review_functional_case_minder_ida', 'TEST_MINDER_REVIEW_ID_GYQ2', 'TEST_FUNCTIONAL_MINDER_CASE_ID_4', 'UNDER_REVIEWED', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 100 ),
('case_review_functional_case_minder_idb', 'TEST_MINDER_REVIEW_ID_GYQ2', 'TEST_FUNCTIONAL_MINDER_CASE_ID_5', 'UNDER_REVIEWED', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 100 ),
('case_review_functional_case_minder_idc', 'TEST_MINDER_REVIEW_ID_GYQ2', 'TEST_FUNCTIONAL_MINDER_CASE_ID_6', 'UNDER_REVIEWED', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 100 );
INSERT INTO case_review_functional_case_user(case_id, review_id, user_id)
VALUES ('TEST_FUNCTIONAL_MINDER_CASE_ID_1', 'TEST_MINDER_REVIEW_ID_GYQ', 'admin'),
('TEST_FUNCTIONAL_MINDER_CASE_ID_2', 'TEST_MINDER_REVIEW_ID_GYQ', 'admin'),
('TEST_FUNCTIONAL_MINDER_CASE_ID_3', 'TEST_MINDER_REVIEW_ID_GYQ', 'admin'),
('TEST_FUNCTIONAL_MINDER_CASE_ID_4', 'TEST_MINDER_REVIEW_ID_GYQ', 'admin'),
('TEST_FUNCTIONAL_MINDER_CASE_ID_5', 'TEST_MINDER_REVIEW_ID_GYQ', 'admin'),
('TEST_FUNCTIONAL_MINDER_CASE_ID_6', 'TEST_MINDER_REVIEW_ID_GYQ', 'admin'),
('TEST_FUNCTIONAL_MINDER_CASE_ID_1', 'TEST_MINDER_REVIEW_ID_GYQ2', 'admin'),
('TEST_FUNCTIONAL_MINDER_CASE_ID_2', 'TEST_MINDER_REVIEW_ID_GYQ2', 'admin'),
('TEST_FUNCTIONAL_MINDER_CASE_ID_3', 'TEST_MINDER_REVIEW_ID_GYQ2', 'admin'),
('TEST_FUNCTIONAL_MINDER_CASE_ID_4', 'TEST_MINDER_REVIEW_ID_GYQ2', 'admin'),
('TEST_FUNCTIONAL_MINDER_CASE_ID_5', 'TEST_MINDER_REVIEW_ID_GYQ2', 'admin'),
('TEST_FUNCTIONAL_MINDER_CASE_ID_6', 'TEST_MINDER_REVIEW_ID_GYQ2', 'admin');