323 lines
11 KiB
Vue
323 lines
11 KiB
Vue
<template>
|
||
<div v-for="(group, index) in selectedNode.props.groups" :key="index + '_g'" class="group">
|
||
<div class="group-header">
|
||
<span class="group-name">条件组 {{ groupNames[index] }}</span>
|
||
<div class="group-cp">
|
||
<span>组内条件关系:</span>
|
||
<el-switch v-model="group.groupType" active-color="#409EFF"
|
||
inactive-color="#c1c1c1" active-value="AND" inactive-value="OR"
|
||
active-text="且" inactive-text="或"/>
|
||
</div>
|
||
|
||
<div class="group-operation">
|
||
<el-popover placement="bottom" title="选择审批条件" width="300" trigger="click">
|
||
<template #reference>
|
||
<el-icon :size="18" class="group-icon">
|
||
<Plus/>
|
||
</el-icon>
|
||
</template>
|
||
<div>以下条件将决定具体的审批流程</div>
|
||
<el-checkbox-group v-model="group.cids" value-key="id">
|
||
<el-checkbox :label="condition.id" v-for="(condition, cindex) in conditionList" :key="condition.id"
|
||
@change="conditionChange(cindex, group)">
|
||
{{ condition.title }}
|
||
</el-checkbox>
|
||
</el-checkbox-group>
|
||
</el-popover>
|
||
<el-icon :size="18" class="group-icon" @click="delGroup(index)">
|
||
<Close/>
|
||
</el-icon>
|
||
</div>
|
||
</div>
|
||
<div class="group-content">
|
||
<p v-if="group.conditions.length === 0">点击右上角 + 为本条件组添加条件</p>
|
||
<div v-else>
|
||
<el-form ref="condition-form">
|
||
<!--构建表达式-->
|
||
<el-form-item v-for="(condition, cindex) in group.conditions" :key="condition.id + '_' + cindex">
|
||
<ellipsis slot="label" hover-tip :content="condition.title"/>
|
||
<span v-if="condition.valueType === ValueType.string">
|
||
<el-select placeholder="判断符" style="width: 120px;" v-model="condition.compare"
|
||
@change="condition.value = []" filterable>
|
||
<el-option label="等于" value="="></el-option>
|
||
<el-option label="包含在" value="IN"></el-option>
|
||
</el-select>
|
||
<span v-if="isSelect(condition.id)" style="margin-left: 10px">
|
||
<el-select v-if="condition.compare === 'IN'" style="width: 280px;" clearable multiple size="small"
|
||
v-model="condition.value" placeholder="选择值" filterable>
|
||
<el-option v-for="(option, oi) in getOptions(condition.id)" :key="oi" :label="option"
|
||
:value="option"></el-option>
|
||
</el-select>
|
||
<el-select v-else style="width: 280px;" clearable size="small" v-model="condition.value[0]"
|
||
placeholder="选择值" filterable>
|
||
<el-option v-for="(option, oi) in getOptions(condition.id)" :key="oi" :label="option"
|
||
:value="option"></el-option>
|
||
</el-select>
|
||
</span>
|
||
<span v-else style="margin-left: 10px">
|
||
<el-input v-if="condition.compare === '='" style="width: 280px;" placeholder="输入比较值"
|
||
v-model="condition.value[0]"/>
|
||
<el-select v-else style="width: 280px;" multiple clearable filterable allow-create size="small"
|
||
v-model="condition.value" placeholder="输入可能包含的值"></el-select>
|
||
</span>
|
||
</span>
|
||
<span v-else-if="condition.valueType === ValueType.number">
|
||
<el-select size="small" placeholder="判断符" style="width: 120px;" v-model="condition.compare" filterable>
|
||
<el-option :label="exp.label" :value="exp.value" :key="exp.value" v-for="exp in explains"></el-option>
|
||
</el-select>
|
||
<span style="margin-left: 10px">
|
||
<el-input style="width: 280px;" v-if="conditionValType(condition.compare) === 0"
|
||
placeholder="输入比较值" type="number" v-model="condition.value[0]"/>
|
||
<el-select style="width: 280px;" multiple filterable allow-create
|
||
v-else-if="conditionValType(condition.compare) === 1"
|
||
v-model="condition.value" placeholder="输入可能包含的值"></el-select>
|
||
<span v-else>
|
||
<el-input style="width: 130px;" type="number" placeholder="输入比较值"
|
||
v-model="condition.value[0]"/>
|
||
<span> ~
|
||
<el-input style="width: 130px;" type="number" placeholder="输入比较值"
|
||
v-model="condition.value[1]"/>
|
||
</span>
|
||
</span>
|
||
</span>
|
||
</span>
|
||
<span v-else-if="condition.valueType === ValueType.user">
|
||
<span class="item-desc" style="margin-right: 20px">属于某部门 / 为某些人其中之一</span>
|
||
<el-button size="mini" :icon="Plus" type="primary" @click="selectUser(condition.value, 'user')"
|
||
round>选择人员/部门</el-button>
|
||
<org-items :modelValue="users"/>
|
||
</span>
|
||
<span v-else-if="condition.valueType === ValueType.dept">
|
||
<span class="item-desc" style="margin-right: 20px">为某部门 / 某部门下的部门</span>
|
||
<el-button size="mini" :icon="Plus" type="primary" @click="selectUser(condition.value, 'dept')"
|
||
round>选择部门</el-button>
|
||
<org-items :modelValue="users"/>
|
||
</span>
|
||
<span v-else-if="condition.valueType === ValueType.date"></span>
|
||
<el-icon class="delete-icon" @click="delSubCondition(group, cindex)">
|
||
<Minus/>
|
||
</el-icon>
|
||
</el-form-item>
|
||
</el-form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<org-picker title="请选择人员/部门" multiple ref="orgPicker" :v-model="users" @ok="selected"></org-picker>
|
||
</template>
|
||
|
||
<script setup>
|
||
import OrgPicker from "../common/UserPicker.vue";
|
||
import OrgItems from "../common/RoleItems.vue";
|
||
import {ValueType} from '@/views/workflow/form/ComponentsConfigExport.js'
|
||
import {computed, ref} from 'vue'
|
||
import {useProcessStore} from '@/stores/processStore.js'
|
||
import Ellipsis from '../common/Ellipsis.vue'
|
||
import {Plus, Minus} from '@element-plus/icons-vue'
|
||
|
||
const processStore = useProcessStore()
|
||
|
||
const orgPicker = ref()
|
||
const users = ref([])
|
||
// const orgType = ref('user')
|
||
const showOrgSelect = ref(false)
|
||
const groupNames = ref(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'])
|
||
const supportTypes = ref([ValueType.number, ValueType.string])
|
||
const explains = ref(
|
||
[
|
||
{label: '等于', value: '='},
|
||
{label: '大于', value: '>'},
|
||
{label: '大于等于', value: '>='},
|
||
{label: '小于', value: '<'},
|
||
{label: '小于等于', value: '<='},
|
||
{label: '包含在', value: 'IN'},
|
||
{label: 'x < 值 < x', value: 'B'},
|
||
{label: 'x ≤ 值 < x', value: 'AB'},
|
||
{label: 'x < 值 ≤ x', value: 'BA'},
|
||
{label: 'x ≤ 值 ≤ x', value: 'ABA'},
|
||
]
|
||
)
|
||
|
||
const selectedNode = computed(() => {
|
||
//当前选择的节点
|
||
return processStore.getSelectedNode()
|
||
})
|
||
|
||
const processFromPerms = computed(() => {
|
||
return processStore.getDesign().processFromPerms;
|
||
});
|
||
|
||
const conditionList = computed(() => {
|
||
//条件数组
|
||
//构造可用条件选项
|
||
const conditionItems = []
|
||
filterConditionMosr(conditionItems)
|
||
// processStore.getDesign().formItems.forEach(item => filterCondition(item, conditionItems))
|
||
// if (conditionItems.length === 0 || conditionItems[0].id !== 'root') {
|
||
// conditionItems.unshift({id: 'root', title: '发起人', valueType: 'User'})
|
||
// }
|
||
// conditionItems.unshift({id: 'root', title: '发起人', valueType: 'User'})
|
||
return conditionItems
|
||
})
|
||
|
||
const isSelect = (processDefinitionKey) => {
|
||
//判断是否被选择
|
||
let form = processStore.getFormMap().get(processDefinitionKey)
|
||
return (form && (form.name === 'SelectInput' || form.name === 'MultipleSelect'))
|
||
}
|
||
|
||
const getOptions = (processDefinitionKey) => {
|
||
//获取到对应的option选项
|
||
return processStore.getFormMap().get(processDefinitionKey).props.options || []
|
||
}
|
||
|
||
const conditionValType = (type) => {
|
||
//条件类型选择
|
||
switch (type) {
|
||
case '=':
|
||
case '>':
|
||
case '>=':
|
||
case '<':
|
||
case '<=':
|
||
return 0;
|
||
case 'IN':
|
||
return 1;
|
||
default:
|
||
return 2;
|
||
}
|
||
}
|
||
|
||
const selectUser = (value, orgType) => {
|
||
//选择用户,倒开组织选择器
|
||
// orgType.value = orgType
|
||
users.value = value
|
||
orgPicker.value.showUserPicker()
|
||
}
|
||
const filterConditionMosr = (list) => {
|
||
processFromPerms.value.forEach((item) => {
|
||
console.log(item)
|
||
if (item.required && supportTypes.value.indexOf(item.valueType) > -1){
|
||
list.push({title: item.title, id: item.id, valueType: item.valueType})
|
||
}
|
||
})
|
||
}
|
||
|
||
const filterCondition = (item, list) => {
|
||
//从表单中过滤出可以选择的条件
|
||
if (item.name === 'SpanLayout') {
|
||
item.props.items.forEach(sub => filterCondition(sub, list))
|
||
} else if (supportTypes.value.indexOf(item.valueType) > -1 && item.props.required) {
|
||
list.push({title: item.title, id: item.id, valueType: item.valueType})
|
||
}
|
||
}
|
||
|
||
const selected = (selected) => {
|
||
let userInfoList = []
|
||
for (let val of selected) {
|
||
let userInfo = {
|
||
id: val.id,
|
||
roleName: val.name
|
||
}
|
||
userInfoList.push(userInfo)
|
||
}
|
||
users.value = userInfoList
|
||
//组织选择器的选中回调函数
|
||
// users.value.length = 0
|
||
processStore.getAssignedUser().forEach(u => users.value = userInfoList)
|
||
}
|
||
|
||
const delGroup = (index) => {
|
||
//删除条件组
|
||
processStore.getSelectedNode().props.groups.splice(index, 1)
|
||
}
|
||
|
||
const delSubCondition = (group, index) => {
|
||
//删除
|
||
group.cids.splice(index, 1)
|
||
group.conditions.splice(index, 1)
|
||
}
|
||
|
||
const conditionChange = (index, group) => {
|
||
//条件组进行发生了改变
|
||
//判断新增的
|
||
group.cids.forEach(cid => {
|
||
if (0 > group.conditions.findIndex(cd => cd.id === cid)) {
|
||
//新增条件
|
||
let condition = {...conditionList.value[index]}
|
||
condition.compare = '';
|
||
condition.value = []
|
||
group.conditions.push(condition)
|
||
}
|
||
})
|
||
for (let i = 0; i < group.conditions.length; i++) {
|
||
//去除没有选中的
|
||
if (group.cids.indexOf(group.conditions[i].id) < 0) {
|
||
group.conditions.splice(i, 1)
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.group {
|
||
margin-bottom: 20px;
|
||
color: #5e5e5e;
|
||
overflow: hidden;
|
||
border-radius: 6px;
|
||
border: 1px solid #e3e3e3;
|
||
|
||
.group-header {
|
||
padding: 5px 10px;
|
||
background: #e3e3e3;
|
||
position: relative;
|
||
|
||
div {
|
||
display: inline-block;
|
||
}
|
||
|
||
.group-name {
|
||
font-size: small;
|
||
}
|
||
|
||
.group-cp {
|
||
font-size: small;
|
||
position: absolute;
|
||
left: 100px;
|
||
display: flex;
|
||
top: 5px;
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
|
||
.group-operation {
|
||
position: absolute;
|
||
right: 10px;
|
||
|
||
.group-icon {
|
||
cursor: pointer;
|
||
}
|
||
}
|
||
}
|
||
|
||
.group-content {
|
||
padding: 10px 5px;
|
||
|
||
p {
|
||
text-align: center;
|
||
font-size: small;
|
||
}
|
||
|
||
.delete-icon {
|
||
position: absolute;
|
||
cursor: pointer;
|
||
top: 12px;
|
||
right: 10px;
|
||
}
|
||
}
|
||
|
||
.condition-title {
|
||
display: block;
|
||
width: 100px;
|
||
}
|
||
}
|
||
</style>
|