feat:【antd】【bpm】bpmn 设计器:服务任务中新增执行类型,来自:https://github.com/yudaocode/yudao-ui-admin-vue3/pull/200/
This commit is contained in:
@@ -0,0 +1,184 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, ref, watch } from 'vue';
|
||||||
|
|
||||||
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
|
||||||
|
import { Button, Input, Modal } from 'ant-design-vue';
|
||||||
|
|
||||||
|
defineOptions({ name: 'HttpHeaderEditor' });
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:modelValue', 'save']);
|
||||||
|
|
||||||
|
interface HeaderItem {
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dialogVisible = computed({
|
||||||
|
get: () => props.modelValue,
|
||||||
|
set: (val) => emit('update:modelValue', val),
|
||||||
|
});
|
||||||
|
|
||||||
|
const headerList = ref<HeaderItem[]>([]);
|
||||||
|
|
||||||
|
// 解析请求头字符串为列表
|
||||||
|
const parseHeaders = (headersStr: string): HeaderItem[] => {
|
||||||
|
if (!headersStr || !headersStr.trim()) {
|
||||||
|
return [{ key: '', value: '' }];
|
||||||
|
}
|
||||||
|
|
||||||
|
const lines = headersStr.split('\n').filter((line) => line.trim());
|
||||||
|
const parsed = lines.map((line) => {
|
||||||
|
const colonIndex = line.indexOf(':');
|
||||||
|
if (colonIndex > 0) {
|
||||||
|
return {
|
||||||
|
key: line.slice(0, Math.max(0, colonIndex)).trim(),
|
||||||
|
value: line.slice(Math.max(0, colonIndex + 1)).trim(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return { key: line.trim(), value: '' };
|
||||||
|
});
|
||||||
|
|
||||||
|
return parsed.length > 0 ? parsed : [{ key: '', value: '' }];
|
||||||
|
};
|
||||||
|
|
||||||
|
// 将列表转换为请求头字符串
|
||||||
|
const stringifyHeaders = (headers: HeaderItem[]): string => {
|
||||||
|
return headers
|
||||||
|
.filter((item) => item.key.trim())
|
||||||
|
.map((item) => `${item.key}: ${item.value}`)
|
||||||
|
.join('\n');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加请求头
|
||||||
|
const addHeader = () => {
|
||||||
|
headerList.value.push({ key: '', value: '' });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 移除请求头
|
||||||
|
const removeHeader = (index: number) => {
|
||||||
|
if (headerList.value.length === 1) {
|
||||||
|
// 至少保留一行
|
||||||
|
headerList.value = [{ key: '', value: '' }];
|
||||||
|
} else {
|
||||||
|
headerList.value.splice(index, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 保存
|
||||||
|
const handleSave = () => {
|
||||||
|
const headersStr = stringifyHeaders(headerList.value);
|
||||||
|
emit('save', headersStr);
|
||||||
|
dialogVisible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭
|
||||||
|
const handleClose = () => {
|
||||||
|
dialogVisible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听对话框打开,初始化数据
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
(val) => {
|
||||||
|
if (val) {
|
||||||
|
headerList.value = parseHeaders(props.headers);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Modal
|
||||||
|
v-model:open="dialogVisible"
|
||||||
|
title="编辑请求头"
|
||||||
|
width="600px"
|
||||||
|
:mask-closable="false"
|
||||||
|
@cancel="handleClose"
|
||||||
|
>
|
||||||
|
<div class="header-editor">
|
||||||
|
<div class="header-list">
|
||||||
|
<div
|
||||||
|
v-for="(item, index) in headerList"
|
||||||
|
:key="index"
|
||||||
|
class="header-item"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
v-model:value="item.key"
|
||||||
|
placeholder="请输入参数名"
|
||||||
|
class="header-key"
|
||||||
|
allow-clear
|
||||||
|
/>
|
||||||
|
<span class="separator">:</span>
|
||||||
|
<Input
|
||||||
|
v-model:value="item.value"
|
||||||
|
placeholder="请输入参数值 (支持表达式 ${变量名})"
|
||||||
|
class="header-value"
|
||||||
|
allow-clear
|
||||||
|
/>
|
||||||
|
<Button type="text" danger size="small" @click="removeHeader(index)">
|
||||||
|
<template #icon>
|
||||||
|
<IconifyIcon icon="ep:delete" />
|
||||||
|
</template>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Button type="primary" class="add-btn" @click="addHeader">
|
||||||
|
<template #icon>
|
||||||
|
<IconifyIcon icon="ep:plus" />
|
||||||
|
</template>
|
||||||
|
添加请求头
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<Button @click="handleClose">取消</Button>
|
||||||
|
<Button type="primary" @click="handleSave">保存</Button>
|
||||||
|
</template>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.header-editor {
|
||||||
|
.header-list {
|
||||||
|
max-height: 400px;
|
||||||
|
overflow-y: auto;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
.header-key {
|
||||||
|
flex: 0 0 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.separator {
|
||||||
|
color: #606266;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-value {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-btn {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,7 +1,21 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { nextTick, onBeforeUnmount, ref, toRaw, watch } from 'vue';
|
import { inject, nextTick, onBeforeUnmount, ref, toRaw, watch } from 'vue';
|
||||||
|
|
||||||
import { FormItem, Input, Select } from 'ant-design-vue';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
FormItem,
|
||||||
|
Input,
|
||||||
|
RadioButton,
|
||||||
|
RadioGroup,
|
||||||
|
Select,
|
||||||
|
Switch,
|
||||||
|
Textarea,
|
||||||
|
} from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { updateElementExtensions } from '../../../utils';
|
||||||
|
import HttpHeaderEditor from './HttpHeaderEditor.vue';
|
||||||
|
|
||||||
defineOptions({ name: 'ServiceTask' });
|
defineOptions({ name: 'ServiceTask' });
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -9,38 +23,281 @@ const props = defineProps({
|
|||||||
type: { type: String, default: '' },
|
type: { type: String, default: '' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultTaskForm = ref({
|
const prefix = (inject('prefix', 'flowable') || 'flowable') as string;
|
||||||
|
const flowableTypeKey = `${prefix}:type`;
|
||||||
|
const flowableFieldType = `${prefix}:Field`;
|
||||||
|
|
||||||
|
const HTTP_FIELD_NAMES = [
|
||||||
|
'requestMethod',
|
||||||
|
'requestUrl',
|
||||||
|
'requestHeaders',
|
||||||
|
'disallowRedirects',
|
||||||
|
'ignoreException',
|
||||||
|
'saveResponseParameters',
|
||||||
|
'resultVariablePrefix',
|
||||||
|
'saveResponseParametersTransient',
|
||||||
|
'saveResponseVariableAsJson',
|
||||||
|
];
|
||||||
|
const HTTP_BOOLEAN_FIELDS = new Set([
|
||||||
|
'disallowRedirects',
|
||||||
|
'ignoreException',
|
||||||
|
'saveResponseParameters',
|
||||||
|
'saveResponseParametersTransient',
|
||||||
|
'saveResponseVariableAsJson',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const DEFAULT_TASK_FORM = {
|
||||||
executeType: '',
|
executeType: '',
|
||||||
class: '',
|
class: '',
|
||||||
expression: '',
|
expression: '',
|
||||||
delegateExpression: '',
|
delegateExpression: '',
|
||||||
});
|
};
|
||||||
|
|
||||||
const serviceTaskForm = ref<any>({});
|
const DEFAULT_HTTP_FORM = {
|
||||||
|
requestMethod: 'GET',
|
||||||
|
requestUrl: '',
|
||||||
|
requestHeaders: 'Content-Type: application/json',
|
||||||
|
resultVariablePrefix: '',
|
||||||
|
disallowRedirects: false,
|
||||||
|
ignoreException: false,
|
||||||
|
saveResponseParameters: false,
|
||||||
|
saveResponseParametersTransient: false,
|
||||||
|
saveResponseVariableAsJson: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const serviceTaskForm = ref({ ...DEFAULT_TASK_FORM });
|
||||||
|
const httpTaskForm = ref<any>({ ...DEFAULT_HTTP_FORM });
|
||||||
const bpmnElement = ref();
|
const bpmnElement = ref();
|
||||||
|
const httpInitializing = ref(false);
|
||||||
|
const showHeaderEditor = ref(false);
|
||||||
|
|
||||||
const bpmnInstances = () => (window as any)?.bpmnInstances;
|
const bpmnInstances = () => (window as any)?.bpmnInstances;
|
||||||
|
|
||||||
const resetTaskForm = () => {
|
// 判断字符串是否包含表达式
|
||||||
for (const key in defaultTaskForm.value) {
|
const isExpression = (value: string): boolean => {
|
||||||
const value =
|
if (!value) return false;
|
||||||
// @ts-ignore
|
// 检测 ${...} 或 #{...} 格式的表达式
|
||||||
bpmnElement.value?.businessObject[key] || defaultTaskForm.value[key];
|
return /\$\{[^}]+\}/.test(value) || /#\{[^}]+\}/.test(value);
|
||||||
serviceTaskForm.value[key] = value;
|
};
|
||||||
if (value) {
|
|
||||||
serviceTaskForm.value.executeType = key;
|
const collectHttpExtensionInfo = () => {
|
||||||
|
const businessObject = bpmnElement.value?.businessObject;
|
||||||
|
const extensionElements = businessObject?.extensionElements;
|
||||||
|
const httpFields = new Map<string, string>();
|
||||||
|
const httpFieldTypes = new Map<string, 'expression' | 'string'>();
|
||||||
|
const otherExtensions: any[] = [];
|
||||||
|
|
||||||
|
extensionElements?.values?.forEach((item: any) => {
|
||||||
|
if (
|
||||||
|
item?.$type === flowableFieldType &&
|
||||||
|
HTTP_FIELD_NAMES.includes(item.name)
|
||||||
|
) {
|
||||||
|
const value = item.string ?? item.stringValue ?? item.expression ?? '';
|
||||||
|
const fieldType = item.expression ? 'expression' : 'string';
|
||||||
|
httpFields.set(item.name, value);
|
||||||
|
httpFieldTypes.set(item.name, fieldType);
|
||||||
|
} else {
|
||||||
|
otherExtensions.push(item);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return { httpFields, httpFieldTypes, otherExtensions };
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetHttpDefaults = () => {
|
||||||
|
httpInitializing.value = true;
|
||||||
|
httpTaskForm.value = { ...DEFAULT_HTTP_FORM };
|
||||||
|
nextTick(() => {
|
||||||
|
httpInitializing.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetHttpForm = () => {
|
||||||
|
httpInitializing.value = true;
|
||||||
|
const { httpFields } = collectHttpExtensionInfo();
|
||||||
|
const nextForm: any = { ...DEFAULT_HTTP_FORM };
|
||||||
|
|
||||||
|
HTTP_FIELD_NAMES.forEach((name) => {
|
||||||
|
const stored = httpFields.get(name);
|
||||||
|
if (stored !== undefined) {
|
||||||
|
nextForm[name] = HTTP_BOOLEAN_FIELDS.has(name)
|
||||||
|
? stored === 'true'
|
||||||
|
: stored;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
httpTaskForm.value = nextForm;
|
||||||
|
nextTick(() => {
|
||||||
|
httpInitializing.value = false;
|
||||||
|
updateHttpExtensions(true);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetServiceTaskForm = () => {
|
||||||
|
const businessObject = bpmnElement.value?.businessObject;
|
||||||
|
const nextForm = { ...DEFAULT_TASK_FORM };
|
||||||
|
|
||||||
|
if (businessObject) {
|
||||||
|
if (businessObject.class) {
|
||||||
|
nextForm.class = businessObject.class;
|
||||||
|
nextForm.executeType = 'class';
|
||||||
|
}
|
||||||
|
if (businessObject.expression) {
|
||||||
|
nextForm.expression = businessObject.expression;
|
||||||
|
nextForm.executeType = 'expression';
|
||||||
|
}
|
||||||
|
if (businessObject.delegateExpression) {
|
||||||
|
nextForm.delegateExpression = businessObject.delegateExpression;
|
||||||
|
nextForm.executeType = 'delegateExpression';
|
||||||
|
}
|
||||||
|
if (businessObject.$attrs?.[flowableTypeKey] === 'http') {
|
||||||
|
nextForm.executeType = 'http';
|
||||||
|
} else {
|
||||||
|
// 兜底:如缺少 flowable:type=http,但扩展里已有 HTTP 的字段,也认为是 HTTP
|
||||||
|
const { httpFields } = collectHttpExtensionInfo();
|
||||||
|
if (httpFields.size > 0) {
|
||||||
|
nextForm.executeType = 'http';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceTaskForm.value = nextForm;
|
||||||
|
|
||||||
|
if (nextForm.executeType === 'http') {
|
||||||
|
resetHttpForm();
|
||||||
|
} else {
|
||||||
|
resetHttpDefaults();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateElementTask = () => {
|
const shouldPersistField = (name: string, value: any) => {
|
||||||
const taskAttr = Object.create(null);
|
if (HTTP_BOOLEAN_FIELDS.has(name)) return true;
|
||||||
const type = serviceTaskForm.value.executeType;
|
if (name === 'requestMethod') return true;
|
||||||
for (const key in serviceTaskForm.value) {
|
if (name === 'requestUrl') return !!value;
|
||||||
if (key !== 'executeType' && key !== type) taskAttr[key] = null;
|
return value !== undefined && value !== '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateHttpExtensions = (force = false) => {
|
||||||
|
if (!bpmnElement.value) return;
|
||||||
|
if (
|
||||||
|
!force &&
|
||||||
|
(httpInitializing.value || serviceTaskForm.value.executeType !== 'http')
|
||||||
|
) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
taskAttr[type] = serviceTaskForm.value[type] || '';
|
|
||||||
|
const {
|
||||||
|
httpFields: existingFields,
|
||||||
|
httpFieldTypes: existingTypes,
|
||||||
|
otherExtensions,
|
||||||
|
} = collectHttpExtensionInfo();
|
||||||
|
|
||||||
|
const desiredEntries: [string, string][] = [];
|
||||||
|
HTTP_FIELD_NAMES.forEach((name) => {
|
||||||
|
const rawValue = httpTaskForm.value[name];
|
||||||
|
if (!shouldPersistField(name, rawValue)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const persisted = HTTP_BOOLEAN_FIELDS.has(name)
|
||||||
|
? String(!!rawValue)
|
||||||
|
: (rawValue === undefined
|
||||||
|
? ''
|
||||||
|
: String(rawValue));
|
||||||
|
|
||||||
|
desiredEntries.push([name, persisted]);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 检查是否有变化:不仅比较值,还要比较字段类型(string vs expression)
|
||||||
|
if (!force && desiredEntries.length === existingFields.size) {
|
||||||
|
let noChange = true;
|
||||||
|
for (const [name, value] of desiredEntries) {
|
||||||
|
const existingValue = existingFields.get(name);
|
||||||
|
const existingType = existingTypes.get(name);
|
||||||
|
const currentType = isExpression(value) ? 'expression' : 'string';
|
||||||
|
if (existingValue !== value || existingType !== currentType) {
|
||||||
|
noChange = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (noChange) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const moddle = bpmnInstances().moddle;
|
||||||
|
const httpFieldElements = desiredEntries.map(([name, value]) => {
|
||||||
|
// 根据值是否包含表达式来决定使用 string 还是 expression 属性
|
||||||
|
const isExpr = isExpression(value);
|
||||||
|
return moddle.create(flowableFieldType, {
|
||||||
|
name,
|
||||||
|
...(isExpr ? { expression: value } : { string: value }),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
updateElementExtensions(bpmnElement.value, [
|
||||||
|
...otherExtensions,
|
||||||
|
...httpFieldElements,
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeHttpExtensions = () => {
|
||||||
|
if (!bpmnElement.value) return;
|
||||||
|
const { httpFields, otherExtensions } = collectHttpExtensionInfo();
|
||||||
|
if (httpFields.size === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (otherExtensions.length === 0) {
|
||||||
|
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||||
|
extensionElements: null,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateElementExtensions(bpmnElement.value, otherExtensions);
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateElementTask = () => {
|
||||||
|
if (!bpmnElement.value) return;
|
||||||
|
|
||||||
|
const taskAttr: Record<string, any> = {
|
||||||
|
class: null,
|
||||||
|
expression: null,
|
||||||
|
delegateExpression: null,
|
||||||
|
[flowableTypeKey]: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const type = serviceTaskForm.value.executeType;
|
||||||
|
if (
|
||||||
|
type === 'class' ||
|
||||||
|
type === 'expression' ||
|
||||||
|
type === 'delegateExpression'
|
||||||
|
) {
|
||||||
|
taskAttr[type] = serviceTaskForm.value[type] || null;
|
||||||
|
} else if (type === 'http') {
|
||||||
|
taskAttr[flowableTypeKey] = 'http';
|
||||||
|
}
|
||||||
|
|
||||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), taskAttr);
|
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), taskAttr);
|
||||||
|
|
||||||
|
if (type === 'http') {
|
||||||
|
updateHttpExtensions(true);
|
||||||
|
} else {
|
||||||
|
removeHttpExtensions();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleExecuteTypeChange = (value: any) => {
|
||||||
|
serviceTaskForm.value.executeType = value;
|
||||||
|
if (value === 'http') {
|
||||||
|
resetHttpForm();
|
||||||
|
}
|
||||||
|
updateElementTask();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleHeadersSave = (headersStr: string) => {
|
||||||
|
httpTaskForm.value.requestHeaders = headersStr;
|
||||||
};
|
};
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
@@ -52,11 +309,19 @@ watch(
|
|||||||
() => {
|
() => {
|
||||||
bpmnElement.value = bpmnInstances().bpmnElement;
|
bpmnElement.value = bpmnInstances().bpmnElement;
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
resetTaskForm();
|
resetServiceTaskForm();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => httpTaskForm.value,
|
||||||
|
() => {
|
||||||
|
updateHttpExtensions();
|
||||||
|
},
|
||||||
|
{ deep: true },
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -68,7 +333,9 @@ watch(
|
|||||||
{ label: 'Java类', value: 'class' },
|
{ label: 'Java类', value: 'class' },
|
||||||
{ label: '表达式', value: 'expression' },
|
{ label: '表达式', value: 'expression' },
|
||||||
{ label: '代理表达式', value: 'delegateExpression' },
|
{ label: '代理表达式', value: 'delegateExpression' },
|
||||||
|
{ label: 'HTTP 调用', value: 'http' },
|
||||||
]"
|
]"
|
||||||
|
@change="handleExecuteTypeChange"
|
||||||
/>
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem
|
<FormItem
|
||||||
@@ -107,5 +374,62 @@ watch(
|
|||||||
@change="updateElementTask"
|
@change="updateElementTask"
|
||||||
/>
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
<template v-if="serviceTaskForm.executeType === 'http'">
|
||||||
|
<FormItem label="请求方法" key="http-method">
|
||||||
|
<RadioGroup v-model:value="httpTaskForm.requestMethod">
|
||||||
|
<RadioButton value="GET">GET</RadioButton>
|
||||||
|
<RadioButton value="POST">POST</RadioButton>
|
||||||
|
<RadioButton value="PUT">PUT</RadioButton>
|
||||||
|
<RadioButton value="DELETE">DELETE</RadioButton>
|
||||||
|
</RadioGroup>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="请求地址" key="http-url" name="requestUrl">
|
||||||
|
<Input v-model:value="httpTaskForm.requestUrl" allow-clear />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="请求头" key="http-headers">
|
||||||
|
<div class="flex w-full items-start gap-2">
|
||||||
|
<Textarea
|
||||||
|
v-model:value="httpTaskForm.requestHeaders"
|
||||||
|
:auto-size="{ minRows: 4, maxRows: 8 }"
|
||||||
|
readonly
|
||||||
|
placeholder="点击右侧编辑按钮添加请求头"
|
||||||
|
class="min-w-0 flex-1"
|
||||||
|
/>
|
||||||
|
<Button type="primary" @click="showHeaderEditor = true">
|
||||||
|
<template #icon>
|
||||||
|
<IconifyIcon icon="ep:edit" />
|
||||||
|
</template>
|
||||||
|
编辑
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="禁止重定向" key="http-disallow-redirects">
|
||||||
|
<Switch v-model:checked="httpTaskForm.disallowRedirects" />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="忽略异常" key="http-ignore-exception">
|
||||||
|
<Switch v-model:checked="httpTaskForm.ignoreException" />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="保存返回变量" key="http-save-response">
|
||||||
|
<Switch v-model:checked="httpTaskForm.saveResponseParameters" />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="是否瞬间变量" key="http-save-transient">
|
||||||
|
<Switch
|
||||||
|
v-model:checked="httpTaskForm.saveResponseParametersTransient"
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="返回变量前缀" key="http-result-variable-prefix">
|
||||||
|
<Input v-model:value="httpTaskForm.resultVariablePrefix" />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="格式化返回为JSON" key="http-save-json">
|
||||||
|
<Switch v-model:checked="httpTaskForm.saveResponseVariableAsJson" />
|
||||||
|
</FormItem>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 请求头编辑器 -->
|
||||||
|
<HttpHeaderEditor
|
||||||
|
v-model="showHeaderEditor"
|
||||||
|
:headers="httpTaskForm.requestHeaders"
|
||||||
|
@save="handleHeadersSave"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user