feat: [BPM 工作流] Simple 模型 - 触发器节点条件设置
parent
9587a8cdcd
commit
688f7c9083
|
@ -0,0 +1,70 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ConditionGroup } from '../../../consts';
|
||||||
|
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
|
import { cloneDeep } from '@vben/utils';
|
||||||
|
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { ConditionType, DEFAULT_CONDITION_GROUP_VALUE } from '../../../consts';
|
||||||
|
import Condition from './condition.vue';
|
||||||
|
|
||||||
|
defineOptions({ name: 'ConditionDialog' });
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
updateCondition: [condition: object];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const conditionData = ref<{
|
||||||
|
conditionExpression?: string;
|
||||||
|
conditionGroups?: ConditionGroup;
|
||||||
|
conditionType: ConditionType;
|
||||||
|
}>({
|
||||||
|
conditionType: ConditionType.RULE,
|
||||||
|
conditionGroups: cloneDeep(DEFAULT_CONDITION_GROUP_VALUE),
|
||||||
|
});
|
||||||
|
|
||||||
|
// 条件组件的引用
|
||||||
|
const conditionRef = ref();
|
||||||
|
|
||||||
|
const [Modal, modalApi] = useVbenModal({
|
||||||
|
title: '条件配置',
|
||||||
|
destroyOnClose: true,
|
||||||
|
draggable: true,
|
||||||
|
async onConfirm() {
|
||||||
|
// 校验表单
|
||||||
|
if (!conditionRef.value) return;
|
||||||
|
const valid = await conditionRef.value.validate().catch(() => false);
|
||||||
|
if (!valid) {
|
||||||
|
message.warning('请完善条件规则');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 设置完的条件传递给父组件
|
||||||
|
emit('updateCondition', conditionData.value);
|
||||||
|
modalApi.close();
|
||||||
|
},
|
||||||
|
onCancel() {
|
||||||
|
modalApi.close();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const open = (conditionObj: any | undefined) => {
|
||||||
|
if (conditionObj) {
|
||||||
|
conditionData.value.conditionType = conditionObj.conditionType;
|
||||||
|
conditionData.value.conditionExpression = conditionObj.conditionExpression;
|
||||||
|
conditionData.value.conditionGroups = conditionObj.conditionGroups;
|
||||||
|
}
|
||||||
|
modalApi.open();
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({ open });
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<Modal class="w-1/2">
|
||||||
|
<Condition ref="conditionRef" v-model="conditionData" />
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
|
@ -0,0 +1,323 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { Rule } from 'ant-design-vue/es/form';
|
||||||
|
|
||||||
|
import type { Ref } from 'vue';
|
||||||
|
|
||||||
|
import { computed, inject, reactive, ref } from 'vue';
|
||||||
|
|
||||||
|
import { IconifyIcon, Plus, Trash2 } from '@vben/icons';
|
||||||
|
import { cloneDeep } from '@vben/utils';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
Col,
|
||||||
|
Form,
|
||||||
|
FormItem,
|
||||||
|
Input,
|
||||||
|
Radio,
|
||||||
|
RadioGroup,
|
||||||
|
Row,
|
||||||
|
Select,
|
||||||
|
SelectOption,
|
||||||
|
Space,
|
||||||
|
Switch,
|
||||||
|
Textarea,
|
||||||
|
Tooltip,
|
||||||
|
} from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { BpmModelFormType } from '#/utils/constants';
|
||||||
|
|
||||||
|
import {
|
||||||
|
COMPARISON_OPERATORS,
|
||||||
|
CONDITION_CONFIG_TYPES,
|
||||||
|
ConditionType,
|
||||||
|
DEFAULT_CONDITION_GROUP_VALUE,
|
||||||
|
} from '../../../consts';
|
||||||
|
import { useFormFieldsAndStartUser } from '../../../helpers';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'Condition',
|
||||||
|
});
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const emit = defineEmits(['update:modelValue']);
|
||||||
|
const condition = computed({
|
||||||
|
get() {
|
||||||
|
return props.modelValue;
|
||||||
|
},
|
||||||
|
set(newValue) {
|
||||||
|
emit('update:modelValue', newValue);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const formType = inject<Ref<number>>('formType'); // 表单类型
|
||||||
|
const conditionConfigTypes = computed(() => {
|
||||||
|
return CONDITION_CONFIG_TYPES.filter((item) => {
|
||||||
|
// 业务表单暂时去掉条件规则选项
|
||||||
|
return !(
|
||||||
|
formType?.value === BpmModelFormType.CUSTOM &&
|
||||||
|
item.value === ConditionType.RULE
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 条件规则可选择的表单字段 */
|
||||||
|
const fieldOptions = useFormFieldsAndStartUser();
|
||||||
|
|
||||||
|
// 表单校验规则
|
||||||
|
const formRules: Record<string, Rule[]> = reactive({
|
||||||
|
conditionType: [
|
||||||
|
{ required: true, message: '配置方式不能为空', trigger: 'change' },
|
||||||
|
],
|
||||||
|
conditionExpression: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '条件表达式不能为空',
|
||||||
|
trigger: ['blur', 'change'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
const formRef = ref(); // 表单 Ref
|
||||||
|
|
||||||
|
/** 切换条件配置方式 */
|
||||||
|
const changeConditionType = () => {
|
||||||
|
if (
|
||||||
|
condition.value.conditionType === ConditionType.RULE &&
|
||||||
|
!condition.value.conditionGroups
|
||||||
|
) {
|
||||||
|
condition.value.conditionGroups = cloneDeep(DEFAULT_CONDITION_GROUP_VALUE);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const deleteConditionGroup = (conditions: any, index: number) => {
|
||||||
|
conditions.splice(index, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteConditionRule = (condition: any, index: number) => {
|
||||||
|
condition.rules.splice(index, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addConditionRule = (condition: any, index: number) => {
|
||||||
|
const rule = {
|
||||||
|
opCode: '==',
|
||||||
|
leftSide: undefined,
|
||||||
|
rightSide: '',
|
||||||
|
};
|
||||||
|
condition.rules.splice(index + 1, 0, rule);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addConditionGroup = (conditions: any) => {
|
||||||
|
const condition = {
|
||||||
|
and: true,
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
opCode: '==',
|
||||||
|
leftSide: undefined,
|
||||||
|
rightSide: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
conditions.push(condition);
|
||||||
|
};
|
||||||
|
|
||||||
|
const validate = async () => {
|
||||||
|
if (!formRef.value) return false;
|
||||||
|
return await formRef.value.validate();
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({ validate });
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<Form
|
||||||
|
ref="formRef"
|
||||||
|
:model="condition"
|
||||||
|
:rules="formRules"
|
||||||
|
:label-col="{ span: 24 }"
|
||||||
|
:wrapper-col="{ span: 24 }"
|
||||||
|
>
|
||||||
|
<FormItem label="配置方式" name="conditionType">
|
||||||
|
<RadioGroup
|
||||||
|
v-model:value="condition.conditionType"
|
||||||
|
@change="changeConditionType"
|
||||||
|
>
|
||||||
|
<Radio
|
||||||
|
v-for="(dict, indexConditionType) in conditionConfigTypes"
|
||||||
|
:key="indexConditionType"
|
||||||
|
:value="dict.value"
|
||||||
|
>
|
||||||
|
{{ dict.label }}
|
||||||
|
</Radio>
|
||||||
|
</RadioGroup>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem
|
||||||
|
v-if="
|
||||||
|
condition.conditionType === ConditionType.RULE &&
|
||||||
|
condition.conditionGroups
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div class="mb-5 flex w-full justify-between">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="mr-4">条件组关系</div>
|
||||||
|
<Switch
|
||||||
|
v-model:checked="condition.conditionGroups.and"
|
||||||
|
checked-children="且"
|
||||||
|
un-checked-children="或"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Space direction="vertical" size="small" class="w-11/12 pl-1">
|
||||||
|
<template #split>
|
||||||
|
{{ condition.conditionGroups.and ? '且' : '或' }}
|
||||||
|
</template>
|
||||||
|
<Card
|
||||||
|
class="group relative w-full hover:border-[#1890ff]"
|
||||||
|
v-for="(equation, cIdx) in condition.conditionGroups.conditions"
|
||||||
|
:key="cIdx"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="absolute left-0 top-0 z-[1] flex cursor-pointer opacity-0 group-hover:opacity-100"
|
||||||
|
v-if="condition.conditionGroups.conditions.length > 1"
|
||||||
|
>
|
||||||
|
<IconifyIcon
|
||||||
|
color="#0089ff"
|
||||||
|
icon="ep:circle-close-filled"
|
||||||
|
class="size-4"
|
||||||
|
@click="
|
||||||
|
deleteConditionGroup(condition.conditionGroups.conditions, cIdx)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<template #extra>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div>条件组</div>
|
||||||
|
<div class="flex">
|
||||||
|
<div class="mr-4">规则关系</div>
|
||||||
|
<Switch
|
||||||
|
v-model:checked="equation.and"
|
||||||
|
checked-children="且"
|
||||||
|
un-checked-children="或"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<Row
|
||||||
|
:gutter="8"
|
||||||
|
class="mb-2"
|
||||||
|
v-for="(rule, rIdx) in equation.rules"
|
||||||
|
:key="rIdx"
|
||||||
|
>
|
||||||
|
<Col :span="8">
|
||||||
|
<FormItem
|
||||||
|
:name="[
|
||||||
|
'conditionGroups',
|
||||||
|
'conditions',
|
||||||
|
cIdx,
|
||||||
|
'rules',
|
||||||
|
rIdx,
|
||||||
|
'leftSide',
|
||||||
|
]"
|
||||||
|
:rules="{
|
||||||
|
required: true,
|
||||||
|
message: '左值不能为空',
|
||||||
|
trigger: 'change',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
v-model:value="rule.leftSide"
|
||||||
|
allow-clear
|
||||||
|
placeholder="请选择表单字段"
|
||||||
|
>
|
||||||
|
<SelectOption
|
||||||
|
v-for="(field, fIdx) in fieldOptions"
|
||||||
|
:key="fIdx"
|
||||||
|
:label="field.title"
|
||||||
|
:value="field.field"
|
||||||
|
:disabled="!field.required"
|
||||||
|
>
|
||||||
|
<Tooltip
|
||||||
|
title="表单字段非必填时不能作为流程分支条件"
|
||||||
|
placement="right"
|
||||||
|
v-if="!field.required"
|
||||||
|
>
|
||||||
|
<span>{{ field.title }}</span>
|
||||||
|
</Tooltip>
|
||||||
|
<template v-else>{{ field.title }}</template>
|
||||||
|
</SelectOption>
|
||||||
|
</Select>
|
||||||
|
</FormItem>
|
||||||
|
</Col>
|
||||||
|
<Col :span="6">
|
||||||
|
<Select v-model:value="rule.opCode" placeholder="请选择操作符">
|
||||||
|
<SelectOption
|
||||||
|
v-for="operator in COMPARISON_OPERATORS"
|
||||||
|
:key="operator.value"
|
||||||
|
:label="operator.label"
|
||||||
|
:value="operator.value"
|
||||||
|
>
|
||||||
|
{{ operator.label }}
|
||||||
|
</SelectOption>
|
||||||
|
</Select>
|
||||||
|
</Col>
|
||||||
|
<Col :span="7">
|
||||||
|
<FormItem
|
||||||
|
:name="[
|
||||||
|
'conditionGroups',
|
||||||
|
'conditions',
|
||||||
|
cIdx,
|
||||||
|
'rules',
|
||||||
|
rIdx,
|
||||||
|
'rightSide',
|
||||||
|
]"
|
||||||
|
:rules="{
|
||||||
|
required: true,
|
||||||
|
message: '右值不能为空',
|
||||||
|
trigger: ['blur', 'change'],
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
v-model:value="rule.rightSide"
|
||||||
|
placeholder="请输入右值"
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
</Col>
|
||||||
|
<Col :span="3">
|
||||||
|
<div class="flex h-[32px] items-center">
|
||||||
|
<Trash2
|
||||||
|
v-if="equation.rules.length > 1"
|
||||||
|
class="mr-2 size-4 cursor-pointer text-red-500"
|
||||||
|
@click="deleteConditionRule(equation, rIdx)"
|
||||||
|
/>
|
||||||
|
<Plus
|
||||||
|
class="size-4 cursor-pointer text-blue-500"
|
||||||
|
@click="addConditionRule(equation, rIdx)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Card>
|
||||||
|
</Space>
|
||||||
|
<div title="添加条件组" class="mt-4 cursor-pointer">
|
||||||
|
<Plus
|
||||||
|
class="size-[24px] text-blue-500"
|
||||||
|
@click="addConditionGroup(condition.conditionGroups?.conditions)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem
|
||||||
|
v-if="condition.conditionType === ConditionType.EXPRESSION"
|
||||||
|
label="条件表达式"
|
||||||
|
name="conditionExpression"
|
||||||
|
>
|
||||||
|
<Textarea
|
||||||
|
v-model:value="condition.conditionExpression"
|
||||||
|
placeholder="请输入条件表达式"
|
||||||
|
allow-clear
|
||||||
|
:auto-size="{ minRows: 3, maxRows: 6 }"
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
|
</template>
|
|
@ -38,10 +38,11 @@ import {
|
||||||
import {
|
import {
|
||||||
getConditionShowText,
|
getConditionShowText,
|
||||||
useFormFields,
|
useFormFields,
|
||||||
|
useFormFieldsAndStartUser,
|
||||||
useNodeName,
|
useNodeName,
|
||||||
useWatchNode,
|
useWatchNode,
|
||||||
} from '../../helpers';
|
} from '../../helpers';
|
||||||
// TODO import ConditionDialog from './modules/condition-dialog.vue';
|
import ConditionDialog from './modules/condition-dialog.vue';
|
||||||
import HttpRequestSetting from './modules/http-request-setting.vue';
|
import HttpRequestSetting from './modules/http-request-setting.vue';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
|
@ -215,8 +216,7 @@ const openFormSettingCondition = (
|
||||||
conditionDialog.open(formSetting);
|
conditionDialog.open(formSetting);
|
||||||
};
|
};
|
||||||
/** 处理条件配置保存 */
|
/** 处理条件配置保存 */
|
||||||
/* 暂时注释掉未使用的函数
|
const handleConditionUpdate = (index: number, condition: any) => {
|
||||||
const _handleConditionUpdate = (index: number, condition: any) => {
|
|
||||||
if (configForm.value.formSettings![index]) {
|
if (configForm.value.formSettings![index]) {
|
||||||
configForm.value.formSettings![index].conditionType =
|
configForm.value.formSettings![index].conditionType =
|
||||||
condition.conditionType;
|
condition.conditionType;
|
||||||
|
@ -226,14 +226,15 @@ const _handleConditionUpdate = (index: number, condition: any) => {
|
||||||
condition.conditionGroups;
|
condition.conditionGroups;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
*/
|
// 包含发起人字段的表单字段
|
||||||
|
const includeStartUserFormFields = useFormFieldsAndStartUser();
|
||||||
/** 条件配置展示 */
|
/** 条件配置展示 */
|
||||||
const showConditionText = (formSetting: FormTriggerSetting) => {
|
const showConditionText = (formSetting: FormTriggerSetting) => {
|
||||||
return getConditionShowText(
|
return getConditionShowText(
|
||||||
formSetting.conditionType,
|
formSetting.conditionType,
|
||||||
formSetting.conditionExpression,
|
formSetting.conditionExpression,
|
||||||
formSetting.conditionGroups,
|
formSetting.conditionGroups,
|
||||||
formFields,
|
includeStartUserFormFields,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -457,17 +458,17 @@ onMounted(() => {
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- TODO 条件设置 -->
|
<ConditionDialog
|
||||||
<!-- <ConditionDialog
|
|
||||||
:ref="`condition-${index}`"
|
:ref="`condition-${index}`"
|
||||||
@update-condition="(val) => handleConditionUpdate(index, val)"
|
@update-condition="(val) => handleConditionUpdate(index, val)"
|
||||||
/> -->
|
/>
|
||||||
<Row>
|
<Row>
|
||||||
<Col :span="24">
|
<Col :span="24">
|
||||||
<div class="cursor-pointer" v-if="formSetting.conditionType">
|
<div class="cursor-pointer" v-if="formSetting.conditionType">
|
||||||
<Tag
|
<Tag
|
||||||
color="success"
|
color="success"
|
||||||
closable
|
closable
|
||||||
|
class="text-sm"
|
||||||
@close="deleteFormSettingCondition(formSetting)"
|
@close="deleteFormSettingCondition(formSetting)"
|
||||||
@click="openFormSettingCondition(index, formSetting)"
|
@click="openFormSettingCondition(index, formSetting)"
|
||||||
>
|
>
|
||||||
|
@ -605,17 +606,18 @@ onMounted(() => {
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- TODO 条件设置 -->
|
<!-- 条件设置 -->
|
||||||
<!-- <ConditionDialog
|
<ConditionDialog
|
||||||
:ref="`condition-${index}`"
|
:ref="`condition-${index}`"
|
||||||
@update-condition="(val) => handleConditionUpdate(index, val)"
|
@update-condition="(val) => handleConditionUpdate(index, val)"
|
||||||
/> -->
|
/>
|
||||||
<Row>
|
<Row>
|
||||||
<Col :span="24">
|
<Col :span="24">
|
||||||
<div class="cursor-pointer" v-if="formSetting.conditionType">
|
<div class="cursor-pointer" v-if="formSetting.conditionType">
|
||||||
<Tag
|
<Tag
|
||||||
color="warning"
|
color="success"
|
||||||
closable
|
closable
|
||||||
|
class="text-sm"
|
||||||
@close="deleteFormSettingCondition(formSetting)"
|
@close="deleteFormSettingCondition(formSetting)"
|
||||||
@click="openFormSettingCondition(index, formSetting)"
|
@click="openFormSettingCondition(index, formSetting)"
|
||||||
>
|
>
|
||||||
|
|
|
@ -475,9 +475,9 @@ export type ListenerHandler = {
|
||||||
* 条件规则结构定义
|
* 条件规则结构定义
|
||||||
*/
|
*/
|
||||||
export type ConditionRule = {
|
export type ConditionRule = {
|
||||||
leftSide: string;
|
leftSide: string | undefined;
|
||||||
opCode: string;
|
opCode: string;
|
||||||
rightSide: string;
|
rightSide: string | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -725,7 +725,7 @@ export const DEFAULT_CONDITION_GROUP_VALUE = {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
opCode: '==',
|
opCode: '==',
|
||||||
leftSide: '',
|
leftSide: undefined,
|
||||||
rightSide: '',
|
rightSide: '',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in New Issue