diff --git a/frontend/src/business/components/api/automation/ApiAutomation.vue b/frontend/src/business/components/api/automation/ApiAutomation.vue index 5a06f413b8..6da49bc742 100644 --- a/frontend/src/business/components/api/automation/ApiAutomation.vue +++ b/frontend/src/business/components/api/automation/ApiAutomation.vue @@ -329,34 +329,27 @@ export default { }, handleTabClose() { let message = ""; - if (!this.isSave) { - this.tabs.forEach(t => { - this.diff(t); - if (t && this.isSave) { - message += t.currentScenario.name + ","; - this.isSave = false; - } - }); - if (message !== "") { - this.$alert(this.$t('commons.scenario') + " [ " + message.substr(0, message.length - 1) + " ] " + this.$t('commons.confirm_info'), '', { - confirmButtonText: this.$t('commons.confirm'), - cancelButtonText: this.$t('commons.cancel'), - callback: (action) => { - if (action === 'confirm') { - this.tabs = []; - this.activeName = "default"; - this.isSave = false; - } else { - this.isSave = false; - } - } - }); - } else { - this.tabs = []; - this.activeName = "default"; - this.refresh(); + this.tabs.forEach(t => { + this.diff(t); + if (t && this.isSave) { + message += t.currentScenario.name + ","; this.isSave = false; } + }); + if (message !== "") { + this.$alert(this.$t('commons.scenario') + " [ " + message.substr(0, message.length - 1) + " ] " + this.$t('commons.confirm_info'), '', { + confirmButtonText: this.$t('commons.confirm'), + cancelButtonText: this.$t('commons.cancel'), + callback: (action) => { + if (action === 'confirm') { + this.tabs = []; + this.activeName = "default"; + this.isSave = false; + } else { + this.isSave = false; + } + } + }); } else { this.tabs = []; this.activeName = "default"; @@ -391,6 +384,7 @@ export default { }, diff(t) { if (t.currentScenario.type !== "add") { + let v1 = t.currentScenario.scenarioDefinitionOrg; let v2 = { apiScenarioModuleId: t.currentScenario.apiScenarioModuleId, @@ -414,6 +408,12 @@ export default { this.isSave = true; } } + if (t.currentScenario.type === 'add') { + this.isSave = true; + } + if (t.currentScenario.copy === true) { + this.isSave = true; + } }, deleteResourceIds(array) { if (array instanceof Array && array.length > 0) { @@ -500,39 +500,36 @@ export default { }, closeConfirm(targetName) { let message = ""; - let tab = this.tabs.filter(tab => tab.name === targetName); - if (!this.isSave) { - tab.forEach(t => { - this.diff(t); - if (t && this.isSave) { - message += t.currentScenario.name + ","; + this.tabs.forEach(tab => { + if (tab.name === targetName) { + this.diff(tab); + if (tab && this.isSave) { + message += tab.currentScenario.name + ","; + } + if (tab) { + let index = this.tabs.filter(t => t === tab); + index.splice(0, 1); + tab = undefined; + } + } + }) + if (message !== "") { + this.$alert(this.$t('commons.scenario') + " [ " + message.substr(0, message.length - 1) + " ] " + this.$t('commons.confirm_info'), '', { + confirmButtonText: this.$t('commons.confirm'), + cancelButtonText: this.$t('commons.cancel'), + callback: (action) => { + if (action === 'confirm') { + this.removeTab(targetName); + this.isSave = false; + } else { + this.isSave = false; + } } }); - if (message !== "") { - this.$alert(this.$t('commons.scenario') + " [ " + message.substr(0, message.length - 1) + " ] " + this.$t('commons.confirm_info'), '', { - confirmButtonText: this.$t('commons.confirm'), - cancelButtonText: this.$t('commons.cancel'), - callback: (action) => { - if (action === 'confirm') { - this.removeTab(targetName); - this.isSave = false; - } else { - this.isSave = false; - } - } - }); - } else { - this.isSave = false; - this.removeTab(targetName); - } } else { this.isSave = false; this.removeTab(targetName); } - if (tab) { - tab.splice(0, 1); - tab = undefined; - } if (this.tabs && this.tabs.length === 0) { this.refreshAll(); } @@ -572,7 +569,6 @@ export default { if (data) { this.setTabTitle(data); } - this.isSave = true; }, refreshTree() { if (this.$refs.nodeTree) { diff --git a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue index 7d964d4ec7..242610b811 100644 --- a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue +++ b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue @@ -1510,7 +1510,26 @@ export default { if (this.currentScenario.tags instanceof String) { this.currentScenario.tags = JSON.parse(this.currentScenario.tags); } + if (this.currentScenario.copy) { + this.currentScenario.copy = null; + } + if (this.currentScenario.type) { + this.currentScenario.type = null; + } this.pluginDelStep = false; + // 记录改变后的数据数据 + let v1 = { + apiScenarioModuleId: this.currentScenario.apiScenarioModuleId, + name: this.currentScenario.name, + status: this.currentScenario.status, + principal: this.currentScenario.principal, + level: this.currentScenario.level, + tags: this.currentScenario.tags, + description: this.currentScenario.description, + scenarioDefinition: JSON.parse(JSON.stringify(this.scenarioDefinition)) + }; + this.currentScenario.scenarioDefinitionOrg = v1; + this.currentScenario.scenarioDefinition = this.scenarioDefinition; this.$emit('refresh', this.currentScenario); resolve(); }); diff --git a/frontend/src/business/components/api/definition/ApiDefinition.vue b/frontend/src/business/components/api/definition/ApiDefinition.vue index c2a2f4f6eb..e8ae9a28e4 100644 --- a/frontend/src/business/components/api/definition/ApiDefinition.vue +++ b/frontend/src/business/components/api/definition/ApiDefinition.vue @@ -548,6 +548,7 @@ export default { return; } let api = { + name: '', status: "Underway", method: "GET", userId: getCurrentUser().id, @@ -576,11 +577,15 @@ export default { let tabs = this.apiTabs[0]; let message = ""; let tab = this.apiTabs; - delete tab[0]; tab.forEach(t => { if (t.type === 'ADD' && t.api && this.$store.state.apiMap.has(t.api.id) && (this.$store.state.apiMap.get(t.api.id).get("responseChange") === true || this.$store.state.apiMap.get(t.api.id).get("requestChange") === true || this.$store.state.apiMap.get(t.api.id).get("fromChange") === true)) { message += t.api.name + ","; + } else if (t.type === 'ADD' && t.title === this.$t('api_test.definition.request.title')) { + message += this.$t('api_test.definition.request.title') + ","; + } + if (t.type === 'ADD' && t.isCopy) { + message += t.api.name + ","; } }); if (message !== "") { @@ -603,28 +608,45 @@ export default { } }, closeConfirm(targetName) { + let message = ""; let tab = this.apiTabs; + let id; tab.forEach(t => { if (t.name === targetName) { if (t.api && this.$store.state.apiMap.size > 0 && this.$store.state.apiMap.has(t.api.id)) { + id = t.api.id; if (this.$store.state.apiMap.get(t.api.id).get("responseChange") === true || this.$store.state.apiMap.get(t.api.id).get("requestChange") === true || this.$store.state.apiMap.get(t.api.id).get("fromChange") === true) { - this.$alert(this.$t('commons.api') + " [ " + t.api.name + " ] " + this.$t('commons.confirm_info'), '', { - confirmButtonText: this.$t('commons.confirm'), - cancelButtonText: this.$t('commons.cancel'), - callback: (action) => { - if (action === 'confirm') { - this.$store.state.apiMap.delete(t.api.id); - this.handleTabRemove(targetName); - } - } - }); + message += t.api.name + ","; + id = t.api.id; } - } else { - this.handleTabRemove(targetName); + } else if (t.type === 'ADD' && t.title === this.$t('api_test.definition.request.title')) { + message += this.$t('api_test.definition.request.title') + ","; + id = t.api.id; + } + if (t.type === 'ADD' && t.isCopy) { + message += t.api.name + ","; + id = t.api.id; } } }); + if (message !== "") { + this.$alert(this.$t('commons.api') + " [ " + message.substr(0, message.length - 1) + " ] " + this.$t('commons.confirm_info'), '', { + confirmButtonText: this.$t('commons.confirm'), + cancelButtonText: this.$t('commons.cancel'), + callback: (action) => { + if (action === 'confirm') { + this.$store.state.apiMap.delete(id); + this.handleTabRemove(targetName); + } + } + }); + } else { + if (id) { + this.$store.state.apiMap.delete(id); + } + this.handleTabRemove(targetName); + } }, handleTabRemove(targetName) { let tabs = this.apiTabs; @@ -680,6 +702,7 @@ export default { closable: true, type: action, api: api, + isCopy: api ? api.isCopy : false }); if (action === "ADD") { this.activeTab = "api"; @@ -827,6 +850,11 @@ export default { saveApi(data) { this.setTabTitle(data); this.refresh(data); + this.apiTabs.forEach(t => { + if (t.api && t.api.id === data.id) { + t.isCopy = false; + } + }) }, showExecResult(row) { diff --git a/frontend/src/business/components/api/definition/components/ApiConfig.vue b/frontend/src/business/components/api/definition/components/ApiConfig.vue index 0bbc37cd62..a72f3c0792 100644 --- a/frontend/src/business/components/api/definition/components/ApiConfig.vue +++ b/frontend/src/business/components/api/definition/components/ApiConfig.vue @@ -276,7 +276,8 @@ export default { data.remark = response.data.remark; this.$emit('saveApi', data); }); - this.$store.state.apiMap.delete(this.currentApi.id); + this.$store.state.apiStatus.set("responseChange", false); + this.$store.state.apiMap.set(this.currentApi.id, this.$store.state.apiStatus); this.responseCount = 0; this.count = 0 }, diff --git a/frontend/src/business/components/api/definition/components/EditCompleteContainer.vue b/frontend/src/business/components/api/definition/components/EditCompleteContainer.vue index c2d654283a..cecb85e8b4 100644 --- a/frontend/src/business/components/api/definition/components/EditCompleteContainer.vue +++ b/frontend/src/business/components/api/definition/components/EditCompleteContainer.vue @@ -254,7 +254,6 @@ export default { this.$emit("runTest", data); }, saveApi(data) { - this.$emit("saveApi", data); if (data != null && data.tags !== 'null' && data.tags !== undefined) { if (Object.prototype.toString.call(data.tags) === "[object String]") { data.tags = JSON.parse(data.tags); @@ -263,7 +262,9 @@ export default { Object.assign(this.currentApi, data); this.currentApi.isCopy = false; this.mockSetting(); + this.$emit("saveApi", data); this.reload(); + }, createRootModel() { this.$emit("createRootModel"); diff --git a/frontend/src/business/components/api/definition/components/case/ApiCaseItem.vue b/frontend/src/business/components/api/definition/components/case/ApiCaseItem.vue index 275a0a7e7d..581f24155e 100644 --- a/frontend/src/business/components/api/definition/components/case/ApiCaseItem.vue +++ b/frontend/src/business/components/api/definition/components/case/ApiCaseItem.vue @@ -262,7 +262,9 @@ export default { showFollow: false, beforeRequest: {}, compare: [], - isSave: false + isSave: false, + tagCount: 0, + requestCount: 0, } }, props: { @@ -320,8 +322,57 @@ export default { if (this.currentApi && this.currentApi.request) { this.beforeRequest = JSON.parse(JSON.stringify(this.currentApi.request)); } + this.reload(); + }, + watch: { + 'apiCase.name': { + handler(v) { + this.saveStatus(); + } + }, + 'apiCase.priority': { + handler(v) { + this.saveStatus(); + } + }, + 'apiCase.caseStatus': { + handler(v) { + this.saveStatus(); + } + }, + 'apiCase.tags': { + handler(v) { + this.tagCount++; + if (this.tagCount > 2) { + this.saveStatus(); + } + } + }, + 'apiCase.request': { + handler(v) { + this.requestCount++; + if (this.requestCount > 1) { + this.saveStatus(); + } + } + } + }, + mounted() { + if (!(this.$store.state.apiCaseMap instanceof Map)) { + this.$store.state.apiCaseMap = new Map(); + } + if (this.apiCase.id) { + this.$store.state.apiCaseMap.set(this.apiCase.id, 0); + } }, methods: { + saveStatus() { + if (this.$store.state.apiCaseMap && this.apiCase.id) { + let change = this.$store.state.apiCaseMap.get(this.apiCase.id); + change = change + 1; + this.$store.state.apiCaseMap.set(this.apiCase.id, change); + } + }, currentUser: () => { return getCurrentUser(); }, @@ -434,7 +485,10 @@ export default { reload() { this.saveLoading = true this.$nextTick(() => { - this.saveLoading = false + this.saveLoading = false; + if (this.apiCase.id) { + this.$store.state.apiCaseMap.set(this.apiCase.id, 0); + } }); }, sort(stepArray) { @@ -505,7 +559,10 @@ export default { row.createTime = data.createTime; row.updateTime = data.updateTime; this.compare = []; + row.type = null; this.$success(this.$t('commons.save_success')); + this.tagCount = 0; + this.requestCount = 0; this.reload(); this.isSave = false; // 刷新编辑后用例列表 diff --git a/frontend/src/business/components/api/definition/components/case/ApiCaseList.vue b/frontend/src/business/components/api/definition/components/case/ApiCaseList.vue index a23537b06b..52556fa3d5 100644 --- a/frontend/src/business/components/api/definition/components/case/ApiCaseList.vue +++ b/frontend/src/business/components/api/definition/components/case/ApiCaseList.vue @@ -236,12 +236,48 @@ export default { } }, apiCaseClose() { - this.apiCaseList = []; - this.visible = false; - if (this.$route.fullPath !== this.$route.path) { - this.$router.replace({path: '/api/definition'}); + if (this.apiCaseList && this.apiCaseList.length > 0) { + console.log(this.apiCaseList) + let message = ""; + if (this.$store.state.apiCaseMap.has(this.apiCaseList[0].id) && this.$store.state.apiCaseMap.get(this.apiCaseList[0].id) > 1) { + message += this.apiCaseList[0].name + ","; + } + if (this.apiCaseList[0].type === 'AddCase') { + message += this.apiCaseList[0].name + ","; + } + if (message !== "") { + this.$alert(this.$t('commons.api_case') + " [ " + message.substr(0, message.length - 1) + " ] " + this.$t('commons.confirm_info'), '', { + confirmButtonText: this.$t('commons.confirm'), + cancelButtonText: this.$t('commons.cancel'), + callback: (action) => { + if (action === 'confirm') { + this.$store.state.apiCaseMap.delete(this.apiCaseList[0].id); + this.apiCaseList = []; + this.visible = false; + if (this.$route.fullPath !== this.$route.path) { + this.$router.replace({path: '/api/definition'}); + } + this.$emit('refresh'); + } + } + }); + } else { + this.apiCaseList = []; + this.visible = false; + if (this.$route.fullPath !== this.$route.path) { + this.$router.replace({path: '/api/definition'}); + } + this.$emit('refresh'); + } + } else { + this.apiCaseList = []; + this.visible = false; + if (this.$route.fullPath !== this.$route.path) { + this.$router.replace({path: '/api/definition'}); + } + this.$emit('refresh'); } - this.$emit('refresh'); + }, refreshModule() { this.$emit('refreshModule'); @@ -367,7 +403,8 @@ export default { active: true, tags: [], uuid: newUuid, - caseStatus: "Underway" + caseStatus: "Underway", + type: 'AddCase' }; request.projectId = getCurrentProjectID(); obj.request = request; @@ -375,6 +412,7 @@ export default { } }, copyCase(data) { + data.type = 'AddCase'; this.apiCaseList.unshift(data); }, diff --git a/frontend/src/business/components/api/definition/components/complete/EditCompleteHTTPApi.vue b/frontend/src/business/components/api/definition/components/complete/EditCompleteHTTPApi.vue index 9d77d85763..97cf5dbb20 100644 --- a/frontend/src/business/components/api/definition/components/complete/EditCompleteHTTPApi.vue +++ b/frontend/src/business/components/api/definition/components/complete/EditCompleteHTTPApi.vue @@ -467,7 +467,8 @@ export default { } this.$emit('saveApi', this.httpForm); this.count = 0; - this.$store.state.apiMap.delete(this.httpForm.id); + this.$store.state.apiStatus.set("fromChange", false); + this.$store.state.apiMap.set(this.httpForm.id, this.$store.state.apiStatus); } else { return false; } diff --git a/frontend/src/business/components/track/case/TestCase.vue b/frontend/src/business/components/track/case/TestCase.vue index e4b3149547..1699e09296 100644 --- a/frontend/src/business/components/track/case/TestCase.vue +++ b/frontend/src/business/components/track/case/TestCase.vue @@ -435,6 +435,12 @@ export default { if (t && this.$store.state.testCaseMap.has(t.testCaseInfo.id) && this.$store.state.testCaseMap.get(t.testCaseInfo.id) > 1) { message += t.testCaseInfo.name + ","; } + if (t.label === this.$t('test_track.case.create')) { + message += this.$t('test_track.case.create') + ","; + } + if (t.testCaseInfo.isCopy) { + message += t.testCaseInfo.name + ","; + } }) if (message !== "") { this.$alert(this.$t('commons.track') + " [ " + message.substr(0, message.length - 1) + " ] " + this.$t('commons.confirm_info'), '', { @@ -457,8 +463,18 @@ export default { }, closeConfirm(targetName) { let t = this.tabs.filter(tab => tab.name === targetName); + let message = ""; if (t && this.$store.state.testCaseMap.has(t[0].testCaseInfo.id) && this.$store.state.testCaseMap.get(t[0].testCaseInfo.id) > 0) { - this.$alert(this.$t('commons.track') + " [ " + t[0].testCaseInfo.name + " ] " + this.$t('commons.confirm_info'), '', { + message += t[0].testCaseInfo.name + ","; + } + if (t[0].label === this.$t('test_track.case.create')) { + message += this.$t('test_track.case.create') + ","; + } + if (t[0].testCaseInfo.isCopy) { + message += t[0].testCaseInfo.name + ","; + } + if (message !== "") { + this.$alert(this.$t('commons.track') + " [ " + message.substr(0, message.length - 1) + " ] " + this.$t('commons.confirm_info'), '', { confirmButtonText: this.$t('commons.confirm'), cancelButtonText: this.$t('commons.cancel'), callback: (action) => { diff --git a/frontend/src/business/components/track/case/components/TestCaseEdit.vue b/frontend/src/business/components/track/case/components/TestCaseEdit.vue index 48f852021c..6c9fec1181 100644 --- a/frontend/src/business/components/track/case/components/TestCaseEdit.vue +++ b/frontend/src/business/components/track/case/components/TestCaseEdit.vue @@ -696,7 +696,7 @@ export default { this.path = "/test/case/edit"; // this.operationType = "edit" this.$emit("refreshTestCase",); - this.$store.state.testCaseMap.delete(this.form.id); + this.$store.state.testCaseMap.set(this.form.id, 0); //this.tableType = 'edit'; this.$emit("refresh", response.data); if (this.form.id) { @@ -709,7 +709,9 @@ export default { } this.form.id = response.data.id; this.currentTestCaseInfo.id = response.data.id; - + if (this.currentTestCaseInfo.isCopy) { + this.currentTestCaseInfo.isCopy = null; + } if (callback) { callback(this); } diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js index 1644a133c3..fd9c47f136 100644 --- a/frontend/src/store/index.js +++ b/frontend/src/store/index.js @@ -32,6 +32,7 @@ const state = { scenarioEnvMap: new Map(), apiMap: new Map(), apiStatus: new Map(), + apiCaseMap: new Map(), testCaseMap: new Map(), curTabId: null, testCaseDefaultValue: {},