feat: 更换使用条件组件
parent
099b81cb2d
commit
53e6d6aa61
|
@ -510,8 +510,8 @@ export const APPROVE_METHODS: DictDataVO[] = [
|
||||||
]
|
]
|
||||||
|
|
||||||
export const CONDITION_CONFIG_TYPES: DictDataVO[] = [
|
export const CONDITION_CONFIG_TYPES: DictDataVO[] = [
|
||||||
{ label: '条件表达式', value: ConditionType.EXPRESSION },
|
{ label: '条件规则', value: ConditionType.RULE },
|
||||||
{ label: '条件规则', value: ConditionType.RULE }
|
{ label: '条件表达式', value: ConditionType.EXPRESSION }
|
||||||
]
|
]
|
||||||
|
|
||||||
// 时间单位类型
|
// 时间单位类型
|
||||||
|
|
|
@ -42,123 +42,7 @@
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-form-item label="配置方式" prop="conditionType">
|
<Condition v-model="routeGroups[index]" />
|
||||||
<el-radio-group v-model="item.conditionType" @change="changeConditionType">
|
|
||||||
<el-radio
|
|
||||||
v-for="(dict, indexConditionType) in conditionConfigTypes"
|
|
||||||
:key="indexConditionType"
|
|
||||||
:value="dict.value"
|
|
||||||
:label="dict.value"
|
|
||||||
>
|
|
||||||
{{ dict.label }}
|
|
||||||
</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
<!-- TODO @lesan:1)1、2 使用枚举;2)默认先 条件组关系,再 条件表达式;3)这种可以封装成一个小组件么? -->
|
|
||||||
<el-form-item
|
|
||||||
v-if="item.conditionType === 1"
|
|
||||||
label="条件表达式"
|
|
||||||
prop="conditionExpression"
|
|
||||||
>
|
|
||||||
<el-input
|
|
||||||
type="textarea"
|
|
||||||
v-model="item.conditionExpression"
|
|
||||||
clearable
|
|
||||||
style="width: 100%"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item v-if="item.conditionType === 2" label="条件规则">
|
|
||||||
<div class="condition-group-tool">
|
|
||||||
<div class="flex items-center">
|
|
||||||
<div class="mr-4">条件组关系</div>
|
|
||||||
<el-switch
|
|
||||||
v-model="item.conditionGroups.and"
|
|
||||||
inline-prompt
|
|
||||||
active-text="且"
|
|
||||||
inactive-text="或"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-space direction="vertical" :spacer="item.conditionGroups.and ? '且' : '或'">
|
|
||||||
<el-card
|
|
||||||
class="condition-group"
|
|
||||||
style="width: 530px"
|
|
||||||
v-for="(condition, cIdx) in item.conditionGroups.conditions"
|
|
||||||
:key="cIdx"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="condition-group-delete"
|
|
||||||
v-if="item.conditionGroups.conditions.length > 1"
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
color="#0089ff"
|
|
||||||
icon="ep:circle-close-filled"
|
|
||||||
:size="18"
|
|
||||||
@click="deleteConditionGroup(item.conditionGroups.conditions, cIdx)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<template #header>
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<div>条件组</div>
|
|
||||||
<div class="flex">
|
|
||||||
<div class="mr-4">规则关系</div>
|
|
||||||
<el-switch
|
|
||||||
v-model="condition.and"
|
|
||||||
inline-prompt
|
|
||||||
active-text="且"
|
|
||||||
inactive-text="或"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<div class="flex pt-2" v-for="(rule, rIdx) in condition.rules" :key="rIdx">
|
|
||||||
<div class="mr-2">
|
|
||||||
<el-select style="width: 160px" v-model="rule.leftSide">
|
|
||||||
<el-option
|
|
||||||
v-for="(field, fIdx) in fieldOptions"
|
|
||||||
:key="fIdx"
|
|
||||||
:label="field.title"
|
|
||||||
:value="field.field"
|
|
||||||
:disabled="!field.required"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
<div class="mr-2">
|
|
||||||
<el-select v-model="rule.opCode" style="width: 100px">
|
|
||||||
<el-option
|
|
||||||
v-for="operator in COMPARISON_OPERATORS"
|
|
||||||
:key="operator.value"
|
|
||||||
:label="operator.label"
|
|
||||||
:value="operator.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
<div class="mr-2">
|
|
||||||
<el-input v-model="rule.rightSide" style="width: 160px" />
|
|
||||||
</div>
|
|
||||||
<div class="mr-1 flex items-center" v-if="condition.rules.length > 1">
|
|
||||||
<Icon
|
|
||||||
icon="ep:delete"
|
|
||||||
:size="18"
|
|
||||||
@click="deleteConditionRule(condition, rIdx)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<Icon icon="ep:plus" :size="18" @click="addConditionRule(condition, rIdx)" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
</el-space>
|
|
||||||
<div title="添加条件组" class="mt-4 cursor-pointer">
|
|
||||||
<Icon
|
|
||||||
color="#0089ff"
|
|
||||||
icon="ep:plus"
|
|
||||||
:size="24"
|
|
||||||
@click="addConditionGroup(item.conditionGroups.conditions)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
|
@ -177,18 +61,9 @@
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Plus } from '@element-plus/icons-vue'
|
import { Plus } from '@element-plus/icons-vue'
|
||||||
import {
|
import { SimpleFlowNode, NodeType, ConditionType, RouteCondition } from '../consts'
|
||||||
SimpleFlowNode,
|
|
||||||
NodeType,
|
|
||||||
CONDITION_CONFIG_TYPES,
|
|
||||||
ConditionType,
|
|
||||||
COMPARISON_OPERATORS,
|
|
||||||
RouteCondition,
|
|
||||||
ProcessVariableEnum
|
|
||||||
} from '../consts'
|
|
||||||
import { useWatchNode, useDrawer, useNodeName } from '../node'
|
import { useWatchNode, useDrawer, useNodeName } from '../node'
|
||||||
import { BpmModelFormType } from '@/utils/constants'
|
import Condition from './components/Condition.vue'
|
||||||
import { useFormFields } from '../node'
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'RouteNodeConfig'
|
name: 'RouteNodeConfig'
|
||||||
})
|
})
|
||||||
|
@ -206,28 +81,6 @@ const { settingVisible, closeDrawer, openDrawer } = useDrawer()
|
||||||
const currentNode = useWatchNode(props)
|
const currentNode = useWatchNode(props)
|
||||||
// 节点名称
|
// 节点名称
|
||||||
const { nodeName, showInput, clickIcon, blurEvent } = useNodeName(NodeType.ROUTE_BRANCH_NODE)
|
const { nodeName, showInput, clickIcon, blurEvent } = useNodeName(NodeType.ROUTE_BRANCH_NODE)
|
||||||
const formType = inject<Ref<number>>('formType') // 表单类型
|
|
||||||
const conditionConfigTypes = computed(() => {
|
|
||||||
return CONDITION_CONFIG_TYPES.filter((item) => {
|
|
||||||
// 业务表单暂时去掉条件规则选项
|
|
||||||
if (formType?.value === BpmModelFormType.CUSTOM && item.value === ConditionType.RULE) {
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
/** 条件规则可选择的表单字段 */
|
|
||||||
const fieldOptions = computed(() => {
|
|
||||||
const fieldsCopy = useFormFields().slice()
|
|
||||||
// 固定添加发起人 ID 字段
|
|
||||||
fieldsCopy.unshift({
|
|
||||||
field: ProcessVariableEnum.START_USER_ID,
|
|
||||||
title: '发起人',
|
|
||||||
required: true
|
|
||||||
})
|
|
||||||
return fieldsCopy
|
|
||||||
})
|
|
||||||
const routeGroups = ref<RouteCondition[]>([])
|
const routeGroups = ref<RouteCondition[]>([])
|
||||||
const nodeOptions = ref()
|
const nodeOptions = ref()
|
||||||
|
|
||||||
|
@ -279,48 +132,10 @@ const getShowText = () => {
|
||||||
return `${routeGroups.value.length}条路由分支`
|
return `${routeGroups.value.length}条路由分支`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @lesan:这个需要实现么?
|
|
||||||
const changeConditionType = () => {}
|
|
||||||
|
|
||||||
const deleteConditionGroup = (conditions, index) => {
|
|
||||||
conditions.splice(index, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
const deleteConditionRule = (condition, index) => {
|
|
||||||
condition.rules.splice(index, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
const addConditionRule = (condition, index) => {
|
|
||||||
const rule = {
|
|
||||||
type: 1,
|
|
||||||
opName: '等于',
|
|
||||||
opCode: '==',
|
|
||||||
leftSide: '',
|
|
||||||
rightSide: ''
|
|
||||||
}
|
|
||||||
condition.rules.splice(index + 1, 0, rule)
|
|
||||||
}
|
|
||||||
|
|
||||||
const addConditionGroup = (conditions) => {
|
|
||||||
const condition = {
|
|
||||||
and: true,
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
type: 1,
|
|
||||||
opName: '等于',
|
|
||||||
opCode: '==',
|
|
||||||
leftSide: '',
|
|
||||||
rightSide: ''
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
conditions.push(condition)
|
|
||||||
}
|
|
||||||
|
|
||||||
const addRouteGroup = () => {
|
const addRouteGroup = () => {
|
||||||
routeGroups.value.push({
|
routeGroups.value.push({
|
||||||
nodeId: '',
|
nodeId: '',
|
||||||
conditionType: ConditionType.EXPRESSION,
|
conditionType: ConditionType.RULE,
|
||||||
conditionExpression: '',
|
conditionExpression: '',
|
||||||
conditionGroups: {
|
conditionGroups: {
|
||||||
and: true,
|
and: true,
|
||||||
|
@ -347,7 +162,7 @@ const deleteRouteGroup = (index) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const getRoutableNode = () => {
|
const getRoutableNode = () => {
|
||||||
// TODO 还需要满足以下要求
|
// TODO @lesan 还需要满足以下要求
|
||||||
// 并行分支、包容分支内部节点不能跳转到外部节点
|
// 并行分支、包容分支内部节点不能跳转到外部节点
|
||||||
// 条件分支节点可以向上跳转到外部节点
|
// 条件分支节点可以向上跳转到外部节点
|
||||||
let node = processNodeTree?.value
|
let node = processNodeTree?.value
|
||||||
|
@ -369,39 +184,3 @@ const getRoutableNode = () => {
|
||||||
|
|
||||||
defineExpose({ openDrawer, showRouteNodeConfig }) // 暴露方法给父组件
|
defineExpose({ openDrawer, showRouteNodeConfig }) // 暴露方法给父组件
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.condition-group-tool {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
width: 500px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.condition-group {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-color: #0089ff;
|
|
||||||
|
|
||||||
.condition-group-delete {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.condition-group-delete {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
display: flex;
|
|
||||||
cursor: pointer;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
::v-deep(.el-card__header) {
|
|
||||||
padding: 8px var(--el-card-padding);
|
|
||||||
border-bottom: 1px solid var(--el-card-border-color);
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -0,0 +1,242 @@
|
||||||
|
<template>
|
||||||
|
<el-form ref="formRef" :model="condition" :rules="formRules" label-position="top">
|
||||||
|
<el-form-item label="配置方式" prop="conditionType">
|
||||||
|
<el-radio-group v-model="condition.conditionType">
|
||||||
|
<el-radio
|
||||||
|
v-for="(dict, indexConditionType) in conditionConfigTypes"
|
||||||
|
:key="indexConditionType"
|
||||||
|
:value="dict.value"
|
||||||
|
:label="dict.value"
|
||||||
|
>
|
||||||
|
{{ dict.label }}
|
||||||
|
</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
v-if="condition.conditionType === ConditionType.EXPRESSION"
|
||||||
|
label="条件表达式"
|
||||||
|
prop="conditionExpression"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
type="textarea"
|
||||||
|
v-model="condition.conditionExpression"
|
||||||
|
clearable
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-if="condition.conditionType === ConditionType.RULE" label="条件规则">
|
||||||
|
<div class="condition-group-tool">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="mr-4">条件组关系</div>
|
||||||
|
<el-switch
|
||||||
|
v-model="condition.conditionGroups.and"
|
||||||
|
inline-prompt
|
||||||
|
active-text="且"
|
||||||
|
inactive-text="或"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-space direction="vertical" :spacer="condition.conditionGroups.and ? '且' : '或'">
|
||||||
|
<el-card
|
||||||
|
class="condition-group"
|
||||||
|
style="width: 530px"
|
||||||
|
v-for="(equation, cIdx) in condition.conditionGroups.conditions"
|
||||||
|
:key="cIdx"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="condition-group-delete"
|
||||||
|
v-if="condition.conditionGroups.conditions.length > 1"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
color="#0089ff"
|
||||||
|
icon="ep:circle-close-filled"
|
||||||
|
:size="18"
|
||||||
|
@click="deleteConditionGroup(condition.conditionGroups.conditions, cIdx)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<template #header>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div>条件组</div>
|
||||||
|
<div class="flex">
|
||||||
|
<div class="mr-4">规则关系</div>
|
||||||
|
<el-switch
|
||||||
|
v-model="equation.and"
|
||||||
|
inline-prompt
|
||||||
|
active-text="且"
|
||||||
|
inactive-text="或"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div class="flex pt-2" v-for="(rule, rIdx) in equation.rules" :key="rIdx">
|
||||||
|
<div class="mr-2">
|
||||||
|
<el-select style="width: 160px" v-model="rule.leftSide">
|
||||||
|
<el-option
|
||||||
|
v-for="(field, fIdx) in fieldOptions"
|
||||||
|
:key="fIdx"
|
||||||
|
:label="field.title"
|
||||||
|
:value="field.field"
|
||||||
|
:disabled="!field.required"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="mr-2">
|
||||||
|
<el-select v-model="rule.opCode" style="width: 100px">
|
||||||
|
<el-option
|
||||||
|
v-for="operator in COMPARISON_OPERATORS"
|
||||||
|
:key="operator.value"
|
||||||
|
:label="operator.label"
|
||||||
|
:value="operator.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="mr-2">
|
||||||
|
<el-input v-model="rule.rightSide" style="width: 160px" />
|
||||||
|
</div>
|
||||||
|
<div class="mr-1 flex items-center" v-if="equation.rules.length > 1">
|
||||||
|
<Icon icon="ep:delete" :size="18" @click="deleteConditionRule(equation, rIdx)" />
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<Icon icon="ep:plus" :size="18" @click="addConditionRule(equation, rIdx)" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-space>
|
||||||
|
<div title="添加条件组" class="mt-4 cursor-pointer">
|
||||||
|
<Icon
|
||||||
|
color="#0089ff"
|
||||||
|
icon="ep:plus"
|
||||||
|
:size="24"
|
||||||
|
@click="addConditionGroup(condition.conditionGroups.conditions)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
CONDITION_CONFIG_TYPES,
|
||||||
|
COMPARISON_OPERATORS,
|
||||||
|
ConditionType,
|
||||||
|
ProcessVariableEnum
|
||||||
|
} from '../../consts'
|
||||||
|
import { BpmModelFormType } from '@/utils/constants'
|
||||||
|
import { useFormFields } from '../../node'
|
||||||
|
|
||||||
|
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) => {
|
||||||
|
// 业务表单暂时去掉条件规则选项
|
||||||
|
if (formType?.value === BpmModelFormType.CUSTOM && item.value === ConditionType.RULE) {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
/** 条件规则可选择的表单字段 */
|
||||||
|
const fieldOptions = computed(() => {
|
||||||
|
const fieldsCopy = useFormFields().slice()
|
||||||
|
// 固定添加发起人 ID 字段
|
||||||
|
fieldsCopy.unshift({
|
||||||
|
field: ProcessVariableEnum.START_USER_ID,
|
||||||
|
title: '发起人',
|
||||||
|
required: true
|
||||||
|
})
|
||||||
|
return fieldsCopy
|
||||||
|
})
|
||||||
|
// 表单校验规则
|
||||||
|
const formRules = reactive({
|
||||||
|
conditionType: [{ required: true, message: '配置方式不能为空', trigger: 'blur' }],
|
||||||
|
conditionExpression: [{ required: true, message: '条件表达式不能为空', trigger: 'blur' }]
|
||||||
|
})
|
||||||
|
const formRef = ref() // 表单 Ref
|
||||||
|
|
||||||
|
const deleteConditionGroup = (conditions, index) => {
|
||||||
|
conditions.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteConditionRule = (condition, index) => {
|
||||||
|
condition.rules.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const addConditionRule = (condition, index) => {
|
||||||
|
const rule = {
|
||||||
|
type: 1,
|
||||||
|
opName: '等于',
|
||||||
|
opCode: '==',
|
||||||
|
leftSide: '',
|
||||||
|
rightSide: ''
|
||||||
|
}
|
||||||
|
condition.rules.splice(index + 1, 0, rule)
|
||||||
|
}
|
||||||
|
|
||||||
|
const addConditionGroup = (conditions) => {
|
||||||
|
const condition = {
|
||||||
|
and: true,
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
type: 1,
|
||||||
|
opName: '等于',
|
||||||
|
opCode: '==',
|
||||||
|
leftSide: '',
|
||||||
|
rightSide: ''
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
conditions.push(condition)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.condition-group-tool {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 500px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.condition-group {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #0089ff;
|
||||||
|
|
||||||
|
.condition-group-delete {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.condition-group-delete {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep(.el-card__header) {
|
||||||
|
padding: 8px var(--el-card-padding);
|
||||||
|
border-bottom: 1px solid var(--el-card-border-color);
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue