fix(测试跟踪): 功能用例回收站模块树显示优化

--bug=1015082 --user=陈建星 【测试跟踪】功能用例列表,点击回收站/公共用例库后,再点击左侧的全部用例没有反应 https://www.tapd.cn/55049933/s/1205996
This commit is contained in:
chenjianxing 2022-07-21 14:48:08 +08:00 committed by jianxing
parent dfc7483ab5
commit 98f0c6b623
12 changed files with 149 additions and 54 deletions

View File

@ -269,8 +269,6 @@
<select id="publicList" resultType="io.metersphere.track.dto.TestCaseDTO">
select
project_version.name as versionName,
project_version.id as versionId,
test_case.last_execute_result,
<if test="request.selectFields != null and request.selectFields.size() > 0">
<foreach collection="request.selectFields" item="field" separator=",">
@ -278,20 +276,17 @@
</foreach>
</if>
<if test="request.selectFields == null or request.selectFields.size() == 0">
test_case.id, test_case.node_id, test_case.node_path, test_case.project_id, test_case.`name`,
test_case.id, test_case.node_id, test_case.node_path, test_case.project_id, test_case.`name`, test_case.version_id,
test_case.`type`, test_case.maintainer, test_case.priority, test_case.`method`,
test_case.create_time, test_case.update_time, test_case.test_id, test_case.sort, test_case.num,
test_case.other_test_name, test_case.review_status, test_case.tags,
test_case.demand_id, test_case.demand_name, test_case.`status`,
test_case.custom_num, test_case.step_model, test_case.create_user,u.name as createName,
test_case.custom_num, test_case.step_model, test_case.create_user,
test_case.custom_fields,test_case.case_public ,
project.workspace_id , project.name as projectName ,test_case.ref_id ,test_case.`order`
</if>
from test_case left join user u on test_case.create_user=u.id
left join (select id,workspace_id,NAME from project where workspace_id =#{request.workspaceId})
project on test_case.project_id = project.id
left join project_version on project.id = project_version.project_id and project_version.id =
test_case.version_id
from test_case
inner join project on test_case.project_id = project.id and workspace_id = #{request.workspaceId}
<include refid="queryPublicCaseWhere"></include>
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.orders"/>
@ -301,7 +296,8 @@
select
distinct test_case.project_id
from test_case
<include refid="queryPublicCaseWhere"></include>
<include refid="queryPublicCaseWhere"/>
and test_case.project_id in (select id from project where workspace_id=#{request.workspaceId})
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.orders"/>
</select>
@ -313,27 +309,27 @@
<select id="getCountNodes" resultType="io.metersphere.track.dto.TestCaseNodeDTO">
select tcn.id, count(*) as caseNum
from test_case
inner join test_case_node tcn on test_case.node_id = tcn.id
left join test_case_node tcn on test_case.node_id = tcn.id
<include refid="queryWhereCondition"/>
group by test_case.node_id
group by tcn.id
</select>
<select id="getTestPlanRelateCountNodes" resultType="io.metersphere.track.dto.TestCaseNodeDTO">
select tcn.id, count(*) as caseNum, test_case.project_id
from test_case
left join test_plan_test_case tptc on tptc.case_id = test_case.id and tptc.plan_id = #{request.planId}
inner join test_case_node tcn on test_case.node_id = tcn.id
left join test_case_node tcn on test_case.node_id = tcn.id
<include refid="queryWhereCondition"/>
and tptc.case_id is null
group by test_case.node_id
group by tcn.id
</select>
<select id="getTestReviewRelateCountNodes" resultType="io.metersphere.track.dto.TestCaseNodeDTO">
select tcn.id, count(*) as caseNum, test_case.project_id
from test_case
left join test_case_review_test_case tcrtc on tcrtc.case_id = test_case.id and tcrtc.review_id = #{request.reviewId}
inner join test_case_node tcn on test_case.node_id = tcn.id
left join test_case_node tcn on test_case.node_id = tcn.id
<include refid="queryWhereCondition"/>
and tcrtc.case_id is null
group by test_case.node_id
group by tcn.id
</select>
<select id="listByMethod" resultType="io.metersphere.track.dto.TestCaseDTO">
select load_test.id, load_test.name, load_test.project_id,'性能测试' as type, project_version.name as version_name
@ -531,9 +527,6 @@
#{nodeId}
</foreach>
</if>
<if test="request.workspaceId != null">
AND test_case.project_id in (select id from project where workspace_id=#{request.workspaceId})
</if>
and test_case.case_public = TRUE
<include refid="filters"/>
<if test="request.caseCoverage == 'uncoverage' ">
@ -1257,11 +1250,11 @@
</select>
<select id="getWorkspaceCountNodes" resultType="io.metersphere.track.dto.TestCaseNodeDTO">
select tcn.id, count(*) as caseNum, test_case.project_id
from test_case_node tcn
inner join test_case on test_case.node_id = tcn.id
from test_case
left join test_case_node tcn on test_case.node_id = tcn.id
inner join project p on p.id = test_case.project_id
<include refid="queryWhereCondition"/>
and p.workspace_id = #{request.workspaceId}
group by test_case.node_id;
group by tcn.id;
</select>
</mapper>

View File

@ -552,9 +552,9 @@
select tcn.id, count(*) as caseNum, test_case.project_id
from test_plan_test_case
inner join test_case on test_plan_test_case.case_id = test_case.id
inner join test_case_node tcn on test_case.node_id = tcn.id
left join test_case_node tcn on test_case.node_id = tcn.id
<include refid="queryWhereCondition"/>
group by test_case.node_id;
group by tcn.id;
</select>
<select id="getExecResultMapByPlanId" resultType="io.metersphere.track.dto.CountMapDTO">
select status as `key`, count(*) as `value`

View File

@ -470,9 +470,9 @@
select tcn.id, count(*) as caseNum, test_case.project_id
from test_case_review_test_case
inner join test_case on test_case_review_test_case.case_id = test_case.id
inner join test_case_node tcn on test_case.node_id = tcn.id
left join test_case_node tcn on test_case.node_id = tcn.id
<include refid="queryWhereCondition"/>
group by test_case.node_id;
group by tcn.id;
</select>
<sql id="queryVersionCondition">
<if test="request.versionId != null">

View File

@ -158,6 +158,10 @@ public class NodeTreeService<T extends TreeNodeDTO> {
projectNode.setLabel(project.getName());
projectNode.setChildren(testCaseNodes);
projectNode.setCaseNum(testCaseNodes.stream().mapToInt(TreeNodeDTO::getCaseNum).sum());
if (countMap.get(null) != null) {
// 如果模块删除了, 回收站中的用例归到项目模块下
projectNode.setCaseNum(projectNode.getCaseNum() + countMap.get(null));
}
if (!org.springframework.util.CollectionUtils.isEmpty(testCaseNodes)) {
list.add(projectNode);
}

View File

@ -79,6 +79,11 @@ public class TestCaseNodeController {
return testCaseNodeService.getPublicCaseNode(workspaceId, request);
}
@PostMapping("/list/trash/{projectId}")
public List<TestCaseNodeDTO> getTrashCaseNode(@PathVariable String projectId, @RequestBody QueryTestCaseRequest request) {
return testCaseNodeService.getTrashCaseNode(projectId, request);
}
@PostMapping("/list/plan/relate")
public List<TestCaseNodeDTO> getRelatePlanNodes(@RequestBody QueryTestCaseRequest request) {
checkPermissionService.checkTestPlanOwner(request.getPlanId());

View File

@ -144,16 +144,6 @@ public class TestCaseNodeService extends NodeTreeService<TestCaseNodeDTO> {
return getNodeTreeByProjectId(projectId, new QueryTestCaseRequest());
}
public List<TestCaseNodeDTO> getNodeTreeByProjectId(String projectId, QueryTestCaseRequest request) {
// 判断当前项目下是否有默认模块没有添加默认模块
this.getDefaultNode(projectId);
request.setProjectId(projectId);
request.setUserId(SessionUtils.getUserId());
List<TestCaseNodeDTO> countMNodes = extTestCaseMapper.getCountNodes(request);
List<TestCaseNodeDTO> testCaseNodes = extTestCaseNodeMapper.getNodeTreeByProjectId(projectId);
return getNodeTrees(testCaseNodes, getCountMap(countMNodes));
}
private Map<String, Integer> parseModuleCountList(List<Map<String, Object>> moduleCountList) {
Map<String, Integer> returnMap = new HashMap<>();
for (Map<String, Object> map : moduleCountList) {
@ -254,6 +244,16 @@ public class TestCaseNodeService extends NodeTreeService<TestCaseNodeDTO> {
return list;
}
public List<TestCaseNodeDTO> getNodeTreeByProjectId(String projectId, QueryTestCaseRequest request) {
// 判断当前项目下是否有默认模块没有添加默认模块
this.getDefaultNode(projectId);
request.setProjectId(projectId);
request.setUserId(SessionUtils.getUserId());
List<TestCaseNodeDTO> countMNodes = extTestCaseMapper.getCountNodes(request);
List<TestCaseNodeDTO> testCaseNodes = extTestCaseNodeMapper.getNodeTreeByProjectId(projectId);
return getNodeTrees(testCaseNodes, getCountMap(countMNodes));
}
/**
* 获取当前计划下
* 有关联数据的节点
@ -276,6 +276,13 @@ public class TestCaseNodeService extends NodeTreeService<TestCaseNodeDTO> {
return getNodeTreeWithPruningTree(countModules);
}
public List<TestCaseNodeDTO> getTrashCaseNode(String projectId, QueryTestCaseRequest request) {
request.setProjectId(projectId);
List<TestCaseNodeDTO> countModules = extTestCaseMapper.getCountNodes(request);
countModules.forEach(item -> item.setProjectId(projectId));
return getNodeTreeWithPruningTree(countModules);
}
public List<TestCaseNodeDTO> getNodeByPlanId(String planId) {
return this.getNodeByPlanId(planId, new QueryTestPlanCaseRequest());
}

View File

@ -763,7 +763,14 @@ public class TestCaseService {
if (request.getFilters() != null && !request.getFilters().containsKey("status")) {
request.getFilters().put("status", new ArrayList<>(0));
}
if (StringUtils.isBlank(request.getWorkspaceId())) {
MSException.throwException("workspaceId could not be null!");
}
request.setProjectId(null);
List<TestCaseDTO> returnList = extTestCaseMapper.publicList(request);
ServiceUtils.buildVersionInfo(returnList);
ServiceUtils.buildProjectInfo(returnList);
buildUserInfo(returnList);
returnList = this.parseStatus(returnList);
return returnList;
}

View File

@ -24,10 +24,18 @@
<ms-aside-container v-if="showPublicNode">
<test-case-public-node-tree
:case-condition="condition"
@nodeSelectEvent="publicNodeChange"
ref="publicNodeTree"/>
</ms-aside-container>
<ms-aside-container v-if="showTrashNode">
<test-case-trash-node-tree
:case-condition="condition"
@nodeSelectEvent="trashNodeChange"
ref="trashNodeTree"/>
</ms-aside-container>
<ms-main-container>
<el-tabs v-model="activeName" @tab-click="addTab" @tab-remove="closeConfirm">
<el-tab-pane name="trash" v-if="trashEnable" :label="$t('commons.trash')">
@ -43,13 +51,12 @@
:trash-enable="true"
:current-version="currentTrashVersion"
:version-enable="versionEnable"
@refreshTable="refresh"
@testCaseEdit="editTestCase"
@testCaseCopy="copyTestCase"
@testCaseDetail="showTestCaseDetail"
@getTrashList="getTrashList"
@getPublicList="getPublicList"
@refresh="refresh"
@refresh="refreshTrashNode"
@refreshAll="refreshAll"
@setCondition="setCondition"
@search="refreshTreeByCaseFilter"
@ -225,6 +232,7 @@ import {openMinderConfirm} from "@/business/components/track/common/minder/minde
import TestCaseEditShow from "@/business/components/track/case/components/TestCaseEditShow";
import {PROJECT_ID} from "@/common/js/constants";
import TestCasePublicNodeTree from "@/business/components/track/module/TestCasePublicNodeTree";
import TestCaseTrashNodeTree from "@/business/components/track/module/TestCaseTrashNodeTree";
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
const VersionSelect = requireComponent.keys().length > 0 ? requireComponent("./version/VersionSelect.vue") : {};
@ -232,6 +240,7 @@ const VersionSelect = requireComponent.keys().length > 0 ? requireComponent("./v
export default {
name: "TestCase",
components: {
TestCaseTrashNodeTree,
TestCasePublicNodeTree,
IsChangeConfirm,
TestCaseMinder,
@ -304,7 +313,7 @@ export default {
this.init(to);
},
activeName(newVal, oldVal) {
this.isAsideHidden = this.activeName === 'default' || this.activeName === 'trash';
this.isAsideHidden = this.activeName === 'default';
if (oldVal !== 'default' && newVal === 'default' && this.$refs.minder) {
this.$refs.minder.refresh();
}
@ -319,8 +328,10 @@ export default {
trashEnable() {
if (this.trashEnable) {
this.activeName = 'trash';
} else {
this.actciveName = 'default';
this.publicEnable = false;
this.$nextTick(() => {
this.$refs.trashNodeTree.list();
});
}
},
publicEnable() {
@ -329,8 +340,7 @@ export default {
this.$nextTick(() => {
this.$refs.publicNodeTree.list();
});
} else {
this.activeName = 'default';
this.trashEnable = false;
}
},
'$store.state.temWorkspaceId'() {
@ -352,6 +362,9 @@ export default {
showPublicNode() {
return this.activeName === 'public';
},
showTrashNode() {
return this.activeName === 'trash';
},
projectId() {
return getCurrentProjectID();
},
@ -473,6 +486,11 @@ export default {
this.$nextTick(() => {
this.publicEnable = true;
})
} else if (tab.name === 'trash') {
this.trashEnable = false;
this.$nextTick(() => {
this.trashEnable = true;
})
}
setCurTabId(this, tab, 'testCaseEdit');
@ -593,6 +611,11 @@ export default {
this.$refs.testCasePublicList.initTableData(nodeIds);
}
},
trashNodeChange(node, nodeIds, pNodes) {
if (this.$refs.testCaseTrashList) {
this.$refs.testCaseTrashList.initTableData(nodeIds);
}
},
increase(id) {
this.$refs.nodeTree.increase(id);
},
@ -668,10 +691,15 @@ export default {
}
this.refreshAll(data);
},
refreshTrashNode() {
this.$refs.trashNodeTree.list();
},
refreshTreeByCaseFilter() {
if (this.publicEnable) {
this.$refs.publicNodeTree.list(this.condition);
} else if (!this.trashEnable) {
this.$refs.publicNodeTree.list();
} else if (this.trashEnable) {
this.$refs.trashNodeTree.list();
} else {
this.$refs.nodeTree.list();
}
},

View File

@ -934,7 +934,7 @@ export default {
param.ids = [testCase.id];
param.projectId = getCurrentProjectID();
this.$post('/test/case/reduction', param, () => {
this.$emit('refreshTable');
this.$emit('refresh');
this.initTableData();
this.$success(this.$t('commons.save_success'));
});
@ -959,7 +959,7 @@ export default {
batchReduction() {
let param = buildBatchParam(this, this.$refs.table.selectIds);
this.$post('/test/case/reduction', param, () => {
this.$emit('refreshTable');
this.$emit('refresh');
this.initTableData();
this.$success(this.$t('commons.save_success'));
});
@ -973,6 +973,7 @@ export default {
this.$post('/test/case/batch/delete', param, () => {
this.$refs.table.clear();
this.$emit("refresh");
this.initTableData();
this.$success(this.$t('commons.delete_success'));
});
}
@ -1007,6 +1008,7 @@ export default {
_handleDelete(testCase) {
let testCaseId = testCase.id;
this.$post('/test/case/delete/' + testCaseId, {}, () => {
this.$emit('refresh');
this.initTableData();
this.$success(this.$t('commons.delete_success'));
this.$emit('decrease', testCase.nodeId);

View File

@ -14,6 +14,9 @@ import {getTestCasePublicNodes} from "@/network/testCase";
export default {
name: "TestCasePublicNodeTree",
components: {MsNodeTree},
props: {
caseCondition: Object
},
data() {
return {
publicTreeNodes: [],
@ -24,12 +27,8 @@ export default {
publicNodeChange(node, nodeIds, pNodes) {
this.$emit("nodeSelectEvent", node, node.data.id === 'root' ? [] : nodeIds, pNodes);
},
list(caseCondition) {
let condition = {
...caseCondition
};
condition.projectId = null;
this.result = getTestCasePublicNodes(condition, data => {
list() {
this.result = getTestCasePublicNodes(this.caseCondition, data => {
this.publicTreeNodes = data;
if (this.$refs.publicNodeTree) {
this.publicTreeNodes.forEach(firstLevel => {

View File

@ -0,0 +1,46 @@
<template>
<ms-node-tree class="node-tree"
v-loading="result.loading"
local-suffix="test_case"
default-label="未规划用例"
@nodeSelectEvent="publicNodeChange"
:tree-nodes="trashTreeNodes"
ref="trashNodeTree"/>
</template>
<script>
import MsNodeTree from "@/business/components/track/common/NodeTree";
import {getTestCaseTrashNodes} from "@/network/testCase";
export default {
name: "TestCaseTrashNodeTree",
components: {MsNodeTree},
props: {
caseCondition: Object
},
data() {
return {
trashTreeNodes: [],
result: {}
}
},
methods: {
publicNodeChange(node, nodeIds, pNodes) {
this.$emit("nodeSelectEvent", node, node.data.id === 'root' ? [] : nodeIds, pNodes);
},
list() {
this.result = getTestCaseTrashNodes(this.caseCondition, data => {
this.trashTreeNodes = data;
if (this.$refs.trashNodeTree) {
this.trashTreeNodes.forEach(firstLevel => {
this.$refs.trashNodeTree.nodeExpand(firstLevel);
})
}
});
},
}
}
</script>
<style scoped>
</style>

View File

@ -3,7 +3,7 @@ import {success} from "@/common/js/message";
import i18n from "@/i18n/i18n";
import {basePost} from "@/network/base-network";
import {baseGet} from "./base-network";
import {getCurrentWorkspaceId} from "@/common/js/utils";
import {getCurrentProjectID, getCurrentWorkspaceId} from "@/common/js/utils";
export const minderPageInfoMap = new Map();
@ -101,6 +101,10 @@ export function getTestCasePublicNodes(param, callback) {
return basePost('/case/node/list/public/' + getCurrentWorkspaceId(), param, callback);
}
export function getTestCaseTrashNodes(param, callback) {
return basePost('/case/node/list/trash/' + getCurrentProjectID(), param, callback);
}
export function getRelationshipCase(id, relationshipType, callback) {
return baseGet('/test/case/relationship/case/' + id + '/' + relationshipType, callback);
}