fix(接口自动化): 修复接口复制重复保存问题;优化操作日志页面

--bug=1007956 --user=赵勇 【接口测试】复制接口后多次点保存会提示接口地址已存在 https://www.tapd.cn/55049933/s/1068905
This commit is contained in:
fit2-zhao 2021-11-17 11:28:33 +08:00 committed by fit2-zhao
parent 095cdd5baa
commit e8337b7ffa
4 changed files with 301 additions and 311 deletions

View File

@ -57,7 +57,7 @@
left join `user` t1 ON t.user_id = t1.id left join `user` t1 ON t.user_id = t1.id
left join test_resource_pool t2 on t.actuator = t2.id left join test_resource_pool t2 on t.actuator = t2.id
left join api_test_case t4 on t4.id = t.resource_id left join api_test_case t4 on t4.id = t.resource_id
where t4.id=#{id} and t.content != "" LIMIT 5; where t4.id=#{id} and t.content != "" order by t.create_time desc LIMIT 5;
</select> </select>
<select id="getScenario" resultType="io.metersphere.task.dto.TaskCenterDTO" parameterType="java.lang.String"> <select id="getScenario" resultType="io.metersphere.task.dto.TaskCenterDTO" parameterType="java.lang.String">

View File

@ -28,326 +28,316 @@
</template> </template>
<script> <script>
import MsEditCompleteHttpApi from "./complete/EditCompleteHTTPApi"; import MsEditCompleteHttpApi from "./complete/EditCompleteHTTPApi";
import MsEditCompleteTcpApi from "./complete/EditCompleteTCPApi"; import MsEditCompleteTcpApi from "./complete/EditCompleteTCPApi";
import MsEditCompleteDubboApi from "./complete/EditCompleteDubboApi"; import MsEditCompleteDubboApi from "./complete/EditCompleteDubboApi";
import MsEditCompleteSqlApi from "./complete/EditCompleteSQLApi"; import MsEditCompleteSqlApi from "./complete/EditCompleteSQLApi";
import {Body} from "../model/ApiTestModel"; import {Body} from "../model/ApiTestModel";
import {getCurrentProjectID, getUUID} from "@/common/js/utils"; import {getCurrentProjectID, getUUID} from "@/common/js/utils";
import {createComponent, Request} from "./jmeter/components"; import {createComponent, Request} from "./jmeter/components";
import Sampler from "./jmeter/components/sampler/sampler"; import Sampler from "./jmeter/components/sampler/sampler";
import {WORKSPACE_ID} from '@/common/js/constants'; import {WORKSPACE_ID} from '@/common/js/constants';
import {handleCtrlSEvent} from "../../../../../common/js/utils"; import {handleCtrlSEvent} from "../../../../../common/js/utils";
import {ELEMENT_TYPE, TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting"; import {ELEMENT_TYPE, TYPE_TO_C} from "@/business/components/api/automation/scenario/Setting";
export default { export default {
name: "ApiConfig", name: "ApiConfig",
components: {MsEditCompleteHttpApi, MsEditCompleteTcpApi, MsEditCompleteDubboApi, MsEditCompleteSqlApi}, components: {MsEditCompleteHttpApi, MsEditCompleteTcpApi, MsEditCompleteDubboApi, MsEditCompleteSqlApi},
data() { data() {
return { return {
reqUrl: "", reqUrl: "",
request: Sampler, request: Sampler,
config: {}, config: {},
response: {}, response: {},
maintainerOptions: [], maintainerOptions: [],
count: 0, count: 0,
responseCount: 0, responseCount: 0,
} }
}, },
props: { props: {
currentApi: {}, currentApi: {},
moduleOptions: {}, moduleOptions: {},
currentProtocol: String, currentProtocol: String,
syncTabs: Array, syncTabs: Array,
projectId: String projectId: String
}, },
watch: { watch: {
request: { 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) { handler(newObj, oldObj) {
this.responseCount++; this.count++
if (this.responseCount > 1) { if (this.count > 2) {
this.$store.state.apiStatus.set("responseChange", true); this.$store.state.apiStatus.set("requestChange", true);
this.$store.state.apiMap.set(this.currentApi.id, this.$store.state.apiStatus); this.$store.state.apiMap.set(this.currentApi.id, this.$store.state.apiStatus);
} }
}, },
deep: true deep: true
}, },
created() { },
this.getMaintainerOptions(); response: {
switch (this.currentProtocol) { handler(newObj, oldObj) {
case Request.TYPES.SQL: this.responseCount++;
this.initSql(); if (this.responseCount > 1) {
break; this.$store.state.apiStatus.set("responseChange", true);
case Request.TYPES.DUBBO: this.$store.state.apiMap.set(this.currentApi.id, this.$store.state.apiStatus);
this.initDubbo();
break;
case Request.TYPES.TCP:
this.initTcp();
break;
default:
this.initHttp();
break;
}
this.formatApi();
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: { deep: true
changeTab(type){ },
this.$emit("changeTab",type); created() {
}, this.getMaintainerOptions();
addListener() { switch (this.currentProtocol) {
document.addEventListener("keydown", this.createCtrlSHandle); case Request.TYPES.SQL:
// document.addEventListener("keydown", (even => handleCtrlSEvent(even, this.$refs.httpApi.saveApi))); this.initSql();
}, break;
removeListener() { case Request.TYPES.DUBBO:
document.removeEventListener("keydown", this.createCtrlSHandle); this.initDubbo();
}, break;
createCtrlSHandle(event) { case Request.TYPES.TCP:
if (this.$refs.httpApi) { this.initTcp();
handleCtrlSEvent(event, this.$refs.httpApi.saveApi); break;
} default:
else if (this.$refs.tcpApi) { this.initHttp();
handleCtrlSEvent(event, this.$refs.tcpApi.saveApi); break;
}
else if (this.$refs.dubboApi) {
handleCtrlSEvent(event, this.$refs.dubboApi.saveApi);
}
else if (this.$refs.sqlApi) {
handleCtrlSEvent(event, this.$refs.sqlApi.saveApi);
}
},
runTest(data) {
this.setParameters(data);
let bodyFiles = this.getBodyUploadFiles(data);
this.$fileUpload(this.reqUrl, null, bodyFiles, data, response => {
this.$success(this.$t('commons.save_success'));
this.reqUrl = "/api/definition/update";
let newData = response.data;
data.request = JSON.parse(newData.request);
this.$emit('runTest', data);
});
},
mockConfig(data) {
this.$emit('mockConfig', data);
},
createRootModelInTree() {
this.$emit("createRootModel");
},
getMaintainerOptions() {
this.$post('/user/project/member/tester/list', {projectId: getCurrentProjectID()}, response => {
this.maintainerOptions = response.data;
});
},
setRequest() {
if (this.currentApi.request != undefined && this.currentApi.request != null) {
if (Object.prototype.toString.call(this.currentApi.request).match(/\[object (\w+)\]/)[1].toLowerCase() === 'object') {
this.request = this.currentApi.request;
} else {
this.request = JSON.parse(this.currentApi.request);
}
if (!this.request.headers) {
this.request.headers = [];
}
this.currentApi.request = this.request;
return true;
}
return false;
},
initSql() {
if (!this.setRequest()) {
this.request = createComponent("JDBCSampler");
this.currentApi.request = this.request;
}
if (!this.currentApi.request.variables) {
this.currentApi.request.variables = [];
}
},
initDubbo() {
if (!this.setRequest()) {
this.request = createComponent("DubboSampler");
this.currentApi.request = this.request;
}
},
initTcp() {
if (!this.setRequest()) {
this.request = createComponent("TCPSampler");
this.currentApi.request = this.request;
}
},
initHttp() {
if (!this.setRequest()) {
this.request = createComponent("HTTPSamplerProxy");
this.currentApi.request = this.request;
}
},
sort(stepArray) {
if (stepArray) {
for (let i in stepArray) {
if (!stepArray[i].clazzName) {
stepArray[i].clazzName = TYPE_TO_C.get(stepArray[i].type);
}
if (stepArray[i].type === "Assertions" && !stepArray[i].document) {
stepArray[i].document = {type: "JSON", data: {xmlFollowAPI: false, jsonFollowAPI: false, json: [], xml: []}};
}
if (stepArray[i].hashTree && stepArray[i].hashTree.length > 0) {
this.sort(stepArray[i].hashTree);
}
}
}
},
formatApi() {
if (this.currentApi.response != null && this.currentApi.response != 'null' && this.currentApi.response != undefined) {
if (Object.prototype.toString.call(this.currentApi.response).match(/\[object (\w+)\]/)[1].toLowerCase() === 'object') {
this.response = this.currentApi.response;
} else {
this.response = JSON.parse(this.currentApi.response);
}
} else {
this.response = {headers: [], body: new Body(), statusCode: [], type: "HTTP"};
}
if (this.currentApi && this.currentApi.id && !this.currentApi.isCopy) {
this.reqUrl = "/api/definition/update";
} else {
this.reqUrl = "/api/definition/create";
}
if (!this.request.hashTree) {
this.request.hashTree = [];
}
if (this.request.body && !this.request.body.binary) {
this.request.body.binary = [];
}
//
if (this.response.body) {
let body = new Body();
Object.assign(body, this.response.body);
if (!body.binary) {
body.binary = [];
}
if (!body.kvs) {
body.kvs = [];
}
if (!body.binary) {
body.binary = [];
}
this.response.body = body;
}
this.request.clazzName = TYPE_TO_C.get(this.request.type);
this.sort(this.request.hashTree);
},
saveApi(data) {
this.setParameters(data);
let bodyFiles = this.getBodyUploadFiles(data);
data.requestId = data.request.id;
if(data.request) {
this.sort(data.request.hashTree);
}
this.$fileUpload(this.reqUrl, null, bodyFiles, data, () => {
this.$success(this.$t('commons.save_success'));
this.reqUrl = "/api/definition/update";
this.currentApi.isCopy = false;
this.$emit('saveApi', data);
});
this.$store.state.apiMap.delete(this.currentApi.id);
},
handleSave() {
if (this.$refs.httpApi) {
this.$refs.httpApi.saveApi();
}
else if (this.$refs.tcpApi) {
this.$refs.tcpApi.saveApi();
}
else if (this.$refs.dubboApi) {
this.$refs.dubboApi.saveApi();
}
else if (this.$refs.sqlApi) {
this.$refs.sqlApi.saveApi();
}
},
setParameters(data) {
data.projectId = this.projectId;
this.request.name = this.currentApi.name;
data.protocol = this.currentProtocol;
data.request = this.request;
data.request.name = data.name;
if (this.currentProtocol === "DUBBO" || this.currentProtocol === "dubbo://") {
data.request.protocol = "dubbo://";
} else {
data.request.protocol = this.currentProtocol;
}
if (data.isCopy) {
data.id = getUUID();
} else {
if (data.id) {
data.request.id = data.id;
} else {
data.id = data.request.id;
}
}
if (!data.method) {
data.method = this.currentProtocol;
}
data.response = this.response;
},
getBodyUploadFiles(data) {
let bodyUploadFiles = [];
data.bodyUploadIds = [];
let request = data.request;
if (request.body) {
if (request.body.kvs) {
request.body.kvs.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
// let fileId = getUUID().substring(0, 8);
item.name = item.file.name;
// item.id = fileId;
// data.bodyUploadIds.push(fileId);
bodyUploadFiles.push(item.file);
}
});
}
});
}
if (request.body.binary) {
request.body.binary.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
let fileId = getUUID().substring(0, 8);
item.name = item.file.name;
item.id = fileId;
data.bodyUploadIds.push(fileId);
bodyUploadFiles.push(item.file);
}
});
}
});
}
}
return bodyUploadFiles;
},
} }
this.formatApi();
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: {
changeTab(type) {
this.$emit("changeTab", type);
},
addListener() {
document.addEventListener("keydown", this.createCtrlSHandle);
},
removeListener() {
document.removeEventListener("keydown", this.createCtrlSHandle);
},
createCtrlSHandle(event) {
if (this.$refs.httpApi) {
handleCtrlSEvent(event, this.$refs.httpApi.saveApi);
} else if (this.$refs.tcpApi) {
handleCtrlSEvent(event, this.$refs.tcpApi.saveApi);
} else if (this.$refs.dubboApi) {
handleCtrlSEvent(event, this.$refs.dubboApi.saveApi);
} else if (this.$refs.sqlApi) {
handleCtrlSEvent(event, this.$refs.sqlApi.saveApi);
}
},
runTest(data) {
this.setParameters(data);
let bodyFiles = this.getBodyUploadFiles(data);
this.$fileUpload(this.reqUrl, null, bodyFiles, data, response => {
this.$success(this.$t('commons.save_success'));
this.reqUrl = "/api/definition/update";
let newData = response.data;
data.request = JSON.parse(newData.request);
this.$emit('runTest', data);
});
},
mockConfig(data) {
this.$emit('mockConfig', data);
},
createRootModelInTree() {
this.$emit("createRootModel");
},
getMaintainerOptions() {
this.$post('/user/project/member/tester/list', {projectId: getCurrentProjectID()}, response => {
this.maintainerOptions = response.data;
});
},
setRequest() {
if (this.currentApi.request != undefined && this.currentApi.request != null) {
if (Object.prototype.toString.call(this.currentApi.request).match(/\[object (\w+)\]/)[1].toLowerCase() === 'object') {
this.request = this.currentApi.request;
} else {
this.request = JSON.parse(this.currentApi.request);
}
if (!this.request.headers) {
this.request.headers = [];
}
this.currentApi.request = this.request;
return true;
}
return false;
},
initSql() {
if (!this.setRequest()) {
this.request = createComponent("JDBCSampler");
this.currentApi.request = this.request;
}
if (!this.currentApi.request.variables) {
this.currentApi.request.variables = [];
}
},
initDubbo() {
if (!this.setRequest()) {
this.request = createComponent("DubboSampler");
this.currentApi.request = this.request;
}
},
initTcp() {
if (!this.setRequest()) {
this.request = createComponent("TCPSampler");
this.currentApi.request = this.request;
}
},
initHttp() {
if (!this.setRequest()) {
this.request = createComponent("HTTPSamplerProxy");
this.currentApi.request = this.request;
}
},
sort(stepArray) {
if (stepArray) {
for (let i in stepArray) {
if (!stepArray[i].clazzName) {
stepArray[i].clazzName = TYPE_TO_C.get(stepArray[i].type);
}
if (stepArray[i].type === "Assertions" && !stepArray[i].document) {
stepArray[i].document = {type: "JSON", data: {xmlFollowAPI: false, jsonFollowAPI: false, json: [], xml: []}};
}
if (stepArray[i].hashTree && stepArray[i].hashTree.length > 0) {
this.sort(stepArray[i].hashTree);
}
}
}
},
formatApi() {
if (this.currentApi.response != null && this.currentApi.response != 'null' && this.currentApi.response != undefined) {
if (Object.prototype.toString.call(this.currentApi.response).match(/\[object (\w+)\]/)[1].toLowerCase() === 'object') {
this.response = this.currentApi.response;
} else {
this.response = JSON.parse(this.currentApi.response);
}
} else {
this.response = {headers: [], body: new Body(), statusCode: [], type: "HTTP"};
}
if (this.currentApi && this.currentApi.id && !this.currentApi.isCopy) {
this.reqUrl = "/api/definition/update";
} else {
this.reqUrl = "/api/definition/create";
}
if (!this.request.hashTree) {
this.request.hashTree = [];
}
if (this.request.body && !this.request.body.binary) {
this.request.body.binary = [];
}
//
if (this.response.body) {
let body = new Body();
Object.assign(body, this.response.body);
if (!body.binary) {
body.binary = [];
}
if (!body.kvs) {
body.kvs = [];
}
if (!body.binary) {
body.binary = [];
}
this.response.body = body;
}
this.request.clazzName = TYPE_TO_C.get(this.request.type);
this.sort(this.request.hashTree);
},
saveApi(data) {
this.setParameters(data);
let bodyFiles = this.getBodyUploadFiles(data);
data.requestId = data.request.id;
if (data.request) {
this.sort(data.request.hashTree);
}
this.$fileUpload(this.reqUrl, null, bodyFiles, data, () => {
this.$success(this.$t('commons.save_success'));
this.reqUrl = "/api/definition/update";
this.currentApi.isCopy = false;
this.$emit('saveApi', data);
});
this.$store.state.apiMap.delete(this.currentApi.id);
},
handleSave() {
if (this.$refs.httpApi) {
this.$refs.httpApi.saveApi();
} else if (this.$refs.tcpApi) {
this.$refs.tcpApi.saveApi();
} else if (this.$refs.dubboApi) {
this.$refs.dubboApi.saveApi();
} else if (this.$refs.sqlApi) {
this.$refs.sqlApi.saveApi();
}
},
setParameters(data) {
data.projectId = this.projectId;
this.request.name = this.currentApi.name;
data.protocol = this.currentProtocol;
data.request = this.request;
data.request.name = data.name;
if (this.currentProtocol === "DUBBO" || this.currentProtocol === "dubbo://") {
data.request.protocol = "dubbo://";
} else {
data.request.protocol = this.currentProtocol;
}
if (data.isCopy) {
data.id = getUUID();
} else {
if (data.id) {
data.request.id = data.id;
} else {
data.id = data.request.id;
}
}
if (!data.method) {
data.method = this.currentProtocol;
}
data.response = this.response;
},
getBodyUploadFiles(data) {
let bodyUploadFiles = [];
data.bodyUploadIds = [];
let request = data.request;
if (request.body) {
if (request.body.kvs) {
request.body.kvs.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
item.name = item.file.name;
bodyUploadFiles.push(item.file);
}
});
}
});
}
if (request.body.binary) {
request.body.binary.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
let fileId = getUUID().substring(0, 8);
item.name = item.file.name;
item.id = fileId;
data.bodyUploadIds.push(fileId);
bodyUploadFiles.push(item.file);
}
});
}
});
}
}
return bodyUploadFiles;
},
} }
}
</script> </script>
<style scoped> <style scoped>

View File

@ -249,6 +249,7 @@ export default {
} }
} }
Object.assign(this.currentApi, data); Object.assign(this.currentApi, data);
this.currentApi.isCopy = false;
this.mockSetting(); this.mockSetting();
this.reload(); this.reload();
}, },

View File

@ -84,7 +84,6 @@
</el-row> </el-row>
</el-form> </el-form>
</div> </div>
</template> </template>
<el-table border class="adjust-table" :data="tableData" ref="operLog" <el-table border class="adjust-table" :data="tableData" ref="operLog"
:height="screenHeight"> :height="screenHeight">
@ -149,7 +148,7 @@ export default {
condition: {}, condition: {},
tableData: [], tableData: [],
userList: [], userList: [],
screenHeight: 'calc(100vh - 215px)', screenHeight: 'calc(100vh - 270px)',
LOG_TYPE: new LOG_TYPE(this), LOG_TYPE: new LOG_TYPE(this),
LOG_TYPE_MAP: new LOG_TYPE_MAP(this), LOG_TYPE_MAP: new LOG_TYPE_MAP(this),
sysList: sysList, sysList: sysList,