diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.xml index 8c44f7b5e0..4da6213863 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.xml @@ -269,8 +269,6 @@ @@ -313,27 +309,27 @@ diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanTestCaseMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanTestCaseMapper.xml index 312b04b00a..610854640d 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanTestCaseMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanTestCaseMapper.xml @@ -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 - group by test_case.node_id; + group by tcn.id; diff --git a/backend/src/main/java/io/metersphere/service/NodeTreeService.java b/backend/src/main/java/io/metersphere/service/NodeTreeService.java index 37d7db135c..d4d65e2208 100644 --- a/backend/src/main/java/io/metersphere/service/NodeTreeService.java +++ b/backend/src/main/java/io/metersphere/service/NodeTreeService.java @@ -158,6 +158,10 @@ public class NodeTreeService { 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); } diff --git a/backend/src/main/java/io/metersphere/track/controller/TestCaseNodeController.java b/backend/src/main/java/io/metersphere/track/controller/TestCaseNodeController.java index 0a2e2da65f..6b044c35d4 100644 --- a/backend/src/main/java/io/metersphere/track/controller/TestCaseNodeController.java +++ b/backend/src/main/java/io/metersphere/track/controller/TestCaseNodeController.java @@ -79,6 +79,11 @@ public class TestCaseNodeController { return testCaseNodeService.getPublicCaseNode(workspaceId, request); } + @PostMapping("/list/trash/{projectId}") + public List getTrashCaseNode(@PathVariable String projectId, @RequestBody QueryTestCaseRequest request) { + return testCaseNodeService.getTrashCaseNode(projectId, request); + } + @PostMapping("/list/plan/relate") public List getRelatePlanNodes(@RequestBody QueryTestCaseRequest request) { checkPermissionService.checkTestPlanOwner(request.getPlanId()); diff --git a/backend/src/main/java/io/metersphere/track/service/TestCaseNodeService.java b/backend/src/main/java/io/metersphere/track/service/TestCaseNodeService.java index b73eed0466..f4510f9416 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestCaseNodeService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestCaseNodeService.java @@ -144,16 +144,6 @@ public class TestCaseNodeService extends NodeTreeService { return getNodeTreeByProjectId(projectId, new QueryTestCaseRequest()); } - public List getNodeTreeByProjectId(String projectId, QueryTestCaseRequest request) { - // 判断当前项目下是否有默认模块,没有添加默认模块 - this.getDefaultNode(projectId); - request.setProjectId(projectId); - request.setUserId(SessionUtils.getUserId()); - List countMNodes = extTestCaseMapper.getCountNodes(request); - List testCaseNodes = extTestCaseNodeMapper.getNodeTreeByProjectId(projectId); - return getNodeTrees(testCaseNodes, getCountMap(countMNodes)); - } - private Map parseModuleCountList(List> moduleCountList) { Map returnMap = new HashMap<>(); for (Map map : moduleCountList) { @@ -254,6 +244,16 @@ public class TestCaseNodeService extends NodeTreeService { return list; } + public List getNodeTreeByProjectId(String projectId, QueryTestCaseRequest request) { + // 判断当前项目下是否有默认模块,没有添加默认模块 + this.getDefaultNode(projectId); + request.setProjectId(projectId); + request.setUserId(SessionUtils.getUserId()); + List countMNodes = extTestCaseMapper.getCountNodes(request); + List testCaseNodes = extTestCaseNodeMapper.getNodeTreeByProjectId(projectId); + return getNodeTrees(testCaseNodes, getCountMap(countMNodes)); + } + /** * 获取当前计划下 * 有关联数据的节点 @@ -276,6 +276,13 @@ public class TestCaseNodeService extends NodeTreeService { return getNodeTreeWithPruningTree(countModules); } + public List getTrashCaseNode(String projectId, QueryTestCaseRequest request) { + request.setProjectId(projectId); + List countModules = extTestCaseMapper.getCountNodes(request); + countModules.forEach(item -> item.setProjectId(projectId)); + return getNodeTreeWithPruningTree(countModules); + } + public List getNodeByPlanId(String planId) { return this.getNodeByPlanId(planId, new QueryTestPlanCaseRequest()); } diff --git a/backend/src/main/java/io/metersphere/track/service/TestCaseService.java b/backend/src/main/java/io/metersphere/track/service/TestCaseService.java index bd66027403..0a845364b7 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestCaseService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestCaseService.java @@ -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 returnList = extTestCaseMapper.publicList(request); + ServiceUtils.buildVersionInfo(returnList); + ServiceUtils.buildProjectInfo(returnList); + buildUserInfo(returnList); returnList = this.parseStatus(returnList); return returnList; } diff --git a/frontend/src/business/components/track/case/TestCase.vue b/frontend/src/business/components/track/case/TestCase.vue index 7e01ab0603..959e233ebe 100644 --- a/frontend/src/business/components/track/case/TestCase.vue +++ b/frontend/src/business/components/track/case/TestCase.vue @@ -24,10 +24,18 @@ + + + + @@ -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(); } }, diff --git a/frontend/src/business/components/track/case/components/TestCaseList.vue b/frontend/src/business/components/track/case/components/TestCaseList.vue index b89964790e..494c4dc66a 100644 --- a/frontend/src/business/components/track/case/components/TestCaseList.vue +++ b/frontend/src/business/components/track/case/components/TestCaseList.vue @@ -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); diff --git a/frontend/src/business/components/track/module/TestCasePublicNodeTree.vue b/frontend/src/business/components/track/module/TestCasePublicNodeTree.vue index 83493f705d..675d38db2f 100644 --- a/frontend/src/business/components/track/module/TestCasePublicNodeTree.vue +++ b/frontend/src/business/components/track/module/TestCasePublicNodeTree.vue @@ -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 => { diff --git a/frontend/src/business/components/track/module/TestCaseTrashNodeTree.vue b/frontend/src/business/components/track/module/TestCaseTrashNodeTree.vue new file mode 100644 index 0000000000..61f86bdb06 --- /dev/null +++ b/frontend/src/business/components/track/module/TestCaseTrashNodeTree.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/frontend/src/network/testCase.js b/frontend/src/network/testCase.js index e234293cb9..e770152481 100644 --- a/frontend/src/network/testCase.js +++ b/frontend/src/network/testCase.js @@ -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); }