diff --git a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java index ff8b40415f..45eddfa5c8 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -73,25 +73,6 @@ public class ApiAutomationService { List list = extApiScenarioMapper.list(request); ApiTagExample example = new ApiTagExample(); example.createCriteria().andProjectIdEqualTo(request.getProjectId()); - List tags = apiTagMapper.selectByExample(example); - Map tagMap = tags.stream().collect(Collectors.toMap(ApiTag::getId, ApiTag::getName)); - Gson gs = new Gson(); - list.forEach(item -> { - if (item.getTagId() != null) { - StringBuilder buf = new StringBuilder(); - gs.fromJson(item.getTagId(), List.class).forEach(t -> { - buf.append(tagMap.get(t)); - buf.append(","); - }); - if (buf != null && buf.length() > 0) { - String tagNames = buf.toString().substring(0, buf.toString().length() - 1); - List tagList = Arrays.asList(tagNames.split(",")); - item.setTagNames(tagList); - } else { - item.setTagNames(new ArrayList<>()); - } - } - }); return list; } diff --git a/backend/src/main/resources/db/migration/V50__api_scenario.sql b/backend/src/main/resources/db/migration/V50__api_scenario.sql index b682f0c220..7afc0d42ac 100644 --- a/backend/src/main/resources/db/migration/V50__api_scenario.sql +++ b/backend/src/main/resources/db/migration/V50__api_scenario.sql @@ -58,14 +58,4 @@ CREATE TABLE `api_scenario_report_detail` ( `project_id` varchar(64) NOT NULL COMMENT 'scenario ID', `content` longblob COMMENT 'Report Content', PRIMARY KEY (`report_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -CREATE TABLE `api_tag` ( - `id` varchar(50) NOT NULL COMMENT 'Test ID', - `project_id` varchar(50) NOT NULL COMMENT 'Project ID this test belongs to', - `name` varchar(200) NOT NULL COMMENT 'api tag', - `user_id` varchar(64) DEFAULT NULL COMMENT 'User ID', - `create_time` bigint(13) NOT NULL COMMENT 'Create timestamp', - `update_time` bigint(13) NOT NULL COMMENT 'Update timestamp', - PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index cc05d4c0c6..8f2fc5b9ee 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -17,29 +17,30 @@ "@fortawesome/vue-fontawesome": "^0.1.9", "axios": "^0.19.0", "core-js": "^3.4.3", + "diffable-html": "^4.0.0", "echarts": "^4.6.0", + "el-table-infinite-scroll": "^1.0.10", "element-ui": "^2.13.0", + "html2canvas": "^1.0.0-rc.7", + "js-base64": "^3.4.4", + "json-bigint": "^1.0.0", + "jsoneditor": "^9.1.2", + "jspdf": "^2.1.1", + "md5": "^2.3.0", + "mockjs": "^1.1.0", + "nprogress": "^0.2.0", + "sha.js": "^2.4.11", "vue": "^2.6.10", + "vue-calendar-heatmap": "^0.8.4", "vue-echarts": "^4.1.0", "vue-i18n": "^8.15.3", + "vue-input-tag": "^2.0.7", + "vue-pdf": "^4.2.0", "vue-router": "^3.1.3", "vuedraggable": "^2.23.2", "vuex": "^3.1.2", - "vue-calendar-heatmap": "^0.8.4", - "mockjs": "^1.1.0", - "md5": "^2.3.0", - "sha.js": "^2.4.11", - "js-base64": "^3.4.4", - "json-bigint": "^1.0.0", - "html2canvas": "^1.0.0-rc.7", - "jspdf": "^2.1.1", - "yan-progress": "^1.0.3", - "nprogress": "^0.2.0", - "el-table-infinite-scroll": "^1.0.10", - "vue-pdf": "^4.2.0", - "diffable-html": "^4.0.0", "xml-js": "^1.6.11", - "jsoneditor": "^9.1.2" + "yan-progress": "^1.0.3" }, "devDependencies": { "@vue/cli-plugin-babel": "^4.1.0", diff --git a/frontend/src/business/components/api/automation/scenario/AddTag.vue b/frontend/src/business/components/api/automation/scenario/AddTag.vue deleted file mode 100644 index f9c073820e..0000000000 --- a/frontend/src/business/components/api/automation/scenario/AddTag.vue +++ /dev/null @@ -1,126 +0,0 @@ - - - diff --git a/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue b/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue index 1e1bea9afc..aeaf0ac2bf 100644 --- a/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue +++ b/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue @@ -25,9 +25,9 @@ - + @@ -167,6 +167,11 @@ let data = response.data; this.total = data.itemCount; this.tableData = data.listObject; + this.tableData.forEach(item => { + if (item.tagId && item.tagId.length > 0) { + item.tagId = JSON.parse(item.tagId); + } + }) this.loading = false; }); }, diff --git a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue index 5df9e6e1f0..f9dd18c3bf 100644 --- a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue +++ b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue @@ -80,24 +80,7 @@ - - - - {{ $t('api_test.automation.create_tag') }} - - - - + @@ -259,8 +242,6 @@ - - @@ -293,13 +274,14 @@ import MsApiCustomize from "./ApiCustomize"; import {getUUID, getCurrentProjectID} from "@/common/js/utils"; import ApiEnvironmentConfig from "../../definition/components/environment/ApiEnvironmentConfig"; - import MsAddTag from "./AddTag"; + import MsInputTag from "./MsInputTag"; import MsRun from "./DebugRun"; import MsImportApiScenario from "./ImportApiScenario"; import MsApiScenarioComponent from "./ApiScenarioComponent"; import MsApiReportDetail from "../report/ApiReportDetail"; import MsScenarioParameters from "./ScenarioParameters"; import ApiImport from "../../definition/components/import/ApiImport"; + import InputTag from 'vue-input-tag' export default { name: "EditApiScenario", @@ -311,7 +293,7 @@ ApiEnvironmentConfig, MsScenarioParameters, MsApiReportDetail, - MsAddTag, MsRun, + MsInputTag, MsRun, MsApiScenarioComponent, MsImportApiScenario, MsJsr233Processor, @@ -323,6 +305,7 @@ MsApiComponent, MsApiCustomize, ApiImport, + InputTag, }, data() { return { @@ -341,7 +324,6 @@ principal: [{required: true, message: this.$t('api_test.definition.request.responsible'), trigger: 'change'}], }, environments: [], - tags: [], currentEnvironmentId: "", maintainerOptions: [], value: API_STATUS[0].id, @@ -366,7 +348,8 @@ visibleRef: "", enableCookieShare: false, } - }, + } + , created() { if (!this.currentScenario.apiScenarioModuleId) { this.currentScenario.apiScenarioModuleId = ""; @@ -374,11 +357,12 @@ this.projectId = getCurrentProjectID(); this.operatingElements = ELEMENTS.get("ALL"); this.getMaintainerOptions(); - this.refreshTags(); this.getApiScenario(); this.getEnvironments(); - }, - watch: {}, + } + , + watch: {} + , methods: { addComponent(type) { switch (type) { @@ -423,7 +407,8 @@ } this.sort(); this.reload(); - }, + } + , nodeClick(e) { if (e.referenced != 'REF' && e.referenced != 'Deleted') { this.operatingElements = ELEMENTS.get(e.type); @@ -431,16 +416,19 @@ this.operatingElements = []; } this.selectedTreeNode = e; - }, + } + , showAll() { this.operatingElements = ELEMENTS.get("ALL"); this.selectedTreeNode = undefined; this.reload(); - }, + } + , apiListImport() { this.visibleRef = getUUID(); this.apiListVisible = true; - }, + } + , recursiveSorting(arr) { for (let i in arr) { arr[i].index = Number(i) + 1; @@ -448,7 +436,8 @@ this.recursiveSorting(arr[i].hashTree); } } - }, + } + , sort() { for (let i in this.scenarioDefinition) { this.scenarioDefinition[i].index = Number(i) + 1; @@ -456,7 +445,8 @@ this.recursiveSorting(this.scenarioDefinition[i].hashTree); } } - }, + } + , addCustomizeApi(request) { this.customizeVisible = false; request.enable === undefined ? request.enable = true : request.enable; @@ -468,7 +458,8 @@ this.customizeRequest = {}; this.sort(); this.reload(); - }, + } + , addScenario(arr) { if (arr && arr.length > 0) { arr.forEach(item => { @@ -483,7 +474,8 @@ this.sort(); this.reload(); this.scenarioVisible = false; - }, + } + , setApiParameter(item, refType, referenced) { let request = {}; if (Object.prototype.toString.call(item.request).indexOf("String") > 0) { @@ -512,7 +504,8 @@ } else { this.scenarioDefinition.push(request); } - }, + } + , pushApiOrCase(referenced) { if (this.currentRow.cases.length === 0 && this.currentRow.apis.length === 0) { this.$warning(this.$t('api_test.automation.reference_info')); @@ -529,13 +522,15 @@ this.currentRow.apis = []; this.sort(); this.reload(); - }, + } + , getMaintainerOptions() { let workspaceId = localStorage.getItem(WORKSPACE_ID); this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => { this.maintainerOptions = response.data; }); - }, + } + , openTagConfig() { if (!this.projectId) { this.$error(this.$t('api_test.select_project')); @@ -543,20 +538,6 @@ } this.$refs.tag.open(); }, - refreshTags() { - let obj = {projectId: this.projectId}; - let tagIds = []; - this.$post('/api/tag/list', obj, response => { - this.tags = response.data; - this.tags.forEach(item => { - tagIds.push(item.id); - }) - if (this.currentScenario.tagId != undefined && this.currentScenario.tagId.length > 0) { - this.currentScenario.tagId = this.currentScenario.tagId.filter(id => tagIds.indexOf(id) != -1); - } - }); - - }, remove(row, node) { const parent = node.parent const hashTree = parent.data.hashTree || parent.data; @@ -564,7 +545,8 @@ hashTree.splice(index, 1); this.sort(); this.reload(); - }, + } + , copyRow(row, node) { const parent = node.parent const hashTree = parent.data.hashTree || parent.data; @@ -574,13 +556,15 @@ hashTree.push(obj); this.sort(); this.reload(); - }, + } + , reload() { this.loading = true this.$nextTick(() => { this.loading = false }) - }, + } + , runDebug() { /*触发执行操作*/ if (!this.currentEnvironmentId) { @@ -593,7 +577,8 @@ environmentId: this.currentEnvironmentId, hashTree: this.scenarioDefinition }; this.reportId = getUUID().substring(0, 8); - }, + } + , getEnvironments() { if (this.projectId) { this.$get('/api/environment/list/' + this.projectId, response => { @@ -603,17 +588,20 @@ }); }); } - }, + } + , openEnvironmentConfig() { if (!this.projectId) { this.$error(this.$t('api_test.select_project')); return; } this.$refs.environmentConfig.open(this.projectId); - }, + } + , environmentConfigClose() { this.getEnvironments(); - }, + } + , allowDrop(draggingNode, dropNode, dropType) { if (dropType != "inner") { return true; @@ -622,21 +610,25 @@ return true; } return false; - }, + } + , allowDrag(draggingNode, dropNode, dropType) { this.sort(); this.reload(); - }, + } + , nodeExpand(data) { if (data.resourceId) { this.expandedNode.push(data.resourceId); } - }, + } + , nodeCollapse(data) { if (data.resourceId) { this.expandedNode.splice(this.expandedNode.indexOf(data.resourceId), 1); } - }, + } + , getPath(id) { if (id === null) { return null; @@ -645,7 +637,8 @@ return item.id === id ? item.path : ""; }); return path[0].path; - }, + } + , setFiles(item, bodyUploadFiles, obj) { if (item.body) { if (item.body.kvs) { @@ -683,7 +676,8 @@ }); } } - }, + } + , recursiveFile(arr, bodyUploadFiles, obj) { arr.forEach(item => { this.setFiles(item, bodyUploadFiles, obj); @@ -691,7 +685,8 @@ this.recursiveFile(item.hashTree, bodyUploadFiles, obj); } }); - }, + } + , getBodyUploadFiles(obj) { let bodyUploadFiles = []; obj.bodyUploadIds = []; @@ -702,7 +697,8 @@ } }) return bodyUploadFiles; - }, + } + , editScenario() { this.$refs['currentScenario'].validate((valid) => { if (valid) { @@ -714,12 +710,15 @@ if (response.data) { this.currentScenario.id = response.data.id; } - this.currentScenario.tagId = JSON.parse(this.currentScenario.tagId); + if (this.currentScenario.tagId instanceof String) { + this.currentScenario.tagId = JSON.parse(this.currentScenario.tagId); + } this.$emit('refresh'); }) } }) - }, + } + , getApiScenario() { if (this.currentScenario.tagId != undefined && !(this.currentScenario.tagId instanceof Array)) { this.currentScenario.tagId = JSON.parse(this.currentScenario.tagId); @@ -743,7 +742,8 @@ } }) } - }, + } + , setParameter() { this.currentScenario.stepTotal = this.scenarioDefinition.length; this.currentScenario.projectId = getCurrentProjectID(); @@ -762,18 +762,22 @@ this.currentScenario.apiScenarioModuleId = this.currentModule.id; } this.currentScenario.projectId = this.projectId; - }, + } + , runRefresh() { this.debugVisible = true; this.loading = false; - }, + } + , showScenarioParameters() { this.$refs.scenarioParameters.open(this.currentScenario.variables); - }, + } + , addParameters(data) { this.currentScenario.variables = data; this.reload(); - }, + } + , apiImport(importData) { if (importData && importData.data) { importData.data.forEach(item => { @@ -939,4 +943,9 @@ font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial, sans-serif; font-size: 13px; } + + /deep/ .el-form-item__content { + line-height: 100%; + } + diff --git a/frontend/src/business/components/api/automation/scenario/MsInputTag.vue b/frontend/src/business/components/api/automation/scenario/MsInputTag.vue new file mode 100644 index 0000000000..c012ca59fc --- /dev/null +++ b/frontend/src/business/components/api/automation/scenario/MsInputTag.vue @@ -0,0 +1,69 @@ + + + + +