【Simple设计器】流程模型->基本信息->谁可以发起,支持指定多个部门

指定部门可以在部门新增成员后无需重新修改相关流程

# Conflicts:
#	src/components/SimpleProcessDesignerV2/src/nodes-config/StartUserNodeConfig.vue
#	src/views/bpm/model/form/index.vue
This commit is contained in:
郑威
2025-03-17 15:33:11 +08:00
parent 41f2c7199e
commit 1b3cbfc881
8 changed files with 279 additions and 22 deletions

View File

@@ -0,0 +1,120 @@
<template>
<Dialog v-model="dialogVisible" title="部门选择" width="600">
<el-row v-loading="formLoading">
<el-col :span="24">
<ContentWrap class="h-1/1">
<el-tree
ref="treeRef"
:data="deptTree"
:props="defaultProps"
show-checkbox
:check-strictly="checkStrictly"
check-on-click-node
default-expand-all
highlight-current
node-key="id"
@check="handleCheck"
/>
</ContentWrap>
</el-col>
</el-row>
<template #footer>
<el-button
:disabled="formLoading || !selectedDeptIds?.length"
type="primary"
@click="submitForm"
>
</el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script lang="ts" setup>
import { defaultProps, handleTree } from '@/utils/tree'
import * as DeptApi from '@/api/system/dept'
defineOptions({ name: 'DeptSelectForm' })
const emit = defineEmits<{
confirm: [deptList: any[]]
}>()
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const props = defineProps({
// 是否严格的遵循父子不互相关联
checkStrictly: {
type: Boolean,
default: false
},
// 是否支持多选
multiple: {
type: Boolean,
default: true
}
})
const treeRef = ref()
const deptTree = ref<Tree[]>([]) // 部门树形结构
const selectedDeptIds = ref<number[]>([]) // 选中的部门ID列表
const dialogVisible = ref(false) // 弹窗的是否展示
const formLoading = ref(false) // 表单的加载中
/** 打开弹窗 */
const open = async (selectedList?: DeptApi.DeptVO[]) => {
resetForm()
formLoading.value = true
try {
// 加载部门列表
const deptData = await DeptApi.getSimpleDeptList()
deptTree.value = handleTree(deptData)
} finally {
formLoading.value = false
}
dialogVisible.value = true
// 设置已选择的部门
if (selectedList?.length) {
await nextTick()
const selectedIds = selectedList.map(dept => dept.id).filter((id): id is number => id !== undefined)
selectedDeptIds.value = selectedIds
treeRef.value?.setCheckedKeys(selectedIds)
}
}
/** 处理选中状态变化 */
const handleCheck = (data: any, checked: any) => {
selectedDeptIds.value = treeRef.value.getCheckedKeys()
if (!props.multiple && selectedDeptIds.value.length > 1) {
// 单选模式下,只保留最后选择的节点
const lastSelectedId = selectedDeptIds.value[selectedDeptIds.value.length - 1]
selectedDeptIds.value = [lastSelectedId]
treeRef.value.setCheckedKeys([lastSelectedId])
}
}
/** 提交选择 */
const submitForm = async () => {
try {
// 获取选中的完整部门数据
const checkedNodes = treeRef.value.getCheckedNodes()
message.success(t('common.updateSuccess'))
dialogVisible.value = false
emit('confirm', checkedNodes)
} finally {
}
}
/** 重置表单 */
const resetForm = () => {
deptTree.value = []
selectedDeptIds.value = []
if (treeRef.value) {
treeRef.value.setCheckedKeys([])
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
</script>

View File

@@ -59,6 +59,11 @@ const props = defineProps({
startUserIds: {
type: Array,
required: false
},
// 可发起流程的部门编号
startDeptIds: {
type: Array,
required: false
}
})
@@ -82,6 +87,7 @@ provide('deptList', deptOptions)
provide('userGroupList', userGroupOptions)
provide('deptTree', deptTreeOptions)
provide('startUserIds', props.startUserIds)
provide('startDeptIds', props.startDeptIds)
provide('tasks', [])
provide('processInstance', {})
const message = useMessage() // 国际化

View File

@@ -25,21 +25,38 @@
</template>
<el-tabs type="border-card" v-model="activeTabName">
<el-tab-pane label="权限" name="user">
<el-text v-if="!startUserIds || startUserIds.length === 0"> 全部成员可以发起流程 </el-text>
<el-text v-else-if="startUserIds.length == 1">
{{ getUserNicknames(startUserIds) }} 可发起流程
</el-text>
<el-text v-else>
<el-tooltip
class="box-item"
effect="dark"
placement="top"
:content="getUserNicknames(startUserIds)"
>
{{ getUserNicknames(startUserIds.slice(0, 2)) }}
{{ startUserIds.length }} 人可发起流程
</el-tooltip>
</el-text>
<el-text v-if="(!startUserIds || startUserIds.length === 0) && (!startDeptIds || startDeptIds.length === 0)"> 全部成员可以发起流程 </el-text>
<div v-else-if="startUserIds && startUserIds.length > 0">
<el-text v-if="startUserIds.length == 1">
{{ getUserNicknames(startUserIds) }} 可发起流程
</el-text>
<el-text v-else>
<el-tooltip
class="box-item"
effect="dark"
placement="top"
:content="getUserNicknames(startUserIds)"
>
{{ getUserNicknames(startUserIds.slice(0,2)) }} {{ startUserIds.length }} 人可发起流程
</el-tooltip>
</el-text>
</div>
<div v-else-if="startDeptIds && startDeptIds.length > 0">
<el-text v-if="startDeptIds.length == 1">
{{ getDeptNames(startDeptIds) }} 可发起流程
</el-text>
<el-text v-else>
<el-tooltip
class="box-item"
effect="dark"
placement="top"
:content="getDeptNames(startDeptIds)"
>
{{ getDeptNames(startDeptIds.slice(0,2)) }} {{ startDeptIds.length }} 个部门的人可发起流程
</el-tooltip>
</el-text>
</div>
</el-tab-pane>
<el-tab-pane label="表单字段权限" name="fields" v-if="formType === 10">
<div class="field-setting-pane">
@@ -107,6 +124,7 @@
import { SimpleFlowNode, NodeType, FieldPermissionType, START_USER_BUTTON_SETTING } from '../consts'
import { useWatchNode, useDrawer, useNodeName, useFormFieldsPermission } from '../node'
import * as UserApi from '@/api/system/user'
import * as DeptApi from '@/api/system/dept'
defineOptions({
name: 'StartUserNodeConfig'
})
@@ -118,8 +136,12 @@ const props = defineProps({
})
// 可发起流程的用户编号
const startUserIds = inject<Ref<any[]>>('startUserIds')
// 可发起流程的部门编号
const startDeptIds = inject<Ref<any[]>>('startDeptIds')
// 用户列表
const userOptions = inject<Ref<UserApi.UserVO[]>>('userList')
// 部门列表
const deptOptions = inject<Ref<DeptApi.DeptVO[]>>('deptList')
// 抽屉配置
const { settingVisible, closeDrawer, openDrawer } = useDrawer()
// 当前节点
@@ -145,6 +167,19 @@ const getUserNicknames = (userIds: number[]): string => {
})
return nicknames.join(',')
}
const getDeptNames = (deptIds: number[]): string => {
if (!deptIds || deptIds.length === 0) {
return ''
}
const deptNames: string[] = []
deptIds.forEach((deptId) => {
const found = deptOptions?.value.find((item) => item.id === deptId)
if (found && found.name) {
deptNames.push(found.name)
}
})
return deptNames.join(',')
}
// 保存配置
const saveConfig = async () => {
activeTabName.value = 'user'