refactor(系统设置): 自定义函数

This commit is contained in:
shiziyuan9527 2021-09-15 14:20:01 +08:00 committed by 刘瑞斌
parent 09b0693187
commit fbd163cdd4
10 changed files with 203 additions and 67 deletions

View File

@ -0,0 +1,12 @@
package io.metersphere.base.mapper.ext;
import io.metersphere.base.domain.CustomFunction;
import io.metersphere.controller.request.CustomFunctionRequest;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface ExtCustomFunctionMapper {
List<CustomFunction> queryAll(@Param("request")CustomFunctionRequest request);
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="io.metersphere.base.mapper.ext.ExtCustomFunctionMapper">
<select id="queryAll" resultType="io.metersphere.base.domain.CustomFunction">
select id, name, tags, type, description, create_time, update_time, project_id from custom_function
<where>
<if test="request.name != null and request.name!=''">
and (custom_function.name like CONCAT('%', #{request.name},'%')
or custom_function.tags like CONCAT('%', #{request.name},'%'))
</if>
<if test="request.projectId != null">
and custom_function.project_id = #{request.projectId}
</if>
<if test="request.type != null">
and custom_function.type = #{request.type}
</if>
</where>
</select>
</mapper>

View File

@ -8,6 +8,7 @@ import io.metersphere.base.domain.CustomFunction;
import io.metersphere.base.domain.CustomFunctionExample; import io.metersphere.base.domain.CustomFunctionExample;
import io.metersphere.base.domain.CustomFunctionWithBLOBs; import io.metersphere.base.domain.CustomFunctionWithBLOBs;
import io.metersphere.base.mapper.CustomFunctionMapper; import io.metersphere.base.mapper.CustomFunctionMapper;
import io.metersphere.base.mapper.ext.ExtCustomFunctionMapper;
import io.metersphere.commons.constants.ApiRunMode; import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.BeanUtils; import io.metersphere.commons.utils.BeanUtils;
@ -34,6 +35,8 @@ public class CustomFunctionService {
@Resource @Resource
private CustomFunctionMapper customFunctionMapper; private CustomFunctionMapper customFunctionMapper;
@Resource @Resource
private ExtCustomFunctionMapper extCustomFunctionMapper;
@Resource
private JMeterService jMeterService; private JMeterService jMeterService;
public CustomFunctionWithBLOBs save(CustomFunctionRequest request) { public CustomFunctionWithBLOBs save(CustomFunctionRequest request) {
@ -76,17 +79,9 @@ public class CustomFunctionService {
String projectId = request.getProjectId(); String projectId = request.getProjectId();
if (StringUtils.isBlank(projectId)) { if (StringUtils.isBlank(projectId)) {
projectId = SessionUtils.getCurrentProjectId(); projectId = SessionUtils.getCurrentProjectId();
request.setProjectId(projectId);
} }
CustomFunctionExample example = new CustomFunctionExample(); return extCustomFunctionMapper.queryAll(request);
CustomFunctionExample.Criteria criteria = example.createCriteria();
criteria.andProjectIdEqualTo(projectId);
if (StringUtils.isNotBlank(request.getType())) {
criteria.andTypeEqualTo(request.getType());
}
if (StringUtils.isNotBlank(request.getName())) {
criteria.andNameEqualTo(request.getName());
}
return customFunctionMapper.selectByExample(example);
} }
public void update(CustomFunctionRequest request) { public void update(CustomFunctionRequest request) {

View File

@ -23,6 +23,8 @@
</el-link> </el-link>
<custom-function-relate ref="customFunctionRelate" @addCustomFuncScript="addCustomFuncScript"/> <custom-function-relate ref="customFunctionRelate" @addCustomFuncScript="addCustomFuncScript"/>
<!--接口列表-->
<api-func-relevance @save="apiSave" @close="apiClose" ref="apiFuncRelevance"/>
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
@ -32,9 +34,11 @@
import MsCodeEdit from "../../../definition/components/MsCodeEdit"; import MsCodeEdit from "../../../definition/components/MsCodeEdit";
import MsDropdown from "../../../../common/components/MsDropdown"; import MsDropdown from "../../../../common/components/MsDropdown";
import CustomFunctionRelate from "@/business/components/settings/project/function/CustomFunctionRelate"; import CustomFunctionRelate from "@/business/components/settings/project/function/CustomFunctionRelate";
import {getCodeTemplate} from "@/business/components/settings/project/function/custom-function";
import ApiFuncRelevance from "@/business/components/settings/project/function/ApiFuncRelevance";
export default { export default {
name: "Jsr233ProcessorContent", name: "Jsr233ProcessorContent",
components: {MsDropdown, MsCodeEdit, CustomFunctionRelate}, components: {MsDropdown, MsCodeEdit, CustomFunctionRelate, ApiFuncRelevance},
data() { data() {
return { return {
jsr223ProcessorData: {}, jsr223ProcessorData: {},
@ -100,8 +104,17 @@
title: "插入自定义函数", title: "插入自定义函数",
command: "custom_function", command: "custom_function",
index: "custom_function" index: "custom_function"
},
{
title: "从API定义导入",
command: "api_definition",
index: "api_definition"
},
{
title: "新API测试[JSON]",
command: "new_api_request",
index: "new_api_request"
} }
], ],
isCodeEditAlive: true, isCodeEditAlive: true,
languages: [ languages: [
@ -168,8 +181,74 @@
doFuncLink(funcLink) { doFuncLink(funcLink) {
if (funcLink.command === 'custom_function') { if (funcLink.command === 'custom_function') {
this.$refs.customFunctionRelate.open(this.jsr223ProcessorData.scriptLanguage); this.$refs.customFunctionRelate.open(this.jsr223ProcessorData.scriptLanguage);
} else if (funcLink.command === 'api_definition') {
this.$refs.apiFuncRelevance.open();
} else if (funcLink.command === 'new_api_request') {
// requestObj
let headers = new Map();
headers.set('Content-type', 'application/json');
let code = getCodeTemplate(this.jsr223ProcessorData.scriptLanguage, {requestHeaders: headers});
let codeStr = this.jsr223ProcessorData.script + "\n\n" + code;
this.jsr223ProcessorData.script = this.jsr223ProcessorData.script ? codeStr : code;
this.reload();
} }
}, },
apiSave(data, env) {
// data; env:
let condition = env.config.httpConfig.conditions || [];
let requestUrl = "";
if (condition && condition.length > 0) {
//
let protocol = condition[0].protocol ? condition[0].protocol : "http";
requestUrl = protocol + "://" + condition[0].socket;
}
// todo
if (data.length > 5) {
this.$warning("最多可以选择5个接口");
return;
}
let code = "";
if (data.length > 0) {
data.forEach(dt => {
let param = this.parseRequestObj(dt, requestUrl);
code += '\n' + getCodeTemplate(this.jsr223ProcessorData.scriptLanguage, param);
})
}
if (code) {
let codeStr = this.jsr223ProcessorData.script + code;
this.jsr223ProcessorData.script = this.jsr223ProcessorData.script ? codeStr : code;
this.reload();
} else {
//todo
this.$warning("无对应语言模版");
}
this.$refs.apiFuncRelevance.close();
},
parseRequestObj(data, requestUrl) {
let requestHeaders = new Map();
let requestMethod = "";
let requestBody = "";
let request = JSON.parse(data.request);
//
requestUrl = requestUrl + request.path;
requestMethod = request.method;
let headers = request.headers;
if (headers && headers.length > 0) {
headers.forEach(header => {
if (header.name) {
requestHeaders.set(header.name, header.value);
}
})
}
let body = request.body;
if (body.json) {
requestBody = body.raw;
}
return {requestUrl, requestHeaders, requestMethod, requestBody}
},
apiClose() {
},
} }
} }
</script> </script>

View File

@ -22,11 +22,12 @@
</template> </template>
<script> <script>
import ApiEnvironmentConfig from "../../../test/components/ApiEnvironmentConfig";
import {parseEnvironment} from "../../../test/model/EnvironmentModel"; import {parseEnvironment} from "../../../test/model/EnvironmentModel";
export default { export default {
name: "MsEnvironmentSelect", name: "MsEnvironmentSelect",
components: {ApiEnvironmentConfig}, components: {
ApiEnvironmentConfig: () => import('@/business/components/api/test/components/ApiEnvironmentConfig')
},
data() { data() {
return { return {
environments: [], environments: [],

View File

@ -161,7 +161,7 @@ export default {
this.$get('/api/environment/get/' + environmentId, response => { this.$get('/api/environment/get/' + environmentId, response => {
let environment = response.data; let environment = response.data;
parseEnvironment(environment); parseEnvironment(environment);
this.$emit("save", apis, environment, "API"); this.$emit("save", apis, environment);
}); });
}); });
} else { } else {
@ -177,7 +177,7 @@ export default {
this.$get('/api/environment/get/' + environmentId, response => { this.$get('/api/environment/get/' + environmentId, response => {
let environment = response.data; let environment = response.data;
parseEnvironment(environment); parseEnvironment(environment);
this.$emit("save", apiCases, environment, "CASE"); this.$emit("save", apiCases, environment);
}); });
}); });
} }

View File

@ -3,7 +3,7 @@
<el-card class="table-card"> <el-card class="table-card">
<template v-slot:header> <template v-slot:header>
<ms-table-header :show-create="false" :condition.sync="condition" <ms-table-header :show-create="false" :condition.sync="condition"
:title="'自定义函数'" @search="init"> :title="'自定义函数'" @search="init" :tip="'根据 名称/标签 搜索'">
<template v-slot:button> <template v-slot:button>
<ms-table-button icon="el-icon-circle-plus-outline" :content="'创建函数'" @click="handleCreate"/> <ms-table-button icon="el-icon-circle-plus-outline" :content="'创建函数'" @click="handleCreate"/>
</template> </template>

View File

@ -8,7 +8,7 @@
style="width: 350px;float: left;" style="width: 350px;float: left;"
:closable="false" show-icon> :closable="false" show-icon>
</el-alert> </el-alert>
<ms-table-search-bar :condition.sync="condition" @change="init" class="search-bar" :tip="'根据名称搜索'"/> <ms-table-search-bar :condition.sync="condition" @change="init" class="search-bar" :tip="'根据 名称/标签 搜索'"/>
<el-table border class="adjust-table" :data="data" style="width: 100%" ref="table" <el-table border class="adjust-table" :data="data" style="width: 100%" ref="table"
highlight-current-row @current-change="handleCurrentChange"> highlight-current-row @current-change="handleCurrentChange">
<el-table-column prop="name" :label="$t('commons.name')" show-overflow-tooltip/> <el-table-column prop="name" :label="$t('commons.name')" show-overflow-tooltip/>

View File

@ -231,10 +231,9 @@ export default {
}, },
{ {
title: "新API测试[JSON]", title: "新API测试[JSON]",
command: "new_api", command: "new_api_request",
index: "new_api" index: "new_api_request"
} }
], ],
response: {}, response: {},
request: {}, request: {},
@ -300,6 +299,14 @@ export default {
this.$refs.customFunctionRelate.open(this.form.type); this.$refs.customFunctionRelate.open(this.form.type);
} else if (funcLink.command === 'api_definition') { } else if (funcLink.command === 'api_definition') {
this.$refs.apiFuncRelevance.open(); this.$refs.apiFuncRelevance.open();
} else if (funcLink.command === 'new_api_request') {
// requestObj
let headers = new Map();
headers.set('Content-type', 'application/json');
let code = getCodeTemplate(this.form.type, {requestHeaders: headers});
let codeStr = this.form.script + "\n\n" + code;
this.form.script = this.form.script ? codeStr : code;
this.reloadCodeEdit();
} }
}, },
reload() { reload() {
@ -377,21 +384,43 @@ export default {
this.form.script = this.form.script + '\n\n' + script; this.form.script = this.form.script + '\n\n' + script;
this.reloadCodeEdit(); this.reloadCodeEdit();
}, },
apiSave(data, env, type) { apiSave(data, env) {
// dataenv: // data; env:
let condition = env.config.httpConfig.conditions || []; let condition = env.config.httpConfig.conditions || [];
let requestUrl = ""; let requestUrl = "";
let requestHeaders = new Map;
let requestMethod = "";
let requestBody = "";
if (condition && condition.length > 0) { if (condition && condition.length > 0) {
// //
let protocol = condition[0].protocol ? condition[0].protocol : "http"; let protocol = condition[0].protocol ? condition[0].protocol : "http";
requestUrl = protocol + "://" + condition[0].socket; requestUrl = protocol + "://" + condition[0].socket;
} }
// todo // todo
if (data.length > 5) {
this.$warning("最多可以选择5个接口");
return;
}
let code = "";
if (data.length > 0) { if (data.length > 0) {
let request = JSON.parse(data[0].request); data.forEach(dt => {
let param = this.parseRequestObj(dt, requestUrl);
code += '\n' + getCodeTemplate(this.form.type, param);
})
}
if (code) {
let codeStr = this.form.script + code;
this.form.script = this.form.script ? codeStr : code;
this.reloadCodeEdit();
} else {
//todo
this.$warning("无对应语言模版");
}
this.$refs.apiFuncRelevance.close();
},
parseRequestObj(data, requestUrl) {
let requestHeaders = new Map();
let requestMethod = "";
let requestBody = "";
let request = JSON.parse(data.request);
//
requestUrl = requestUrl + request.path; requestUrl = requestUrl + request.path;
requestMethod = request.method; requestMethod = request.method;
let headers = request.headers; let headers = request.headers;
@ -406,18 +435,7 @@ export default {
if (body.json) { if (body.json) {
requestBody = body.raw; requestBody = body.raw;
} }
} return {requestUrl, requestHeaders, requestMethod, requestBody}
let param = {requestUrl, requestHeaders, requestMethod, requestBody};
let code = getCodeTemplate(this.form.type, param);
if (code) {
let codeStr = this.form.script + "\n\n" + code;
this.form.script = this.form.script ? codeStr : code;
this.reloadCodeEdit();
} else {
//todo
this.$warning("无对应语言模版");
}
this.$refs.apiFuncRelevance.close();
}, },
apiClose() { apiClose() {

View File

@ -16,21 +16,31 @@ export function getCodeTemplate(language, requestObj) {
} }
function groovyCode(obj) { function groovyCode(obj) {
let {requestHeaders, requestBody, requestUrl, requestMethod} = obj; let {requestHeaders = new Map(), requestBody = "", requestUrl = "", requestMethod = ""} = obj;
let headers = "", body = JSON.stringify(requestBody); let headers = "", body = JSON.stringify(requestBody);
for (let [k, v] of requestHeaders) { for (let [k, v] of requestHeaders) {
// 拼装映射
headers += `['${k}':'${v}']`; headers += `['${k}':'${v}']`;
} }
return ` headers = headers === "" ? "[]" : headers;
import groovy.json.JsonOutput let params = "";
params += `[
'url': '${requestUrl}',
'method': '${requestMethod}',
'headers': ${headers}, // 请求headers 例:['Content-type':'application/json']
'data': ${body} // 参数
]`
return `import groovy.json.JsonOutput
import groovy.json.JsonSlurper import groovy.json.JsonSlurper
def http_post() { def http_post() {
def headers = ${headers} // 请求headers 例:['Content-type':'application/json'] def params = ${params}
def headers = params['headers']
// json数据 // json数据
def data = ${body} def data = params['data']
def conn = new URL("${requestUrl}").openConnection() def conn = new URL(params['url']).openConnection()
conn.setRequestMethod("${requestMethod}") conn.setRequestMethod(params['method'])
if (data) { if (data) {
headers.each { headers.each {
k,v -> conn.setRequestProperty(k, v); k,v -> conn.setRequestProperty(k, v);
@ -46,6 +56,5 @@ def http_post() {
log.info(conn.content.text) log.info(conn.content.text)
} }
http_post() http_post()
`; `;
} }