feat_功能用例_接口定义_用户离开页面提醒保存数据 --story=1002981 --user=王孝刚 9.所有页面点关闭时先判断页面是否有修改,有则提示用户是否需要保存 https://www.tapd.cn/55049933/s/1060185
This commit is contained in:
parent
f8516212c9
commit
e9664eddc0
|
@ -29,7 +29,7 @@
|
||||||
class="ms-api-button"
|
class="ms-api-button"
|
||||||
ref="environmentSelect"/>
|
ref="environmentSelect"/>
|
||||||
<!-- 主框架列表 -->
|
<!-- 主框架列表 -->
|
||||||
<el-tabs v-model="apiDefaultTab" @edit="handleTabRemove" @tab-click="addTab">
|
<el-tabs v-model="apiDefaultTab" @edit="closeConfirm" @tab-click="addTab">
|
||||||
<el-tab-pane
|
<el-tab-pane
|
||||||
name="trash"
|
name="trash"
|
||||||
:label="$t('commons.trash')" v-if="trashEnable">
|
:label="$t('commons.trash')" v-if="trashEnable">
|
||||||
|
@ -527,9 +527,58 @@ export default {
|
||||||
},
|
},
|
||||||
handleTabClose() {
|
handleTabClose() {
|
||||||
let tabs = this.apiTabs[0];
|
let tabs = this.apiTabs[0];
|
||||||
|
let message = "";
|
||||||
|
let tab = this.apiTabs;
|
||||||
|
delete tab[0];
|
||||||
|
tab.forEach(t => {
|
||||||
|
if (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 + ",";
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (message !== "") {
|
||||||
|
this.$alert("接口[ " + message.substr(0, message.length - 1) + " ]未保存,是否确认关闭全部?", '', {
|
||||||
|
confirmButtonText: this.$t('commons.confirm'),
|
||||||
|
cancelButtonText: this.$t('commons.cancel'),
|
||||||
|
callback: (action) => {
|
||||||
|
if (action === 'confirm') {
|
||||||
|
this.$store.state.apiMap.clear();
|
||||||
this.apiTabs = [];
|
this.apiTabs = [];
|
||||||
this.apiDefaultTab = tabs.name;
|
this.apiDefaultTab = tabs.name;
|
||||||
this.apiTabs.push(tabs);
|
this.apiTabs.push(tabs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.apiTabs = [];
|
||||||
|
this.apiDefaultTab = tabs.name;
|
||||||
|
this.apiTabs.push(tabs);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
closeConfirm(targetName) {
|
||||||
|
let tabs = this.apiTabs;
|
||||||
|
if(!tabs[1].api) {
|
||||||
|
this.handleTabRemove(targetName);
|
||||||
|
}
|
||||||
|
if (tabs[1].api && this.$store.state.apiMap.size > 0) {
|
||||||
|
if (this.$store.state.apiMap.get(tabs[1].api.id).get("responseChange") === true || this.$store.state.apiMap.get(tabs[1].api.id).get("requestChange") === true ||
|
||||||
|
this.$store.state.apiMap.get(tabs[1].api.id).get("fromChange") === true) {
|
||||||
|
this.$alert("接口[ " + tabs[1].api.name + " ]未保存,是否确认关闭?", '', {
|
||||||
|
confirmButtonText: this.$t('commons.confirm'),
|
||||||
|
cancelButtonText: this.$t('commons.cancel'),
|
||||||
|
callback: (action) => {
|
||||||
|
if (action === 'confirm') {
|
||||||
|
this.$store.state.apiMap.delete(tabs[1].api.id);
|
||||||
|
this.handleTabRemove(targetName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else{
|
||||||
|
this.$store.state.apiMap.delete(tabs[1].api.id);
|
||||||
|
this.handleTabRemove(targetName);
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
handleTabRemove(targetName) {
|
handleTabRemove(targetName) {
|
||||||
let tabs = this.apiTabs;
|
let tabs = this.apiTabs;
|
||||||
|
|
|
@ -51,6 +51,8 @@
|
||||||
config: {},
|
config: {},
|
||||||
response: {},
|
response: {},
|
||||||
maintainerOptions: [],
|
maintainerOptions: [],
|
||||||
|
count: 0,
|
||||||
|
responseCount: 0,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -60,6 +62,28 @@
|
||||||
syncTabs: Array,
|
syncTabs: Array,
|
||||||
projectId: String
|
projectId: String
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
request: {
|
||||||
|
handler(newObj, oldObj) {
|
||||||
|
this.count++
|
||||||
|
if (this.count > 2) {
|
||||||
|
this.$store.state.apiStatus.set("requestChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.currentApi.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
response: {
|
||||||
|
handler(newObj, oldObj) {
|
||||||
|
this.responseCount++;
|
||||||
|
if (this.responseCount > 1) {
|
||||||
|
this.$store.state.apiStatus.set("responseChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.currentApi.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
|
},
|
||||||
created() {
|
created() {
|
||||||
this.getMaintainerOptions();
|
this.getMaintainerOptions();
|
||||||
switch (this.currentProtocol) {
|
switch (this.currentProtocol) {
|
||||||
|
@ -78,6 +102,12 @@
|
||||||
}
|
}
|
||||||
this.formatApi();
|
this.formatApi();
|
||||||
this.addListener();
|
this.addListener();
|
||||||
|
if (!(this.$store.state.apiMap instanceof Map)) {
|
||||||
|
this.$store.state.apiMap = new Map();
|
||||||
|
}
|
||||||
|
if (!(this.$store.state.apiStatus instanceof Map)) {
|
||||||
|
this.$store.state.apiStatus = new Map();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
changeTab(type){
|
changeTab(type){
|
||||||
|
@ -233,6 +263,7 @@
|
||||||
this.currentApi.isCopy = false;
|
this.currentApi.isCopy = false;
|
||||||
this.$emit('saveApi', data);
|
this.$emit('saveApi', data);
|
||||||
});
|
});
|
||||||
|
this.$store.state.apiMap.delete(this.currentApi.id);
|
||||||
},
|
},
|
||||||
handleSave() {
|
handleSave() {
|
||||||
if (this.$refs.httpApi) {
|
if (this.$refs.httpApi) {
|
||||||
|
|
|
@ -92,6 +92,48 @@
|
||||||
moduleOptions: Array,
|
moduleOptions: Array,
|
||||||
basisData: {},
|
basisData: {},
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
'basicForm.name': {
|
||||||
|
handler(v, v1) {
|
||||||
|
if (v && v1 && v !== v1) {
|
||||||
|
this.$store.state.apiStatus.set("fromChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.basicForm.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'basicForm.moduleId': {
|
||||||
|
handler(v, v1) {
|
||||||
|
if (v && v1 && v !== v1) {
|
||||||
|
this.$store.state.apiStatus.set("fromChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.basicForm.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'basicForm.status': {
|
||||||
|
handler(v, v1) {
|
||||||
|
if (v && v1 && v !== v1) {
|
||||||
|
this.$store.state.apiStatus.set("fromChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.basicForm.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'basicForm.follows': {
|
||||||
|
handler(v, v1) {
|
||||||
|
if (v && v1 && JSON.stringify(v) !== JSON.stringify(v1)) {
|
||||||
|
this.$store.state.apiStatus.set("fromChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.basicForm.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'basicForm.description': {
|
||||||
|
handler(v, v1) {
|
||||||
|
if (v && v1 && v !== v1) {
|
||||||
|
this.$store.state.apiStatus.set("fromChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.basicForm.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
created() {
|
created() {
|
||||||
this.getMaintainerOptions();
|
this.getMaintainerOptions();
|
||||||
this.basicForm = this.basisData;
|
this.basicForm = this.basisData;
|
||||||
|
|
|
@ -191,6 +191,62 @@
|
||||||
},
|
},
|
||||||
props: {moduleOptions: {}, request: {}, response: {}, basisData: {}, syncTabs: Array, projectId: String},
|
props: {moduleOptions: {}, request: {}, response: {}, basisData: {}, syncTabs: Array, projectId: String},
|
||||||
watch: {
|
watch: {
|
||||||
|
'httpForm.name': {
|
||||||
|
handler(v, v1) {
|
||||||
|
if (v && v1 && v !== v1) {
|
||||||
|
this.$store.state.apiStatus.set("fromChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.httpForm.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'httpForm.path': {
|
||||||
|
handler(v, v1) {
|
||||||
|
if (v && v1 && v !== v1) {
|
||||||
|
this.$store.state.apiStatus.set("fromChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.httpForm.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'httpForm.userId': {
|
||||||
|
handler(v, v1) {
|
||||||
|
if (v && v1 && v !== v1) {
|
||||||
|
this.$store.state.apiStatus.set("fromChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.httpForm.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'httpForm.moduleId': {
|
||||||
|
handler(v, v1) {
|
||||||
|
if (v && v1 && v !== v1) {
|
||||||
|
this.$store.state.apiStatus.set("fromChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.httpForm.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'httpForm.status': {
|
||||||
|
handler(v, v1) {
|
||||||
|
if (v && v1 && v !== v1) {
|
||||||
|
this.$store.state.apiStatus.set("fromChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.httpForm.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'httpForm.follows': {
|
||||||
|
handler(v, v1) {
|
||||||
|
if (v && v1 && JSON.stringify(v) !== JSON.stringify(v1)) {
|
||||||
|
this.$store.state.apiStatus.set("fromChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.httpForm.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'httpForm.description': {
|
||||||
|
handler(v, v1) {
|
||||||
|
if (v && v1 && v !== v1) {
|
||||||
|
this.$store.state.apiStatus.set("fromChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.httpForm.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
syncTabs() {
|
syncTabs() {
|
||||||
if (this.basisData && this.syncTabs && this.syncTabs.includes(this.basisData.id)) {
|
if (this.basisData && this.syncTabs && this.syncTabs.includes(this.basisData.id)) {
|
||||||
// 标示接口在其他地方更新过,当前页面需要同步
|
// 标示接口在其他地方更新过,当前页面需要同步
|
||||||
|
|
|
@ -136,6 +136,56 @@
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
'basicForm.name': {
|
||||||
|
handler(v, v1) {
|
||||||
|
if (v && v1 && v !== v1) {
|
||||||
|
this.$store.state.apiStatus.set("fromChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.basicForm.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'basicForm.userId': {
|
||||||
|
handler(v, v1) {
|
||||||
|
if (v && v1 && v !== v1) {
|
||||||
|
this.$store.state.apiStatus.set("fromChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.basicForm.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'basicForm.moduleId': {
|
||||||
|
handler(v, v1) {
|
||||||
|
if (v && v1 && v !== v1) {
|
||||||
|
this.$store.state.apiStatus.set("fromChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.basicForm.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'basicForm.status': {
|
||||||
|
handler(v, v1) {
|
||||||
|
if (v && v1 && v !== v1) {
|
||||||
|
this.$store.state.apiStatus.set("fromChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.basicForm.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'basicForm.follows': {
|
||||||
|
handler(v, v1) {
|
||||||
|
if (v && v1 && JSON.stringify(v) !== JSON.stringify(v1)) {
|
||||||
|
this.$store.state.apiStatus.set("fromChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.basicForm.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'basicForm.description': {
|
||||||
|
handler(v, v1) {
|
||||||
|
if (v && v1 && v !== v1) {
|
||||||
|
this.$store.state.apiStatus.set("fromChange", true);
|
||||||
|
this.$store.state.apiMap.set(this.basicForm.id, this.$store.state.apiStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getMaintainerOptions() {
|
getMaintainerOptions() {
|
||||||
this.$post('/user/project/member/tester/list', {projectId: getCurrentProjectID()}, response => {
|
this.$post('/user/project/member/tester/list', {projectId: getCurrentProjectID()}, response => {
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
</ms-aside-container>
|
</ms-aside-container>
|
||||||
|
|
||||||
<ms-main-container>
|
<ms-main-container>
|
||||||
<el-tabs v-model="activeName" @tab-click="addTab" @tab-remove="removeTab">
|
<el-tabs v-model="activeName" @tab-click="addTab" @tab-remove="closeConfirm">
|
||||||
<el-tab-pane name="trash" v-if="trashEnable" :label="$t('commons.trash')">
|
<el-tab-pane name="trash" v-if="trashEnable" :label="$t('commons.trash')">
|
||||||
<test-case-list
|
<test-case-list
|
||||||
:checkRedirectID="checkRedirectID"
|
:checkRedirectID="checkRedirectID"
|
||||||
|
@ -313,9 +313,48 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleTabClose() {
|
handleTabClose() {
|
||||||
|
let message = "";
|
||||||
|
this.tabs.forEach(t => {
|
||||||
|
if (t && this.$store.state.testCaseMap.has(t.testCaseInfo.id) && this.$store.state.testCaseMap.get(t.testCaseInfo.id) > 1) {
|
||||||
|
message += t.testCaseInfo.name + ",";
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (message !== "") {
|
||||||
|
this.$alert("用例[ " + message.substr(0, message.length - 1) + " ]未保存,是否确认关闭全部?", '', {
|
||||||
|
confirmButtonText: this.$t('commons.confirm'),
|
||||||
|
cancelButtonText: this.$t('commons.cancel'),
|
||||||
|
callback: (action) => {
|
||||||
|
if (action === 'confirm') {
|
||||||
|
this.$store.state.testCaseMap.clear();
|
||||||
this.tabs = [];
|
this.tabs = [];
|
||||||
this.activeName = "default";
|
this.activeName = "default";
|
||||||
this.refresh();
|
this.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.tabs = [];
|
||||||
|
this.activeName = "default";
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
closeConfirm(targetName) {
|
||||||
|
let t = this.tabs.filter(tab => tab.name === targetName);
|
||||||
|
if (t && this.$store.state.testCaseMap.has(t[0].testCaseInfo.id) && this.$store.state.testCaseMap.get(t[0].testCaseInfo.id) > 1) {
|
||||||
|
this.$alert("用例[ " + t[0].testCaseInfo.name + " ]未保存,是否确认关闭?", '', {
|
||||||
|
confirmButtonText: this.$t('commons.confirm'),
|
||||||
|
cancelButtonText: this.$t('commons.cancel'),
|
||||||
|
callback: (action) => {
|
||||||
|
if (action === 'confirm') {
|
||||||
|
this.$store.state.testCaseMap.delete(t[0].testCaseInfo.id);
|
||||||
|
this.removeTab(targetName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.$store.state.testCaseMap.delete(t[0].testCaseInfo.id);
|
||||||
|
this.removeTab(targetName);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
removeTab(targetName) {
|
removeTab(targetName) {
|
||||||
this.tabs = this.tabs.filter(tab => tab.name !== targetName);
|
this.tabs = this.tabs.filter(tab => tab.name !== targetName);
|
||||||
|
|
|
@ -96,7 +96,7 @@ export default {
|
||||||
watch: {
|
watch: {
|
||||||
treeNodes() {
|
treeNodes() {
|
||||||
this.getModuleOptions();
|
this.getModuleOptions();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
projectId() {
|
projectId() {
|
||||||
|
|
|
@ -308,6 +308,18 @@
|
||||||
!hasPermission('PROJECT_TRACK_CASE:READ+EDIT');
|
!hasPermission('PROJECT_TRACK_CASE:READ+EDIT');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
form: {
|
||||||
|
handler(val) {
|
||||||
|
if (this.$store.state.testCaseMap) {
|
||||||
|
let change = this.$store.state.testCaseMap.get(this.form.id);
|
||||||
|
change = change + 1;
|
||||||
|
this.$store.state.testCaseMap.set(this.form.id, change);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.getSelectOptions();
|
this.getSelectOptions();
|
||||||
if (this.type === 'edit' || this.type === 'copy') {
|
if (this.type === 'edit' || this.type === 'copy') {
|
||||||
|
@ -330,6 +342,10 @@
|
||||||
this.form.module = this.treeNodes[0].id;
|
this.form.module = this.treeNodes[0].id;
|
||||||
this.form.nodePath = this.treeNodes[0].path;
|
this.form.nodePath = this.treeNodes[0].path;
|
||||||
}
|
}
|
||||||
|
if (!(this.$store.state.testCaseMap instanceof Map)) {
|
||||||
|
this.$store.state.testCaseMap = new Map();
|
||||||
|
}
|
||||||
|
this.$store.state.testCaseMap.set(this.form.id, 0);
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.projectId = this.projectIds;
|
this.projectId = this.projectIds;
|
||||||
|
@ -557,7 +573,7 @@
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.showInputTag = true;
|
this.showInputTag = true;
|
||||||
});
|
});
|
||||||
|
this.$store.state.testCaseMap.set(this.form.id, 0);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
async setFormData(testCase) {
|
async setFormData(testCase) {
|
||||||
|
@ -645,6 +661,7 @@
|
||||||
// 保存用例后刷新附件
|
// 保存用例后刷新附件
|
||||||
this.$refs.otherInfo.getFileMetaData(this.form.id);
|
this.$refs.otherInfo.getFileMetaData(this.form.id);
|
||||||
});
|
});
|
||||||
|
this.$store.state.testCaseMap.set(this.form.id, 0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
buildParam() {
|
buildParam() {
|
||||||
|
|
|
@ -31,6 +31,9 @@ const state = {
|
||||||
currentProjectIsCustomNum: false,
|
currentProjectIsCustomNum: false,
|
||||||
testCaseTemplate: {},
|
testCaseTemplate: {},
|
||||||
scenarioMap: new Map(),
|
scenarioMap: new Map(),
|
||||||
|
apiMap: new Map(),
|
||||||
|
apiStatus: new Map(),
|
||||||
|
testCaseMap: new Map()
|
||||||
}
|
}
|
||||||
|
|
||||||
const store = new Vuex.Store({
|
const store = new Vuex.Store({
|
||||||
|
|
Loading…
Reference in New Issue