diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger3Parser.java b/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger3Parser.java index 8b5400bc40..6e23699cd6 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger3Parser.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger3Parser.java @@ -295,6 +295,7 @@ public class Swagger3Parser extends SwaggerAbstractParser { } private void parseKvBody(Schema schema, Body body, Object data, Map infoMap) { + if (data == null) return; if (data instanceof JSONObject) { ((JSONObject) data).forEach((k, v) -> { Schema dataSchema = (Schema) v; @@ -311,6 +312,9 @@ public class Swagger3Parser extends SwaggerAbstractParser { body.getKvs().add(kv); }); } else { + if (data instanceof String && StringUtils.isBlank((String) data)) { + return; + } Schema dataSchema = (Schema) data; KeyValue kv = new KeyValue(schema.getName(), String.valueOf(dataSchema.getExample()), schema.getDescription()); Schema schemaInfo = infoMap.get(schema.getName()); diff --git a/backend/src/main/java/io/metersphere/controller/MinderExtraNodeController.java b/backend/src/main/java/io/metersphere/controller/MinderExtraNodeController.java index 89fd85b1c9..d6ea25332b 100644 --- a/backend/src/main/java/io/metersphere/controller/MinderExtraNodeController.java +++ b/backend/src/main/java/io/metersphere/controller/MinderExtraNodeController.java @@ -1,11 +1,11 @@ package io.metersphere.controller; import io.metersphere.base.domain.MinderExtraNode; -import io.metersphere.commons.constants.PermissionConstants; import io.metersphere.service.MinderExtraNodeService; -import io.metersphere.track.request.MinderExtraNodeEditRequest; -import org.apache.shiro.authz.annotation.RequiresPermissions; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.util.List; @@ -17,11 +17,11 @@ public class MinderExtraNodeController { @Resource MinderExtraNodeService minderExtraNodeService; - @PostMapping("/batch/edit") - @RequiresPermissions(PermissionConstants.PROJECT_TRACK_CASE_READ_EDIT) - public void minderEdit(@RequestBody MinderExtraNodeEditRequest request) { - minderExtraNodeService.batchEdit(request); - } +// @PostMapping("/batch/edit") +// @RequiresPermissions(PermissionConstants.PROJECT_TRACK_CASE_READ_EDIT) +// public void minderEdit(@RequestBody TestCaseMinderEditRequest.MinderExtraNodeEditRequest request) { +// minderExtraNodeService.batchEdit(request); +// } @GetMapping("/list/{groupId}/{parentId}") public List list(@PathVariable String groupId, @PathVariable String parentId) { diff --git a/backend/src/main/java/io/metersphere/service/MinderExtraNodeService.java b/backend/src/main/java/io/metersphere/service/MinderExtraNodeService.java index b263f154de..da68defe58 100644 --- a/backend/src/main/java/io/metersphere/service/MinderExtraNodeService.java +++ b/backend/src/main/java/io/metersphere/service/MinderExtraNodeService.java @@ -4,16 +4,14 @@ import com.alibaba.fastjson.JSONObject; import io.metersphere.base.domain.MinderExtraNode; import io.metersphere.base.domain.MinderExtraNodeExample; import io.metersphere.base.mapper.MinderExtraNodeMapper; -import io.metersphere.track.request.MinderExtraNodeEditRequest; +import io.metersphere.track.request.testcase.TestCaseMinderEditRequest; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.List; import java.util.Map; -import java.util.UUID; @Service @Transactional(rollbackFor = Exception.class) @@ -22,8 +20,9 @@ public class MinderExtraNodeService { @Resource MinderExtraNodeMapper minderExtraNodeMapper; - public void batchEdit(MinderExtraNodeEditRequest request) { - Map> data = request.getData(); + public void batchEdit(TestCaseMinderEditRequest request) { + TestCaseMinderEditRequest.MinderExtraNodeEditRequest extraNodeRequest = request.getExtraNodeRequest(); + Map> data = extraNodeRequest.getData(); if (data != null) { data.forEach((parentId, nodes) -> { nodes.forEach(node -> { @@ -32,16 +31,14 @@ public class MinderExtraNodeService { minderExtraNode.setParentId(parentId); JSONObject nodeObj = JSONObject.parseObject(node); String id = nodeObj.getString("id"); - if (StringUtils.isBlank(id) || id.length() < 20) { - minderExtraNode.setId(UUID.randomUUID().toString()); - minderExtraNode.setGroupId(request.getGroupId()); - minderExtraNode.setType(request.getType()); - nodeObj.put("id", minderExtraNode.getId()); + minderExtraNode.setId(id); + if (nodeObj.getBoolean("isEdit")) { + minderExtraNodeMapper.updateByPrimaryKeySelective(minderExtraNode); + } else { + minderExtraNode.setGroupId(extraNodeRequest.getGroupId()); + minderExtraNode.setType(extraNodeRequest.getType()); minderExtraNode.setNodeData(nodeObj.toJSONString()); minderExtraNodeMapper.insert(minderExtraNode); - } else { - minderExtraNode.setId(id); - minderExtraNodeMapper.updateByPrimaryKeySelective(minderExtraNode); } }); }); @@ -59,4 +56,4 @@ public class MinderExtraNodeService { example.createCriteria().andParentIdEqualTo(parentId).andGroupIdEqualTo(groupId); return minderExtraNodeMapper.selectByExampleWithBLOBs(example); } -} \ No newline at end of file +} diff --git a/backend/src/main/java/io/metersphere/track/request/MinderExtraNodeEditRequest.java b/backend/src/main/java/io/metersphere/track/request/MinderExtraNodeEditRequest.java deleted file mode 100644 index 6988cffabe..0000000000 --- a/backend/src/main/java/io/metersphere/track/request/MinderExtraNodeEditRequest.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.metersphere.track.request; - -import io.metersphere.base.domain.MinderExtraNode; -import lombok.Getter; -import lombok.Setter; - -import java.util.List; -import java.util.Map; - -@Getter -@Setter -public class MinderExtraNodeEditRequest extends MinderExtraNode { - private String projectId; - // 删除的id - private List ids; - // key 为父节点id - private Map> data; -} diff --git a/backend/src/main/java/io/metersphere/track/request/testcase/TestCaseMinderEditRequest.java b/backend/src/main/java/io/metersphere/track/request/testcase/TestCaseMinderEditRequest.java index 3661a13f0a..65d2400882 100644 --- a/backend/src/main/java/io/metersphere/track/request/testcase/TestCaseMinderEditRequest.java +++ b/backend/src/main/java/io/metersphere/track/request/testcase/TestCaseMinderEditRequest.java @@ -1,22 +1,42 @@ package io.metersphere.track.request.testcase; +import io.metersphere.base.domain.MinderExtraNode; +import io.metersphere.base.domain.TestCaseNode; import io.metersphere.base.domain.TestCaseWithBLOBs; import lombok.Getter; import lombok.Setter; import java.util.List; +import java.util.Map; @Getter @Setter public class TestCaseMinderEditRequest { private String projectId; private List ids; - List data; + private List data; + private List testCaseNodes; + + private MinderExtraNodeEditRequest extraNodeRequest; + + @Getter + @Setter + public static class MinderExtraNodeEditRequest extends MinderExtraNode { + private Map> data; + } @Getter @Setter public static class TestCaseMinderEditItem extends TestCaseWithBLOBs { + private Boolean isEdit; private String targetId; private String moveMode; } + + @Getter + @Setter + public static class TestCaseNodeMinderEditItem extends TestCaseNode { + private Boolean isEdit; + private List nodeIds; + } } 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 d0afcd86ed..ba4f362205 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestCaseNodeService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestCaseNodeService.java @@ -10,6 +10,7 @@ import io.metersphere.base.mapper.ext.ExtTestCaseNodeMapper; import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper; import io.metersphere.commons.constants.TestCaseConstants; import io.metersphere.commons.exception.MSException; +import io.metersphere.commons.utils.BeanUtils; import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.commons.utils.SessionUtils; import io.metersphere.dto.NodeNumDTO; @@ -23,10 +24,7 @@ import io.metersphere.service.NodeTreeService; import io.metersphere.track.dto.TestCaseDTO; import io.metersphere.track.dto.TestCaseNodeDTO; import io.metersphere.track.dto.TestPlanCaseDTO; -import io.metersphere.track.request.testcase.DragNodeRequest; -import io.metersphere.track.request.testcase.QueryNodeRequest; -import io.metersphere.track.request.testcase.QueryTestCaseRequest; -import io.metersphere.track.request.testcase.TestCaseBatchRequest; +import io.metersphere.track.request.testcase.*; import io.metersphere.track.request.testplancase.QueryTestPlanCaseRequest; import org.apache.commons.lang3.StringUtils; import org.apache.ibatis.session.ExecutorType; @@ -65,8 +63,6 @@ public class TestCaseNodeService extends NodeTreeService { @Resource ProjectMapper projectMapper; @Resource - TestCaseReviewService testCaseReviewService; - @Resource TestCaseReviewTestCaseMapper testCaseReviewTestCaseMapper; @Resource TestCaseReviewMapper testCaseReviewMapper; @@ -79,7 +75,9 @@ public class TestCaseNodeService extends NodeTreeService { validateNode(node); node.setCreateTime(System.currentTimeMillis()); node.setUpdateTime(System.currentTimeMillis()); - node.setId(UUID.randomUUID().toString()); + if (StringUtils.isBlank(node.getId())) { + node.setId(UUID.randomUUID().toString()); + } node.setCreateUser(SessionUtils.getUserId()); double pos = getNextLevelPos(node.getProjectId(), node.getLevel(), node.getParentId()); node.setPos(pos); @@ -91,8 +89,6 @@ public class TestCaseNodeService extends NodeTreeService { return extTestCaseNodeMapper.getNodes(nodeId); } - ; - private void validateNode(TestCaseNode node) { if (node.getLevel() > TestCaseConstants.MAX_NODE_DEPTH) { throw new RuntimeException(Translator.get("test_case_node_level_tip") @@ -236,25 +232,27 @@ public class TestCaseNodeService extends NodeTreeService { public int editNode(DragNodeRequest request) { request.setUpdateTime(System.currentTimeMillis()); checkTestCaseNodeExist(request); - List testCases = QueryTestCaseByNodeIds(request.getNodeIds()); - - testCases.forEach(testCase -> { - StringBuilder path = new StringBuilder(testCase.getNodePath()); - List pathLists = Arrays.asList(path.toString().split("/")); - pathLists.set(request.getLevel(), request.getName()); - path.delete(0, path.length()); - for (int i = 1; i < pathLists.size(); i++) { - path = path.append("/").append(pathLists.get(i)); - } - testCase.setNodePath(path.toString()); - }); - - batchUpdateTestCase(testCases); - + if (!CollectionUtils.isEmpty(request.getNodeIds())) { + List testCases = QueryTestCaseByNodeIds(request.getNodeIds()); + testCases.forEach(testCase -> { + StringBuilder path = new StringBuilder(testCase.getNodePath()); + List pathLists = Arrays.asList(path.toString().split("/")); + pathLists.set(request.getLevel(), request.getName()); + path.delete(0, path.length()); + for (int i = 1; i < pathLists.size(); i++) { + path = path.append("/").append(pathLists.get(i)); + } + testCase.setNodePath(path.toString()); + }); + batchUpdateTestCase(testCases); + } return testCaseNodeMapper.updateByPrimaryKeySelective(request); } public int deleteNode(List nodeIds) { + if (CollectionUtils.isEmpty(nodeIds)) { + return 1; + } TestCaseService testCaseService = CommonBeanFactory.getBean(TestCaseService.class); List testCaseIdList = this.selectCaseIdByNodeIds(nodeIds); TestCaseBatchRequest request = new TestCaseBatchRequest(); @@ -770,4 +768,29 @@ public class TestCaseNodeService extends NodeTreeService { testCaseExample.createCriteria().andProjectIdEqualTo(projectId).andStatusEqualTo("Trash"); return testCaseMapper.countByExample(testCaseExample); } + + public void minderEdit(TestCaseMinderEditRequest request) { + deleteNode(request.getIds()); + + List testCaseNodes = request.getTestCaseNodes(); + if (org.apache.commons.collections.CollectionUtils.isNotEmpty(testCaseNodes)) { + + for (TestCaseMinderEditRequest.TestCaseNodeMinderEditItem item: testCaseNodes) { + if (StringUtils.isBlank(item.getParentId()) || item.getParentId().equals("root")) { + item.setParentId(""); + } + item.setProjectId(request.getProjectId()); + if (item.getIsEdit()) { + DragNodeRequest editNode = new DragNodeRequest(); + BeanUtils.copyBean(editNode, item); + editNode(editNode); + } else { + TestCaseNode testCaseNode = new TestCaseNode(); + BeanUtils.copyBean(testCaseNode, item); + testCaseNode.setProjectId(request.getProjectId()); + addNode(testCaseNode); + } + } + } + } } 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 e48e5ab184..c77cb959df 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestCaseService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestCaseService.java @@ -145,6 +145,8 @@ public class TestCaseService { @Resource @Lazy private TestPlanService testPlanService; + @Resource + private MinderExtraNodeService minderExtraNodeService; private void setNode(TestCaseWithBLOBs testCase) { if (StringUtils.isEmpty(testCase.getNodeId()) || "default-module".equals(testCase.getNodeId())) { @@ -1480,10 +1482,15 @@ public class TestCaseService { } public void minderEdit(TestCaseMinderEditRequest request) { + + deleteToGcBatch(request.getIds()); + + testCaseNodeService.minderEdit(request); + List data = request.getData(); if (CollectionUtils.isNotEmpty(data)) { List editIds = data.stream() - .filter(t -> StringUtils.isNotBlank(t.getId()) && t.getId().length() > 20) + .filter(TestCaseMinderEditRequest.TestCaseMinderEditItem::getIsEdit) .map(TestCaseWithBLOBs::getId).collect(Collectors.toList()); Map testCaseMap = new HashMap<>(); @@ -1494,31 +1501,29 @@ public class TestCaseService { testCaseMap = testCaseWithBLOBs.stream().collect(Collectors.toMap(TestCaseWithBLOBs::getId, t -> t)); } - Map finalTestCaseMap = testCaseMap; - data.forEach(item -> { + for (TestCaseMinderEditRequest.TestCaseMinderEditItem item: data) { if (StringUtils.isBlank(item.getNodeId()) || item.getNodeId().equals("root")) { item.setNodeId(""); } item.setProjectId(request.getProjectId()); - if (StringUtils.isBlank(item.getId()) || item.getId().length() < 20) { - item.setId(UUID.randomUUID().toString()); - item.setMaintainer(SessionUtils.getUserId()); - EditTestCaseRequest editTestCaseRequest = new EditTestCaseRequest(); - BeanUtils.copyBean(editTestCaseRequest, item); - addTestCase(editTestCaseRequest); - changeOrder(item, request.getProjectId()); - } else { - TestCaseWithBLOBs dbCase = finalTestCaseMap.get(item.getId()); + if (item.getIsEdit()) { + TestCaseWithBLOBs dbCase = testCaseMap.get(item.getId()); if (editCustomFieldsPriority(dbCase, item.getPriority())) { item.setCustomFields(dbCase.getCustomFields()); } editTestCase(item); changeOrder(item, request.getProjectId()); + } else { + item.setMaintainer(SessionUtils.getUserId()); + EditTestCaseRequest editTestCaseRequest = new EditTestCaseRequest(); + BeanUtils.copyBean(editTestCaseRequest, item); + addTestCase(editTestCaseRequest); + changeOrder(item, request.getProjectId()); } - }); + } } - List ids = request.getIds(); - deleteToGcBatch(ids); + + minderExtraNodeService.batchEdit(request); } private void changeOrder(TestCaseMinderEditRequest.TestCaseMinderEditItem item, String projectId) { diff --git a/backend/src/main/java/io/metersphere/track/service/TestPlanReportService.java b/backend/src/main/java/io/metersphere/track/service/TestPlanReportService.java index 7cf918972c..420e5ad9cd 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestPlanReportService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestPlanReportService.java @@ -268,9 +268,9 @@ public class TestPlanReportService { // testPlanReport.setPrincipal(testPlan.getPrincipal()); if (testPlanReport.getIsScenarioExecuting() || testPlanReport.getIsApiCaseExecuting() || testPlanReport.getIsPerformanceExecuting()) { - testPlanReport.setStatus(APITestStatus.Running.name()); + testPlanReport.setStatus(TestPlanReportStatus.RUNNING.name()); } else { - testPlanReport.setStatus(APITestStatus.Completed.name()); + testPlanReport.setStatus(TestPlanReportStatus.COMPLETED.name()); } testPlanReportMapper.insert(testPlanReport); diff --git a/frontend/package.json b/frontend/package.json index baa35d5733..8aabb05eea 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -54,7 +54,7 @@ "vue-float-action-button": "^0.6.6", "vue-i18n": "^8.15.3", "vue-jsonpath-picker": "^1.1.5", - "vue-minder-editor-plus": "1.0.30", + "vue-minder-editor-plus": "1.0.33", "vue-papa-parse": "^2.0.0", "vue-pdf": "^4.2.0", "vue-router": "^3.1.3", diff --git a/frontend/src/business/components/common/components/MsModuleMinder.vue b/frontend/src/business/components/common/components/MsModuleMinder.vue index 85b97adf60..7a301bd8c4 100644 --- a/frontend/src/business/components/common/components/MsModuleMinder.vue +++ b/frontend/src/business/components/common/components/MsModuleMinder.vue @@ -69,7 +69,13 @@ export default { priorityDisableCheck: Function, disabled: Boolean, ignoreNum: Boolean, - showModuleTag: Boolean + showModuleTag: Boolean, + moduleDisable: { + type: Boolean, + default() { + return true; + } + } }, data() { return { @@ -80,6 +86,7 @@ export default { disable: true, id: "root", type: 'node', + level: 0, resource: this.showModuleTag ? ['模块'] : [], path: "", tagEnable: this.tagEnable @@ -150,8 +157,9 @@ export default { data: { text: item.name, id: item.id, - disable: true, + disable: this.moduleDisable, type: 'node', + level: item.level, resource: this.showModuleTag ? ['模块'] : [], caseNum: item.caseNum, path: root.data.path + "/" + item.name, @@ -206,9 +214,10 @@ export default { data: { text: nodeData.name, id: nodeData.id, - disable: true, + disable: this.moduleDisable, tagEnable: this.tagEnable, type: 'node', + level: nodeData.level, resource: this.showModuleTag ? ['模块'] : [], }, children: [] diff --git a/frontend/src/business/components/track/common/minder/TestCaseMinder.vue b/frontend/src/business/components/track/common/minder/TestCaseMinder.vue index 1871d0ec87..8afc87444b 100644 --- a/frontend/src/business/components/track/common/minder/TestCaseMinder.vue +++ b/frontend/src/business/components/track/common/minder/TestCaseMinder.vue @@ -6,6 +6,7 @@ minder-key="testCase" :select-node="selectNode" :distinct-tags="tags" + :module-disable="false" :show-module-tag="true" :tag-edit-check="tagEditCheck()" @afterMount="handleAfterMount" @@ -19,6 +20,7 @@