343 lines
12 KiB
Vue
343 lines
12 KiB
Vue
<template>
|
||
<div>
|
||
<el-form label-position="top" label-width="90px">
|
||
<el-form-item label="选择触发的动作" prop="text" class="user-type">
|
||
<el-radio-group v-model="config.type">
|
||
<el-radio label="WEBHOOK">发送网络请求</el-radio>
|
||
<el-radio label="EMAIL">发送邮件</el-radio>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
<div v-if="config.type === 'WEBHOOK'">
|
||
<el-form-item label="请求地址" prop="text">
|
||
<el-input placeholder="请输入URL地址" v-model="config.http.url">
|
||
<el-select v-model="config.http.method" style="width: 85px;" slot="prepend" placeholder="URL" filterable>
|
||
<el-option label="GET" value="GET"></el-option>
|
||
<el-option label="POST" value="POST"></el-option>
|
||
<el-option label="PUT" value="PUT"></el-option>
|
||
<el-option label="DELETE" value="DELETE"></el-option>
|
||
</el-select>
|
||
</el-input>
|
||
</el-form-item>
|
||
<el-form-item label="Header请求头" prop="text">
|
||
<div slot="label">
|
||
<span style="margin-right: 10px">Header请求头</span>
|
||
<el-button type="primary" @click="addItem(config.http.headers)" link> + 添加</el-button>
|
||
</div>
|
||
<div v-for="(header, index) in config.http.headers" :key="index">
|
||
-
|
||
<el-input placeholder="参数名" style="width: 100px;" v-model="header.name"/>
|
||
<el-radio-group v-model="header.isField">
|
||
<el-radio-button :label="true">表单</el-radio-button>
|
||
<el-radio-button :label="false">固定</el-radio-button>
|
||
</el-radio-group>
|
||
<el-select v-if="header.isField" style="width: 180px;" v-model="header.value"
|
||
placeholder="请选择表单字段" filterable>
|
||
<el-option v-for="form in forms" :key="form.id" :label="form.title" :value="form.title"></el-option>
|
||
</el-select>
|
||
<el-input v-else placeholder="请设置字段值" v-model="header.value" style="width: 180px;"/>
|
||
<el-icon class="el-icon-delete" @click="delItem(config.http.headers, index)"
|
||
style="margin-left: 5px; color: #c75450; cursor: pointer"/>
|
||
</div>
|
||
</el-form-item>
|
||
<el-form-item label="Header请求参数" prop="text">
|
||
<div slot="label">
|
||
<span style="margin-right: 10px">请求参数 </span>
|
||
<el-button style="margin-right: 20px" type="primary" @click="addItem(config.http.params)" link> + 添加</el-button>
|
||
<span>参数类型 - </span>
|
||
<el-radio-group style="margin: 0 5px;" v-model="config.http.contentType">
|
||
<el-radio-button label="JSON">json</el-radio-button>
|
||
<el-radio-button label="FORM">form</el-radio-button>
|
||
</el-radio-group>
|
||
</div>
|
||
<div v-for="(param, index) in config.http.params" :key="index">
|
||
-
|
||
<el-input placeholder="参数名" style="width: 100px;" v-model="param.name"/>
|
||
<el-radio-group style="margin: 0 5px;" v-model="param.isField">
|
||
<el-radio-button :label="true">表单</el-radio-button>
|
||
<el-radio-button :label="false">固定</el-radio-button>
|
||
</el-radio-group>
|
||
<el-select v-if="param.isField" style="width: 180px;" v-model="param.value"
|
||
placeholder="请选择表单字段" filterable>
|
||
<el-option v-for="form in forms" :key="form.id" :label="form.title" :value="form.id"></el-option>
|
||
</el-select>
|
||
<el-input v-else placeholder="请设置字段值" v-model="param.value" style="width: 180px;"/>
|
||
<el-icon class="el-icon-delete" @click="delItem(config.http.params, index)"
|
||
style="margin-left: 5px; color: #c75450; cursor: pointer"/>
|
||
</div>
|
||
<div>
|
||
|
||
</div>
|
||
</el-form-item>
|
||
<!-- <el-form-item label="请求结果处理" prop="text">-->
|
||
<div slot="label">
|
||
<span>请求结果处理</span>
|
||
<span style="margin-left: 20px">自定义脚本: </span>
|
||
<el-switch v-model="config.http.handlerByScript"></el-switch>
|
||
</div>
|
||
<span class="item-desc" v-if="config.http.handlerByScript">
|
||
<p>👉 返回值为 ture 则流程通过,为 false 则流程将被驳回</p>
|
||
<p>👉 (上线注意)占不支持ES高级语法</p>
|
||
<p>👉 (上线注意)不支持浏览器的内置函数</p>
|
||
<!-- <div>支持函数-->
|
||
<!-- <span style="color: dodgerblue">setFormByName(-->
|
||
<!-- <span style="color: #939494">'表单字段名', '表单字段值'</span>-->
|
||
<!-- )</span>-->
|
||
<!-- 可改表单数据-->
|
||
<!-- </div>-->
|
||
</span>
|
||
<span class="item-desc" v-else>👉 无论请求结果如何,均通过</span>
|
||
<div v-if="config.http.handlerByScript">
|
||
<div>
|
||
<el-button @click="requestTestHandler">测试</el-button>
|
||
</div>
|
||
<div>
|
||
<span>请求成功😀:</span>
|
||
<js-code-edit v-model="config.http.success" :editor-placeholder="'请输入js代码'"
|
||
:editor-height="250" :tab-size="2"/>
|
||
</div>
|
||
<div>
|
||
<span>请求失败😥:</span>
|
||
<js-code-edit v-model="config.http.fail" :editor-placeholder="'请输入js代码'"
|
||
:editor-height="250" :tab-size="2"/>
|
||
</div>
|
||
</div>
|
||
<!-- </el-form-item>-->
|
||
</div>
|
||
<div v-else-if="config.type === 'EMAIL'">
|
||
<el-form-item label="邮件主题" prop="text">
|
||
<el-input placeholder="请输入邮件主题" v-model="config.email.subject"/>
|
||
</el-form-item>
|
||
<el-form-item label="收件方" prop="text">
|
||
<el-select style="width: 100%;" v-model="config.email.to" filterable multiple allow-create
|
||
default-first-option placeholder="请输入收件人">
|
||
<el-option v-for="sender in config.email.to" :key="sender" :label="sender" :value="sender"></el-option>
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="抄送方" prop="text">
|
||
<el-select style="width: 100%;" v-model="config.email.cc" filterable multiple allow-create
|
||
default-first-option placeholder="请输入收件人">
|
||
<el-option v-for="item in config.email.cc" :key="item" :label="item" :value="item"></el-option>
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="邮件正文" prop="text">
|
||
<el-input type="textarea" v-model="config.email.content" :rows="4"
|
||
placeholder="邮件内容,支持变量提取表单数据 ${表单字段名} "></el-input>
|
||
</el-form-item>
|
||
</div>
|
||
</el-form>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import {computed, defineProps} from 'vue'
|
||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||
import axios from "axios";
|
||
import {useProcessStore} from '@/stores/processStore.js'
|
||
import JsCodeEdit from "@/components/codeEdit/JsCodeEdit.vue";
|
||
|
||
const processStore = useProcessStore()
|
||
const props = defineProps({
|
||
config: {
|
||
type: Object,
|
||
default: () => {
|
||
return {}
|
||
}
|
||
}
|
||
})
|
||
const forms = computed(() => {
|
||
return processStore.getDesign().formItems || []
|
||
})
|
||
|
||
const addItem = (items) => {
|
||
if (items.length > 0 && (items[items.length - 1].name.trim() === ''
|
||
|| items[items.length - 1].value.trim() === '')) {
|
||
ElMessage.warning("请完善之前项后在添加")
|
||
return;
|
||
}
|
||
items.push({name: '', value: '', isField: true})
|
||
}
|
||
|
||
|
||
const delItem = (items, index) => {
|
||
items.splice(index, 1)
|
||
}
|
||
//url规范性检查
|
||
const restfulCheck = (url) => {
|
||
const httpProtocolPattern = /^http:/;
|
||
const httpsProtocolPattern = /^https:/;
|
||
const restfulUrlPattern = /\/\w+\/\w+(\/\{[^}]+\})*/;
|
||
if (httpProtocolPattern.test(url) || httpsProtocolPattern.test(url)) {
|
||
return restfulUrlPattern.test(url);
|
||
} else {
|
||
return false;
|
||
}
|
||
}
|
||
//是否含有动态参数
|
||
const hasUrlParams = (url) => {
|
||
const pattern = /{[^{}]+}/g;
|
||
let match;
|
||
while ((match = pattern.exec(url)) !== null) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
//获取到动态参数的名称
|
||
const getDynamicParamNames = (url) => {
|
||
const pattern = /{([^{}]+)}/g;
|
||
let match;
|
||
const paramNames = [];
|
||
while ((match = pattern.exec(url)) !== null) {
|
||
if (match[0].startsWith('{') && match[0].endsWith('}')) {
|
||
const paramName = match[1];
|
||
paramNames.push(paramName);
|
||
}
|
||
}
|
||
return paramNames;
|
||
}
|
||
//替换rul动态参数
|
||
const replaceDynamicParams = (url, params) => {
|
||
const dynamicParamPattern = /{\s*(\w+)\s*}/g;
|
||
return url.replace(dynamicParamPattern, (match, param) => {
|
||
return params[param] || '0';
|
||
});
|
||
}
|
||
//获取到参数值
|
||
const getParamsValue = (params, paramName) => {
|
||
for (let param of params) {
|
||
if (param.name === paramName) {
|
||
return param.value
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
//设置头部
|
||
const setHeaders = (http) => {
|
||
let headers = {}
|
||
for (let header of http.headers) {
|
||
if (header.isField) {
|
||
ElMessage.error("测试只支持固定参数")
|
||
return
|
||
}
|
||
if (header.name !== "" && header.value !== "") {
|
||
this.$set(headers, header.name, header.value);
|
||
}
|
||
}
|
||
if (http.contentType === "FORM") {
|
||
this.$set(headers, "Content-Type", "multipart/form-data")
|
||
} else {
|
||
this.$set(headers, "Content-Type", "application/json")
|
||
}
|
||
return headers;
|
||
}
|
||
//设置post和put参数
|
||
const setPostAndPutParams = (http) => {
|
||
let params = {}
|
||
for (let param of http.params) {
|
||
params[param.name] = param.value
|
||
}
|
||
return params;
|
||
}
|
||
//设置get和delete的参数
|
||
const setGetAndDeleteParams = (http) => {
|
||
let dynamicParams = []
|
||
let url = http.url
|
||
let hasParams = hasUrlParams(url)
|
||
if (hasParams) {
|
||
dynamicParams = getDynamicParamNames(url);
|
||
let replaceParams = {}
|
||
for (let paramsName of dynamicParams) {
|
||
let value = getParamsValue(http.params, paramsName)
|
||
if (null == value) {
|
||
ElMessage.error(paramsName + '参数未设置')
|
||
return;
|
||
}
|
||
replaceParams[paramsName] = value
|
||
}
|
||
url = replaceDynamicParams(url, replaceParams);
|
||
}
|
||
if (http.method === "DELETE") {
|
||
return url;
|
||
}
|
||
let getParams = []
|
||
for (let param of http.params) {
|
||
if (dynamicParams.indexOf(param.name) === -1 && param.name !== '' && param.value !== '') {
|
||
getParams.push(param.name + "=" + param.value)
|
||
}
|
||
}
|
||
if (getParams.length > 0) {
|
||
url += "?"
|
||
for (let i = 0; i < getParams.length; i++) {
|
||
if (i !== getParams.length - 1) {
|
||
url += getParams[i] + "&";
|
||
} else {
|
||
url += getParams[i];
|
||
}
|
||
}
|
||
}
|
||
return url;
|
||
}
|
||
//请求测试
|
||
|
||
const requestTestHandler = () => {
|
||
let http = props.config.http;
|
||
if (http.url == null || http.url === '') {
|
||
ElMessage.error("请填写请求路径!")
|
||
return
|
||
}
|
||
if (!restfulCheck(http.url)) {
|
||
ElMessage.error("当前只支持 RESTful URL!")
|
||
return
|
||
}
|
||
let headers = setHeaders(http)
|
||
let request
|
||
switch (http.method) {
|
||
case "GET":
|
||
case "DELETE":
|
||
let url = setGetAndDeleteParams(http)
|
||
if (null == url) {
|
||
return;
|
||
}
|
||
request = axios.request({
|
||
method: http.method,
|
||
url: url,
|
||
headers: headers,
|
||
});
|
||
break;
|
||
case "POST":
|
||
case "PUT":
|
||
request = axios.request({
|
||
method: http.method,
|
||
url: http.url,
|
||
headers: headers,
|
||
data: setPostAndPutParams(http)
|
||
});
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
// console.log("==================[测试打印内容]==================")
|
||
request.then(res => {
|
||
console.log(res)
|
||
if (res.status === 200) {
|
||
let data = res.data
|
||
console.log(data)
|
||
let successFun = eval("(false ||" + http.success + ")");
|
||
let result = successFun(data);
|
||
console.log(result, "成功函数执行的返回结果")
|
||
} else {
|
||
let failFun = eval("(false ||" + http.fail + ")");
|
||
let result = failFun(res);
|
||
console.log(result, "失败函数执行的返回结果")
|
||
}
|
||
}).finally(() => {
|
||
console.log("==================[测试打印结束]==================")
|
||
})
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.item-desc {
|
||
color: #939494;
|
||
}
|
||
</style>
|