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 {
|
||||
getConditionShowText,
|
||||
useFormFields,
|
||||
useFormFieldsAndStartUser,
|
||||
useNodeName,
|
||||
useWatchNode,
|
||||
} 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';
|
||||
|
||||
defineOptions({
|
||||
|
@ -215,8 +216,7 @@ const openFormSettingCondition = (
|
|||
conditionDialog.open(formSetting);
|
||||
};
|
||||
/** 处理条件配置保存 */
|
||||
/* 暂时注释掉未使用的函数
|
||||
const _handleConditionUpdate = (index: number, condition: any) => {
|
||||
const handleConditionUpdate = (index: number, condition: any) => {
|
||||
if (configForm.value.formSettings![index]) {
|
||||
configForm.value.formSettings![index].conditionType =
|
||||
condition.conditionType;
|
||||
|
@ -226,14 +226,15 @@ const _handleConditionUpdate = (index: number, condition: any) => {
|
|||
condition.conditionGroups;
|
||||
}
|
||||
};
|
||||
*/
|
||||
// 包含发起人字段的表单字段
|
||||
const includeStartUserFormFields = useFormFieldsAndStartUser();
|
||||
/** 条件配置展示 */
|
||||
const showConditionText = (formSetting: FormTriggerSetting) => {
|
||||
return getConditionShowText(
|
||||
formSetting.conditionType,
|
||||
formSetting.conditionExpression,
|
||||
formSetting.conditionGroups,
|
||||
formFields,
|
||||
includeStartUserFormFields,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -457,17 +458,17 @@ onMounted(() => {
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<!-- TODO 条件设置 -->
|
||||
<!-- <ConditionDialog
|
||||
<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
|
||||
class="text-sm"
|
||||
@close="deleteFormSettingCondition(formSetting)"
|
||||
@click="openFormSettingCondition(index, formSetting)"
|
||||
>
|
||||
|
@ -605,17 +606,18 @@ onMounted(() => {
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<!-- TODO 条件设置 -->
|
||||
<!-- <ConditionDialog
|
||||
<!-- 条件设置 -->
|
||||
<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"
|
||||
color="success"
|
||||
closable
|
||||
class="text-sm"
|
||||
@close="deleteFormSettingCondition(formSetting)"
|
||||
@click="openFormSettingCondition(index, formSetting)"
|
||||
>
|
||||
|
|
|
@ -475,9 +475,9 @@ export type ListenerHandler = {
|
|||
* 条件规则结构定义
|
||||
*/
|
||||
export type ConditionRule = {
|
||||
leftSide: string;
|
||||
leftSide: string | undefined;
|
||||
opCode: string;
|
||||
rightSide: string;
|
||||
rightSide: string | undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -725,7 +725,7 @@ export const DEFAULT_CONDITION_GROUP_VALUE = {
|
|||
rules: [
|
||||
{
|
||||
opCode: '==',
|
||||
leftSide: '',
|
||||
leftSide: undefined,
|
||||
rightSide: '',
|
||||
},
|
||||
],
|
||||
|
|
Loading…
Reference in New Issue