696 lines
20 KiB
Vue
696 lines
20 KiB
Vue
<script setup lang="ts">
|
|
import type { Rule } from 'ant-design-vue/es/form';
|
|
import type { SelectValue } from 'ant-design-vue/es/select';
|
|
|
|
import type {
|
|
FormTriggerSetting,
|
|
SimpleFlowNode,
|
|
TriggerSetting,
|
|
} from '../../consts';
|
|
|
|
import { computed, getCurrentInstance, onMounted, reactive, ref } from 'vue';
|
|
|
|
import { useVbenDrawer } from '@vben/common-ui';
|
|
import { IconifyIcon, Trash2 } from '@vben/icons';
|
|
import { cloneDeep } from '@vben/utils';
|
|
|
|
import {
|
|
Button,
|
|
Card,
|
|
Col,
|
|
Divider,
|
|
Form,
|
|
FormItem,
|
|
Input,
|
|
message,
|
|
Row,
|
|
Select,
|
|
SelectOption,
|
|
Tag,
|
|
} from 'ant-design-vue';
|
|
|
|
import {
|
|
DEFAULT_CONDITION_GROUP_VALUE,
|
|
NodeType,
|
|
TRIGGER_TYPES,
|
|
TriggerTypeEnum,
|
|
} from '../../consts';
|
|
import {
|
|
getConditionShowText,
|
|
useFormFields,
|
|
useNodeName,
|
|
useWatchNode,
|
|
} from '../../helpers';
|
|
// TODO import ConditionDialog from './modules/condition-dialog.vue';
|
|
import HttpRequestSetting from './modules/http-request-setting.vue';
|
|
|
|
defineOptions({
|
|
name: 'TriggerNodeConfig',
|
|
});
|
|
|
|
const props = defineProps({
|
|
flowNode: {
|
|
type: Object as () => SimpleFlowNode,
|
|
required: true,
|
|
},
|
|
});
|
|
|
|
const { proxy } = getCurrentInstance() as any;
|
|
|
|
// 抽屉配置
|
|
const [Drawer, drawerApi] = useVbenDrawer({
|
|
header: true,
|
|
closable: true,
|
|
title: '',
|
|
onCancel() {
|
|
drawerApi.close();
|
|
},
|
|
onConfirm() {
|
|
saveConfig();
|
|
},
|
|
});
|
|
|
|
// 当前节点
|
|
const currentNode = useWatchNode(props);
|
|
// 节点名称
|
|
const { nodeName, showInput, clickIcon, blurEvent } = useNodeName(
|
|
NodeType.TRIGGER_NODE,
|
|
);
|
|
// 触发器表单配置
|
|
const formRef = ref(); // 表单 Ref
|
|
// 表单校验规则
|
|
const formRules: Record<string, Rule[]> = reactive({
|
|
type: [{ required: true, message: '触发器类型不能为空', trigger: 'change' }],
|
|
'httpRequestSetting.url': [
|
|
{ required: true, message: '请求地址不能为空', trigger: 'blur' },
|
|
],
|
|
});
|
|
// 触发器配置表单数据
|
|
const configForm = ref<TriggerSetting>({
|
|
type: TriggerTypeEnum.HTTP_REQUEST,
|
|
httpRequestSetting: {
|
|
url: '',
|
|
header: [],
|
|
body: [],
|
|
response: [],
|
|
},
|
|
formSettings: [
|
|
{
|
|
conditionGroups: cloneDeep(DEFAULT_CONDITION_GROUP_VALUE),
|
|
updateFormFields: {},
|
|
deleteFields: [],
|
|
},
|
|
],
|
|
});
|
|
// 流程表单字段
|
|
const formFields = useFormFields();
|
|
|
|
// 可选的修改的表单字段
|
|
const optionalUpdateFormFields = computed(() => {
|
|
return formFields.map((field) => ({
|
|
title: field.title,
|
|
field: field.field,
|
|
disabled: false,
|
|
}));
|
|
});
|
|
|
|
let originalSetting: TriggerSetting | undefined;
|
|
|
|
/** 触发器类型改变了 */
|
|
const changeTriggerType = () => {
|
|
if (configForm.value.type === TriggerTypeEnum.HTTP_REQUEST) {
|
|
configForm.value.httpRequestSetting =
|
|
originalSetting?.type === TriggerTypeEnum.HTTP_REQUEST &&
|
|
originalSetting.httpRequestSetting
|
|
? originalSetting.httpRequestSetting
|
|
: {
|
|
url: '',
|
|
header: [],
|
|
body: [],
|
|
response: [],
|
|
};
|
|
configForm.value.formSettings = undefined;
|
|
return;
|
|
}
|
|
|
|
if (configForm.value.type === TriggerTypeEnum.HTTP_CALLBACK) {
|
|
configForm.value.httpRequestSetting =
|
|
originalSetting?.type === TriggerTypeEnum.HTTP_CALLBACK &&
|
|
originalSetting.httpRequestSetting
|
|
? originalSetting.httpRequestSetting
|
|
: {
|
|
url: '',
|
|
header: [],
|
|
body: [],
|
|
response: [],
|
|
};
|
|
configForm.value.formSettings = undefined;
|
|
return;
|
|
}
|
|
|
|
if (configForm.value.type === TriggerTypeEnum.FORM_UPDATE) {
|
|
configForm.value.formSettings =
|
|
originalSetting?.type === TriggerTypeEnum.FORM_UPDATE &&
|
|
originalSetting.formSettings
|
|
? originalSetting.formSettings
|
|
: [
|
|
{
|
|
conditionGroups: cloneDeep(DEFAULT_CONDITION_GROUP_VALUE),
|
|
updateFormFields: {},
|
|
deleteFields: [],
|
|
},
|
|
];
|
|
configForm.value.httpRequestSetting = undefined;
|
|
return;
|
|
}
|
|
|
|
if (configForm.value.type === TriggerTypeEnum.FORM_DELETE) {
|
|
configForm.value.formSettings =
|
|
originalSetting?.type === TriggerTypeEnum.FORM_DELETE &&
|
|
originalSetting.formSettings
|
|
? originalSetting.formSettings
|
|
: [
|
|
{
|
|
conditionGroups: cloneDeep(DEFAULT_CONDITION_GROUP_VALUE),
|
|
updateFormFields: undefined,
|
|
deleteFields: [],
|
|
},
|
|
];
|
|
configForm.value.httpRequestSetting = undefined;
|
|
}
|
|
};
|
|
|
|
/** 添加新的修改表单设置 */
|
|
const addFormSetting = () => {
|
|
configForm.value.formSettings!.push({
|
|
conditionGroups: cloneDeep(DEFAULT_CONDITION_GROUP_VALUE),
|
|
updateFormFields: {},
|
|
deleteFields: [],
|
|
});
|
|
};
|
|
|
|
/** 删除修改表单设置 */
|
|
const deleteFormSetting = (index: number) => {
|
|
configForm.value.formSettings!.splice(index, 1);
|
|
};
|
|
|
|
/** 添加条件配置 */
|
|
const addFormSettingCondition = (
|
|
index: number,
|
|
formSetting: FormTriggerSetting,
|
|
) => {
|
|
const conditionDialog = proxy.$refs[`condition-${index}`][0];
|
|
conditionDialog.open(formSetting);
|
|
};
|
|
/** 删除条件配置 */
|
|
const deleteFormSettingCondition = (formSetting: FormTriggerSetting) => {
|
|
formSetting.conditionType = undefined;
|
|
};
|
|
/** 打开条件配置弹窗 */
|
|
const openFormSettingCondition = (
|
|
index: number,
|
|
formSetting: FormTriggerSetting,
|
|
) => {
|
|
const conditionDialog = proxy.$refs[`condition-${index}`][0];
|
|
conditionDialog.open(formSetting);
|
|
};
|
|
/** 处理条件配置保存 */
|
|
/* 暂时注释掉未使用的函数
|
|
const _handleConditionUpdate = (index: number, condition: any) => {
|
|
if (configForm.value.formSettings![index]) {
|
|
configForm.value.formSettings![index].conditionType =
|
|
condition.conditionType;
|
|
configForm.value.formSettings![index].conditionExpression =
|
|
condition.conditionExpression;
|
|
configForm.value.formSettings![index].conditionGroups =
|
|
condition.conditionGroups;
|
|
}
|
|
};
|
|
*/
|
|
/** 条件配置展示 */
|
|
const showConditionText = (formSetting: FormTriggerSetting) => {
|
|
return getConditionShowText(
|
|
formSetting.conditionType,
|
|
formSetting.conditionExpression,
|
|
formSetting.conditionGroups,
|
|
formFields,
|
|
);
|
|
};
|
|
|
|
/** 添加修改字段设置项 */
|
|
const addFormFieldSetting = (formSetting: FormTriggerSetting) => {
|
|
if (!formSetting) return;
|
|
if (!formSetting.updateFormFields) {
|
|
formSetting.updateFormFields = {};
|
|
}
|
|
formSetting.updateFormFields[''] = undefined;
|
|
};
|
|
/** 更新字段 KEY */
|
|
const updateFormFieldKey = (
|
|
formSetting: FormTriggerSetting,
|
|
oldKey: string,
|
|
newKey: SelectValue,
|
|
) => {
|
|
if (!formSetting?.updateFormFields || !newKey) return;
|
|
const value = formSetting.updateFormFields[oldKey];
|
|
delete formSetting.updateFormFields[oldKey];
|
|
formSetting.updateFormFields[String(newKey)] = value;
|
|
};
|
|
|
|
/** 删除修改字段设置项 */
|
|
const deleteFormFieldSetting = (
|
|
formSetting: FormTriggerSetting,
|
|
key: string,
|
|
) => {
|
|
if (!formSetting?.updateFormFields) return;
|
|
delete formSetting.updateFormFields[key];
|
|
};
|
|
|
|
/** 保存配置 */
|
|
const saveConfig = async () => {
|
|
if (!formRef.value) return false;
|
|
const valid = await formRef.value.validate();
|
|
if (!valid) return false;
|
|
const showText = getShowText();
|
|
if (!showText) return false;
|
|
currentNode.value.name = nodeName.value!;
|
|
currentNode.value.showText = showText;
|
|
switch (configForm.value.type) {
|
|
case TriggerTypeEnum.FORM_DELETE: {
|
|
configForm.value.httpRequestSetting = undefined;
|
|
// 清理修改字段相关的数据
|
|
configForm.value.formSettings?.forEach((setting) => {
|
|
setting.updateFormFields = undefined;
|
|
});
|
|
|
|
break;
|
|
}
|
|
case TriggerTypeEnum.FORM_UPDATE: {
|
|
configForm.value.httpRequestSetting = undefined;
|
|
// 清理删除字段相关的数据
|
|
configForm.value.formSettings?.forEach((setting) => {
|
|
setting.deleteFields = undefined;
|
|
});
|
|
|
|
break;
|
|
}
|
|
case TriggerTypeEnum.HTTP_REQUEST: {
|
|
configForm.value.formSettings = undefined;
|
|
|
|
break;
|
|
}
|
|
// No default
|
|
}
|
|
currentNode.value.triggerSetting = configForm.value;
|
|
drawerApi.close();
|
|
return true;
|
|
};
|
|
|
|
/** 获取节点展示内容 */
|
|
const getShowText = (): string => {
|
|
let showText = '';
|
|
switch (configForm.value.type) {
|
|
case TriggerTypeEnum.FORM_DELETE: {
|
|
for (const [index, setting] of configForm.value.formSettings!.entries()) {
|
|
if (!setting.deleteFields || setting.deleteFields.length === 0) {
|
|
message.warning(`请选择表单设置${index + 1}要删除的字段`);
|
|
return '';
|
|
}
|
|
}
|
|
showText = '删除表单数据';
|
|
|
|
break;
|
|
}
|
|
case TriggerTypeEnum.FORM_UPDATE: {
|
|
for (const [index, setting] of configForm.value.formSettings!.entries()) {
|
|
if (
|
|
!setting.updateFormFields ||
|
|
Object.keys(setting.updateFormFields).length === 0
|
|
) {
|
|
message.warning(`请添加表单设置${index + 1}的修改字段`);
|
|
return '';
|
|
}
|
|
}
|
|
showText = '修改表单数据';
|
|
|
|
break;
|
|
}
|
|
case TriggerTypeEnum.HTTP_CALLBACK:
|
|
case TriggerTypeEnum.HTTP_REQUEST: {
|
|
showText = `${configForm.value.httpRequestSetting?.url}`;
|
|
|
|
break;
|
|
}
|
|
// No default
|
|
}
|
|
return showText;
|
|
};
|
|
|
|
/** 显示触发器节点配置, 由父组件传过来 */
|
|
const showTriggerNodeConfig = (node: SimpleFlowNode) => {
|
|
nodeName.value = node.name;
|
|
originalSetting = node.triggerSetting
|
|
? cloneDeep(node.triggerSetting)
|
|
: undefined;
|
|
if (node.triggerSetting) {
|
|
configForm.value = {
|
|
type: node.triggerSetting.type,
|
|
httpRequestSetting: node.triggerSetting.httpRequestSetting || {
|
|
url: '',
|
|
header: [],
|
|
body: [],
|
|
response: [],
|
|
},
|
|
formSettings: node.triggerSetting.formSettings || [
|
|
{
|
|
conditionGroups: cloneDeep(DEFAULT_CONDITION_GROUP_VALUE),
|
|
updateFormFields: {},
|
|
deleteFields: [],
|
|
},
|
|
],
|
|
};
|
|
}
|
|
drawerApi.open();
|
|
};
|
|
|
|
// 暴露方法给父组件
|
|
defineExpose({ showTriggerNodeConfig });
|
|
|
|
onMounted(() => {
|
|
// 初始化可能需要的操作
|
|
});
|
|
</script>
|
|
<template>
|
|
<Drawer class="w-[580px]">
|
|
<template #title>
|
|
<div class="config-header">
|
|
<Input
|
|
v-if="showInput"
|
|
type="text"
|
|
class="config-editable-input"
|
|
@blur="blurEvent()"
|
|
v-model:value="nodeName"
|
|
:placeholder="nodeName"
|
|
/>
|
|
<div v-else class="node-name">
|
|
{{ nodeName }}
|
|
<IconifyIcon class="ml-1" icon="ep:edit-pen" @click="clickIcon()" />
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<div>
|
|
<Form
|
|
ref="formRef"
|
|
:model="configForm"
|
|
:label-col="{ span: 24 }"
|
|
:wrapper-col="{ span: 24 }"
|
|
:rules="formRules"
|
|
>
|
|
<FormItem label="触发器类型" name="type">
|
|
<Select v-model:value="configForm.type" @change="changeTriggerType">
|
|
<SelectOption
|
|
v-for="(item, index) in TRIGGER_TYPES"
|
|
:key="index"
|
|
:value="item.value"
|
|
:label="item.label"
|
|
>
|
|
{{ item.label }}
|
|
</SelectOption>
|
|
</Select>
|
|
</FormItem>
|
|
<!-- HTTP 请求触发器 -->
|
|
<div
|
|
v-if="
|
|
[
|
|
TriggerTypeEnum.HTTP_REQUEST,
|
|
TriggerTypeEnum.HTTP_CALLBACK,
|
|
].includes(configForm.type) && configForm.httpRequestSetting
|
|
"
|
|
>
|
|
<HttpRequestSetting
|
|
v-model:setting="configForm.httpRequestSetting"
|
|
:response-enable="configForm.type === TriggerTypeEnum.HTTP_REQUEST"
|
|
form-item-prefix="httpRequestSetting"
|
|
/>
|
|
</div>
|
|
|
|
<!-- 表单数据修改触发器 -->
|
|
<div v-if="configForm.type === TriggerTypeEnum.FORM_UPDATE">
|
|
<div
|
|
v-for="(formSetting, index) in configForm.formSettings"
|
|
:key="index"
|
|
>
|
|
<Card class="mt-4">
|
|
<template #title>
|
|
<div class="flex w-full items-center justify-between">
|
|
<span>修改表单设置 {{ index + 1 }}</span>
|
|
<Button
|
|
v-if="configForm.formSettings!.length > 1"
|
|
shape="circle"
|
|
class="flex items-center justify-center"
|
|
@click="deleteFormSetting(index)"
|
|
>
|
|
<template #icon>
|
|
<IconifyIcon icon="ep:close" />
|
|
</template>
|
|
</Button>
|
|
</div>
|
|
</template>
|
|
|
|
<!-- TODO 条件设置 -->
|
|
<!-- <ConditionDialog
|
|
:ref="`condition-${index}`"
|
|
@update-condition="(val) => handleConditionUpdate(index, val)"
|
|
/> -->
|
|
<Row>
|
|
<Col :span="24">
|
|
<div class="cursor-pointer" v-if="formSetting.conditionType">
|
|
<Tag
|
|
color="success"
|
|
closable
|
|
@close="deleteFormSettingCondition(formSetting)"
|
|
@click="openFormSettingCondition(index, formSetting)"
|
|
>
|
|
{{ showConditionText(formSetting) }}
|
|
</Tag>
|
|
</div>
|
|
<Button
|
|
v-else
|
|
type="link"
|
|
class="flex items-center p-0"
|
|
@click="addFormSettingCondition(index, formSetting)"
|
|
>
|
|
<template #icon>
|
|
<IconifyIcon icon="ep:link" />
|
|
</template>
|
|
添加条件
|
|
</Button>
|
|
</Col>
|
|
</Row>
|
|
<Divider>修改表单字段设置</Divider>
|
|
<!-- 表单字段修改设置 -->
|
|
<Row
|
|
:gutter="8"
|
|
v-for="key in Object.keys(formSetting.updateFormFields || {})"
|
|
:key="key"
|
|
>
|
|
<Col :span="8">
|
|
<FormItem>
|
|
<Select
|
|
:value="key || undefined"
|
|
@change="
|
|
(newKey) => updateFormFieldKey(formSetting, key, newKey)
|
|
"
|
|
placeholder="请选择表单字段"
|
|
:disabled="key !== ''"
|
|
allow-clear
|
|
>
|
|
<SelectOption
|
|
v-for="(field, fIdx) in optionalUpdateFormFields"
|
|
:key="fIdx"
|
|
:label="field.title"
|
|
:value="field.field"
|
|
:disabled="field.disabled"
|
|
>
|
|
{{ field.title }}
|
|
</SelectOption>
|
|
</Select>
|
|
</FormItem>
|
|
</Col>
|
|
<Col :span="4">
|
|
<FormItem>的值设置为</FormItem>
|
|
</Col>
|
|
<Col :span="10">
|
|
<FormItem
|
|
:name="['formSettings', index, 'updateFormFields', key]"
|
|
:rules="{
|
|
required: true,
|
|
message: '值不能为空',
|
|
trigger: 'blur',
|
|
}"
|
|
>
|
|
<Input
|
|
v-model:value="formSetting.updateFormFields![key]"
|
|
placeholder="请输入值"
|
|
allow-clear
|
|
:disabled="!key"
|
|
/>
|
|
</FormItem>
|
|
</Col>
|
|
<Col :span="2">
|
|
<div class="flex h-[32px] items-center">
|
|
<Trash2
|
|
class="size-4 cursor-pointer text-red-500"
|
|
@click="deleteFormFieldSetting(formSetting, key)"
|
|
/>
|
|
</div>
|
|
</Col>
|
|
</Row>
|
|
|
|
<!-- 添加表单字段按钮 -->
|
|
<Row>
|
|
<Col :span="24">
|
|
<Button
|
|
type="link"
|
|
class="flex items-center p-0"
|
|
@click="addFormFieldSetting(formSetting)"
|
|
>
|
|
<template #icon>
|
|
<IconifyIcon icon="ep:memo" />
|
|
</template>
|
|
添加修改字段
|
|
</Button>
|
|
</Col>
|
|
</Row>
|
|
</Card>
|
|
</div>
|
|
|
|
<!-- 添加新的设置 -->
|
|
<Row class="mt-6">
|
|
<Col :span="24">
|
|
<Button
|
|
class="flex items-center p-0"
|
|
type="link"
|
|
@click="addFormSetting"
|
|
>
|
|
<template #icon>
|
|
<IconifyIcon icon="ep:setting" />
|
|
</template>
|
|
添加设置
|
|
</Button>
|
|
</Col>
|
|
</Row>
|
|
</div>
|
|
|
|
<!-- 表单数据删除触发器 -->
|
|
<div v-if="configForm.type === TriggerTypeEnum.FORM_DELETE">
|
|
<div
|
|
v-for="(formSetting, index) in configForm.formSettings"
|
|
:key="index"
|
|
>
|
|
<Card class="mt-4">
|
|
<template #title>
|
|
<div class="flex w-full items-center justify-between">
|
|
<span>删除表单设置 {{ index + 1 }}</span>
|
|
<Button
|
|
v-if="configForm.formSettings!.length > 1"
|
|
shape="circle"
|
|
class="flex items-center justify-center"
|
|
@click="deleteFormSetting(index)"
|
|
>
|
|
<template #icon>
|
|
<IconifyIcon icon="ep:close" />
|
|
</template>
|
|
</Button>
|
|
</div>
|
|
</template>
|
|
|
|
<!-- TODO 条件设置 -->
|
|
<!-- <ConditionDialog
|
|
:ref="`condition-${index}`"
|
|
@update-condition="(val) => handleConditionUpdate(index, val)"
|
|
/> -->
|
|
<Row>
|
|
<Col :span="24">
|
|
<div class="cursor-pointer" v-if="formSetting.conditionType">
|
|
<Tag
|
|
color="warning"
|
|
closable
|
|
@close="deleteFormSettingCondition(formSetting)"
|
|
@click="openFormSettingCondition(index, formSetting)"
|
|
>
|
|
{{ showConditionText(formSetting) }}
|
|
</Tag>
|
|
</div>
|
|
<Button
|
|
v-else
|
|
type="link"
|
|
class="flex items-center p-0"
|
|
@click="addFormSettingCondition(index, formSetting)"
|
|
>
|
|
<template #icon>
|
|
<IconifyIcon icon="ep:link" />
|
|
</template>
|
|
添加条件
|
|
</Button>
|
|
</Col>
|
|
</Row>
|
|
|
|
<Divider>删除表单字段设置</Divider>
|
|
<!-- 表单字段删除设置 -->
|
|
<div class="flex flex-wrap gap-2">
|
|
<Select
|
|
v-model:value="formSetting.deleteFields"
|
|
mode="multiple"
|
|
placeholder="请选择要删除的字段"
|
|
class="w-full"
|
|
>
|
|
<SelectOption
|
|
v-for="field in formFields"
|
|
:key="field.field"
|
|
:label="field.title"
|
|
:value="field.field"
|
|
>
|
|
{{ field.title }}
|
|
</SelectOption>
|
|
</Select>
|
|
</div>
|
|
</Card>
|
|
</div>
|
|
|
|
<!-- 添加新的设置 -->
|
|
<Row class="mt-6">
|
|
<Col :span="24">
|
|
<Button
|
|
class="flex items-center p-0"
|
|
type="link"
|
|
@click="addFormSetting"
|
|
>
|
|
<template #icon>
|
|
<IconifyIcon icon="ep:setting" />
|
|
</template>
|
|
添加设置
|
|
</Button>
|
|
</Col>
|
|
</Row>
|
|
</div>
|
|
</Form>
|
|
</div>
|
|
<template #footer>
|
|
<div class="flex justify-end">
|
|
<Button type="primary" @click="saveConfig">确 定</Button>
|
|
<Button class="ml-2" @click="drawerApi.close()">取 消</Button>
|
|
</div>
|
|
</template>
|
|
</Drawer>
|
|
</template>
|
|
<style lang="scss" scoped>
|
|
.config-editable-input {
|
|
&:focus {
|
|
outline: 0;
|
|
border-color: #40a9ff;
|
|
box-shadow: 0 0 0 2px rgb(24 144 255 / 20%);
|
|
}
|
|
}
|
|
</style>
|