!296 feat: [bpm][antd] bpmn设计器脚本任务优化
Merge pull request !296 from Jason/dev
This commit is contained in:
@@ -500,7 +500,7 @@ onMounted(async () => {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Divider orientation="left">审批人为空时</Divider>
|
<Divider orientation="left">审批人为空时</Divider>
|
||||||
<Form.Item prop="assignEmptyHandlerType">
|
<Form.Item name="assignEmptyHandlerType">
|
||||||
<RadioGroup
|
<RadioGroup
|
||||||
v-model:value="assignEmptyHandlerType"
|
v-model:value="assignEmptyHandlerType"
|
||||||
@change="updateAssignEmptyHandlerType"
|
@change="updateAssignEmptyHandlerType"
|
||||||
@@ -517,7 +517,7 @@ onMounted(async () => {
|
|||||||
<Form.Item
|
<Form.Item
|
||||||
v-if="assignEmptyHandlerType === AssignEmptyHandlerType.ASSIGN_USER"
|
v-if="assignEmptyHandlerType === AssignEmptyHandlerType.ASSIGN_USER"
|
||||||
label="指定用户"
|
label="指定用户"
|
||||||
prop="assignEmptyHandlerUserIds"
|
name="assignEmptyHandlerUserIds"
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
v-model:value="assignEmptyUserIds"
|
v-model:value="assignEmptyUserIds"
|
||||||
@@ -677,7 +677,7 @@ onMounted(async () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Divider orientation="left">是否需要签名</Divider>
|
<Divider orientation="left">是否需要签名</Divider>
|
||||||
<Form.Item prop="signEnable">
|
<Form.Item name="signEnable">
|
||||||
<Switch
|
<Switch
|
||||||
v-model:checked="signEnable.value"
|
v-model:checked="signEnable.value"
|
||||||
checked-children="是"
|
checked-children="是"
|
||||||
@@ -687,7 +687,7 @@ onMounted(async () => {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Divider orientation="left">审批意见</Divider>
|
<Divider orientation="left">审批意见</Divider>
|
||||||
<Form.Item prop="reasonRequire">
|
<Form.Item name="reasonRequire">
|
||||||
<Switch
|
<Switch
|
||||||
v-model:checked="reasonRequire.value"
|
v-model:checked="reasonRequire.value"
|
||||||
checked-children="必填"
|
checked-children="必填"
|
||||||
@@ -697,162 +697,3 @@ onMounted(async () => {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.button-setting-pane {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
margin-top: 8px;
|
|
||||||
font-size: 14px;
|
|
||||||
|
|
||||||
.button-setting-desc {
|
|
||||||
padding-right: 8px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-setting-title {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
height: 45px;
|
|
||||||
padding-left: 12px;
|
|
||||||
background-color: #f8fafc0a;
|
|
||||||
border: 1px solid #1f38581a;
|
|
||||||
|
|
||||||
& > :first-child {
|
|
||||||
width: 100px !important;
|
|
||||||
text-align: left !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > :last-child {
|
|
||||||
text-align: center !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-title-label {
|
|
||||||
width: 150px;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 700;
|
|
||||||
color: #000;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-setting-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
height: 38px;
|
|
||||||
padding-left: 12px;
|
|
||||||
border: 1px solid #1f38581a;
|
|
||||||
border-top: 0;
|
|
||||||
|
|
||||||
& > :first-child {
|
|
||||||
width: 100px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > :last-child {
|
|
||||||
text-align: center !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-setting-item-label {
|
|
||||||
width: 150px;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
text-align: left;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editable-title-input {
|
|
||||||
max-width: 130px;
|
|
||||||
height: 24px;
|
|
||||||
margin-left: 4px;
|
|
||||||
line-height: 24px;
|
|
||||||
border: 1px solid #d9d9d9;
|
|
||||||
border-radius: 4px;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
outline: 0;
|
|
||||||
border-color: #40a9ff;
|
|
||||||
box-shadow: 0 0 0 2px rgb(24 144 255 / 20%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.field-setting-pane {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
font-size: 14px;
|
|
||||||
|
|
||||||
.field-setting-desc {
|
|
||||||
padding-right: 8px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.field-permit-title {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
height: 45px;
|
|
||||||
padding-left: 12px;
|
|
||||||
line-height: 45px;
|
|
||||||
background-color: #f8fafc0a;
|
|
||||||
border: 1px solid #1f38581a;
|
|
||||||
|
|
||||||
.first-title {
|
|
||||||
text-align: left !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.other-titles {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.setting-title-label {
|
|
||||||
display: inline-block;
|
|
||||||
width: 100px;
|
|
||||||
padding: 5px 0;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 700;
|
|
||||||
color: #000;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.field-setting-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
height: 38px;
|
|
||||||
padding-left: 12px;
|
|
||||||
border: 1px solid #1f38581a;
|
|
||||||
border-top: 0;
|
|
||||||
|
|
||||||
.field-setting-item-label {
|
|
||||||
display: inline-block;
|
|
||||||
width: 100px;
|
|
||||||
min-height: 16px;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
cursor: text;
|
|
||||||
}
|
|
||||||
|
|
||||||
.field-setting-item-group {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.item-radio-wrap {
|
|
||||||
display: inline-block;
|
|
||||||
width: 100px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -526,7 +526,7 @@ watch(
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem
|
<FormItem
|
||||||
label="重试周期"
|
label="重试周期"
|
||||||
prop="timeCycle"
|
name="timeCycle"
|
||||||
v-if="loopInstanceForm.asyncAfter || loopInstanceForm.asyncBefore"
|
v-if="loopInstanceForm.asyncAfter || loopInstanceForm.asyncBefore"
|
||||||
key="timeCycle"
|
key="timeCycle"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,35 +1,20 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, ref, watch } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
|
||||||
import { Button, Input, Modal } from 'ant-design-vue';
|
import { Button, Input } from 'ant-design-vue';
|
||||||
|
|
||||||
defineOptions({ name: 'HttpHeaderEditor' });
|
defineOptions({ name: 'HttpHeaderEditor' });
|
||||||
|
|
||||||
const props = defineProps({
|
const emit = defineEmits(['save']);
|
||||||
modelValue: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
headers: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue', 'save']);
|
|
||||||
|
|
||||||
interface HeaderItem {
|
interface HeaderItem {
|
||||||
key: string;
|
key: string;
|
||||||
value: string;
|
value: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dialogVisible = computed({
|
|
||||||
get: () => props.modelValue,
|
|
||||||
set: (val) => emit('update:modelValue', val),
|
|
||||||
});
|
|
||||||
|
|
||||||
const headerList = ref<HeaderItem[]>([]);
|
const headerList = ref<HeaderItem[]>([]);
|
||||||
|
|
||||||
// 解析请求头字符串为列表
|
// 解析请求头字符串为列表
|
||||||
@@ -80,52 +65,42 @@ const removeHeader = (index: number) => {
|
|||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
const headersStr = stringifyHeaders(headerList.value);
|
const headersStr = stringifyHeaders(headerList.value);
|
||||||
emit('save', headersStr);
|
emit('save', headersStr);
|
||||||
dialogVisible.value = false;
|
modalApi.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 关闭
|
const [Modal, modalApi] = useVbenModal({
|
||||||
const handleClose = () => {
|
destroyOnClose: true,
|
||||||
dialogVisible.value = false;
|
onOpenChange(isOpen) {
|
||||||
};
|
if (!isOpen) {
|
||||||
|
return;
|
||||||
// 监听对话框打开,初始化数据
|
|
||||||
watch(
|
|
||||||
() => props.modelValue,
|
|
||||||
(val) => {
|
|
||||||
if (val) {
|
|
||||||
headerList.value = parseHeaders(props.headers);
|
|
||||||
}
|
}
|
||||||
|
const { headers } = modalApi.getData();
|
||||||
|
headerList.value = parseHeaders(headers);
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
onConfirm: handleSave,
|
||||||
);
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Modal
|
<Modal title="编辑请求头" class="w-3/5">
|
||||||
v-model:open="dialogVisible"
|
<div class="space-y-4">
|
||||||
title="编辑请求头"
|
<div class="mb-2 space-y-3 overflow-y-auto">
|
||||||
width="600px"
|
|
||||||
:mask-closable="false"
|
|
||||||
@cancel="handleClose"
|
|
||||||
>
|
|
||||||
<div class="header-editor">
|
|
||||||
<div class="header-list">
|
|
||||||
<div
|
<div
|
||||||
v-for="(item, index) in headerList"
|
v-for="(item, index) in headerList"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="header-item"
|
class="flex items-center gap-2"
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
v-model:value="item.key"
|
v-model:value="item.key"
|
||||||
placeholder="请输入参数名"
|
placeholder="请输入参数名"
|
||||||
class="header-key"
|
class="w-48"
|
||||||
allow-clear
|
allow-clear
|
||||||
/>
|
/>
|
||||||
<span class="separator">:</span>
|
<span class="font-medium text-gray-600">:</span>
|
||||||
<Input
|
<Input
|
||||||
v-model:value="item.value"
|
v-model:value="item.value"
|
||||||
placeholder="请输入参数值 (支持表达式 ${变量名})"
|
placeholder="请输入参数值 (支持表达式 ${变量名})"
|
||||||
class="header-value"
|
class="flex-1"
|
||||||
allow-clear
|
allow-clear
|
||||||
/>
|
/>
|
||||||
<Button type="text" danger size="small" @click="removeHeader(index)">
|
<Button type="text" danger size="small" @click="removeHeader(index)">
|
||||||
@@ -135,50 +110,12 @@ watch(
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Button type="primary" class="add-btn" @click="addHeader">
|
<Button type="primary" class="w-full" @click="addHeader">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<IconifyIcon icon="ep:plus" />
|
<IconifyIcon icon="ep:plus" />
|
||||||
</template>
|
</template>
|
||||||
添加请求头
|
添加请求头
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
|
||||||
<Button @click="handleClose">取消</Button>
|
|
||||||
<Button type="primary" @click="handleSave">保存</Button>
|
|
||||||
</template>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.header-editor {
|
|
||||||
.header-list {
|
|
||||||
max-height: 400px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-item {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
|
|
||||||
.header-key {
|
|
||||||
flex: 0 0 180px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.separator {
|
|
||||||
font-weight: 500;
|
|
||||||
color: #606266;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-value {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.add-btn {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import { nextTick, onBeforeUnmount, ref, toRaw, watch } from 'vue';
|
import { nextTick, onBeforeUnmount, ref, toRaw, watch } from 'vue';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
Form,
|
||||||
FormItem,
|
FormItem,
|
||||||
Input,
|
Input,
|
||||||
Select,
|
Select,
|
||||||
@@ -75,47 +76,50 @@ watch(
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<FormItem label="脚本格式">
|
<Form :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
|
||||||
<Input
|
<FormItem label="脚本格式">
|
||||||
v-model:value="scriptTaskForm.scriptFormat"
|
<Input
|
||||||
allow-clear
|
v-model:value="scriptTaskForm.scriptFormat"
|
||||||
@input="updateElementTask()"
|
allow-clear
|
||||||
@change="updateElementTask()"
|
@input="updateElementTask()"
|
||||||
/>
|
@change="updateElementTask()"
|
||||||
</FormItem>
|
/>
|
||||||
<FormItem label="脚本类型">
|
</FormItem>
|
||||||
<Select v-model:value="scriptTaskForm.scriptType">
|
<!-- TODO scriptType 外部资源 和 内联脚本, flowable 文档 https://www.flowable.com/open-source/docs/bpmn/ch07b-BPMN-Constructs#script-task 没看到到有相应的属性 -->
|
||||||
<SelectOption value="inline">内联脚本</SelectOption>
|
<FormItem label="脚本类型">
|
||||||
<SelectOption value="external">外部资源</SelectOption>
|
<Select v-model:value="scriptTaskForm.scriptType">
|
||||||
</Select>
|
<SelectOption value="inline">内联脚本</SelectOption>
|
||||||
</FormItem>
|
<SelectOption value="external">外部资源</SelectOption>
|
||||||
<FormItem label="脚本" v-show="scriptTaskForm.scriptType === 'inline'">
|
</Select>
|
||||||
<Textarea
|
</FormItem>
|
||||||
v-model:value="scriptTaskForm.script"
|
<FormItem label="脚本" v-show="scriptTaskForm.scriptType === 'inline'">
|
||||||
:auto-size="{ minRows: 2, maxRows: 4 }"
|
<Textarea
|
||||||
allow-clear
|
v-model:value="scriptTaskForm.script"
|
||||||
@input="updateElementTask()"
|
:auto-size="{ minRows: 2, maxRows: 4 }"
|
||||||
@change="updateElementTask()"
|
allow-clear
|
||||||
/>
|
@input="updateElementTask()"
|
||||||
</FormItem>
|
@change="updateElementTask()"
|
||||||
<FormItem
|
/>
|
||||||
label="资源地址"
|
</FormItem>
|
||||||
v-show="scriptTaskForm.scriptType === 'external'"
|
<FormItem
|
||||||
>
|
label="资源地址"
|
||||||
<Input
|
v-show="scriptTaskForm.scriptType === 'external'"
|
||||||
v-model:value="scriptTaskForm.resource"
|
>
|
||||||
allow-clear
|
<Input
|
||||||
@input="updateElementTask()"
|
v-model:value="scriptTaskForm.resource"
|
||||||
@change="updateElementTask()"
|
allow-clear
|
||||||
/>
|
@input="updateElementTask()"
|
||||||
</FormItem>
|
@change="updateElementTask()"
|
||||||
<FormItem label="结果变量">
|
/>
|
||||||
<Input
|
</FormItem>
|
||||||
v-model:value="scriptTaskForm.resultVariable"
|
<FormItem label="结果变量">
|
||||||
allow-clear
|
<Input
|
||||||
@input="updateElementTask()"
|
v-model:value="scriptTaskForm.resultVariable"
|
||||||
@change="updateElementTask()"
|
allow-clear
|
||||||
/>
|
@input="updateElementTask()"
|
||||||
</FormItem>
|
@change="updateElementTask()"
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
<!-- eslint-disable prettier/prettier -->
|
<!-- eslint-disable prettier/prettier -->
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { inject, nextTick, onBeforeUnmount, ref, toRaw, watch } from 'vue';
|
import { inject, nextTick, onBeforeUnmount, ref, watch } from 'vue';
|
||||||
|
|
||||||
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
Form,
|
||||||
FormItem,
|
FormItem,
|
||||||
Input,
|
Input,
|
||||||
RadioButton,
|
RadioButton,
|
||||||
@@ -70,7 +72,6 @@ const serviceTaskForm = ref({ ...DEFAULT_TASK_FORM });
|
|||||||
const httpTaskForm = ref<any>({ ...DEFAULT_HTTP_FORM });
|
const httpTaskForm = ref<any>({ ...DEFAULT_HTTP_FORM });
|
||||||
const bpmnElement = ref();
|
const bpmnElement = ref();
|
||||||
const httpInitializing = ref(false);
|
const httpInitializing = ref(false);
|
||||||
const showHeaderEditor = ref(false);
|
|
||||||
|
|
||||||
const bpmnInstances = () => (window as any)?.bpmnInstances;
|
const bpmnInstances = () => (window as any)?.bpmnInstances;
|
||||||
|
|
||||||
@@ -179,7 +180,10 @@ const shouldPersistField = (name: string, value: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateHttpExtensions = (force = false) => {
|
const updateHttpExtensions = (force = false) => {
|
||||||
if (!bpmnElement.value) return;
|
const instances = bpmnInstances();
|
||||||
|
if (!instances || !instances.bpmnElement) return;
|
||||||
|
// 直接使用原始BPMN元素,避免Vue响应式代理问题
|
||||||
|
const bpmnElement = instances.bpmnElement;
|
||||||
if (
|
if (
|
||||||
!force &&
|
!force &&
|
||||||
(httpInitializing.value || serviceTaskForm.value.executeType !== 'http')
|
(httpInitializing.value || serviceTaskForm.value.executeType !== 'http')
|
||||||
@@ -236,31 +240,37 @@ const updateHttpExtensions = (force = false) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
updateElementExtensions(bpmnElement.value, [
|
updateElementExtensions(bpmnElement, [
|
||||||
...otherExtensions,
|
...otherExtensions,
|
||||||
...httpFieldElements,
|
...httpFieldElements,
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeHttpExtensions = () => {
|
const removeHttpExtensions = () => {
|
||||||
if (!bpmnElement.value) return;
|
const instances = bpmnInstances();
|
||||||
|
if (!instances || !instances.bpmnElement) return;
|
||||||
|
// 直接使用原始BPMN元素,避免Vue响应式代理问题
|
||||||
|
const bpmnElement = instances.bpmnElement;
|
||||||
const { httpFields, otherExtensions } = collectHttpExtensionInfo();
|
const { httpFields, otherExtensions } = collectHttpExtensionInfo();
|
||||||
if (httpFields.size === 0) {
|
if (httpFields.size === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (otherExtensions.length === 0) {
|
if (otherExtensions.length === 0) {
|
||||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
bpmnInstances().modeling.updateProperties(bpmnElement, {
|
||||||
extensionElements: null,
|
extensionElements: null,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateElementExtensions(bpmnElement.value, otherExtensions);
|
updateElementExtensions(bpmnElement, otherExtensions);
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateElementTask = () => {
|
const updateElementTask = () => {
|
||||||
if (!bpmnElement.value) return;
|
const instances = bpmnInstances();
|
||||||
|
if (!instances || !instances.bpmnElement) return;
|
||||||
|
// 直接使用原始BPMN元素,避免Vue响应式代理问题
|
||||||
|
const bpmnElement = instances.bpmnElement;
|
||||||
|
|
||||||
const taskAttr: Record<string, any> = {
|
const taskAttr: Record<string, any> = {
|
||||||
class: null,
|
class: null,
|
||||||
@@ -280,7 +290,7 @@ const updateElementTask = () => {
|
|||||||
taskAttr[flowableTypeKey] = 'http';
|
taskAttr[flowableTypeKey] = 'http';
|
||||||
}
|
}
|
||||||
|
|
||||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), taskAttr);
|
bpmnInstances().modeling.updateProperties(bpmnElement, taskAttr);
|
||||||
|
|
||||||
if (type === 'http') {
|
if (type === 'http') {
|
||||||
updateHttpExtensions(true);
|
updateHttpExtensions(true);
|
||||||
@@ -297,10 +307,24 @@ const handleExecuteTypeChange = (value: any) => {
|
|||||||
updateElementTask();
|
updateElementTask();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** 打开请求头编辑器 */
|
||||||
|
const openHttpHeaderEditor = () => {
|
||||||
|
httpHeaderEditorApi
|
||||||
|
.setData({
|
||||||
|
headers: httpTaskForm.value.requestHeaders,
|
||||||
|
})
|
||||||
|
.open();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 保存请求头 */
|
||||||
const handleHeadersSave = (headersStr: string) => {
|
const handleHeadersSave = (headersStr: string) => {
|
||||||
httpTaskForm.value.requestHeaders = headersStr;
|
httpTaskForm.value.requestHeaders = headersStr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [HttpHeaderEditorModal, httpHeaderEditorApi] = useVbenModal({
|
||||||
|
connectedComponent: HttpHeaderEditor,
|
||||||
|
});
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
bpmnElement.value = null;
|
bpmnElement.value = null;
|
||||||
});
|
});
|
||||||
@@ -327,110 +351,140 @@ watch(
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<FormItem label="执行类型" key="executeType">
|
<Form :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
|
||||||
<Select
|
<FormItem label="执行类型" key="executeType">
|
||||||
v-model:value="serviceTaskForm.executeType"
|
<Select
|
||||||
:options="[
|
v-model:value="serviceTaskForm.executeType"
|
||||||
{ label: 'Java类', value: 'class' },
|
:options="[
|
||||||
{ label: '表达式', value: 'expression' },
|
{ label: 'Java类', value: 'class' },
|
||||||
{ label: '代理表达式', value: 'delegateExpression' },
|
{ label: '表达式', value: 'expression' },
|
||||||
{ label: 'HTTP 调用', value: 'http' },
|
{ label: '代理表达式', value: 'delegateExpression' },
|
||||||
]"
|
{ label: 'HTTP 调用', value: 'http' },
|
||||||
@change="handleExecuteTypeChange"
|
]"
|
||||||
/>
|
@change="handleExecuteTypeChange"
|
||||||
</FormItem>
|
|
||||||
<FormItem
|
|
||||||
v-if="serviceTaskForm.executeType === 'class'"
|
|
||||||
label="Java类"
|
|
||||||
name="class"
|
|
||||||
key="execute-class"
|
|
||||||
>
|
|
||||||
<Input
|
|
||||||
v-model:value="serviceTaskForm.class"
|
|
||||||
allow-clear
|
|
||||||
@change="updateElementTask"
|
|
||||||
/>
|
|
||||||
</FormItem>
|
|
||||||
<FormItem
|
|
||||||
v-if="serviceTaskForm.executeType === 'expression'"
|
|
||||||
label="表达式"
|
|
||||||
name="expression"
|
|
||||||
key="execute-expression"
|
|
||||||
>
|
|
||||||
<Input
|
|
||||||
v-model:value="serviceTaskForm.expression"
|
|
||||||
allow-clear
|
|
||||||
@change="updateElementTask"
|
|
||||||
/>
|
|
||||||
</FormItem>
|
|
||||||
<FormItem
|
|
||||||
v-if="serviceTaskForm.executeType === 'delegateExpression'"
|
|
||||||
label="代理表达式"
|
|
||||||
name="delegateExpression"
|
|
||||||
key="execute-delegate"
|
|
||||||
>
|
|
||||||
<Input
|
|
||||||
v-model:value="serviceTaskForm.delegateExpression"
|
|
||||||
allow-clear
|
|
||||||
@change="updateElementTask"
|
|
||||||
/>
|
|
||||||
</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>
|
||||||
<FormItem label="返回变量前缀" key="http-result-variable-prefix">
|
<FormItem
|
||||||
<Input v-model:value="httpTaskForm.resultVariablePrefix" />
|
v-if="serviceTaskForm.executeType === 'class'"
|
||||||
|
label="Java类"
|
||||||
|
name="class"
|
||||||
|
key="execute-class"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
v-model:value="serviceTaskForm.class"
|
||||||
|
allow-clear
|
||||||
|
@change="updateElementTask"
|
||||||
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem label="格式化返回为JSON" key="http-save-json">
|
<FormItem
|
||||||
<Switch v-model:checked="httpTaskForm.saveResponseVariableAsJson" />
|
v-if="serviceTaskForm.executeType === 'expression'"
|
||||||
|
label="表达式"
|
||||||
|
name="expression"
|
||||||
|
key="execute-expression"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
v-model:value="serviceTaskForm.expression"
|
||||||
|
allow-clear
|
||||||
|
@change="updateElementTask"
|
||||||
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</template>
|
<FormItem
|
||||||
|
v-if="serviceTaskForm.executeType === 'delegateExpression'"
|
||||||
|
label="代理表达式"
|
||||||
|
name="delegateExpression"
|
||||||
|
key="execute-delegate"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
v-model:value="serviceTaskForm.delegateExpression"
|
||||||
|
allow-clear
|
||||||
|
@change="updateElementTask"
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
<template v-if="serviceTaskForm.executeType === 'http'">
|
||||||
|
<FormItem label="请求方法" key="http-method" name="requestMethod">
|
||||||
|
<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" name="requestHeaders">
|
||||||
|
<div class="flex w-full flex-col gap-2">
|
||||||
|
<Textarea
|
||||||
|
v-model:value="httpTaskForm.requestHeaders"
|
||||||
|
:auto-size="{ minRows: 4, maxRows: 8 }"
|
||||||
|
readonly
|
||||||
|
placeholder="点击右侧编辑按钮添加请求头"
|
||||||
|
class="min-w-0 flex-1"
|
||||||
|
/>
|
||||||
|
<div class="flex w-full items-center justify-center">
|
||||||
|
<Button
|
||||||
|
class="flex flex-1 items-center justify-center"
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
@click="openHttpHeaderEditor"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<IconifyIcon icon="ep:edit" />
|
||||||
|
</template>
|
||||||
|
编辑
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem
|
||||||
|
label="禁止重定向"
|
||||||
|
key="http-disallow-redirects"
|
||||||
|
name="disallowRedirects"
|
||||||
|
>
|
||||||
|
<Switch v-model:checked="httpTaskForm.disallowRedirects" />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem
|
||||||
|
label="忽略异常"
|
||||||
|
key="http-ignore-exception"
|
||||||
|
name="ignoreException"
|
||||||
|
>
|
||||||
|
<Switch v-model:checked="httpTaskForm.ignoreException" />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem
|
||||||
|
label="保存返回变量"
|
||||||
|
key="http-save-response"
|
||||||
|
name="saveResponseParameters"
|
||||||
|
>
|
||||||
|
<Switch v-model:checked="httpTaskForm.saveResponseParameters" />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem
|
||||||
|
label="是否瞬间变量"
|
||||||
|
key="http-save-transient"
|
||||||
|
name="saveResponseParametersTransient"
|
||||||
|
>
|
||||||
|
<Switch
|
||||||
|
v-model:checked="httpTaskForm.saveResponseParametersTransient"
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem
|
||||||
|
label="返回变量前缀"
|
||||||
|
key="http-result-variable-prefix"
|
||||||
|
name="resultVariablePrefix"
|
||||||
|
>
|
||||||
|
<Input v-model:value="httpTaskForm.resultVariablePrefix" />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem
|
||||||
|
label="保存为 JSON 变量"
|
||||||
|
:label-col="{ span: 8 }"
|
||||||
|
:wrapper-col="{ span: 16 }"
|
||||||
|
key="http-save-json"
|
||||||
|
name="saveResponseVariableAsJson"
|
||||||
|
>
|
||||||
|
<Switch v-model:checked="httpTaskForm.saveResponseVariableAsJson" />
|
||||||
|
</FormItem>
|
||||||
|
</template>
|
||||||
|
</Form>
|
||||||
<!-- 请求头编辑器 -->
|
<!-- 请求头编辑器 -->
|
||||||
<HttpHeaderEditor
|
<HttpHeaderEditorModal @save="handleHeadersSave" />
|
||||||
v-model="showHeaderEditor"
|
|
||||||
:headers="httpTaskForm.requestHeaders"
|
|
||||||
@save="handleHeadersSave"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user