Commit ab9ce936 by jason

仿钉钉流程设计器- 删除第1版,新增连续多级部分负责人策略

parent fd13eb7f
/* stylelint-disable order/properties-order */
<template>
<div class="add-node-btn-box">
<div class="add-node-btn">
<el-popover placement="right-start" v-model="visible" width="auto">
<div class="add-node-popover-body">
<a class="add-node-popover-item approver" @click="addType(1)">
<div class="item-wrapper">
<span class="iconfont icon-approve"></span>
</div>
<p>审批人</p>
</a>
<!-- TODO 暂时去掉未完成
<a class="add-node-popover-item notifier" @click="addType(2)">
<div class="item-wrapper">
<span class="iconfont"></span>
</div>
<p>抄送人</p>
</a>
<a class="add-node-popover-item condition" @click="addType(4)">
<div class="item-wrapper">
<span class="iconfont"></span>
</div>
<p>条件分支</p>
</a>
-->
<a class="add-node-popover-item notifier" @click="addType(2)">
<div class="item-wrapper">
<span class="iconfont icon-copy"></span>
</div>
<p>抄送人</p>
</a>
<a class="add-node-popover-item condition" @click="addType(4)">
<div class="item-wrapper">
<span class="iconfont icon-exclusive"></span>
</div>
<p>条件分支</p>
</a>
<a class="add-node-popover-item condition" @click="addType(5)">
<div class="item-wrapper">
<span class="iconfont icon-parallel"></span>
</div>
<p>并行分支</p>
</a>
<a class="add-node-popover-item condition" @click="addType(7)">
<div class="item-wrapper">
<span class="iconfont icon-Inclusive"></span>
</div>
<p>包容分支</p>
</a>
</div>
<template #reference>
<button class="btn" type="button" v-if="showAddButton">
<span><Icon icon="ep:plus" class="addIcon" :size="14" /></span>
</button>
</template>
</el-popover>
</div>
</div>
</template>
<script lang="ts" setup>
import { NodeType } from './consts'
import { ref } from 'vue'
import { generateUUID } from '@/utils'
let props = defineProps({
childNodeP: {
type: Object,
default: () => ({})
},
showAddButton: {
type: Boolean,
default: true
}
})
let emits = defineEmits(['update:childNodeP'])
let visible = ref(false)
const defaultFieldsPermission = inject('defaultFieldsPermission')
const addType = (type: number) => {
visible.value = false
// 审核节点
if (type === NodeType.APPROVE_USER_NODE) {
const data = {
name: '审核人',
error: true,
type: 1,
// 审批节点配置
attributes: {
approveMethod: undefined,
candidateStrategy: undefined,
candidateParam: undefined,
fieldsPermission: defaultFieldsPermission
},
childNode: props.childNodeP
}
emits('update:childNodeP', data)
}
// 抄送节点
if (type === NodeType.CC_USER_NODE) {
const data = {
name: '抄送人',
type: 2, // TODO @jason:这个要不要搞成枚举?NodeType 里貌似有枚举
error: true,
// 抄送节点配置
attributes: {
candidateStrategy: undefined,
candidateParam: undefined
},
childNode: props.childNodeP
}
emits('update:childNodeP', data)
}
// 条件分支
if (type === NodeType.EXCLUSIVE_NODE) {
const data = {
name: '条件分支',
type: 4,
id: 'GateWay_' + generateUUID(),
childNode: props.childNodeP,
conditionNodes: [
{
name: '分支1',
error: true,
type: 3,
priorityLevel: 1,
conditionList: [],
childNode: null
},
{
name: '其它情况',
type: 3,
priorityLevel: 2,
conditionList: [],
childNode: null
}
]
}
emits('update:childNodeP', data)
}
// 并行分支 fork
if (type === NodeType.PARALLEL_NODE_FORK) {
const data = {
name: '并行分支_FORK',
type: 5,
id: 'GateWay_' + generateUUID(),
conditionNodes: [
{
name: '并行1',
error: true,
type: 3,
childNode: null
},
{
name: '并行2',
type: 3,
childNode: null
}
],
childNode: {
id: 'GateWay_' + generateUUID(),
name: '并行分支_JOIN',
type: 6,
error: true,
childNode: props.childNodeP
}
}
emits('update:childNodeP', data)
}
// 包容分支 fork
if (type === NodeType.INCLUSIVE_NODE_FORK) {
const data = {
name: '包容分支_FORK',
type: 7,
id: 'GateWay_' + generateUUID(),
conditionNodes: [
{
name: '分支1',
error: true,
type: 3,
childNode: null
},
{
name: '其它情况',
type: 3,
childNode: null
}
],
childNode: {
id: 'GateWay_' + generateUUID(),
name: '包容分支_JOIN',
type: 8,
error: true,
childNode: props.childNodeP
}
}
emits('update:childNodeP', data)
}
// if (type != 4) {
// var data
// if (type == 1) {
// data = {
// name: '审核人',
// error: true,
// type: 1,
// // 审批节点配置
// attributes : {
// approveMethod : undefined,
// candidateStrategy: undefined,
// candidateParam: undefined
// },
// childNode: props.childNodeP
// }
// } else if (type == 2) {
// data = {
// name: '抄送人',
// type: 2,
// error: true,
// // 抄送节点配置
// attributes : {
// candidateStrategy: undefined,
// candidateParam: undefined
// },
// childNode: props.childNodeP
// }
// }
// emits('update:childNodeP', data)
// } else {
// emits('update:childNodeP', {
// name: '路由',
// type: 4,
// id : 'GateWay_'+ generateUUID(),
// childNode: props.childNodeP,
// conditionNodes: [
// {
// name: '条件1',
// error: true,
// type: 3,
// priorityLevel: 1,
// conditionList: [],
// childNode: null
// },
// {
// name: '其它情况',
// type: 3,
// priorityLevel: 2,
// conditionList: [],
// childNode: null
// }
// ]
// })
// }
}
</script>
<style scoped lang="scss">
.add-node-btn-box {
position: relative;
display: inline-flex;
width: 240px;
-ms-flex-negative: 0;
flex-shrink: 0;
-webkit-box-flex: 1;
-ms-flex-positive: 1;
&::before {
position: absolute;
inset: 0;
z-index: -1;
width: 2px;
height: 100%;
margin: auto;
background-color: #cacaca;
content: '';
}
.add-node-btn {
display: flex;
width: 240px;
padding: 20px 0 32px;
justify-content: center;
flex-shrink: 0;
-webkit-box-flex: 1;
-webkit-box-pack: center;
user-select: none;
flex-grow: 1;
.btn {
position: relative;
width: 30px;
height: 30px;
line-height: 30px;
background: #3296fa;
border: none;
border-radius: 50%;
outline: none;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1);
-webkit-transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
.addIcon {
line-height: 30px;
color: #fff;
}
&:hover {
transform: scale(1.3);
box-shadow: 0 13px 27px 0 rgba(0, 0, 0, 0.1);
}
&:active {
background: #1e83e9;
transform: none;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1);
}
}
}
}
.add-node-popover-body {
display: flex;
.add-node-popover-item {
margin-right: 10px;
cursor: pointer;
text-align: center;
flex: 1;
color: #191f25 !important;
.item-wrapper {
display: inline-block;
width: 80px;
height: 80px;
margin-bottom: 5px;
background: #fff;
border: 1px solid #e2e2e2;
border-radius: 50%;
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
user-select: none;
.iconfont {
font-size: 35px;
line-height: 80px;
}
}
&.approver {
.item-wrapper {
color: #ff943e;
}
}
&.notifier {
.item-wrapper {
color: #3296fa;
}
}
&.condition {
.item-wrapper {
color: #15bc83;
}
}
&:hover {
.item-wrapper {
background: #3296fa;
box-shadow: 0 10px 20px 0 rgba(50, 150, 250, 0.4);
}
.iconfont {
color: #fff;
}
}
&:active {
.item-wrapper {
background: #eaeaea;
box-shadow: none;
}
.iconfont {
color: inherit;
}
}
}
}
</style>
export enum NodeType {
//// -1 根节点流程开始节点 0 发起人 1审批 2抄送 3条件 4路由
ROOT_NODE = -1,
/**
* 发起人节点
*/
START_USER_NODE = 0,
/**
* 审批人节点
*/
APPROVE_USER_NODE = 1,
/**
* 抄送人节点
*/
CC_USER_NODE = 2,
/**
* 条件节点
*/
CONDITION_NODE = 3,
/**
* 条件分支节点
*/
EXCLUSIVE_NODE = 4,
/**
* 并行分支分叉节点
*/
PARALLEL_NODE_FORK = 5,
/**
* 并行分支聚合
*/
PARALLEL_NODE_JOIN = 6,
/**
* 包容分支分叉节点
*/
INCLUSIVE_NODE_FORK = 7,
/**
* 包容分支聚合节点
*/
INCLUSIVE_NODE_JOIN = 8
}
export const NODE_BG_COLOR = new Map()
NODE_BG_COLOR.set(NodeType.START_USER_NODE, '#87, 106, 149')
NODE_BG_COLOR.set(NodeType.APPROVE_USER_NODE, '#255, 148, 62')
NODE_BG_COLOR.set(NodeType.CC_USER_NODE, '#50, 150, 250')
/**
* 节点的标题
*/
export const NODE_TITLE = new Map()
NODE_TITLE.set(NodeType.START_USER_NODE, '发起人')
NODE_TITLE.set(NodeType.APPROVE_USER_NODE, '审批人')
NODE_TITLE.set(NodeType.CC_USER_NODE, '抄送人')
export type WorkFlowNode = {
id: string,
type: NodeType,
name: string,
attributes: any,
// 操作人
childNode?: WorkFlowNode | undefined,
conditionNodes: WorkFlowNode[]
}
\ No newline at end of file
<template>
<el-drawer
:append-to-body="true"
v-model="visible"
:show-close="false"
:size="550"
:before-close="saveConfig"
>
<template #header>
<div class="copy-task-header">抄送人设置</div>
</template>
<div>
<el-form label-position="top" label-width="100px">
<el-form-item label="选择抄送人" prop="candidateStrategy">
<el-select
v-model="candidateConfig.candidateStrategy"
style="width: 100%"
clearable
@change="changecandidateStrategy"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.BPM_TASK_CANDIDATE_STRATEGY)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="candidateConfig.candidateStrategy == 10"
label="指定角色"
prop="candidateParam"
>
<el-select
v-model="candidateConfig.candidateParam"
clearable
multiple
style="width: 100%"
>
<el-option
v-for="item in roleOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="candidateConfig.candidateStrategy == 20 || candidateConfig.candidateStrategy == 21"
label="指定部门"
prop="candidateParam"
span="24"
>
<el-tree-select
ref="treeRef"
v-model="candidateConfig.candidateParam"
:data="deptTreeOptions"
:props="defaultProps"
empty-text="加载中,请稍后"
multiple
node-key="id"
style="width: 100%"
show-checkbox
/>
</el-form-item>
<el-form-item
v-if="candidateConfig.candidateStrategy == 22"
label="指定岗位"
prop="candidateParam"
span="24"
>
<el-select
v-model="candidateConfig.candidateParam"
clearable
multiple
style="width: 100%"
>
<el-option
v-for="item in postOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="
candidateConfig.candidateStrategy == 30 ||
candidateConfig.candidateStrategy == 31 ||
candidateConfig.candidateStrategy == 32
"
label="指定用户"
prop="candidateParam"
span="24"
>
<el-select
v-model="candidateConfig.candidateParam"
clearable
multiple
style="width: 100%"
>
<el-option
v-for="item in userOptions"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="candidateConfig.candidateStrategy === 40"
label="指定用户组"
prop="candidateParam"
>
<el-select
v-model="candidateConfig.candidateParam"
clearable
multiple
style="width: 100%"
>
<el-option
v-for="item in userGroupOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="candidateConfig.candidateStrategy === 60"
label="流程表达式"
prop="candidateParam"
>
<el-input
type="textarea"
v-model="candidateConfig.candidateParam[0]"
clearable
style="width: 100%"
/>
</el-form-item>
</el-form>
</div>
<div class="demo-drawer__footer clear">
<el-button type="primary" @click="saveConfig">确 定</el-button>
<el-button @click="closeDrawer">取 消</el-button>
</div>
</el-drawer>
</template>
<script lang="ts" setup>
import { ref, watch, computed, toRaw } from 'vue'
import { useWorkFlowStoreWithOut } from '@/store/modules/bpm/simpleWorkflow'
import { DICT_TYPE, getIntDictOptions, getDictLabel } from '@/utils/dict'
import { defaultProps, handleTree } from '@/utils/tree'
import * as RoleApi from '@/api/system/role'
import * as DeptApi from '@/api/system/dept'
import * as PostApi from '@/api/system/post'
import * as UserApi from '@/api/system/user'
import * as UserGroupApi from '@/api/bpm/userGroup'
const roleOptions = ref<RoleApi.RoleVO[]>([]) // 角色列表
const postOptions = ref<PostApi.PostVO[]>([]) // 岗位列表
const userOptions = ref<UserApi.UserVO[]>([]) // 用户列表
const deptTreeOptions = ref() // 部门树
const userGroupOptions = ref<UserGroupApi.UserGroupVO[]>([]) // 用户组列表
const candidateConfig = ref({
candidateStrategy: undefined,
candidateParam: []
})
const store = useWorkFlowStoreWithOut()
const { setCopyerDrawer, setCopyerConfig } = store
const copyerDrawer = computed(() => store.copyerDrawer)
const copyerConfig = computed(() => store.copyerConfig)
const visible = computed({
get() {
return copyerDrawer.value
},
set() {
closeDrawer()
}
})
watch(copyerConfig, (val) => {
if (val.value.attributes) {
console.log('val.value.attributes', val.value.attributes)
candidateConfig.value.candidateStrategy = val.value.attributes.candidateStrategy
const candidateParamStr = val.value.attributes.candidateParam
if (val.value.attributes.candidateStrategy === 60) {
candidateConfig.value.candidateParam = [candidateParamStr]
} else {
if (candidateParamStr) {
candidateConfig.value.candidateParam = candidateParamStr.split(',').map((item) => +item)
}
}
// candidateConfig.value = val.value.attributes
}
})
const saveConfig = () => {
const rawConfig = toRaw(copyerConfig.value)
const { candidateStrategy, candidateParam } = toRaw(candidateConfig.value)
const candidateParamStr = candidateParam.join(',')
rawConfig.value.attributes = {
candidateStrategy,
candidateParam: candidateParamStr
}
rawConfig.flag = true
// TODO 进行校验
// setApproverConfig({
// value: approverConfig.value,
// flag: true,
// id: approverConfig1.value.id
// })
setCopyerConfig({
value: rawConfig.value,
flag: true,
id: copyerConfig.value.id
})
console.log('after is copyerConfig', copyerConfig.value)
closeDrawer()
}
const closeDrawer = () => {
setCopyerDrawer(false)
}
const changecandidateStrategy = () => {
candidateConfig.value.candidateParam = []
}
onMounted(async () => {
// 获得角色列表
roleOptions.value = await RoleApi.getSimpleRoleList()
// 获得岗位列表
postOptions.value = await PostApi.getSimplePostList()
// 获得用户列表
userOptions.value = await UserApi.getSimpleUserList()
// 获得部门列表
const deptOptions = await DeptApi.getSimpleDeptList()
deptTreeOptions.value = handleTree(deptOptions, 'id')
// 获得用户组列表
userGroupOptions.value = await UserGroupApi.getUserGroupSimpleList()
})
</script>
<style lang="scss" scoped>
.copy-task-header {
font-size: 16px !important;
}
</style>
// @ts-ignore
import { DictDataVO } from '@/api/system/dict/types'
import { DICT_TYPE, getDictLabel } from '@/utils/dict'
/**
* todo
*/
export const arrToStr = (arr?: [{ name: string }]) => {
if (arr) {
return arr
.map((item) => {
return item.name
})
.toString()
}
}
export const setApproverStr = (nodeConfig: any) => {
if (nodeConfig.settype == 1) {
if (nodeConfig.nodeUserList.length == 1) {
return nodeConfig.nodeUserList[0].name
} else if (nodeConfig.nodeUserList.length > 1) {
if (nodeConfig.examineMode == 1) {
return arrToStr(nodeConfig.nodeUserList)
} else if (nodeConfig.examineMode == 2) {
return nodeConfig.nodeUserList.length + '人会签'
}
}
} else if (nodeConfig.settype == 2) {
const level =
nodeConfig.directorLevel == 1 ? '直接主管' : '第' + nodeConfig.directorLevel + '级主管'
if (nodeConfig.examineMode == 1) {
return level
} else if (nodeConfig.examineMode == 2) {
return level + '会签'
}
} else if (nodeConfig.settype == 4) {
if (nodeConfig.selectRange == 1) {
return '发起人自选'
} else {
if (nodeConfig.nodeUserList.length > 0) {
if (nodeConfig.selectRange == 2) {
return '发起人自选'
} else {
return '发起人从' + nodeConfig.nodeUserList[0].name + '中自选'
}
} else {
return ''
}
}
} else if (nodeConfig.settype == 5) {
return '发起人自己'
} else if (nodeConfig.settype == 7) {
return '从直接主管到通讯录中级别最高的第' + nodeConfig.examineEndDirectorLevel + '个层级主管'
}
}
export const approveMethods: DictDataVO [] = [
{ label: '单人审批', value: 1 }
// { label: '多人审批(所有人审批通过)', value: 2 }
// TODO 更多的类型
];
export const getApproverShowText = (approveMethod :number, candidateStrategy: number) => {
let appoveMethodText = '单人审批'
if(candidateStrategy) {
approveMethods.forEach((item) => {
if (item.value == approveMethod) {
appoveMethodText = item.label
}
})
const strategyText = getDictLabel(
DICT_TYPE.BPM_TASK_CANDIDATE_STRATEGY,
candidateStrategy
)
return `审批方式:${appoveMethodText} <br/>
审批人规则类型:按${strategyText}`
} else {
return ''
}
}
export const copyerStr = ( candidateStrategy: number) => {
// if (nodeConfig.nodeUserList.length != 0) {
// return arrToStr(nodeConfig.nodeUserList)
// } else {
// if (nodeConfig.ccSelfSelectFlag == 1) {
// return '发起人自选'
// }
// }
console.log('candidateStrategy', candidateStrategy);
if(candidateStrategy) {
const strategyText = getDictLabel(
DICT_TYPE.BPM_TASK_CANDIDATE_STRATEGY,
candidateStrategy
)
return `抄送人类型:按${strategyText}`
} else {
return ''
}
}
export const conditionStr = (nodeConfig, index) => {
// const { conditionList, nodeUserList } = nodeConfig.conditionNodes[index]
// if (conditionList.length == 0) {
// return index == nodeConfig.conditionNodes.length - 1 &&
// nodeConfig.conditionNodes[0].conditionList.length != 0
// ? '其他条件进入此流程'
// : '请设置条件'
// return index == nodeConfig.conditionNodes.length - 1 &&
// nodeConfig.conditionNodes[0].conditionList.length != 0
// ? '其他条件进入此流程'
// : '请设置条件'
// console.log('index===>', index);
// console.log('nodeConfig.conditionNodes.length===>', nodeConfig.conditionNodes.length);
if( index === nodeConfig.conditionNodes.length - 1) {
return '其它情况将进入该分支'
} else {
return '请设置条件'
}
// } else {
// let str = ''
// for (let i = 0; i < conditionList.length; i++) {
// const {
// columnId,
// columnType,
// showType,
// showName,
// optType,
// zdy1,
// opt1,
// zdy2,
// opt2,
// fixedDownBoxValue
// } = conditionList[i]
// if (columnId == 0) {
// if (nodeUserList.length != 0) {
// str += '发起人属于:'
// str +=
// nodeUserList
// .map((item) => {
// return item.name
// })
// .join('或') + ' 并且 '
// }
// }
// if (columnType == 'String' && showType == '3') {
// if (zdy1) {
// str += showName + '属于:' + dealStr(zdy1, JSON.parse(fixedDownBoxValue)) + ' 并且 '
// }
// }
// if (columnType == 'Double') {
// if (optType != 6 && zdy1) {
// const optTypeStr = ['', '<', '>', '≤', '=', '≥'][optType]
// str += `${showName} ${optTypeStr} ${zdy1} 并且 `
// } else if (optType == 6 && zdy1 && zdy2) {
// str += `${zdy1} ${opt1} ${showName} ${opt2} ${zdy2} 并且 `
// }
// }
// }
// str ? str.substring(0, str.length - 4) :
return '请设置条件'
// }
}
// export const dealStr = (str: string, obj) => {
// const arr = []
// const list = str.split(',')
// for (const elem in obj) {
// list.map((item) => {
// if (item == elem) {
// arr.push(obj[elem].value)
// }
// })
// }
// return arr.join('或')
// }
export const removeEle = (arr, elem, key = 'id') => {
let includesIndex
arr.map((item, index) => {
if (item[key] == elem[key]) {
includesIndex = index
}
})
arr.splice(includesIndex, 1)
}
export const bgColors = ['87, 106, 149', '255, 148, 62', '50, 150, 250','50, 150, 250','248, 107, 248','244, 118, 118','23, 148, 46','23, 148, 46']
export const placeholderList = ['发起人', '审核人', '抄送人']
export const setTypes = [
{ value: 1, label: '指定成员' },
{ value: 2, label: '主管' },
{ value: 4, label: '发起人自选' },
{ value: 5, label: '发起人自己' },
{ value: 7, label: '连续多级主管' }
]
export const selectModes = [
{ value: 1, label: '选一个人' },
{ value: 2, label: '选多个人' }
]
export const selectRanges = [
{ value: 1, label: '全公司' },
{ value: 2, label: '指定成员' },
{ value: 3, label: '指定角色' }
]
export const optTypes = [
{ value: '1', label: '小于' },
{ value: '2', label: '大于' },
{ value: '3', label: '小于等于' },
{ value: '4', label: '等于' },
{ value: '5', label: '大于等于' },
{ value: '6', label: '介于两个数之间' }
]
......@@ -146,9 +146,9 @@ onMounted(async () => {
processNodeTree.value = {
name: '开始',
type: NodeType.START_EVENT_NODE,
id: 'StartEvent_1', // TODO @jason:这个我们要不要 StartEvent 哈?
id: 'StartEvent',
childNode: {
id: 'EndEvent_1',
id: 'EndEvent',
name: '结束',
type: NodeType.END_EVENT_NODE
}
......
// @ts-ignore
import { DictDataVO } from '@/api/system/dict/types'
/**
* 节点类型
*/
......@@ -85,7 +86,7 @@ export enum CandidateStrategy {
*/
ROLE = 10,
/**
* 指定部门成员
* 部门成员
*/
DEPT_MEMBER = 20,
/**
......@@ -93,6 +94,10 @@ export enum CandidateStrategy {
*/
DEPT_LEADER = 21,
/**
* 连续多级部门的负责人
*/
MULTI_LEVEL_DEPT_LEADER = 23,
/**
* 指定岗位
*/
POST = 22,
......@@ -109,6 +114,14 @@ export enum CandidateStrategy {
*/
START_USER = 36,
/**
* 发起人部门负责人
*/
START_USER_DEPT_LEADER = 37,
/**
* 发起人连续多级部门的负责人
*/
START_USER_MULTI_LEVEL_DEPT_LEADER = 38,
/**
* 指定用户组
*/
USER_GROUP = 40,
......@@ -280,6 +293,21 @@ NODE_DEFAULT_NAME.set(NodeType.USER_TASK_NODE, '审批人')
NODE_DEFAULT_NAME.set(NodeType.COPY_TASK_NODE, '抄送人')
NODE_DEFAULT_NAME.set(NodeType.CONDITION_NODE, '条件')
// 候选人策略。暂时不从字典中取。 后续可能调整。控制显示顺序
export const CANDIDATE_STRATEGY: DictDataVO[] = [
{ label: '指定成员', value: CandidateStrategy.USER },
{ label: '指定角色', value: CandidateStrategy.ROLE },
{ label: '部门成员', value: CandidateStrategy.DEPT_MEMBER },
{ label: '部门负责人', value: CandidateStrategy.DEPT_LEADER },
{ label: '连续多级部门负责人', value: CandidateStrategy.MULTI_LEVEL_DEPT_LEADER },
{ label: '发起人自选', value: CandidateStrategy.START_USER_SELECT },
{ label: '发起人本人', value: CandidateStrategy.START_USER },
{ label: '发起人部门负责人', value: CandidateStrategy.START_USER_DEPT_LEADER },
{ label: '发起人连续部门负责人', value: CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER },
{ label: '用户组', value: CandidateStrategy.USER_GROUP },
{ label: '流程表达式', value: CandidateStrategy.EXPRESSION }
]
export const APPROVE_METHODS: DictDataVO[] = [
{ label: '随机挑选一人审批', value: ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE },
{ label: '多人会签(按通过比例%)', value: ApproveMethodType.APPROVE_BY_RATIO },
......@@ -355,3 +383,21 @@ export const DEFAULT_BUTTON_SETTING: ButtonSetting[] = [
{ id: OpsButtonType.ADD_SIGN, displayName: '加签', enable: false },
{ id: OpsButtonType.RETURN, displayName: '回退', enable: false }
]
export const MULTI_LEVEL_DEPT: DictDataVO = [
{ label: '第1级部门', value: 1 },
{ label: '第2级部门', value: 2 },
{ label: '第3级部门', value: 3 },
{ label: '第4级部门', value: 4 },
{ label: '第5级部门', value: 5 },
{ label: '第6级部门', value: 6 },
{ label: '第7级部门', value: 7 },
{ label: '第8级部门', value: 8 },
{ label: '第9级部门', value: 9 },
{ label: '第10级部门', value: 10 },
{ label: '第11级部门', value: 11 },
{ label: '第12级部门', value: 12 },
{ label: '第13级部门', value: 13 },
{ label: '第14级部门', value: 14 },
{ label: '第15级部门', value: 15 }
]
......@@ -89,9 +89,16 @@ export function useFormFieldsPermission() {
}
export type UserTaskFormType = {
candidateParamArray: any[]
//candidateParamArray: any[]
candidateStrategy: CandidateStrategy
approveMethod: ApproveMethodType
roleIds?: number[] // 角色
deptIds?: number[] // 部门
deptLevel?: number // 部门层级
userIds?: number[] // 用户
userGroups?: number[] // 用户组
postIds?: number[] // 岗位
expression?: string // 流程表达式
approveRatio?: number
rejectHandlerType?: RejectHandlerType
returnNodeId?: string
......@@ -103,8 +110,15 @@ export type UserTaskFormType = {
}
export type CopyTaskFormType = {
candidateParamArray: any[]
// candidateParamArray: any[]
candidateStrategy: CandidateStrategy
roleIds?: number[] // 角色
deptIds?: number[] // 部门
deptLevel?: number // 部门层级
userIds?: number[] // 用户
userGroups?: number[] // 用户组
postIds?: number[] // 岗位
expression?: string // 流程表达式
}
/**
......@@ -120,7 +134,7 @@ export function useNodeForm(nodeType: NodeType) {
const configForm = ref<UserTaskFormType | CopyTaskFormType>()
if (nodeType === NodeType.USER_TASK_NODE) {
configForm.value = {
candidateParamArray: [],
//candidateParamArray: [],
candidateStrategy: CandidateStrategy.USER,
approveMethod: ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE,
approveRatio: 100,
......@@ -134,7 +148,7 @@ export function useNodeForm(nodeType: NodeType) {
}
} else {
configForm.value = {
candidateParamArray: [],
//candidateParamArray: [],
candidateStrategy: CandidateStrategy.USER
}
}
......@@ -143,10 +157,10 @@ export function useNodeForm(nodeType: NodeType) {
let showText = ''
// 指定成员
if (configForm.value?.candidateStrategy === CandidateStrategy.USER) {
if (configForm.value.candidateParamArray?.length > 0) {
if (configForm.value?.userIds!.length > 0) {
const candidateNames: string[] = []
userOptions?.value.forEach((item) => {
if (configForm.value?.candidateParamArray.includes(item.id)) {
if (configForm.value?.userIds!.includes(item.id)) {
candidateNames.push(item.nickname)
}
})
......@@ -155,10 +169,10 @@ export function useNodeForm(nodeType: NodeType) {
}
// 指定角色
if (configForm.value?.candidateStrategy === CandidateStrategy.ROLE) {
if (configForm.value.candidateParamArray?.length > 0) {
if (configForm.value.roleIds!.length > 0) {
const candidateNames: string[] = []
roleOptions?.value.forEach((item) => {
if (configForm.value?.candidateParamArray.includes(item.id)) {
if (configForm.value?.roleIds!.includes(item.id)) {
candidateNames.push(item.name)
}
})
......@@ -168,29 +182,32 @@ export function useNodeForm(nodeType: NodeType) {
// 指定部门
if (
configForm.value?.candidateStrategy === CandidateStrategy.DEPT_MEMBER ||
configForm.value?.candidateStrategy === CandidateStrategy.DEPT_LEADER
configForm.value?.candidateStrategy === CandidateStrategy.DEPT_LEADER ||
configForm.value?.candidateStrategy === CandidateStrategy.MULTI_LEVEL_DEPT_LEADER
) {
if (configForm.value?.candidateParamArray?.length > 0) {
if (configForm.value?.deptIds!.length > 0) {
const candidateNames: string[] = []
deptOptions?.value.forEach((item) => {
if (configForm.value?.candidateParamArray.includes(item.id)) {
if (configForm.value?.deptIds!.includes(item.id!)) {
candidateNames.push(item.name)
}
})
if (configForm.value.candidateStrategy === CandidateStrategy.DEPT_MEMBER) {
showText = `部门成员:${candidateNames.join(',')}`
} else {
} else if (configForm.value.candidateStrategy === CandidateStrategy.DEPT_LEADER) {
showText = `部门的负责人:${candidateNames.join(',')}`
} else {
showText = `多级部门的负责人:${candidateNames.join(',')}`
}
}
}
// 指定岗位
if (configForm.value?.candidateStrategy === CandidateStrategy.POST) {
if (configForm.value.candidateParamArray?.length > 0) {
if (configForm.value.postIds!.length > 0) {
const candidateNames: string[] = []
postOptions?.value.forEach((item) => {
if (configForm.value?.candidateParamArray.includes(item.id)) {
if (configForm.value?.postIds!.includes(item.id!)) {
candidateNames.push(item.name)
}
})
......@@ -199,10 +216,10 @@ export function useNodeForm(nodeType: NodeType) {
}
// 指定用户组
if (configForm.value?.candidateStrategy === CandidateStrategy.USER_GROUP) {
if (configForm.value?.candidateParamArray?.length > 0) {
if (configForm.value?.userGroups!.length > 0) {
const candidateNames: string[] = []
userGroupOptions?.value.forEach((item) => {
if (configForm.value?.candidateParamArray.includes(item.id)) {
if (configForm.value?.userGroups!.includes(item.id)) {
candidateNames.push(item.name)
}
})
......@@ -218,16 +235,116 @@ export function useNodeForm(nodeType: NodeType) {
if (configForm.value?.candidateStrategy === CandidateStrategy.START_USER) {
showText = `发起人自己`
}
// 发起人的部门负责人
if (configForm.value?.candidateStrategy === CandidateStrategy.START_USER_DEPT_LEADER) {
showText = `发起人的部门负责人`
}
// 发起人的部门负责人
if (
configForm.value?.candidateStrategy === CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER
) {
showText = `发起人连续部门负责人`
}
// 流程表达式
if (configForm.value?.candidateStrategy === CandidateStrategy.EXPRESSION) {
if (configForm.value.candidateParamArray?.length > 0) {
showText = `流程表达式:${configForm.value.candidateParamArray[0]}`
}
showText = `流程表达式:${configForm.value.expression}`
}
return showText
}
/**
* 处理候选人参数的赋值
*/
const handleCandidateParam = () => {
let candidateParam: undefined | string = undefined
if (!configForm.value) {
return candidateParam
}
switch (configForm.value.candidateStrategy) {
case CandidateStrategy.USER:
candidateParam = configForm.value.userIds!.join(',')
break
case CandidateStrategy.ROLE:
candidateParam = configForm.value.roleIds!.join(',')
break
case CandidateStrategy.POST:
candidateParam = configForm.value.postIds!.join(',')
break
case CandidateStrategy.USER_GROUP:
candidateParam = configForm.value.userGroups!.join(',')
break
case CandidateStrategy.EXPRESSION:
candidateParam = configForm.value.expression!
break
case CandidateStrategy.DEPT_MEMBER:
case CandidateStrategy.DEPT_LEADER:
candidateParam = configForm.value.deptIds!.join(',')
break
// 发起人部门负责人
case CandidateStrategy.START_USER_DEPT_LEADER:
case CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER:
candidateParam = configForm.value.deptLevel + ''
break
// 指定连续多级部门的负责人
case CandidateStrategy.MULTI_LEVEL_DEPT_LEADER: {
// TODO 是否允许选多个部门
const deptIds = configForm.value.deptIds!.join(',')
candidateParam = deptIds.concat(',' + configForm.value.deptLevel + '')
break
}
default:
break
}
return candidateParam
}
/**
* 解析候选人参数
*/
const parseCandidateParam = (
candidateStrategy: CandidateStrategy,
candidateParam: string | undefined
) => {
if (!configForm.value || !candidateParam) {
return
}
switch (candidateStrategy) {
case CandidateStrategy.USER: {
configForm.value.userIds = candidateParam.split(',').map((item) => +item)
break
}
case CandidateStrategy.ROLE:
configForm.value.roleIds = candidateParam.split(',').map((item) => +item)
break
case CandidateStrategy.POST:
configForm.value.postIds = candidateParam.split(',').map((item) => +item)
break
case CandidateStrategy.USER_GROUP:
configForm.value.userGroups = candidateParam.split(',').map((item) => +item)
break
case CandidateStrategy.EXPRESSION:
configForm.value.expression = candidateParam
break
case CandidateStrategy.DEPT_MEMBER:
case CandidateStrategy.DEPT_LEADER:
configForm.value.deptIds = candidateParam.split(',').map((item) => +item)
break
// 发起人部门负责人
case CandidateStrategy.START_USER_DEPT_LEADER:
case CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER:
configForm.value.deptLevel = +candidateParam
break
// 指定连续多级部门的负责人
case CandidateStrategy.MULTI_LEVEL_DEPT_LEADER: {
// 暂时只能选一个部门
const paramArray = candidateParam.split(',')
configForm.value.deptIds = [+paramArray[0]]
configForm.value.deptLevel = +paramArray[1]
break
}
default:
break
}
}
return {
configForm,
roleOptions,
......@@ -235,6 +352,8 @@ export function useNodeForm(nodeType: NodeType) {
userOptions,
userGroupOptions,
deptTreeOptions,
handleCandidateParam,
parseCandidateParam,
getShowText
}
}
......
......@@ -46,14 +46,9 @@
<el-form-item
v-if="configForm.candidateStrategy == CandidateStrategy.ROLE"
label="指定角色"
prop="candidateParamArray"
prop="roleIds"
>
<el-select
v-model="configForm.candidateParamArray"
clearable
multiple
style="width: 100%"
>
<el-select v-model="configForm.roleIds" clearable multiple style="width: 100%">
<el-option
v-for="item in roleOptions"
:key="item.id"
......@@ -68,12 +63,12 @@
configForm.candidateStrategy == CandidateStrategy.DEPT_LEADER
"
label="指定部门"
prop="candidateParamArray"
prop="deptIds"
span="24"
>
<el-tree-select
ref="treeRef"
v-model="configForm.candidateParamArray"
v-model="configForm.deptIds"
:data="deptTreeOptions"
:props="defaultProps"
empty-text="加载中,请稍后"
......@@ -86,15 +81,10 @@
<el-form-item
v-if="configForm.candidateStrategy == CandidateStrategy.POST"
label="指定岗位"
prop="candidateParamArray"
prop="postIds"
span="24"
>
<el-select
v-model="configForm.candidateParamArray"
clearable
multiple
style="width: 100%"
>
<el-select v-model="configForm.postIds" clearable multiple style="width: 100%">
<el-option
v-for="item in postOptions"
:key="item.id"
......@@ -106,15 +96,10 @@
<el-form-item
v-if="configForm.candidateStrategy == CandidateStrategy.USER"
label="指定用户"
prop="candidateParamArray"
prop="userIds"
span="24"
>
<el-select
v-model="configForm.candidateParamArray"
clearable
multiple
style="width: 100%"
>
<el-select v-model="configForm.userIds" clearable multiple style="width: 100%">
<el-option
v-for="item in userOptions"
:key="item.id"
......@@ -126,14 +111,9 @@
<el-form-item
v-if="configForm.candidateStrategy === CandidateStrategy.USER_GROUP"
label="指定用户组"
prop="candidateParamArray"
prop="userGroups"
>
<el-select
v-model="configForm.candidateParamArray"
clearable
multiple
style="width: 100%"
>
<el-select v-model="configForm.userGroups" clearable multiple style="width: 100%">
<el-option
v-for="item in userGroupOptions"
:key="item.id"
......@@ -146,11 +126,11 @@
<el-form-item
v-if="configForm.candidateStrategy === CandidateStrategy.EXPRESSION"
label="流程表达式"
prop="candidateParamArray"
prop="expression"
>
<el-input
type="textarea"
v-model="configForm.candidateParamArray[0]"
v-model="configForm.expression"
clearable
style="width: 100%"
/>
......@@ -200,7 +180,7 @@
</el-drawer>
</template>
<script setup lang="ts">
import { SimpleFlowNode, CandidateStrategy, NodeType } from '../consts'
import { SimpleFlowNode, CandidateStrategy, NodeType, CANDIDATE_STRATEGY } from '../consts'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import {
useWatchNode,
......@@ -235,7 +215,12 @@ const formRef = ref() // 表单 Ref
// 表单校验规则
const formRules = reactive({
candidateStrategy: [{ required: true, message: '抄送人设置不能为空', trigger: 'change' }],
candidateParamArray: [{ required: true, message: '选项不能为空', trigger: 'blur' }]
userIds: [{ required: true, message: '用户不能为空', trigger: 'change' }],
roleIds: [{ required: true, message: '角色不能为空', trigger: 'change' }],
deptIds: [{ required: true, message: '部门不能为空', trigger: 'change' }],
userGroups: [{ required: true, message: '用户组不能为空', trigger: 'change' }],
postIds: [{ required: true, message: '岗位不能为空', trigger: 'change' }],
expression: [{ required: true, message: '流程表达式不能为空', trigger: 'blur' }]
})
const {
......@@ -245,12 +230,14 @@ const {
userOptions,
userGroupOptions,
deptTreeOptions,
getShowText
getShowText,
handleCandidateParam,
parseCandidateParam
} = useNodeForm(NodeType.COPY_TASK_NODE)
const configForm = tempConfigForm as Ref<CopyTaskFormType>
// 抄送人策略, 去掉发起人自选 和 发起人自己
const copyUserStrategies = computed(() => {
return getIntDictOptions(DICT_TYPE.BPM_TASK_CANDIDATE_STRATEGY).filter(
return CANDIDATE_STRATEGY.filter(
(item) =>
item.value !== CandidateStrategy.START_USER_SELECT &&
item.value !== CandidateStrategy.START_USER
......@@ -258,7 +245,12 @@ const copyUserStrategies = computed(() => {
})
// 改变抄送人设置策略
const changeCandidateStrategy = () => {
configForm.value.candidateParamArray = []
configForm.value.userIds = []
configForm.value.deptIds = []
configForm.value.roleIds = []
configForm.value.postIds = []
configForm.value.userGroups = []
configForm.value.deptLevel = 1
}
// 保存配置
const saveConfig = async () => {
......@@ -269,7 +261,7 @@ const saveConfig = async () => {
const showText = getShowText()
if (!showText) return false
currentNode.value.name = nodeName.value!
currentNode.value.candidateParam = configForm.value.candidateParamArray?.join(',')
handleCandidateParam()
currentNode.value.candidateStrategy = configForm.value.candidateStrategy
currentNode.value.showText = showText
currentNode.value.fieldsPermission = fieldsPermissionConfig.value
......@@ -281,14 +273,7 @@ const showCopyTaskNodeConfig = (node: SimpleFlowNode) => {
nodeName.value = node.name
// 抄送人设置
configForm.value.candidateStrategy = node.candidateStrategy!
const strCandidateParam = node?.candidateParam
if (node.candidateStrategy === CandidateStrategy.EXPRESSION) {
configForm.value.candidateParamArray[0] = strCandidateParam
} else {
if (strCandidateParam) {
configForm.value.candidateParamArray = strCandidateParam.split(',').map((item) => +item)
}
}
parseCandidateParam(node.candidateStrategy!, node?.candidateParam)
// 表单字段权限
getNodeConfigFormFields(node.fieldsPermission)
}
......
......@@ -34,7 +34,7 @@
@change="changeCandidateStrategy"
>
<el-radio
v-for="(dict, index) in getIntDictOptions(DICT_TYPE.BPM_TASK_CANDIDATE_STRATEGY)"
v-for="(dict, index) in CANDIDATE_STRATEGY"
:key="index"
:value="dict.value"
:label="dict.value"
......@@ -47,14 +47,9 @@
<el-form-item
v-if="configForm.candidateStrategy == CandidateStrategy.ROLE"
label="指定角色"
prop="candidateParamArray"
prop="roleIds"
>
<el-select
v-model="configForm.candidateParamArray"
clearable
multiple
style="width: 100%"
>
<el-select v-model="configForm.roleIds" clearable multiple style="width: 100%">
<el-option
v-for="item in roleOptions"
:key="item.id"
......@@ -66,15 +61,16 @@
<el-form-item
v-if="
configForm.candidateStrategy == CandidateStrategy.DEPT_MEMBER ||
configForm.candidateStrategy == CandidateStrategy.DEPT_LEADER
configForm.candidateStrategy == CandidateStrategy.DEPT_LEADER ||
configForm.candidateStrategy == CandidateStrategy.MULTI_LEVEL_DEPT_LEADER
"
label="指定部门"
prop="candidateParamArray"
prop="deptIds"
span="24"
>
<el-tree-select
ref="treeRef"
v-model="configForm.candidateParamArray"
v-model="configForm.deptIds"
:data="deptTreeOptions"
:props="defaultProps"
empty-text="加载中,请稍后"
......@@ -85,17 +81,31 @@
/>
</el-form-item>
<el-form-item
v-if="
configForm.candidateStrategy == CandidateStrategy.MULTI_LEVEL_DEPT_LEADER ||
configForm.candidateStrategy == CandidateStrategy.START_USER_DEPT_LEADER ||
configForm.candidateStrategy == CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER
"
:label="deptLevelLabel!"
prop="deptLevel"
span="24"
>
<el-select v-model="configForm.deptLevel" clearable>
<el-option
v-for="(item, index) in MULTI_LEVEL_DEPT"
:key="index"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="configForm.candidateStrategy == CandidateStrategy.POST"
label="指定岗位"
prop="candidateParamArray"
prop="postIds"
span="24"
>
<el-select
v-model="configForm.candidateParamArray"
clearable
multiple
style="width: 100%"
>
<el-select v-model="configForm.postIds" clearable multiple style="width: 100%">
<el-option
v-for="item in postOptions"
:key="item.id"
......@@ -107,11 +117,11 @@
<el-form-item
v-if="configForm.candidateStrategy == CandidateStrategy.USER"
label="指定用户"
prop="candidateParamArray"
prop="userIds"
span="24"
>
<el-select
v-model="configForm.candidateParamArray"
v-model="configForm.userIds"
clearable
multiple
style="width: 100%"
......@@ -128,14 +138,9 @@
<el-form-item
v-if="configForm.candidateStrategy === CandidateStrategy.USER_GROUP"
label="指定用户组"
prop="candidateParamArray"
prop="userGroups"
>
<el-select
v-model="configForm.candidateParamArray"
clearable
multiple
style="width: 100%"
>
<el-select v-model="configForm.userGroups" clearable multiple style="width: 100%">
<el-option
v-for="item in userGroupOptions"
:key="item.id"
......@@ -147,11 +152,11 @@
<el-form-item
v-if="configForm.candidateStrategy === CandidateStrategy.EXPRESSION"
label="流程表达式"
prop="candidateParamArray"
prop="expression"
>
<el-input
type="textarea"
v-model="configForm.candidateParamArray[0]"
v-model="configForm.expression"
clearable
style="width: 100%"
/>
......@@ -364,9 +369,11 @@ import {
REJECT_HANDLER_TYPES,
DEFAULT_BUTTON_SETTING,
OPERATION_BUTTON_NAME,
ButtonSetting
ButtonSetting,
MULTI_LEVEL_DEPT,
CANDIDATE_STRATEGY
} from '../consts'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import {
useWatchNode,
useNodeName,
......@@ -390,6 +397,15 @@ const props = defineProps({
const emits = defineEmits<{
'find:returnTaskNodes': [nodeList: SimpleFlowNode[]]
}>()
const deptLevelLabel = computed(() => {
let label = '部门负责人来源'
if (configForm.value.candidateStrategy == CandidateStrategy.MULTI_LEVEL_DEPT_LEADER) {
label = label + '(指定部门向上)'
} else {
label = label + '(发起人部门向上)'
}
return label
})
// 监控节点的变化
const currentNode = useWatchNode(props)
// 抽屉配置
......@@ -409,7 +425,12 @@ const formRef = ref() // 表单 Ref
// 表单校验规则
const formRules = reactive({
candidateStrategy: [{ required: true, message: '审批人设置不能为空', trigger: 'change' }],
candidateParamArray: [{ required: true, message: '该选项不能为空', trigger: 'change' }],
userIds: [{ required: true, message: '用户不能为空', trigger: 'change' }],
roleIds: [{ required: true, message: '角色不能为空', trigger: 'change' }],
deptIds: [{ required: true, message: '部门不能为空', trigger: 'change' }],
userGroups: [{ required: true, message: '用户组不能为空', trigger: 'change' }],
postIds: [{ required: true, message: '岗位不能为空', trigger: 'change' }],
expression: [{ required: true, message: '流程表达式不能为空', trigger: 'blur' }],
approveMethod: [{ required: true, message: '多人审批方式不能为空', trigger: 'change' }],
approveRatio: [{ required: true, message: '通过比例不能为空', trigger: 'blur' }],
returnNodeId: [{ required: true, message: '驳回节点不能为空', trigger: 'change' }],
......@@ -426,6 +447,8 @@ const {
userOptions,
userGroupOptions,
deptTreeOptions,
handleCandidateParam,
parseCandidateParam,
getShowText
} = useNodeForm(NodeType.USER_TASK_NODE)
const configForm = tempConfigForm as Ref<UserTaskFormType>
......@@ -433,7 +456,12 @@ const configForm = tempConfigForm as Ref<UserTaskFormType>
const notAllowedMultiApprovers = ref(false)
// 改变审批人设置策略
const changeCandidateStrategy = () => {
configForm.value.candidateParamArray = []
configForm.value.userIds = []
configForm.value.deptIds = []
configForm.value.roleIds = []
configForm.value.postIds = []
configForm.value.userGroups = []
configForm.value.deptLevel = 1
configForm.value.approveMethod = ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE
if (
configForm.value.candidateStrategy === CandidateStrategy.START_USER ||
......@@ -447,7 +475,8 @@ const changeCandidateStrategy = () => {
// 改变审批候选人
const changedCandidateUsers = () => {
if (
configForm.value.candidateParamArray?.length <= 1 &&
configForm.value.userIds &&
configForm.value.userIds?.length <= 1 &&
configForm.value.candidateStrategy === CandidateStrategy.USER
) {
configForm.value.approveMethod = ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE
......@@ -488,7 +517,8 @@ const saveConfig = async () => {
if (!showText) return false
currentNode.value.name = nodeName.value!
currentNode.value.candidateStrategy = configForm.value.candidateStrategy
currentNode.value.candidateParam = configForm.value.candidateParamArray?.join(',')
// 处理 candidateParam 参数
currentNode.value.candidateParam = handleCandidateParam()
// 设置审批方式
currentNode.value.approveMethod = configForm.value.approveMethod
if (configForm.value.approveMethod === ApproveMethodType.APPROVE_BY_RATIO) {
......@@ -521,19 +551,9 @@ const showUserTaskNodeConfig = (node: SimpleFlowNode) => {
nodeName.value = node.name
//1.1 审批人设置
configForm.value.candidateStrategy = node.candidateStrategy!
const strCandidateParam = node?.candidateParam
if (node.candidateStrategy === CandidateStrategy.EXPRESSION) {
configForm.value.candidateParamArray[0] = strCandidateParam
} else {
if (strCandidateParam) {
configForm.value.candidateParamArray = strCandidateParam.split(',').map((item) => +item)
}
}
if (
(configForm.value.candidateParamArray?.length <= 1 &&
node.candidateStrategy === CandidateStrategy.USER) ||
node.candidateStrategy === CandidateStrategy.START_USER
) {
// 解析候选人参数
parseCandidateParam(node.candidateStrategy!, node?.candidateParam)
if (configForm.value.deptIds && configForm.value.deptIds.length > 1) {
notAllowedMultiApprovers.value = true
} else {
notAllowedMultiApprovers.value = false
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment