refactor: 关系图若干优化
This commit is contained in:
parent
e18937a423
commit
411ac0d079
|
@ -23,7 +23,6 @@ import org.springframework.scheduling.annotation.EnableScheduling;
|
|||
JmeterProperties.class
|
||||
})
|
||||
@EnableScheduling
|
||||
//@PropertySource(value = {"file:c:\\opt\\metersphere\\conf\\metersphere.properties"}, encoding = "UTF-8", ignoreResourceNotFound = true)
|
||||
@PropertySource(value = {"file:/opt/metersphere/conf/metersphere.properties"}, encoding = "UTF-8", ignoreResourceNotFound = true)
|
||||
public class Application {
|
||||
public static void main(String[] args) {
|
||||
|
|
|
@ -315,6 +315,11 @@ public class ApiDefinitionController {
|
|||
return apiDefinitionService.getRelationshipApi(id, relationshipType);
|
||||
}
|
||||
|
||||
@GetMapping("/relationship/count/{id}/")
|
||||
public int getRelationshipApi(@PathVariable("id") String id) {
|
||||
return apiDefinitionService.getRelationshipCount(id);
|
||||
}
|
||||
|
||||
@PostMapping("/relationship/relate/{goPage}/{pageSize}")
|
||||
public Pager< List<ApiDefinitionResult>> getRelationshipRelateList(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody ApiDefinitionRequest request) {
|
||||
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
||||
|
|
|
@ -1607,16 +1607,21 @@ public class ApiDefinitionService {
|
|||
return extApiDefinitionMapper.countQuotedApiByProjectId(projectId);
|
||||
}
|
||||
|
||||
public int getRelationshipCount(String id) {
|
||||
return relationshipEdgeService.getRelationshipCount(id, extApiDefinitionMapper::countByIds);
|
||||
}
|
||||
|
||||
public List<RelationshipEdgeDTO> getRelationshipApi(String id, String relationshipType) {
|
||||
List<RelationshipEdge> relationshipEdges = relationshipEdgeService.getRelationshipEdgeByType(id, relationshipType);
|
||||
List<String> ids = relationshipEdgeService.getRelationIdsByType(relationshipType, relationshipEdges);
|
||||
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
ApiDefinitionExample example = new ApiDefinitionExample();
|
||||
example.createCriteria().andIdIn(ids);
|
||||
example.createCriteria().andIdIn(ids).andStatusNotEqualTo("Trash");
|
||||
List<ApiDefinition> apiDefinitions = apiDefinitionMapper.selectByExample(example);
|
||||
Map<String, ApiDefinition> apiMap = apiDefinitions.stream().collect(Collectors.toMap(ApiDefinition::getId, i -> i));
|
||||
List<RelationshipEdgeDTO> results = new ArrayList<>();
|
||||
buildUserInfo(apiDefinitions);
|
||||
for (RelationshipEdge relationshipEdge : relationshipEdges) {
|
||||
RelationshipEdgeDTO relationshipEdgeDTO = new RelationshipEdgeDTO();
|
||||
BeanUtils.copyBean(relationshipEdgeDTO, relationshipEdge);
|
||||
|
@ -1627,8 +1632,9 @@ public class ApiDefinitionService {
|
|||
apiDefinition = apiMap.get(relationshipEdge.getSourceId());
|
||||
}
|
||||
relationshipEdgeDTO.setTargetName(apiDefinition.getName());
|
||||
relationshipEdgeDTO.setCreator(apiDefinition.getCreateUser());
|
||||
relationshipEdgeDTO.setCreator(apiDefinition.getUserId());
|
||||
relationshipEdgeDTO.setTargetNum(apiDefinition.getNum());
|
||||
relationshipEdgeDTO.setStatus(apiDefinition.getStatus());
|
||||
results.add(relationshipEdgeDTO);
|
||||
}
|
||||
return results;
|
||||
|
@ -1636,6 +1642,21 @@ public class ApiDefinitionService {
|
|||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public void buildUserInfo(List<? extends ApiDefinition> apis) {
|
||||
List<String> userIds = new ArrayList();
|
||||
userIds.addAll(apis.stream().map(ApiDefinition::getCreateUser).collect(Collectors.toList()));
|
||||
userIds.addAll(apis.stream().map(ApiDefinition::getDeleteUserId).collect(Collectors.toList()));
|
||||
userIds.addAll(apis.stream().map(ApiDefinition::getUserId).collect(Collectors.toList()));
|
||||
if (!org.apache.commons.collections.CollectionUtils.isEmpty(userIds)) {
|
||||
Map<String, String> userMap = ServiceUtils.getUserNameMap(userIds);
|
||||
apis.forEach(caseResult -> {
|
||||
caseResult.setCreateUser(userMap.get(caseResult.getCreateUser()));
|
||||
caseResult.setDeleteUserId(userMap.get(caseResult.getDeleteUserId()));
|
||||
caseResult.setUserId(userMap.get(caseResult.getUserId()));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public List<ApiDefinitionResult> getRelationshipRelateList(ApiDefinitionRequest request) {
|
||||
request = this.initRequest(request, true, true);
|
||||
List<String> relationshipIds = relationshipEdgeService.getRelationshipIds(request.getId());
|
||||
|
|
|
@ -76,4 +76,6 @@ public interface ExtApiDefinitionMapper {
|
|||
long countQuotedApiByProjectId(String projectId);
|
||||
|
||||
List<RelationshipGraphData.Node> getForGraph(@Param("ids") Set<String> ids);
|
||||
|
||||
int countByIds(@Param("ids") List<String> ids);
|
||||
}
|
||||
|
|
|
@ -720,5 +720,13 @@
|
|||
where t3.api_definition_id = #{apiDefinitionId}
|
||||
and t3.`status`!='Trash'
|
||||
</select>
|
||||
<select id="countByIds" resultType="java.lang.Integer">
|
||||
select count(id) from api_definition
|
||||
where id in
|
||||
<foreach collection="ids" item="id" separator="," open="(" close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
and api_definition.status != 'Trash';
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
|
|
@ -123,4 +123,6 @@ public interface ExtTestCaseMapper {
|
|||
List<TestCase> getTestCase(@Param("request") QueryTestCaseRequest request);
|
||||
|
||||
List<RelationshipGraphData.Node> getTestCaseForGraph(@Param("ids") Set<String> ids);
|
||||
|
||||
int countByIds(@Param("ids") List<String> ids);
|
||||
}
|
||||
|
|
|
@ -574,6 +574,15 @@
|
|||
</foreach>
|
||||
and (test_case.status != 'Trash' or test_case.status is NULL);
|
||||
</select>
|
||||
<select id="countByIds" resultType="java.lang.Integer">
|
||||
select count(id)
|
||||
from test_case
|
||||
where id in
|
||||
<foreach collection="ids" item="id" separator="," open="(" close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
and (test_case.status != 'Trash' or test_case.status is NULL);
|
||||
</select>
|
||||
|
||||
<update id="deleteToGc">
|
||||
update test_case set original_status=status,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package io.metersphere.service;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.base.domain.CustomField;
|
||||
|
@ -13,6 +15,7 @@ import io.metersphere.commons.exception.MSException;
|
|||
import io.metersphere.commons.utils.*;
|
||||
import io.metersphere.controller.request.QueryCustomFieldRequest;
|
||||
import io.metersphere.dto.CustomFieldDao;
|
||||
import io.metersphere.dto.CustomFieldItemDTO;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import io.metersphere.log.utils.ReflexObjectUtil;
|
||||
import io.metersphere.log.vo.DetailColumn;
|
||||
|
@ -205,4 +208,13 @@ public class CustomFieldService {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<CustomFieldItemDTO> getCustomFields(String customFieldsStr) {
|
||||
if (StringUtils.isNotBlank(customFieldsStr)) {
|
||||
if (JSONObject.parse(customFieldsStr) instanceof JSONArray) {
|
||||
return JSONArray.parseArray(customFieldsStr, CustomFieldItemDTO.class);
|
||||
}
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
@ -97,6 +98,17 @@ public class RelationshipEdgeService {
|
|||
return relationshipEdgeMapper.selectByExample(example);
|
||||
}
|
||||
|
||||
public List<RelationshipEdge> getBySourceIdOrTargetId(String id) {
|
||||
RelationshipEdgeExample example = new RelationshipEdgeExample();
|
||||
example.createCriteria()
|
||||
.andSourceIdEqualTo(id);
|
||||
example.or(
|
||||
example.createCriteria()
|
||||
.andTargetIdEqualTo(id)
|
||||
);
|
||||
return relationshipEdgeMapper.selectByExample(example);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存新的边
|
||||
* 校验是否存在环
|
||||
|
@ -128,11 +140,16 @@ public class RelationshipEdgeService {
|
|||
});
|
||||
}
|
||||
|
||||
// 判断是否有环, 两个方向都搜索一遍
|
||||
if (directedCycle(request.getId(), relationshipEdges, new HashSet<>(), true) ||
|
||||
directedCycle(request.getId(), relationshipEdges, new HashSet<>(), false)) {
|
||||
HashSet<String> nodeIds = new HashSet<>();
|
||||
nodeIds.addAll(relationshipEdges.stream().map(RelationshipEdge::getSourceId).collect(Collectors.toSet()));
|
||||
nodeIds.addAll(relationshipEdges.stream().map(RelationshipEdge::getTargetId).collect(Collectors.toSet()));
|
||||
// 判断是否有环
|
||||
HashSet<String> visitedSet = new HashSet<>();
|
||||
nodeIds.forEach(nodeId -> {
|
||||
if (!visitedSet.contains(nodeId) && directedCycle(nodeId, relationshipEdges, new HashSet<>(), visitedSet)) {
|
||||
MSException.throwException("关联后存在循环依赖,请检查依赖关系");
|
||||
};
|
||||
});
|
||||
|
||||
relationshipEdges.forEach(item -> {
|
||||
if (addEdgesIds.contains(item.getSourceId() + item.getTargetId())) {
|
||||
|
@ -186,11 +203,11 @@ public class RelationshipEdgeService {
|
|||
* 给定一点,深度搜索该连通图中是否存在环
|
||||
* @param id
|
||||
* @param edges
|
||||
* @param markSet
|
||||
* @param isForwardDirection
|
||||
* @param markSet 标记该路径上经过的节点
|
||||
* @param visitedSet 标记访问过的节点
|
||||
* @return
|
||||
*/
|
||||
public boolean directedCycle(String id, List<RelationshipEdge> edges, Set<String> markSet, Boolean isForwardDirection) {
|
||||
public boolean directedCycle(String id, List<RelationshipEdge> edges, Set<String> markSet, Set<String> visitedSet) {
|
||||
|
||||
if (markSet.contains(id)) {
|
||||
// 如果已经访问过该节点,则说明存在环
|
||||
|
@ -198,23 +215,19 @@ public class RelationshipEdgeService {
|
|||
}
|
||||
|
||||
markSet.add(id);
|
||||
visitedSet.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)) {
|
||||
if (directedCycle(nextNode, edges, markSet, visitedSet)) {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 关键,递归完这一条路径要把这个标记去掉,否则会误判为有环
|
||||
|
@ -225,17 +238,24 @@ public class RelationshipEdgeService {
|
|||
}
|
||||
|
||||
/**
|
||||
* 给定一个节点获取跟他关联的所有节点的id
|
||||
* 给定一个节点获取直接关联的节点的id
|
||||
* @param nodeId
|
||||
* @return
|
||||
*/
|
||||
public List<String> getRelationshipIds(String nodeId) {
|
||||
List<RelationshipEdge> sourceRelationshipEdges = getBySourceId(nodeId);
|
||||
List<RelationshipEdge> targetRelationshipEdges = getByTargetId(nodeId);
|
||||
List<RelationshipEdge> sourceRelationshipEdges = getBySourceIdOrTargetId(nodeId);
|
||||
List<String> ids = sourceRelationshipEdges.stream().map(RelationshipEdge::getTargetId).collect(Collectors.toList());
|
||||
ids.addAll(targetRelationshipEdges.stream().map(RelationshipEdge::getSourceId).collect(Collectors.toList()));
|
||||
ids.addAll(sourceRelationshipEdges.stream().map(RelationshipEdge::getSourceId).collect(Collectors.toList()));
|
||||
ids.add(nodeId);
|
||||
return ids;
|
||||
}
|
||||
|
||||
public int getRelationshipCount(String id, Function<List<String>, Integer> countByIdsFunc) {
|
||||
List<String> ids = getRelationshipIds(id);
|
||||
ids = ids.stream().filter(i -> !i.equals(id)).collect(Collectors.toList());
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
return countByIdsFunc.apply(ids);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,6 +105,11 @@ public class TestCaseController {
|
|||
return testCaseService.getRelationshipCase(id, relationshipType);
|
||||
}
|
||||
|
||||
@GetMapping("/relationship/case/count/{id}")
|
||||
public int getRelationshipCase(@PathVariable("id") String id) {
|
||||
return testCaseService.getRelationshipCount(id);
|
||||
}
|
||||
|
||||
@GetMapping("recent/{count}")
|
||||
public List<TestCase> recentTestPlans(@PathVariable int count) {
|
||||
String currentWorkspaceId = SessionUtils.getCurrentWorkspaceId();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package io.metersphere.track.issue;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.IssuesMapper;
|
||||
import io.metersphere.base.mapper.ProjectMapper;
|
||||
|
@ -11,10 +10,7 @@ import io.metersphere.commons.utils.*;
|
|||
import io.metersphere.controller.request.IntegrationRequest;
|
||||
import io.metersphere.dto.CustomFieldItemDTO;
|
||||
import io.metersphere.dto.UserDTO;
|
||||
import io.metersphere.service.IntegrationService;
|
||||
import io.metersphere.service.ProjectService;
|
||||
import io.metersphere.service.ResourceService;
|
||||
import io.metersphere.service.UserService;
|
||||
import io.metersphere.service.*;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
import io.metersphere.track.request.testcase.IssuesUpdateRequest;
|
||||
import io.metersphere.track.service.TestCaseIssueService;
|
||||
|
@ -218,13 +214,6 @@ public abstract class AbstractIssuePlatform implements IssuesPlatform {
|
|||
}
|
||||
}
|
||||
|
||||
protected List<CustomFieldItemDTO> getCustomFields(String customFieldsStr) {
|
||||
if (StringUtils.isNotBlank(customFieldsStr)) {
|
||||
return JSONArray.parseArray(customFieldsStr, CustomFieldItemDTO.class);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将html格式的缺陷描述转成ms平台的格式
|
||||
*
|
||||
|
@ -347,7 +336,7 @@ public abstract class AbstractIssuePlatform implements IssuesPlatform {
|
|||
}
|
||||
|
||||
protected void addCustomFields(IssuesUpdateRequest issuesRequest, MultiValueMap<String, Object> paramMap) {
|
||||
List<CustomFieldItemDTO> customFields = getCustomFields(issuesRequest.getCustomFields());
|
||||
List<CustomFieldItemDTO> customFields = CustomFieldService.getCustomFields(issuesRequest.getCustomFields());
|
||||
customFields.forEach(item -> {
|
||||
if (StringUtils.isNotBlank(item.getCustomData())) {
|
||||
paramMap.add(item.getCustomData(), item.getValue());
|
||||
|
|
|
@ -11,6 +11,7 @@ import io.metersphere.commons.utils.EncryptUtils;
|
|||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.dto.CustomFieldItemDTO;
|
||||
import io.metersphere.dto.UserDTO;
|
||||
import io.metersphere.service.CustomFieldService;
|
||||
import io.metersphere.track.dto.DemandDTO;
|
||||
import io.metersphere.track.issue.client.JiraClientV2;
|
||||
import io.metersphere.track.issue.domain.Jira.JiraAddIssueResponse;
|
||||
|
@ -109,7 +110,7 @@ public class JiraPlatform extends AbstractIssuePlatform {
|
|||
}
|
||||
|
||||
public String parseIssueCustomField(String customFieldsStr, JiraIssue jiraIssue) {
|
||||
List<CustomFieldItemDTO> customFields = getCustomFields(customFieldsStr);
|
||||
List<CustomFieldItemDTO> customFields = CustomFieldService.getCustomFields(customFieldsStr);
|
||||
JSONObject fields = jiraIssue.getFields();
|
||||
|
||||
customFields.forEach(item -> {
|
||||
|
@ -286,7 +287,7 @@ public class JiraPlatform extends AbstractIssuePlatform {
|
|||
JSONObject addJiraIssueParam = new JSONObject();
|
||||
addJiraIssueParam.put("fields", fields);
|
||||
|
||||
List<CustomFieldItemDTO> customFields = getCustomFields(issuesRequest.getCustomFields());
|
||||
List<CustomFieldItemDTO> customFields = CustomFieldService.getCustomFields(issuesRequest.getCustomFields());
|
||||
jiraClientV2.setConfig(config);
|
||||
|
||||
customFields.forEach(item -> {
|
||||
|
|
|
@ -15,7 +15,6 @@ import io.metersphere.commons.utils.CommonBeanFactory;
|
|||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.controller.ResultHolder;
|
||||
import io.metersphere.dto.CustomFieldItemDTO;
|
||||
import io.metersphere.dto.UserDTO;
|
||||
import io.metersphere.service.SystemParameterService;
|
||||
import io.metersphere.track.dto.DemandDTO;
|
||||
|
|
|
@ -10,6 +10,7 @@ import io.metersphere.api.dto.automation.ApiScenarioDTO;
|
|||
import io.metersphere.api.dto.automation.ApiScenarioRequest;
|
||||
import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
||||
import io.metersphere.api.dto.definition.ApiTestCaseRequest;
|
||||
import io.metersphere.api.dto.definition.TestPlanApiCaseDTO;
|
||||
import io.metersphere.api.service.ApiAutomationService;
|
||||
import io.metersphere.api.service.ApiTestCaseService;
|
||||
import io.metersphere.base.domain.*;
|
||||
|
@ -1973,8 +1974,9 @@ public class TestCaseService {
|
|||
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
TestCaseExample example = new TestCaseExample();
|
||||
example.createCriteria().andIdIn(ids);
|
||||
List<TestCase> testCaseList = testCaseMapper.selectByExample(example);
|
||||
example.createCriteria().andIdIn(ids).andStatusNotEqualTo("Trash");
|
||||
List<TestCaseWithBLOBs> testCaseList = testCaseMapper.selectByExampleWithBLOBs(example);
|
||||
buildUserInfo(testCaseList);
|
||||
Map<String, TestCase> caseMap = testCaseList.stream().collect(Collectors.toMap(TestCase::getId, i -> i));
|
||||
List<RelationshipEdgeDTO> results = new ArrayList<>();
|
||||
for (RelationshipEdge relationshipEdge : relationshipEdges) {
|
||||
|
@ -1990,10 +1992,30 @@ public class TestCaseService {
|
|||
relationshipEdgeDTO.setCreator(testCase.getCreateUser());
|
||||
relationshipEdgeDTO.setTargetNum(testCase.getNum());
|
||||
relationshipEdgeDTO.setTargetCustomNum(testCase.getCustomNum());
|
||||
relationshipEdgeDTO.setStatus(testCase.getStatus());
|
||||
results.add(relationshipEdgeDTO);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public void buildUserInfo(List<? extends TestCase> testCases) {
|
||||
List<String> userIds = new ArrayList();
|
||||
userIds.addAll(testCases.stream().map(TestCase::getCreateUser).collect(Collectors.toList()));
|
||||
userIds.addAll(testCases.stream().map(TestCase::getDeleteUserId).collect(Collectors.toList()));
|
||||
userIds.addAll(testCases.stream().map(TestCase::getMaintainer).collect(Collectors.toList()));
|
||||
if (!org.apache.commons.collections.CollectionUtils.isEmpty(userIds)) {
|
||||
Map<String, String> userMap = ServiceUtils.getUserNameMap(userIds);
|
||||
testCases.forEach(caseResult -> {
|
||||
caseResult.setCreateUser(userMap.get(caseResult.getCreateUser()));
|
||||
caseResult.setDeleteUserId(userMap.get(caseResult.getDeleteUserId()));
|
||||
caseResult.setMaintainer(userMap.get(caseResult.getMaintainer()));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public int getRelationshipCount(String id) {
|
||||
return relationshipEdgeService.getRelationshipCount(id, extTestCaseMapper::countByIds);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 6aff490dd3321a760e2a519c0cb6aa6c90850f3f
|
||||
Subproject commit a86e39275aae2a3e2e8aae705da5a4dddbd0089d
|
|
@ -9,7 +9,10 @@
|
|||
<form-rich-text-item class="remark-item" :disabled="readOnly && !hasPermissions" :data="api" prop="remark" label-width="0"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('commons.relationship.name')" name="dependencies" class="pane">
|
||||
<dependencies-list :read-only="readOnly" :resource-id="api.id" resource-type="API" ref="dependencies"/>
|
||||
<template v-slot:label>
|
||||
<tab-pane-count :title="$t('commons.relationship.name')" :count="relationshipCount"/>
|
||||
</template>
|
||||
<dependencies-list @setCount="setCount" :read-only="readOnly" :resource-id="api.id" resource-type="API" ref="dependencies"/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-collapse-transition>
|
||||
|
@ -24,13 +27,16 @@ import ApiInfoContainer from "@/business/components/api/definition/components/co
|
|||
import DependenciesList from "@/business/components/common/components/graph/DependenciesList";
|
||||
import FormRichTextItem from "@/business/components/track/case/components/FormRichTextItem";
|
||||
import {hasPermissions} from "@/common/js/utils";
|
||||
import TabPaneCount from "@/business/components/track/plan/view/comonents/report/detail/component/TabPaneCount";
|
||||
import {getRelationshipCountApi} from "@/network/api";
|
||||
export default {
|
||||
name: "ApiOtherInfo",
|
||||
components: {FormRichTextItem, DependenciesList, ApiInfoContainer, MsFormDivider},
|
||||
components: {TabPaneCount, FormRichTextItem, DependenciesList, ApiInfoContainer, MsFormDivider},
|
||||
props: ['api','readOnly'],
|
||||
data() {
|
||||
return {
|
||||
activeName: 'remark'
|
||||
activeName: 'remark',
|
||||
relationshipCount: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -43,8 +49,18 @@ export default {
|
|||
if (this.activeName === 'dependencies') {
|
||||
this.$refs.dependencies.open();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
getRelationshipCountApi(this.api.id, (data) => {
|
||||
this.relationshipCount = data;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
setCount(count) {
|
||||
this.relationshipCount = count;
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -26,6 +26,17 @@
|
|||
min-width="120">
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
prop="status"
|
||||
min-width="120px"
|
||||
:label="$t('api_test.definition.api_status')">
|
||||
<template v-slot:default="scope">
|
||||
<span class="el-dropdown-link">
|
||||
<api-status :value="scope.row.status"/>
|
||||
</span>
|
||||
</template>
|
||||
</ms-table-column>
|
||||
|
||||
</ms-table>
|
||||
|
||||
<api-relationship-relevance
|
||||
|
@ -46,9 +57,12 @@ import RelationshipFunctionalRelevance
|
|||
import {getRelationshipApi} from "@/network/api";
|
||||
import ApiRelationshipRelevance
|
||||
from "@/business/components/api/definition/components/complete/ApiRelationshipRelevance";
|
||||
import ApiStatus from "@/business/components/api/definition/components/list/ApiStatus";
|
||||
export default {
|
||||
name: "ApiRelationshipList",
|
||||
components: {ApiRelationshipRelevance, RelationshipFunctionalRelevance, MsTableSearchBar, MsTableColumn, MsTable},
|
||||
components: {
|
||||
ApiStatus,
|
||||
ApiRelationshipRelevance, RelationshipFunctionalRelevance, MsTableSearchBar, MsTableColumn, MsTable},
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
|
@ -74,6 +88,7 @@ export default {
|
|||
getTableData() {
|
||||
getRelationshipApi(this.apiDefinitionId, this.relationshipType, (data) => {
|
||||
this.data = data;
|
||||
this.$emit('setCount', data.length);
|
||||
});
|
||||
},
|
||||
openRelevance() {
|
||||
|
|
|
@ -1,11 +1,23 @@
|
|||
<template>
|
||||
<div class="dependencies-container">
|
||||
<el-main v-xpack>
|
||||
<i class="el-icon-view" @click="openGraph"></i>
|
||||
</el-main>
|
||||
|
||||
<relationship-list :read-only="readOnly" :title="$t('commons.relationship.pre')" relationship-type="PRE" :resource-id="resourceId" :resource-type="resourceType" ref="preRelationshipList"/>
|
||||
<relationship-list :read-only="readOnly" :title="$t('commons.relationship.post')" relationship-type="POST" :resource-id="resourceId" :resource-type="resourceType" ref="postRelationshipList"/>
|
||||
<el-tooltip v-xpack class="item" effect="dark" :content="$t('commons.relationship.graph')" placement="left">
|
||||
<font-awesome-icon class="graph-icon" :icon="['fas', 'sitemap']" size="lg" @click="openGraph"/>
|
||||
</el-tooltip>
|
||||
|
||||
<relationship-list
|
||||
class="pre-list"
|
||||
:read-only="readOnly" :title="resourceType === 'TEST_CASE' ? $t('commons.relationship.pre_case') : $t('commons.relationship.pre_api')"
|
||||
relationship-type="PRE" :resource-id="resourceId"
|
||||
@setCount="setPreCount"
|
||||
:resource-type="resourceType" ref="preRelationshipList"/>
|
||||
<relationship-list
|
||||
class="post-list"
|
||||
:read-only="readOnly"
|
||||
:title="resourceType === 'TEST_CASE' ? $t('commons.relationship.post_case') : $t('commons.relationship.post_api')"
|
||||
relationship-type="POST" :resource-id="resourceId"
|
||||
@setCount="setPostCount"
|
||||
:resource-type="resourceType" ref="postRelationshipList"/>
|
||||
|
||||
<relationship-graph-drawer v-permission :graph-data="graphData" ref="relationshipGraph"/>
|
||||
|
||||
|
@ -26,7 +38,9 @@ export default {
|
|||
],
|
||||
data() {
|
||||
return {
|
||||
graphData: {}
|
||||
graphData: {},
|
||||
preCount: 0,
|
||||
postCount: 0,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -39,13 +53,26 @@ export default {
|
|||
this.graphData = data;
|
||||
this.$refs.relationshipGraph.open();
|
||||
});
|
||||
}
|
||||
},
|
||||
setPreCount(count) {
|
||||
this.preCount = count;
|
||||
this.$emit('setCount', this.preCount + this.postCount);
|
||||
},
|
||||
setPostCount(count) {
|
||||
this.postCount = count;
|
||||
this.$emit('setCount', this.preCount + this.postCount);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dependencies-container .el-main {
|
||||
.post-list {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.graph-icon {
|
||||
float: right;
|
||||
margin-right: 20px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
:case-id="resourceId"
|
||||
:read-only="readOnly"
|
||||
:relationship-type="relationshipType"
|
||||
@setCount="setCount"
|
||||
@deleteRelationship="handleDelete"
|
||||
ref="testCaseRelationshipList"/>
|
||||
|
||||
|
@ -17,6 +18,7 @@
|
|||
:read-only="readOnly"
|
||||
:api-definition-id="resourceId"
|
||||
:relationship-type="relationshipType"
|
||||
@setCount="setCount"
|
||||
@deleteRelationship="handleDelete"
|
||||
ref="testCaseRelationshipList"/>
|
||||
|
||||
|
@ -66,6 +68,9 @@ export default {
|
|||
this.$success(this.$t('commons.delete_success'));
|
||||
});
|
||||
},
|
||||
setCount(count) {
|
||||
this.$emit('setCount', count);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -337,6 +337,7 @@
|
|||
getTestTemplate()
|
||||
.then((template) => {
|
||||
this.testCaseTemplate = template;
|
||||
this.$store.commit('setTestCaseTemplate', this.testCaseTemplate);
|
||||
initAddFuc();
|
||||
});
|
||||
if (this.selectNode && this.selectNode.data && !this.form.id) {
|
||||
|
@ -461,6 +462,7 @@
|
|||
getTemplate('field/template/case/get/relate/', this)
|
||||
.then((template) => {
|
||||
this.testCaseTemplate = template;
|
||||
this.$store.commit('setTestCaseTemplate', this.testCaseTemplate);
|
||||
initFuc(testCase);
|
||||
});
|
||||
},
|
||||
|
|
|
@ -40,7 +40,10 @@
|
|||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane :label="$t('commons.relationship.name')" name="relationship">
|
||||
<dependencies-list :read-only="readOnly" :resource-id="caseId" resource-type="TEST_CASE" ref="relationship"/>
|
||||
<template v-slot:label>
|
||||
<tab-pane-count :title="$t('commons.relationship.name')" :count="relationshipCount"/>
|
||||
</template>
|
||||
<dependencies-list @setCount="setRelationshipCount" :read-only="readOnly" :resource-id="caseId" resource-type="TEST_CASE" ref="relationship"/>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane :label="$t('test_track.case.attachment')" name="attachment">
|
||||
|
@ -83,10 +86,13 @@ import TestCaseIssueRelate from "@/business/components/track/case/components/Tes
|
|||
import FormRichTextItem from "@/business/components/track/case/components/FormRichTextItem";
|
||||
import TestCaseTestRelate from "@/business/components/track/case/components/TestCaseTestRelate";
|
||||
import DependenciesList from "@/business/components/common/components/graph/DependenciesList";
|
||||
import TabPaneCount from "@/business/components/track/plan/view/comonents/report/detail/component/TabPaneCount";
|
||||
import {getRelationshipCountCase} from "@/network/testCase";
|
||||
|
||||
export default {
|
||||
name: "TestCaseEditOtherInfo",
|
||||
components: {
|
||||
TabPaneCount,
|
||||
DependenciesList,
|
||||
TestCaseTestRelate,
|
||||
FormRichTextItem, TestCaseIssueRelate, TestCaseAttachment, MsRichText, TestCaseRichText},
|
||||
|
@ -99,6 +105,7 @@ export default {
|
|||
fileList: [],
|
||||
tableData: [],
|
||||
demandOptions: [],
|
||||
relationshipCount: 0,
|
||||
//sysList:this.sysList,//一级选择框的数据
|
||||
props: {
|
||||
multiple: true,
|
||||
|
@ -123,12 +130,20 @@ export default {
|
|||
} else if (this.tabActiveName === 'attachment') {
|
||||
this.getFileMetaData();
|
||||
}
|
||||
},
|
||||
caseId() {
|
||||
getRelationshipCountCase(this.caseId, (data) => {
|
||||
this.relationshipCount = data;
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateRemark(text) {
|
||||
this.form.remark = text;
|
||||
},
|
||||
setRelationshipCount(count) {
|
||||
this.relationshipCount = count;
|
||||
},
|
||||
reset() {
|
||||
this.tabActiveName = "remark";
|
||||
},
|
||||
|
|
|
@ -33,6 +33,15 @@
|
|||
min-width="120">
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
prop="status"
|
||||
min-width="100px"
|
||||
:label="$t('api_test.definition.api_case_status')">
|
||||
<template slot-scope="{row}">
|
||||
{{$t(statusMap.get(row.status))}}
|
||||
</template>
|
||||
</ms-table-column>
|
||||
|
||||
</ms-table>
|
||||
|
||||
<relationship-functional-relevance
|
||||
|
@ -68,6 +77,7 @@ export default {
|
|||
],
|
||||
condition: {},
|
||||
options: [],
|
||||
statusMap: new Map,
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
|
@ -78,6 +88,14 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
isCustomNum() {
|
||||
let template = this.$store.state.testCaseTemplate;
|
||||
template.customFields.forEach(item => {
|
||||
if (item.name === '用例状态') {
|
||||
for (let i = 0; i < item.options.length; i++) {
|
||||
this.statusMap.set(item.options[i].value, item.options[i].text);
|
||||
}
|
||||
}
|
||||
});
|
||||
return this.$store.state.currentProjectIsCustomNum;
|
||||
},
|
||||
},
|
||||
|
@ -85,6 +103,7 @@ export default {
|
|||
getTableData() {
|
||||
getRelationshipCase(this.caseId, this.relationshipType, (data) => {
|
||||
this.data = data;
|
||||
this.$emit('setCount', data.length);
|
||||
});
|
||||
},
|
||||
openRelevance() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<span>
|
||||
<span>{{title}}</span>
|
||||
<span class="el-step__icon is-text ms-api-col ms-header" v-if="count > 0">
|
||||
<span class="el-step__icon is-text ms-api-col ms-header" :class="{'fix-color': fixColor}" v-if="count > 0">
|
||||
<span class="el-step__icon-inner">{{count}}</span>
|
||||
</span>
|
||||
</span>
|
||||
|
@ -10,7 +10,7 @@
|
|||
<script>
|
||||
export default {
|
||||
name: "TabPaneCount",
|
||||
props: ['title', 'count']
|
||||
props: ['title', 'count', 'fixColor']
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -24,4 +24,14 @@ export default {
|
|||
/*border-radius: 42%;*/
|
||||
/*margin-left: 4px;*/
|
||||
}
|
||||
|
||||
.fix-color {
|
||||
background: #783887;
|
||||
color: white;
|
||||
/*color: #783887;*/
|
||||
/*height: 20px;*/
|
||||
/*border: 0px !important;*/
|
||||
border-radius: 42%;
|
||||
margin-left: 4px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit a6da67c67e912b419efda9a2cdd2546dcac48075
|
||||
Subproject commit ffab6a94b62dd5a8324b2e226b05ea3f6243f169
|
|
@ -189,13 +189,14 @@ export default {
|
|||
generate_test_data: "Generate test data",
|
||||
relationship: {
|
||||
name: 'Dependencies',
|
||||
pre: 'Prepositional Object',
|
||||
post: 'Postposition Object',
|
||||
pre_case: 'Prepositional Case',
|
||||
post_case: 'Postposition Case',
|
||||
pre_api: 'Prepositional API',
|
||||
post_api: 'Postposition API',
|
||||
graph: 'Dependencies Graph',
|
||||
selected: 'Selected Node',
|
||||
direct: 'Direct Link',
|
||||
indirect: 'Indirect Link',
|
||||
|
||||
},
|
||||
project_setting: "Project Setting",
|
||||
table: {
|
||||
|
|
|
@ -189,9 +189,11 @@ export default {
|
|||
run_fail: "执行失败",
|
||||
relationship: {
|
||||
name: '依赖关系',
|
||||
pre: '前置对象',
|
||||
post: '后置置对象',
|
||||
graph: '依赖图',
|
||||
pre_case: '前置用例',
|
||||
post_case: '后置用例',
|
||||
pre_api: '前置接口',
|
||||
post_api: '后置接口',
|
||||
graph: '依赖关系图',
|
||||
selected: '选中节点',
|
||||
direct: '直接关联',
|
||||
indirect: '间接关联',
|
||||
|
|
|
@ -189,9 +189,11 @@ export default {
|
|||
run_fail: "執行失敗",
|
||||
relationship: {
|
||||
name: '依賴關系',
|
||||
pre: '前置對象',
|
||||
post: '後置置對象',
|
||||
graph: '依賴圖',
|
||||
pre_case: '前置用例',
|
||||
post_case: '後置用例',
|
||||
pre_api: '前置接口',
|
||||
post_api: '後置接口',
|
||||
graph: '依賴關系圖',
|
||||
selected: '選中節點',
|
||||
direct: '直接關聯',
|
||||
indirect: '間接關聯',
|
||||
|
|
|
@ -35,3 +35,7 @@ export function editApiTestCaseOrder(request, callback) {
|
|||
export function getRelationshipApi(id, relationshipType, callback) {
|
||||
return baseGet('/api/definition/relationship/' + id + '/' + relationshipType, callback);
|
||||
}
|
||||
|
||||
export function getRelationshipCountApi(id, callback) {
|
||||
return baseGet('/api/definition/relationship/count/' + id + '/', callback);
|
||||
}
|
||||
|
|
|
@ -70,3 +70,7 @@ export function getTestCaseNodes(projectId, callback) {
|
|||
export function getRelationshipCase(id, relationshipType, callback) {
|
||||
return baseGet('/test/case/relationship/case/' + id + '/' + relationshipType, callback);
|
||||
}
|
||||
|
||||
export function getRelationshipCountCase(id, callback) {
|
||||
return baseGet('/test/case/relationship/case/count/' + id + '/', callback);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,8 @@ const state = {
|
|||
pluginFiles: [],
|
||||
isTestCaseMinderChanged: false,
|
||||
// 当前项目是否勾选自定义ID
|
||||
currentProjectIsCustomNum: false
|
||||
currentProjectIsCustomNum: false,
|
||||
testCaseTemplate: {},
|
||||
}
|
||||
|
||||
const store = new Vuex.Store({
|
||||
|
|
|
@ -17,6 +17,9 @@ const mutations = {
|
|||
setTestPlanViewSelectNode: (state, value) => state.testPlanViewSelectNode = value,
|
||||
setIsTestCaseMinderChanged: (state, value) => state.isTestCaseMinderChanged = value,
|
||||
setCurrentProjectIsCustomNum: (state, value) => state.currentProjectIsCustomNum = value,
|
||||
setTestCaseTemplate: (state, value) => {
|
||||
state.testCaseTemplate = value
|
||||
},
|
||||
}
|
||||
|
||||
export default mutations;
|
||||
|
|
Loading…
Reference in New Issue