From 25d62b63976b5173658e9fa736b96664066756bf Mon Sep 17 00:00:00 2001 From: shiziyuan9527 Date: Thu, 29 Oct 2020 18:16:35 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=B5=8B=E8=AF=95=E8=B7=9F=E8=B8=AA):=20?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B=E5=90=8C=E7=BA=A7=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../metersphere/base/domain/TestCaseNode.java | 2 + .../base/domain/TestCaseNodeExample.java | 112 ++++++++++++++---- .../base/mapper/TestCaseNodeMapper.java | 6 +- .../base/mapper/TestCaseNodeMapper.xml | 67 +++++------ .../controller/TestCaseNodeController.java | 5 + .../track/service/TestCaseNodeService.java | 62 +++++++++- .../components/track/common/NodeTree.vue | 23 +++- 7 files changed, 211 insertions(+), 66 deletions(-) diff --git a/backend/src/main/java/io/metersphere/base/domain/TestCaseNode.java b/backend/src/main/java/io/metersphere/base/domain/TestCaseNode.java index d17174d90e..7ab9e4040b 100644 --- a/backend/src/main/java/io/metersphere/base/domain/TestCaseNode.java +++ b/backend/src/main/java/io/metersphere/base/domain/TestCaseNode.java @@ -19,5 +19,7 @@ public class TestCaseNode implements Serializable { private Long updateTime; + private Double pos; + private static final long serialVersionUID = 1L; } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/domain/TestCaseNodeExample.java b/backend/src/main/java/io/metersphere/base/domain/TestCaseNodeExample.java index 9b76aaada3..b1d94317e9 100644 --- a/backend/src/main/java/io/metersphere/base/domain/TestCaseNodeExample.java +++ b/backend/src/main/java/io/metersphere/base/domain/TestCaseNodeExample.java @@ -245,72 +245,72 @@ public class TestCaseNodeExample { } public Criteria andNameIsNull() { - addCriterion("name is null"); + addCriterion("`name` is null"); return (Criteria) this; } public Criteria andNameIsNotNull() { - addCriterion("name is not null"); + addCriterion("`name` is not null"); return (Criteria) this; } public Criteria andNameEqualTo(String value) { - addCriterion("name =", value, "name"); + addCriterion("`name` =", value, "name"); return (Criteria) this; } public Criteria andNameNotEqualTo(String value) { - addCriterion("name <>", value, "name"); + addCriterion("`name` <>", value, "name"); return (Criteria) this; } public Criteria andNameGreaterThan(String value) { - addCriterion("name >", value, "name"); + addCriterion("`name` >", value, "name"); return (Criteria) this; } public Criteria andNameGreaterThanOrEqualTo(String value) { - addCriterion("name >=", value, "name"); + addCriterion("`name` >=", value, "name"); return (Criteria) this; } public Criteria andNameLessThan(String value) { - addCriterion("name <", value, "name"); + addCriterion("`name` <", value, "name"); return (Criteria) this; } public Criteria andNameLessThanOrEqualTo(String value) { - addCriterion("name <=", value, "name"); + addCriterion("`name` <=", value, "name"); return (Criteria) this; } public Criteria andNameLike(String value) { - addCriterion("name like", value, "name"); + addCriterion("`name` like", value, "name"); return (Criteria) this; } public Criteria andNameNotLike(String value) { - addCriterion("name not like", value, "name"); + addCriterion("`name` not like", value, "name"); return (Criteria) this; } public Criteria andNameIn(List values) { - addCriterion("name in", values, "name"); + addCriterion("`name` in", values, "name"); return (Criteria) this; } public Criteria andNameNotIn(List values) { - addCriterion("name not in", values, "name"); + addCriterion("`name` not in", values, "name"); return (Criteria) this; } public Criteria andNameBetween(String value1, String value2) { - addCriterion("name between", value1, value2, "name"); + addCriterion("`name` between", value1, value2, "name"); return (Criteria) this; } public Criteria andNameNotBetween(String value1, String value2) { - addCriterion("name not between", value1, value2, "name"); + addCriterion("`name` not between", value1, value2, "name"); return (Criteria) this; } @@ -385,62 +385,62 @@ public class TestCaseNodeExample { } public Criteria andLevelIsNull() { - addCriterion("level is null"); + addCriterion("`level` is null"); return (Criteria) this; } public Criteria andLevelIsNotNull() { - addCriterion("level is not null"); + addCriterion("`level` is not null"); return (Criteria) this; } public Criteria andLevelEqualTo(Integer value) { - addCriterion("level =", value, "level"); + addCriterion("`level` =", value, "level"); return (Criteria) this; } public Criteria andLevelNotEqualTo(Integer value) { - addCriterion("level <>", value, "level"); + addCriterion("`level` <>", value, "level"); return (Criteria) this; } public Criteria andLevelGreaterThan(Integer value) { - addCriterion("level >", value, "level"); + addCriterion("`level` >", value, "level"); return (Criteria) this; } public Criteria andLevelGreaterThanOrEqualTo(Integer value) { - addCriterion("level >=", value, "level"); + addCriterion("`level` >=", value, "level"); return (Criteria) this; } public Criteria andLevelLessThan(Integer value) { - addCriterion("level <", value, "level"); + addCriterion("`level` <", value, "level"); return (Criteria) this; } public Criteria andLevelLessThanOrEqualTo(Integer value) { - addCriterion("level <=", value, "level"); + addCriterion("`level` <=", value, "level"); return (Criteria) this; } public Criteria andLevelIn(List values) { - addCriterion("level in", values, "level"); + addCriterion("`level` in", values, "level"); return (Criteria) this; } public Criteria andLevelNotIn(List values) { - addCriterion("level not in", values, "level"); + addCriterion("`level` not in", values, "level"); return (Criteria) this; } public Criteria andLevelBetween(Integer value1, Integer value2) { - addCriterion("level between", value1, value2, "level"); + addCriterion("`level` between", value1, value2, "level"); return (Criteria) this; } public Criteria andLevelNotBetween(Integer value1, Integer value2) { - addCriterion("level not between", value1, value2, "level"); + addCriterion("`level` not between", value1, value2, "level"); return (Criteria) this; } @@ -563,6 +563,66 @@ public class TestCaseNodeExample { addCriterion("update_time not between", value1, value2, "updateTime"); return (Criteria) this; } + + public Criteria andPosIsNull() { + addCriterion("pos is null"); + return (Criteria) this; + } + + public Criteria andPosIsNotNull() { + addCriterion("pos is not null"); + return (Criteria) this; + } + + public Criteria andPosEqualTo(Double value) { + addCriterion("pos =", value, "pos"); + return (Criteria) this; + } + + public Criteria andPosNotEqualTo(Double value) { + addCriterion("pos <>", value, "pos"); + return (Criteria) this; + } + + public Criteria andPosGreaterThan(Double value) { + addCriterion("pos >", value, "pos"); + return (Criteria) this; + } + + public Criteria andPosGreaterThanOrEqualTo(Double value) { + addCriterion("pos >=", value, "pos"); + return (Criteria) this; + } + + public Criteria andPosLessThan(Double value) { + addCriterion("pos <", value, "pos"); + return (Criteria) this; + } + + public Criteria andPosLessThanOrEqualTo(Double value) { + addCriterion("pos <=", value, "pos"); + return (Criteria) this; + } + + public Criteria andPosIn(List values) { + addCriterion("pos in", values, "pos"); + return (Criteria) this; + } + + public Criteria andPosNotIn(List values) { + addCriterion("pos not in", values, "pos"); + return (Criteria) this; + } + + public Criteria andPosBetween(Double value1, Double value2) { + addCriterion("pos between", value1, value2, "pos"); + return (Criteria) this; + } + + public Criteria andPosNotBetween(Double value1, Double value2) { + addCriterion("pos not between", value1, value2, "pos"); + return (Criteria) this; + } } public static class Criteria extends GeneratedCriteria { diff --git a/backend/src/main/java/io/metersphere/base/mapper/TestCaseNodeMapper.java b/backend/src/main/java/io/metersphere/base/mapper/TestCaseNodeMapper.java index f722b5b2a9..4e88faf0e7 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/TestCaseNodeMapper.java +++ b/backend/src/main/java/io/metersphere/base/mapper/TestCaseNodeMapper.java @@ -2,9 +2,8 @@ package io.metersphere.base.mapper; import io.metersphere.base.domain.TestCaseNode; import io.metersphere.base.domain.TestCaseNodeExample; -import org.apache.ibatis.annotations.Param; - import java.util.List; +import org.apache.ibatis.annotations.Param; public interface TestCaseNodeMapper { long countByExample(TestCaseNodeExample example); @@ -15,9 +14,6 @@ public interface TestCaseNodeMapper { int insert(TestCaseNode record); - int insertBatch(@Param("records") List records); - - int insertSelective(TestCaseNode record); List selectByExample(TestCaseNodeExample example); diff --git a/backend/src/main/java/io/metersphere/base/mapper/TestCaseNodeMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/TestCaseNodeMapper.xml index 937db25de9..a85376c6b8 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/TestCaseNodeMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/TestCaseNodeMapper.xml @@ -9,6 +9,7 @@ + @@ -69,7 +70,7 @@ - id, project_id, name, parent_id, level, create_time, update_time + id, project_id, `name`, parent_id, `level`, create_time, update_time, pos @@ -188,13 +181,13 @@ project_id = #{record.projectId,jdbcType=VARCHAR}, - name = #{record.name,jdbcType=VARCHAR}, + `name` = #{record.name,jdbcType=VARCHAR}, parent_id = #{record.parentId,jdbcType=VARCHAR}, - level = #{record.level,jdbcType=INTEGER}, + `level` = #{record.level,jdbcType=INTEGER}, create_time = #{record.createTime,jdbcType=BIGINT}, @@ -202,6 +195,9 @@ update_time = #{record.updateTime,jdbcType=BIGINT}, + + pos = #{record.pos,jdbcType=DOUBLE}, + @@ -211,11 +207,12 @@ update test_case_node set id = #{record.id,jdbcType=VARCHAR}, project_id = #{record.projectId,jdbcType=VARCHAR}, - name = #{record.name,jdbcType=VARCHAR}, + `name` = #{record.name,jdbcType=VARCHAR}, parent_id = #{record.parentId,jdbcType=VARCHAR}, - level = #{record.level,jdbcType=INTEGER}, + `level` = #{record.level,jdbcType=INTEGER}, create_time = #{record.createTime,jdbcType=BIGINT}, - update_time = #{record.updateTime,jdbcType=BIGINT} + update_time = #{record.updateTime,jdbcType=BIGINT}, + pos = #{record.pos,jdbcType=DOUBLE} @@ -227,13 +224,13 @@ project_id = #{projectId,jdbcType=VARCHAR}, - name = #{name,jdbcType=VARCHAR}, + `name` = #{name,jdbcType=VARCHAR}, parent_id = #{parentId,jdbcType=VARCHAR}, - level = #{level,jdbcType=INTEGER}, + `level` = #{level,jdbcType=INTEGER}, create_time = #{createTime,jdbcType=BIGINT}, @@ -241,17 +238,21 @@ update_time = #{updateTime,jdbcType=BIGINT}, + + pos = #{pos,jdbcType=DOUBLE}, + where id = #{id,jdbcType=VARCHAR} update test_case_node set project_id = #{projectId,jdbcType=VARCHAR}, - name = #{name,jdbcType=VARCHAR}, + `name` = #{name,jdbcType=VARCHAR}, parent_id = #{parentId,jdbcType=VARCHAR}, - level = #{level,jdbcType=INTEGER}, + `level` = #{level,jdbcType=INTEGER}, create_time = #{createTime,jdbcType=BIGINT}, - update_time = #{updateTime,jdbcType=BIGINT} + update_time = #{updateTime,jdbcType=BIGINT}, + pos = #{pos,jdbcType=DOUBLE} where id = #{id,jdbcType=VARCHAR} \ No newline at end of file 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 e1109a1428..0a7f52ee72 100644 --- a/backend/src/main/java/io/metersphere/track/controller/TestCaseNodeController.java +++ b/backend/src/main/java/io/metersphere/track/controller/TestCaseNodeController.java @@ -77,4 +77,9 @@ public class TestCaseNodeController { public void dragNode(@RequestBody DragNodeRequest node) { testCaseNodeService.dragNode(node); } + + @PostMapping("/pos") + public void treeSort(@RequestBody List ids) { + testCaseNodeService.sort(ids); + } } 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 4c66a29c5f..5610abfe9f 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestCaseNodeService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestCaseNodeService.java @@ -58,6 +58,8 @@ public class TestCaseNodeService { node.setCreateTime(System.currentTimeMillis()); node.setUpdateTime(System.currentTimeMillis()); node.setId(UUID.randomUUID().toString()); + double pos = getNextLevelPos(node.getProjectId(), node.getLevel()); + node.setPos(pos); testCaseNodeMapper.insertSelective(node); return node.getId(); } @@ -93,7 +95,7 @@ public class TestCaseNodeService { public List getNodeTreeByProjectId(String projectId) { TestCaseNodeExample testCaseNodeExample = new TestCaseNodeExample(); testCaseNodeExample.createCriteria().andProjectIdEqualTo(projectId); - testCaseNodeExample.setOrderByClause("create_time asc"); + testCaseNodeExample.setOrderByClause("pos asc"); List nodes = testCaseNodeMapper.selectByExample(testCaseNodeExample); return getNodeTrees(nodes); } @@ -486,6 +488,8 @@ public class TestCaseNodeService { testCaseNode.setUpdateTime(System.currentTimeMillis()); testCaseNode.setLevel(level); testCaseNode.setId(UUID.randomUUID().toString()); + double pos = getNextLevelPos(projectId, level); + testCaseNode.setPos(pos); testCaseNodeMapper.insert(testCaseNode); return testCaseNode.getId(); } @@ -574,4 +578,60 @@ public class TestCaseNodeService { return projectMapper.selectByPrimaryKey(projectId); } + private TestCaseNode getCaseNode(String id) { + return testCaseNodeMapper.selectByPrimaryKey(id); + } + + + /** + * 测试用例同级模块排序 + * @param ids + */ + public void sort(List ids) { + // 获取同级相邻节点 + String before = ids.get(0); + String id = ids.get(1); + String after = ids.get(2); + + TestCaseNode beforeCase = null; + TestCaseNode afterCase = null; + + TestCaseNode caseNode = getCaseNode(id); + + if (StringUtils.isNotBlank(before)) { + beforeCase = getCaseNode(before); + beforeCase = beforeCase.getLevel().equals(caseNode.getLevel()) ? beforeCase : null; + } + + if (StringUtils.isNotBlank(after)) { + afterCase = getCaseNode(after); + afterCase = afterCase.getLevel().equals(caseNode.getLevel()) ? afterCase : null; + } + + double pos; + + if (beforeCase == null) { + pos = afterCase != null ? afterCase.getPos() / 2.0 : 65536; + } else { + pos = afterCase != null ? (beforeCase.getPos() + afterCase.getPos()) / 2.0 : beforeCase.getPos() + 65536; + } + + // todo pos 低于阈值时,触发更新方法,重新计算此目录的所有同级目录的 pos 值 + + caseNode.setPos(pos); + testCaseNodeMapper.updateByPrimaryKeySelective(caseNode); + } + + public double getNextLevelPos(String projectId, int level) { + TestCaseNodeExample example = new TestCaseNodeExample(); + example.createCriteria().andProjectIdEqualTo(projectId).andLevelEqualTo(level); + example.setOrderByClause("pos desc"); + List list = testCaseNodeMapper.selectByExample(example); + if (!CollectionUtils.isEmpty(list)) { + return list.get(0).getPos() + 65536; + } else { + return 65536; + } + } + } diff --git a/frontend/src/business/components/track/common/NodeTree.vue b/frontend/src/business/components/track/common/NodeTree.vue index 49aac93523..835d6cfc9b 100644 --- a/frontend/src/business/components/track/common/NodeTree.vue +++ b/frontend/src/business/components/track/common/NodeTree.vue @@ -73,7 +73,8 @@ export default { children: "children", label: "label" }, - disabled: false + disabled: false, + list: [] }; }, props: { @@ -108,8 +109,12 @@ export default { methods: { handleDragEnd(draggingNode, dropNode, dropType, ev) { let param = this.buildParam(draggingNode, dropNode, dropType); + + this.list = []; + this.getNodeTree(this.treeNodes,draggingNode.data.id, this.list); this.$post("/case/node/drag", param, () => { draggingNode.data.level = param.level; + this.$post("/case/node/pos", this.list); this.refreshTable(); }, (error) => { this.refreshNode(); @@ -148,6 +153,22 @@ export default { param.nodeIds = nodeIds; return param; }, + getNodeTree(nodes, id, list) { + if (!nodes) { + return; + } + for (let i = 0; i < nodes.length; i++) { + if (nodes[i].id === id) { + i - 1 >= 0 ? list[0] = nodes[i-1].id : list[0] = ""; + list[1] = nodes[i].id; + i + 1 < nodes.length ? list[2] = nodes[i+1].id : list[2] = ""; + return; + } + if (nodes[i].children) { + this.getNodeTree(nodes[i].children, id, list); + } + } + }, refreshTable() { this.$emit('refreshTable'); },