This commit is contained in:
YunaiV
2025-03-30 10:54:06 +08:00
17 changed files with 575 additions and 127 deletions

View File

@@ -0,0 +1,122 @@
<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

@@ -91,6 +91,7 @@ import {
DEFAULT_CONDITION_GROUP_VALUE
} from './consts'
import { generateUUID } from '@/utils'
import { cloneDeep } from 'lodash-es'
defineOptions({
name: 'NodeHandler'
@@ -184,7 +185,7 @@ const addNode = (type: number) => {
conditionSetting: {
defaultFlow: false,
conditionType: ConditionType.RULE,
conditionGroups: DEFAULT_CONDITION_GROUP_VALUE
conditionGroups: cloneDeep(DEFAULT_CONDITION_GROUP_VALUE)
}
},
{
@@ -242,7 +243,7 @@ const addNode = (type: number) => {
conditionSetting: {
defaultFlow: false,
conditionType: ConditionType.RULE,
conditionGroups: DEFAULT_CONDITION_GROUP_VALUE
conditionGroups: cloneDeep(DEFAULT_CONDITION_GROUP_VALUE)
}
},
{

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,46 @@
</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
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 +132,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 +144,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 +175,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'

View File

@@ -254,6 +254,7 @@ import {
import { useWatchNode, useDrawer, useNodeName, useFormFields, getConditionShowText } from '../node'
import HttpRequestSetting from './components/HttpRequestSetting.vue'
import ConditionDialog from './components/ConditionDialog.vue'
import { cloneDeep } from 'lodash-es'
const { proxy } = getCurrentInstance() as any
defineOptions({
@@ -290,7 +291,7 @@ const configForm = ref<TriggerSetting>({
},
formSettings: [
{
conditionGroups: DEFAULT_CONDITION_GROUP_VALUE,
conditionGroups: cloneDeep(DEFAULT_CONDITION_GROUP_VALUE),
updateFormFields: {},
deleteFields: []
}
@@ -346,7 +347,7 @@ const changeTriggerType = () => {
? originalSetting.formSettings
: [
{
conditionGroups: DEFAULT_CONDITION_GROUP_VALUE,
conditionGroups: cloneDeep(DEFAULT_CONDITION_GROUP_VALUE),
updateFormFields: {},
deleteFields: []
}
@@ -361,7 +362,7 @@ const changeTriggerType = () => {
? originalSetting.formSettings
: [
{
conditionGroups: DEFAULT_CONDITION_GROUP_VALUE,
conditionGroups: cloneDeep(DEFAULT_CONDITION_GROUP_VALUE),
updateFormFields: undefined,
deleteFields: []
}
@@ -374,7 +375,7 @@ const changeTriggerType = () => {
/** 添加新的修改表单设置 */
const addFormSetting = () => {
configForm.value.formSettings!.push({
conditionGroups: DEFAULT_CONDITION_GROUP_VALUE,
conditionGroups: cloneDeep(DEFAULT_CONDITION_GROUP_VALUE),
updateFormFields: {},
deleteFields: []
})
@@ -509,7 +510,7 @@ const showTriggerNodeConfig = (node: SimpleFlowNode) => {
},
formSettings: node.triggerSetting.formSettings || [
{
conditionGroups: DEFAULT_CONDITION_GROUP_VALUE,
conditionGroups: cloneDeep(DEFAULT_CONDITION_GROUP_VALUE),
updateFormFields: {},
deleteFields: []
}

View File

@@ -154,6 +154,7 @@ import {
} from '../../consts'
import { BpmModelFormType } from '@/utils/constants'
import { useFormFieldsAndStartUser } from '../../node'
import { cloneDeep } from 'lodash-es'
const props = defineProps({
modelValue: {
@@ -196,7 +197,7 @@ const formRef = ref() // 表单 Ref
const changeConditionType = () => {
if (condition.value.conditionType === ConditionType.RULE) {
if (!condition.value.conditionGroups) {
condition.value.conditionGroups = DEFAULT_CONDITION_GROUP_VALUE
condition.value.conditionGroups = cloneDeep(DEFAULT_CONDITION_GROUP_VALUE)
}
}
}

View File

@@ -1,5 +1,5 @@
<!-- TODO @jason有可能它里面套 Condition -->
<!-- TODO 怕影响其它节点功能后面看看如何如何复用 Condtion -->
<!-- TODO 怕影响其它节点功能后面看看如何如何复用 Condtion -->
<template>
<Dialog v-model="dialogVisible" title="条件配置" width="600px" :fullscreen="false">
<div class="h-410px">
@@ -165,6 +165,7 @@ import {
} from '../../consts'
import { BpmModelFormType } from '@/utils/constants'
import { useFormFieldsAndStartUser } from '../../node'
import { cloneDeep } from 'lodash-es'
defineOptions({
name: 'ConditionDialog'
})
@@ -175,7 +176,7 @@ const condition = ref<{
conditionGroups?: ConditionGroup
}>({
conditionType: ConditionType.RULE,
conditionGroups: DEFAULT_CONDITION_GROUP_VALUE
conditionGroups: cloneDeep(DEFAULT_CONDITION_GROUP_VALUE)
})
const emit = defineEmits<{
@@ -210,7 +211,7 @@ const formRef = ref() // 表单 Ref
const changeConditionType = () => {
if (condition.value.conditionType === ConditionType.RULE) {
if (!condition.value.conditionGroups) {
condition.value.conditionGroups = DEFAULT_CONDITION_GROUP_VALUE
condition.value.conditionGroups = cloneDeep(DEFAULT_CONDITION_GROUP_VALUE)
}
}
}

View File

@@ -108,11 +108,18 @@
<script setup lang="ts">
import NodeHandler from '../NodeHandler.vue'
import ProcessNodeTree from '../ProcessNodeTree.vue'
import { SimpleFlowNode, NodeType, ConditionType, DEFAULT_CONDITION_GROUP_VALUE, NODE_DEFAULT_TEXT } from '../consts'
import {
SimpleFlowNode,
NodeType,
ConditionType,
DEFAULT_CONDITION_GROUP_VALUE,
NODE_DEFAULT_TEXT
} from '../consts'
import { getDefaultConditionNodeName } from '../utils'
import { useTaskStatusClass } from '../node'
import { generateUUID } from '@/utils'
import ConditionNodeConfig from '../nodes-config/ConditionNodeConfig.vue'
import { cloneDeep } from 'lodash-es'
const { proxy } = getCurrentInstance() as any
defineOptions({
name: 'ExclusiveNode'
@@ -149,7 +156,8 @@ const blurEvent = (index: number) => {
showInputs.value[index] = false
const conditionNode = currentNode.value.conditionNodes?.at(index) as SimpleFlowNode
conditionNode.name =
conditionNode.name || getDefaultConditionNodeName(index, conditionNode.conditionSetting?.defaultFlow)
conditionNode.name ||
getDefaultConditionNodeName(index, conditionNode.conditionSetting?.defaultFlow)
}
// 点击条件名称
@@ -181,7 +189,7 @@ const addCondition = () => {
conditionSetting: {
defaultFlow: false,
conditionType: ConditionType.RULE,
conditionGroups: DEFAULT_CONDITION_GROUP_VALUE
conditionGroups: cloneDeep(DEFAULT_CONDITION_GROUP_VALUE)
}
}
conditionNodes.splice(lastIndex, 0, conditionData)

View File

@@ -110,11 +110,18 @@
<script setup lang="ts">
import NodeHandler from '../NodeHandler.vue'
import ProcessNodeTree from '../ProcessNodeTree.vue'
import { SimpleFlowNode, NodeType, ConditionType, DEFAULT_CONDITION_GROUP_VALUE, NODE_DEFAULT_TEXT } from '../consts'
import {
SimpleFlowNode,
NodeType,
ConditionType,
DEFAULT_CONDITION_GROUP_VALUE,
NODE_DEFAULT_TEXT
} from '../consts'
import { useTaskStatusClass } from '../node'
import { getDefaultInclusiveConditionNodeName } from '../utils'
import { generateUUID } from '@/utils'
import ConditionNodeConfig from '../nodes-config/ConditionNodeConfig.vue'
import { cloneDeep } from 'lodash-es'
const { proxy } = getCurrentInstance() as any
defineOptions({
name: 'InclusiveNode'
@@ -153,7 +160,8 @@ const blurEvent = (index: number) => {
showInputs.value[index] = false
const conditionNode = currentNode.value.conditionNodes?.at(index) as SimpleFlowNode
conditionNode.name =
conditionNode.name || getDefaultInclusiveConditionNodeName(index, conditionNode.conditionSetting?.defaultFlow)
conditionNode.name ||
getDefaultInclusiveConditionNodeName(index, conditionNode.conditionSetting?.defaultFlow)
}
// 点击条件名称
@@ -185,7 +193,7 @@ const addCondition = () => {
conditionSetting: {
defaultFlow: false,
conditionType: ConditionType.RULE,
conditionGroups: DEFAULT_CONDITION_GROUP_VALUE
conditionGroups: cloneDeep(DEFAULT_CONDITION_GROUP_VALUE)
}
}
conditionNodes.splice(lastIndex, 0, conditionData)