diff --git a/api-test/backend/src/main/java/io/metersphere/controller/ApiGraphController.java b/api-test/backend/src/main/java/io/metersphere/controller/ApiGraphController.java index 30c4744bd8..2229ad0f6d 100644 --- a/api-test/backend/src/main/java/io/metersphere/controller/ApiGraphController.java +++ b/api-test/backend/src/main/java/io/metersphere/controller/ApiGraphController.java @@ -1,7 +1,7 @@ package io.metersphere.controller; +import io.metersphere.request.GraphBatchRequest; import io.metersphere.service.ApiGraphService; -import io.metersphere.xpack.graph.request.GraphBatchRequest; import io.metersphere.dto.RelationshipGraphData; import org.springframework.web.bind.annotation.*; diff --git a/api-test/backend/src/main/java/io/metersphere/service/ApiGraphService.java b/api-test/backend/src/main/java/io/metersphere/service/ApiGraphService.java index 0ec8e760a5..a960609f7d 100644 --- a/api-test/backend/src/main/java/io/metersphere/service/ApiGraphService.java +++ b/api-test/backend/src/main/java/io/metersphere/service/ApiGraphService.java @@ -1,11 +1,9 @@ package io.metersphere.service; -import io.metersphere.commons.utils.CommonBeanFactory; -import io.metersphere.xpack.graph.request.GraphBatchRequest; import io.metersphere.base.mapper.ext.ExtApiDefinitionMapper; import io.metersphere.base.mapper.ext.ExtApiScenarioMapper; import io.metersphere.dto.RelationshipGraphData; -import io.metersphere.xpack.graph.GraphService; +import io.metersphere.request.GraphBatchRequest; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -19,9 +17,10 @@ public class ApiGraphService { ExtApiDefinitionMapper extApiDefinitionMapper; @Resource private ExtApiScenarioMapper extApiScenarioMapper; + @Resource + private GraphService graphService; public RelationshipGraphData getGraphData(String id, String type) { - GraphService graphService = CommonBeanFactory.getBean(GraphService.class); if (StringUtils.equals(type, "API")) { return graphService.getGraphData(id, extApiDefinitionMapper::getForGraph); } @@ -29,7 +28,6 @@ public class ApiGraphService { } public RelationshipGraphData getGraphDataByCondition(GraphBatchRequest request, String type) { - GraphService graphService = CommonBeanFactory.getBean(GraphService.class); request.getCondition().setNotEqStatus("Trash"); if (StringUtils.equals(type, "API_SCENARIO")) { return graphService.getGraphDataByCondition(request, extApiScenarioMapper::selectIdsByQuery, extApiScenarioMapper::getTestCaseForGraph); diff --git a/api-test/backend/src/main/java/io/metersphere/service/scenario/ApiAutomationRelationshipEdgeService.java b/api-test/backend/src/main/java/io/metersphere/service/scenario/ApiAutomationRelationshipEdgeService.java new file mode 100644 index 0000000000..bc31538323 --- /dev/null +++ b/api-test/backend/src/main/java/io/metersphere/service/scenario/ApiAutomationRelationshipEdgeService.java @@ -0,0 +1,88 @@ +package io.metersphere.service.scenario; + +import io.metersphere.base.domain.ApiScenarioWithBLOBs; +import io.metersphere.request.RelationshipEdgeRequest; +import io.metersphere.service.RelationshipEdgeService; +import io.metersphere.util.ObjectUtil; +import jakarta.annotation.Resource; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.json.JSONArray; +import org.json.JSONObject; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +@Service +@Transactional(rollbackFor = Exception.class) +public class ApiAutomationRelationshipEdgeService { + + @Resource + private RelationshipEdgeService relationshipEdgeService; + + // 初始化场景关系 + public void initRelationshipEdge(ApiScenarioWithBLOBs preBlobs, ApiScenarioWithBLOBs scenarioWithBLOBs) { + if (scenarioWithBLOBs == null || StringUtils.isEmpty(scenarioWithBLOBs.getScenarioDefinition())) { + return; + } + // 更新操作,检查更新前后是否有变更 + List beforeReferenceRelationships = new ArrayList<>(); + if (preBlobs != null && StringUtils.isNotEmpty(preBlobs.getScenarioDefinition())) { + beforeReferenceRelationships = this.contentAnalysis(preBlobs); + } + // 当前场景 + List referenceRelationships = this.contentAnalysis(scenarioWithBLOBs); + + if (CollectionUtils.isNotEmpty(beforeReferenceRelationships)) { + beforeReferenceRelationships.removeAll(referenceRelationships); + // 删除多余的关系 + if (CollectionUtils.isNotEmpty(beforeReferenceRelationships)) { + relationshipEdgeService.delete(scenarioWithBLOBs.getId(),beforeReferenceRelationships); + } + } + + if (CollectionUtils.isNotEmpty(referenceRelationships)) { + RelationshipEdgeRequest request = new RelationshipEdgeRequest(); + request.setId(scenarioWithBLOBs.getId()); + request.setTargetIds(referenceRelationships); + request.setType("API_SCENARIO"); + relationshipEdgeService.saveBatch(request); + } + + } + + private List contentAnalysis(ApiScenarioWithBLOBs scenarioWithBLOBs) { + List referenceRelationships = new ArrayList<>(); + if (scenarioWithBLOBs.getScenarioDefinition().contains("\"referenced\":\"REF\"")) { + // 深度解析对比,防止是复制的关系 + JSONObject element = ObjectUtil.parseObject(scenarioWithBLOBs.getScenarioDefinition()); + // 历史数据处理 + this.relationships(element.getJSONArray("hashTree"), referenceRelationships); + } + return referenceRelationships; + } + + /** + * 只找出场景直接依赖 + * + * @param hashTree + * @param referenceRelationships + */ + public static void relationships(JSONArray hashTree, List referenceRelationships) { + for (int i = 0; i < hashTree.length(); i++) { + JSONObject element = hashTree.getJSONObject(i); + if (element != null && StringUtils.equals(element.get("type").toString(), "scenario") && StringUtils.equals(element.get("referenced").toString(), "REF")) { + if (!referenceRelationships.contains(element.get("id").toString()) && element.get("id").toString().length() < 50) { + referenceRelationships.add(element.get("id").toString()); + } + } else { + if (element.has("hashTree")) { + JSONArray elementJSONArray = element.getJSONArray("hashTree"); + relationships(elementJSONArray, referenceRelationships); + } + } + } + } +} diff --git a/api-test/backend/src/main/java/io/metersphere/service/scenario/ApiScenarioService.java b/api-test/backend/src/main/java/io/metersphere/service/scenario/ApiScenarioService.java index 201189e8fb..12136daab6 100644 --- a/api-test/backend/src/main/java/io/metersphere/service/scenario/ApiScenarioService.java +++ b/api-test/backend/src/main/java/io/metersphere/service/scenario/ApiScenarioService.java @@ -57,7 +57,6 @@ import io.metersphere.service.definition.TcpApiParamService; import io.metersphere.service.ext.ExtApiScheduleService; import io.metersphere.service.ext.ExtFileAssociationService; import io.metersphere.service.plan.TestPlanScenarioCaseService; -import io.metersphere.xpack.api.service.ApiAutomationRelationshipEdgeService; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.BooleanUtils; @@ -159,6 +158,8 @@ public class ApiScenarioService { private ExtTestPlanApiScenarioMapper extTestPlanApiScenarioMapper; @Resource private BaseQuotaService baseQuotaService; + @Resource + private ApiAutomationRelationshipEdgeService apiAutomationRelationshipEdgeService; private ThreadLocal currentScenarioOrder = new ThreadLocal<>(); @@ -290,10 +291,8 @@ public class ApiScenarioService { apiScenarioMapper.insert(scenario); apiScenarioReferenceIdService.saveApiAndScenarioRelation(scenario); // 存储依赖关系 - ApiAutomationRelationshipEdgeService relationshipEdgeService = CommonBeanFactory.getBean(ApiAutomationRelationshipEdgeService.class); - if (relationshipEdgeService != null) { - relationshipEdgeService.initRelationshipEdge(null, scenario); - } + apiAutomationRelationshipEdgeService.initRelationshipEdge(null, scenario); + uploadFiles(request, bodyFiles, scenarioFiles); return scenario; } @@ -396,10 +395,8 @@ public class ApiScenarioService { uploadFiles(request, bodyFiles, scenarioFiles); // 存储依赖关系 - ApiAutomationRelationshipEdgeService relationshipEdgeService = CommonBeanFactory.getBean(ApiAutomationRelationshipEdgeService.class); - if (relationshipEdgeService != null) { - relationshipEdgeService.initRelationshipEdge(beforeScenario, scenario); - } + apiAutomationRelationshipEdgeService.initRelationshipEdge(beforeScenario, scenario); + String defaultVersion = baseProjectVersionMapper.getDefaultVersion(request.getProjectId()); if (StringUtils.equalsIgnoreCase(request.getVersionId(), defaultVersion)) { checkAndSetLatestVersion(beforeScenario.getRefId()); @@ -1332,10 +1329,8 @@ public class ApiScenarioService { sendImportScenarioCreateNotice(scenarioWithBLOBs); batchMapper.insert(scenarioWithBLOBs); // 存储依赖关系 - ApiAutomationRelationshipEdgeService relationshipEdgeService = CommonBeanFactory.getBean(ApiAutomationRelationshipEdgeService.class); - if (relationshipEdgeService != null) { - relationshipEdgeService.initRelationshipEdge(null, scenarioWithBLOBs); - } + apiAutomationRelationshipEdgeService.initRelationshipEdge(null, scenarioWithBLOBs); + apiScenarioReferenceIdService.saveApiAndScenarioRelation(scenarioWithBLOBs); extApiScenarioMapper.clearLatestVersion(scenarioWithBLOBs.getRefId()); extApiScenarioMapper.addLatestVersion(scenarioWithBLOBs.getRefId()); diff --git a/api-test/backend/src/main/java/io/metersphere/util/ObjectUtil.java b/api-test/backend/src/main/java/io/metersphere/util/ObjectUtil.java new file mode 100644 index 0000000000..d2f5795117 --- /dev/null +++ b/api-test/backend/src/main/java/io/metersphere/util/ObjectUtil.java @@ -0,0 +1,22 @@ +package io.metersphere.util; + +import io.metersphere.commons.exception.MSException; +import io.metersphere.commons.utils.JSON; +import org.apache.commons.lang3.StringUtils; +import org.json.JSONObject; + +import java.util.Map; + +public class ObjectUtil { + public static JSONObject parseObject(String value) { + try { + if (StringUtils.isEmpty(value)) { + MSException.throwException("value is null"); + } + Map map = JSON.parseObject(value, Map.class); + return new JSONObject(map); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/api-test/frontend/src/business/automation/scenario/ApiScenarioList.vue b/api-test/frontend/src/business/automation/scenario/ApiScenarioList.vue index 11e1d5e7da..b40f91333a 100644 --- a/api-test/frontend/src/business/automation/scenario/ApiScenarioList.vue +++ b/api-test/frontend/src/business/automation/scenario/ApiScenarioList.vue @@ -360,7 +360,7 @@ @errorRefresh="errorRefresh" ref="runTest"/> - + @@ -472,7 +472,7 @@ export default { MsTableOperatorButton: () => import('metersphere-frontend/src/components/MsTableOperatorButton'), MsTaskCenter: () => import('metersphere-frontend/src/components/task/TaskCenter'), MsRun: () => import('./DebugRun'), - MxRelationshipGraphDrawer: () => import('metersphere-frontend/src/components/graph/MxRelationshipGraphDrawer'), + RelationshipGraphDrawer: () => import('metersphere-frontend/src/components/graph/RelationshipGraphDrawer'), }, props: { referenced: { @@ -637,7 +637,6 @@ export default { { name: this.$t('test_track.case.generate_dependencies'), handleClick: this.generateGraph, - isXPack: true, permissions: ['PROJECT_API_SCENARIO:READ+EDIT'], }, { diff --git a/api-test/frontend/src/business/commons/DependenciesList.vue b/api-test/frontend/src/business/commons/DependenciesList.vue index a30ead7284..7418815568 100644 --- a/api-test/frontend/src/business/commons/DependenciesList.vue +++ b/api-test/frontend/src/business/commons/DependenciesList.vue @@ -1,6 +1,6 @@ @@ -37,7 +37,7 @@ export default { name: 'DependenciesList', components: { RelationshipList, - MxRelationshipGraphDrawer: () => import('metersphere-frontend/src/components/graph/MxRelationshipGraphDrawer'), + RelationshipGraphDrawer: () => import('metersphere-frontend/src/components/graph/RelationshipGraphDrawer'), }, props: ['resourceId', 'resourceType', 'readOnly', 'versionEnable'], data() { diff --git a/api-test/frontend/src/business/definition/components/list/ApiList.vue b/api-test/frontend/src/business/definition/components/list/ApiList.vue index bde9bf8e51..bc00e27b95 100644 --- a/api-test/frontend/src/business/definition/components/list/ApiList.vue +++ b/api-test/frontend/src/business/definition/components/list/ApiList.vue @@ -238,7 +238,7 @@ - + @@ -333,7 +333,7 @@ export default { TableExtendBtns, MsShowReference, MsApiReportStatus: () => import('../../../automation/report/ApiReportStatus'), - MxRelationshipGraphDrawer: () => import('metersphere-frontend/src/components/graph/MxRelationshipGraphDrawer'), + RelationshipGraphDrawer: () => import('metersphere-frontend/src/components/graph/RelationshipGraphDrawer'), }, data() { return { @@ -381,7 +381,6 @@ export default { }, { name: this.$t('test_track.case.generate_dependencies'), - isXPack: true, handleClick: this.generateGraph, permissions: ['PROJECT_API_DEFINITION:READ+EDIT_API'], }, diff --git a/framework/sdk-parent/frontend/src/components/graph/MxRelationshipGraph.vue b/framework/sdk-parent/frontend/src/components/graph/RelationshipGraph.vue similarity index 99% rename from framework/sdk-parent/frontend/src/components/graph/MxRelationshipGraph.vue rename to framework/sdk-parent/frontend/src/components/graph/RelationshipGraph.vue index b68bc3dde7..3a22f6af99 100644 --- a/framework/sdk-parent/frontend/src/components/graph/MxRelationshipGraph.vue +++ b/framework/sdk-parent/frontend/src/components/graph/RelationshipGraph.vue @@ -8,7 +8,7 @@ import DrawerHeader from "../head/DrawerHeader"; import MsChart from "../chart/MsChart"; export default { - name: "MxRelationshipGraph", + name: "RelationshipGraph", components: {MsChart, DrawerHeader, MsDrawer}, props: { data: Array, links: Array, diff --git a/framework/sdk-parent/frontend/src/components/graph/MxRelationshipGraphDrawer.vue b/framework/sdk-parent/frontend/src/components/graph/RelationshipGraphDrawer.vue similarity index 95% rename from framework/sdk-parent/frontend/src/components/graph/MxRelationshipGraphDrawer.vue rename to framework/sdk-parent/frontend/src/components/graph/RelationshipGraphDrawer.vue index 4e506a9614..4a3c74e350 100644 --- a/framework/sdk-parent/frontend/src/components/graph/MxRelationshipGraphDrawer.vue +++ b/framework/sdk-parent/frontend/src/components/graph/RelationshipGraphDrawer.vue @@ -16,10 +16,10 @@