Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
xiaofang li
MeterSphere
Commits
bd2558c0
Commit
bd2558c0
authored
3 years ago
by
chenjianxing
Committed by
jianxing
3 years ago
Browse files
Options
Download
Email Patches
Plain Diff
fix: 关系图保存时检测环并且合并图
parent
03d3dceb
dev
feat_api_custom_field
feat_custom_field
feat_environment_group
feat_environment_group_copy
feat_timing_clean
feat_vc
feat_vc_testtrack
fix_lyh_v1.17
master
pr@dev@feat@四种协议test、case页面优化
pr@dev@feat_add_issueremark
pr@dev@feat_sync
pr@dev@feat_工作空间多项目环境组合
pr@dev@feat_性能测试版本对比页面修改_自动执行
pr@dev@feat_接口测试_文档结构断言
pr@dev@fix
pr@dev@fix_scenario_load_test
pr@dev@fix_sql版本冲突
pr@dev@fix_从公共用例库移除_再编辑用例发现无法加到公共用例库了
pr@dev@fix_代码扫描图标不显示
pr@dev@fix_修复环境设置中编辑下模块和路径匹配时模块和路径允许为空的缺陷
pr@dev@fix_修改db版本号
pr@dev@fix_功能用例版本切换
pr@dev@fix_场景导入按钮失效
pr@dev@fix_应用管理没有自动保存
pr@dev@fix_接口case优化
pr@dev@fix_接口测试_复制接口
pr@dev@fix_接口测试_安全漏洞
pr@dev@fix_接口测试_引用问题
pr@dev@fix_接口用例在定义后面
pr@dev@fix_接口详情-变更历史无变更详情日志
pr@dev@fix_操作日志_增删改查除系统设置中的操作均无法跳转
pr@dev@fix_新增测试阶段字段在筛选列表中未更新
pr@dev@fix_测试跟踪_功能用例_公共用例库_选择修改用例责任人后,新的责任人仍不可编辑和删除该用例
pr@dev@fix_用例评审_测试计划_关注人支持多选
pr@dev@fix_被引用的数据删除显示重复
pr@dev@refactor_menu_pos
pr@dev@refactor_获取场景报告接口效率优化
pr@dev@内置函数构造器优化增加mock数据说明示例及场景变量
pr@master@fix_代码扫描图标不显示
pr@v1.14@fix_接口测试_复制接口
pr@v1.14@fix_用例评审_测试计划_关注人支持多选
pr@v1.15@fix_sync
pr@v1.16@fix_scenario_load
pr@v1.16@fix_接口测试_安全漏洞
pr@v1.16@fix_接口测试_引用问题
pr@v1.16@fix_接口详情-变更历史无变更详情日志
pr@v1.16@fix_测试跟踪_功能用例_公共用例库_选择修改用例责任人后,新的责任人仍不可编辑和删除该用例
pr@v1.16@refactor_获取场景报告接口效率优化
pr@v1.17@feat_我的工作台加版本筛选
pr@v1.17@fix
pr@v1.17@fix_功能用例版本切换
pr@v1.17@fix_新增测试阶段字段在筛选列表中未更新
pr@v1.18@fix_修复环境设置中编辑下模块和路径匹配时模块和路径允许为空的缺陷
refactor_environment_group
refactor_project_setting
refactor_ws_notice_template
repr@dev_master_v1.16@
repr@dev_v1.14@@fix_【接口定义】-添加mock函数时值生成优化+页面翻译“return”
repr@dev_v1.14@f7409212@fix_接口测试_CSV优化
repr@dev_v1.14_v1.16@fc598de402cffa8744ee656948f715c31e7d58a2@refactor_场景资源池执行添加日志打印
repr@dev_v1.16@1abe60fc@fix_接口测试_循环控制器
repr@dev_v1.16@22a21ac3@fix_接口测试_自动化步骤
repr@dev_v1.16@5d8ba4eb@fix_接口详情-变更历史无变更详情日志
repr@dev_v1.16@6de996ff@fix_接口定义_开启过多时环境与接口名称重叠
repr@dev_v1.16@a009bb38@fix_接口测试_场景执行
repr@dev_v1.16@e15672af3dc95618192ee81aedbefffdfd377b8a@fix_代码扫描图标不显示
repr@dev_v1.16@e43c11a7@fix_应用管理没有保存
repr@dev_v1.16@e43c11a7@fix_应用管理没有自动保存
repr@dev_v1.16_v1.17@430a1864ffe9800240f4fbd9b0c92991305c0baa@fix_脑图创建的用例导出状态和责任人为空
repr@dev_v1.16_v1.17@91c1b2a7@fix_接口测试_插件步骤
repr@dev_v1.17@0d05cd92d9a1b005aac8c07594625f3cda8319080d05cd92d9a1b005aac8c07594625f3cda831908@feat_测试跟踪用例版本相关
repr@dev_v1.17@0d05cd92d9a1b005aac8c07594625f3cda831908@fix_功能用例版本管理回收站
repr@dev_v1.18@abc86b09@fix_lyh_dev
repr@devev_v1.16@31e9453dccbf5b363f72b9a2c4d6b1f40d9e92f5@fix_tapd不显示图片
repr@v1.16@fix_JSONPATH断言等有200个字符限制
repr@v1.16_dev@09a4129d@fix_接口测试_调试状态
repr@v1.16_dev@11eb4bc6@feat_error_report
repr@v1.16_dev@6a89622f@fix_接口测试_JSON校验处理
repr@v1.16_dev@d5cf72dc@fix_接口测试_场景报告
repr@v1.16_dev@e2e90011@fix_testplan_用例执行
repr@v1.16_dev@ef78a7eb@fix_xpack_code
repr@v1.16_v1.17_dev@bfb01376@fix_bugs_import_api
repr@v1.16_v1.17_dev@dd1880fa@fix_bugs_0118
seleniumdocker获取报告图表
ui
v1.14
v1.15
v1.16
v1.17
v1.18
工作空间多项目环境组合
v1.18.2-rc2
v1.18.2-rc1
v1.18.2-rc0
v1.18.2-arm64
v1.18.1
v1.18.0
v1.17.3
v1.17.2
v1.17.1
v1.17.0
v1.16.6
v1.16.5
v1.16.4
v1.16.3
v1.16.2
v1.16.1
v1.16.0
v1.15.4
v1.15.3
v1.15.2
v1.15.1
v1.15.0
v1.14.7
v1.14.6
v1.14.5
v1.14.4
v1.14.3
v1.14.2
v1.14.1
v1.14.0
v1.14.0-rc3
v1.14.0-rc2
v1.14.0-rc1
No related merge requests found
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
backend/src/main/java/io/metersphere/base/mapper/ext/ExtRelationshipEdgeMapper.java
+10
-0
...etersphere/base/mapper/ext/ExtRelationshipEdgeMapper.java
backend/src/main/java/io/metersphere/base/mapper/ext/ExtRelationshipEdgeMapper.xml
+17
-0
...metersphere/base/mapper/ext/ExtRelationshipEdgeMapper.xml
backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.xml
+1
-1
...java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.xml
backend/src/main/java/io/metersphere/service/RelationshipEdgeService.java
+87
-27
.../java/io/metersphere/service/RelationshipEdgeService.java
frontend/src/business/components/track/case/components/TestCaseList.vue
+1
-2
...usiness/components/track/case/components/TestCaseList.vue
with
116 additions
and
30 deletions
+116
-30
backend/src/main/java/io/metersphere/base/mapper/ext/ExtRelationshipEdgeMapper.java
0 → 100644
+
10
-
0
View file @
bd2558c0
package
io.metersphere.base.mapper.ext
;
import
org.apache.ibatis.annotations.Param
;
import
java.util.List
;
public
interface
ExtRelationshipEdgeMapper
{
List
<
String
>
getGraphIdsByNodeIds
(
@Param
(
"ids"
)
List
<
String
>
ids
);
}
This diff is collapsed.
Click to expand it.
backend/src/main/java/io/metersphere/base/mapper/ext/ExtRelationshipEdgeMapper.xml
0 → 100644
+
17
-
0
View file @
bd2558c0
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"io.metersphere.base.mapper.ext.ExtRelationshipEdgeMapper"
>
<select
id=
"getGraphIdsByNodeIds"
resultType=
"java.lang.String"
>
select distinct graph_id
from relationship_edge
where source_id in
<foreach
collection=
"ids"
item=
"id"
open=
"("
close=
")"
separator=
","
>
#{id}
</foreach>
or target_id in
<foreach
collection=
"ids"
item=
"id"
open=
"("
close=
")"
separator=
","
>
#{id}
</foreach>
</select>
</mapper>
This diff is collapsed.
Click to expand it.
backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.xml
+
1
-
1
View file @
bd2558c0
...
...
@@ -563,7 +563,7 @@
<foreach
collection=
"ids"
item=
"id"
separator=
","
open=
"("
close=
")"
>
#{id}
</foreach>
and test_case.status != 'Trash';
and
(
test_case.status != 'Trash'
or test_case.status is NULL)
;
</select>
<update
id=
"deleteToGc"
>
...
...
This diff is collapsed.
Click to expand it.
backend/src/main/java/io/metersphere/service/RelationshipEdgeService.java
+
87
-
27
View file @
bd2558c0
...
...
@@ -4,6 +4,8 @@ package io.metersphere.service;
import
io.metersphere.base.domain.RelationshipEdge
;
import
io.metersphere.base.domain.RelationshipEdgeExample
;
import
io.metersphere.base.mapper.RelationshipEdgeMapper
;
import
io.metersphere.base.mapper.ext.ExtRelationshipEdgeMapper
;
import
io.metersphere.commons.exception.MSException
;
import
io.metersphere.commons.utils.SessionUtils
;
import
io.metersphere.controller.request.RelationshipEdgeRequest
;
import
org.apache.commons.collections.CollectionUtils
;
...
...
@@ -15,9 +17,7 @@ import org.springframework.stereotype.Service;
import
org.springframework.transaction.annotation.Transactional
;
import
javax.annotation.Resource
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.UUID
;
import
java.util.*
;
import
java.util.stream.Collectors
;
/**
...
...
@@ -31,6 +31,8 @@ public class RelationshipEdgeService {
@Resource
private
RelationshipEdgeMapper
relationshipEdgeMapper
;
@Resource
private
ExtRelationshipEdgeMapper
extRelationshipEdgeMapper
;
@Resource
private
SqlSessionFactory
sqlSessionFactory
;
public
void
delete
(
String
sourceId
,
String
targetId
)
{
...
...
@@ -95,29 +97,51 @@ public class RelationshipEdgeService {
return
relationshipEdgeMapper
.
selectByExample
(
example
);
}
/**
* 保存新的边
* 校验是否存在环
* 同时将两个不连通的图合并成一个图
* @param request
*/
public
void
saveBatch
(
RelationshipEdgeRequest
request
)
{
SqlSession
sqlSession
=
sqlSessionFactory
.
openSession
(
ExecutorType
.
BATCH
);
RelationshipEdgeMapper
batchMapper
=
sqlSession
.
getMapper
(
RelationshipEdgeMapper
.
class
);
String
graphId
=
getGraphId
(
request
);
// todo 检验是否有环
String
graphId
=
UUID
.
randomUUID
().
toString
(
);
List
<
RelationshipEdge
>
relationshipEdges
=
getEdgesBySaveRequest
(
request
);
Set
<
String
>
addEdgesIds
=
new
HashSet
<>();
if
(
CollectionUtils
.
isNotEmpty
(
request
.
getTargetIds
()))
{
for
(
String
targetId
:
request
.
getTargetIds
()
)
{
request
.
getTargetIds
()
.
forEach
(
targetId
->
{
RelationshipEdge
edge
=
getNewRelationshipEdge
(
graphId
,
request
.
getId
(),
targetId
,
request
.
getType
());
batchMapper
.
insert
(
edge
);
}
relationshipEdges
.
add
(
edge
);
addEdgesIds
.
add
(
edge
.
getSourceId
()
+
edge
.
getTargetId
());
});
}
if
(
CollectionUtils
.
isNotEmpty
(
request
.
getSourceIds
()))
{
for
(
String
sourceId
:
request
.
getSourceIds
()
)
{
request
.
getSourceIds
()
.
forEach
(
sourceId
->
{
RelationshipEdge
edge
=
getNewRelationshipEdge
(
graphId
,
sourceId
,
request
.
getId
(),
request
.
getType
());
batchMapper
.
insert
(
edge
);
}
relationshipEdges
.
add
(
edge
);
addEdgesIds
.
add
(
edge
.
getSourceId
()
+
edge
.
getTargetId
());
});
}
// 判断是否有环, 两个方向都搜索一遍
if
(
directedCycle
(
request
.
getId
(),
relationshipEdges
,
new
HashSet
<>(),
true
)
||
directedCycle
(
request
.
getId
(),
relationshipEdges
,
new
HashSet
<>(),
false
))
{
MSException
.
throwException
(
"关联后存在循环依赖,请检查依赖关系"
);
};
relationshipEdges
.
forEach
(
item
->
{
if
(
addEdgesIds
.
contains
(
item
.
getSourceId
()
+
item
.
getTargetId
()))
{
batchMapper
.
insert
(
item
);
}
else
{
item
.
setGraphId
(
graphId
);
// 把原来图的id设置成合并后新的图的id
batchMapper
.
updateByPrimaryKey
(
item
);
}
});
sqlSession
.
flushStatements
();
}
...
...
@@ -133,15 +157,11 @@ public class RelationshipEdgeService {
}
/**
*
获取当前节点
所在
的
图的
id
*
查找要关联的边
所在图的
所有的边
* @param request
* @return
*/
private
String
getGraphId
(
RelationshipEdgeRequest
request
)
{
// 判断这些顶点是否已经和其他顶点连通
// 连通的话,加到同一个图中,否则新建一个图,即 graphId
String
graphId
=
UUID
.
randomUUID
().
toString
();
public
List
<
RelationshipEdge
>
getEdgesBySaveRequest
(
RelationshipEdgeRequest
request
)
{
List
<
String
>
graphNodes
=
new
ArrayList
<>();
graphNodes
.
add
(
request
.
getId
());
if
(
request
.
getTargetIds
()
!=
null
)
{
...
...
@@ -150,18 +170,58 @@ public class RelationshipEdgeService {
if
(
request
.
getSourceIds
()
!=
null
)
{
graphNodes
.
addAll
(
request
.
getSourceIds
());
}
List
<
String
>
graphIds
=
extRelationshipEdgeMapper
.
getGraphIdsByNodeIds
(
graphNodes
);
if
(
CollectionUtils
.
isEmpty
(
graphIds
))
{
return
new
ArrayList
<>();
}
RelationshipEdgeExample
example
=
new
RelationshipEdgeExample
();
example
.
createCriteria
()
.
andSourceIdIn
(
graphNodes
);
example
.
or
(
example
.
createCriteria
()
.
andTargetIdIn
(
graphNodes
)
);
List
<
RelationshipEdge
>
relationshipEdges
=
relationshipEdgeMapper
.
selectByExample
(
example
);
if
(
CollectionUtils
.
isNotEmpty
(
relationshipEdges
))
{
return
relationshipEdges
.
get
(
0
).
getGraphId
();
.
andGraphIdIn
(
graphIds
);
return
relationshipEdgeMapper
.
selectByExample
(
example
);
}
/**
* 给定一点,深度搜索该连通图中是否存在环
* @param id
* @param edges
* @param markSet
* @param isForwardDirection
* @return
*/
public
boolean
directedCycle
(
String
id
,
List
<
RelationshipEdge
>
edges
,
Set
<
String
>
markSet
,
Boolean
isForwardDirection
)
{
if
(
markSet
.
contains
(
id
))
{
// 如果已经访问过该节点,则说明存在环
return
true
;
}
return
graphId
;
markSet
.
add
(
id
);
ArrayList
<
String
>
nextLevelNodes
=
new
ArrayList
();
for
(
RelationshipEdge
relationshipEdge
:
edges
)
{
if
(
isForwardDirection
)
{
// 正向则搜索 sourceId 是当前节点的边
if
(
id
.
equals
(
relationshipEdge
.
getSourceId
()))
{
nextLevelNodes
.
add
(
relationshipEdge
.
getTargetId
());
}
}
else
{
if
(
id
.
equals
(
relationshipEdge
.
getTargetId
()))
{
nextLevelNodes
.
add
(
relationshipEdge
.
getSourceId
());
}
}
}
for
(
String
nextNode
:
nextLevelNodes
)
{
if
(
directedCycle
(
nextNode
,
edges
,
markSet
,
isForwardDirection
))
{
return
true
;
};
}
// 关键,递归完这一条路径要把这个标记去掉,否则会误判为有环
// 比如 1->3, 1->2->3 , 3 经过多次但是无环
markSet
.
remove
(
id
);
return
false
;
}
/**
...
...
This diff is collapsed.
Click to expand it.
frontend/src/business/components/track/case/components/TestCaseList.vue
+
1
-
2
View file @
bd2558c0
...
...
@@ -446,7 +446,6 @@ export default {
activated
()
{
this
.
getTemplateField
();
this
.
condition
.
filters
=
{
reviewStatus
:
[
"
Prepare
"
,
"
Pass
"
,
"
UnPass
"
]};
this
.
condition
.
filters
=
{
status
:
[
"
Prepare
"
,
"
Underway
"
,
"
Completed
"
]}
let
ids
=
this
.
$route
.
params
.
ids
;
if
(
ids
)
{
this
.
condition
.
ids
=
ids
;
...
...
@@ -458,7 +457,7 @@ export default {
selectNodeIds
()
{
this
.
page
.
currentPage
=
1
;
if
(
!
this
.
trashEnable
){
this
.
condition
.
filters
.
status
=
[
"
Prepare
"
,
"
Underway
"
,
"
Completed
"
];
this
.
condition
.
filters
.
status
=
[];
}
initCondition
(
this
.
condition
,
false
);
this
.
initTableData
();
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Projects
Groups
Snippets
Help