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.CustomFunctionWithBLOBs;
import io.metersphere.base.mapper.CustomFunctionMapper;
import io.metersphere.base.mapper.ext.ExtCustomFunctionMapper;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.BeanUtils;
@ -34,6 +35,8 @@ public class CustomFunctionService {
@Resource
private CustomFunctionMapper customFunctionMapper;
@Resource
private ExtCustomFunctionMapper extCustomFunctionMapper;
@Resource
private JMeterService jMeterService;
public CustomFunctionWithBLOBs save(CustomFunctionRequest request) {
@ -76,17 +79,9 @@ public class CustomFunctionService {
String projectId = request.getProjectId();
if (StringUtils.isBlank(projectId)) {
projectId = SessionUtils.getCurrentProjectId();
request.setProjectId(projectId);
}
CustomFunctionExample example = new CustomFunctionExample();
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);
return extCustomFunctionMapper.queryAll(request);
}
public void update(CustomFunctionRequest request) {

View File

@ -23,6 +23,8 @@
</el-link>
<custom-function-relate ref="customFunctionRelate" @addCustomFuncScript="addCustomFuncScript"/>
<!--接口列表-->
<api-func-relevance @save="apiSave" @close="apiClose" ref="apiFuncRelevance"/>
</el-col>
</el-row>
</div>
@ -32,9 +34,11 @@
import MsCodeEdit from "../../../definition/components/MsCodeEdit";
import MsDropdown from "../../../../common/components/MsDropdown";
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 {
name: "Jsr233ProcessorContent",
components: {MsDropdown, MsCodeEdit, CustomFunctionRelate},
components: {MsDropdown, MsCodeEdit, CustomFunctionRelate, ApiFuncRelevance},
data() {
return {
jsr223ProcessorData: {},
@ -100,8 +104,17 @@
title: "插入自定义函数",
command: "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,
languages: [
@ -168,8 +181,74 @@
doFuncLink(funcLink) {
if (funcLink.command === 'custom_function') {
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>

View File

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

View File

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

View File

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

View File

@ -8,7 +8,7 @@
style="width: 350px;float: left;"
:closable="false" show-icon>
</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"
highlight-current-row @current-change="handleCurrentChange">
<el-table-column prop="name" :label="$t('commons.name')" show-overflow-tooltip/>

View File

@ -231,10 +231,9 @@ export default {
},
{
title: "新API测试[JSON]",
command: "new_api",
index: "new_api"
command: "new_api_request",
index: "new_api_request"
}
],
response: {},
request: {},
@ -300,6 +299,14 @@ export default {
this.$refs.customFunctionRelate.open(this.form.type);
} 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.form.type, {requestHeaders: headers});
let codeStr = this.form.script + "\n\n" + code;
this.form.script = this.form.script ? codeStr : code;
this.reloadCodeEdit();
}
},
reload() {
@ -377,40 +384,29 @@ export default {
this.form.script = this.form.script + '\n\n' + script;
this.reloadCodeEdit();
},
apiSave(data, env, type) {
// dataenv:
apiSave(data, env) {
// data; env:
let condition = env.config.httpConfig.conditions || [];
let requestUrl = "";
let requestHeaders = new Map;
let requestMethod = "";
let requestBody = "";
if (condition && condition.length > 0) {
//
let protocol = condition[0].protocol ? condition[0].protocol : "http";
requestUrl = protocol + "://" + condition[0].socket;
}
// todo
if (data.length > 0) {
let request = JSON.parse(data[0].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;
}
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.form.type, param);
})
}
let param = {requestUrl, requestHeaders, requestMethod, requestBody};
let code = getCodeTemplate(this.form.type, param);
if (code) {
let codeStr = this.form.script + "\n\n" + code;
let codeStr = this.form.script + code;
this.form.script = this.form.script ? codeStr : code;
this.reloadCodeEdit();
} else {
@ -419,6 +415,28 @@ export default {
}
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() {
},

View File

@ -16,36 +16,45 @@ export function getCodeTemplate(language, requestObj) {
}
function groovyCode(obj) {
let {requestHeaders, requestBody, requestUrl, requestMethod} = obj;
let {requestHeaders = new Map(), requestBody = "", requestUrl = "", requestMethod = ""} = obj;
let headers = "", body = JSON.stringify(requestBody);
for (let [k, v] of requestHeaders) {
// 拼装映射
headers += `['${k}':'${v}']`;
}
return `
import groovy.json.JsonOutput
headers = headers === "" ? "[]" : headers;
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
def http_post() {
def headers = ${headers} // 请求headers 例:['Content-type':'application/json']
// json数据
def data = ${body}
def conn = new URL("${requestUrl}").openConnection()
conn.setRequestMethod("${requestMethod}")
if (data) {
headers.each {
k,v -> conn.setRequestProperty(k, v);
}
// 输出请求参数
log.info(data)
conn.doOutput = true
def writer = new OutputStreamWriter(conn.outputStream)
writer.write(data)
writer.flush()
writer.close()
}
log.info(conn.content.text)
def params = ${params}
def headers = params['headers']
// json数据
def data = params['data']
def conn = new URL(params['url']).openConnection()
conn.setRequestMethod(params['method'])
if (data) {
headers.each {
k,v -> conn.setRequestProperty(k, v);
}
// 输出请求参数
log.info(data)
conn.doOutput = true
def writer = new OutputStreamWriter(conn.outputStream)
writer.write(data)
writer.flush()
writer.close()
}
log.info(conn.content.text)
}
http_post()
`;
}