仿钉钉流程设计器- 代码优化
parent
2c11228f55
commit
3a5c93fa84
|
@ -50,6 +50,7 @@ import CopyTaskNode from './nodes/CopyTaskNode.vue'
|
|||
import ExclusiveNode from './nodes/ExclusiveNode.vue'
|
||||
import ParallelNode from './nodes/ParallelNode.vue'
|
||||
import { SimpleFlowNode, NodeType } from './consts'
|
||||
import { useWatchNode } from './node'
|
||||
defineOptions({
|
||||
name: 'ProcessNodeTree'
|
||||
})
|
||||
|
@ -72,15 +73,8 @@ const emits = defineEmits<{
|
|||
]
|
||||
}>()
|
||||
|
||||
const currentNode = ref<SimpleFlowNode>(props.flowNode)
|
||||
const currentNode = useWatchNode(props)
|
||||
|
||||
// 重要:监控节点变化. 重新绘制节点
|
||||
watch(
|
||||
() => props.flowNode,
|
||||
(newValue) => {
|
||||
currentNode.value = newValue
|
||||
}
|
||||
)
|
||||
// 用于删除节点
|
||||
const handleModelValueUpdate = (updateValue) => {
|
||||
emits('update:flowNode', updateValue)
|
||||
|
|
|
@ -138,6 +138,7 @@ const zoomIn = () => {
|
|||
|
||||
onMounted(async () => {
|
||||
const result = await getBpmSimpleModel(props.modelId)
|
||||
console.log('the result is :', result)
|
||||
if (result) {
|
||||
processNodeTree.value = result
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// @ts-ignore
|
||||
import { DictDataVO } from '@/api/system/dict/types'
|
||||
|
||||
/**
|
||||
* 节点类型
|
||||
*/
|
||||
export enum NodeType {
|
||||
/**
|
||||
* 发起人节点
|
||||
|
@ -46,68 +48,37 @@ export enum NodeType {
|
|||
*/
|
||||
INCLUSIVE_NODE_JOIN = 8
|
||||
}
|
||||
// 时间单位枚举
|
||||
export enum TimeUnitType {
|
||||
/**
|
||||
* 分钟
|
||||
*/
|
||||
MINUTE = 1,
|
||||
/**
|
||||
* 小时
|
||||
*/
|
||||
HOUR = 2,
|
||||
/**
|
||||
* 天
|
||||
*/
|
||||
DAY = 3
|
||||
/**
|
||||
* 节点结构定义
|
||||
*/
|
||||
export interface SimpleFlowNode {
|
||||
id: string
|
||||
type: NodeType
|
||||
name: string
|
||||
showText?: string
|
||||
attributes?: any
|
||||
// 孩子节点
|
||||
childNode?: SimpleFlowNode
|
||||
// 条件节点
|
||||
conditionNodes?: SimpleFlowNode[]
|
||||
// 候选人策略
|
||||
candidateStrategy?: number
|
||||
// 候选人参数
|
||||
candidateParam?: string
|
||||
// 多人审批方式
|
||||
approveMethod?: ApproveMethodType
|
||||
//通过比例
|
||||
approveRatio?: number
|
||||
// 审批按钮设置
|
||||
buttonsSetting?: any[]
|
||||
// 表单权限
|
||||
fieldsPermission?: Array<Record<string, string>>
|
||||
// 审批任务超时处理
|
||||
timeoutHandler?: TimeoutHandler
|
||||
// 审批任务拒绝处理
|
||||
rejectHandler?: RejectHandler
|
||||
}
|
||||
|
||||
export enum RejectHandlerType {
|
||||
/**
|
||||
* 结束流程
|
||||
*/
|
||||
FINISH_PROCESS = 1,
|
||||
/**
|
||||
* 驳回到指定节点
|
||||
*/
|
||||
RETURN_USER_TASK = 2
|
||||
}
|
||||
|
||||
// 条件配置类型 ( 用于条件节点配置 )
|
||||
export enum ConditionConfigType {
|
||||
/**
|
||||
* 条件表达式
|
||||
*/
|
||||
EXPRESSION = 1,
|
||||
|
||||
/**
|
||||
* 条件规则
|
||||
*/
|
||||
RULE = 2
|
||||
}
|
||||
// 多人审批方式类型 ( 用于审批节点 )
|
||||
export enum ApproveMethodType {
|
||||
/**
|
||||
* 随机挑选一人审批
|
||||
*/
|
||||
RRANDOM_SELECT_ONE_APPROVE = 1,
|
||||
|
||||
/**
|
||||
* 多人会签(按通过比例)
|
||||
*/
|
||||
APPROVE_BY_RATIO = 2,
|
||||
|
||||
/**
|
||||
* 多人或签(通过只需一人,拒绝只需一人)
|
||||
*/
|
||||
ANY_APPROVE = 3,
|
||||
/**
|
||||
* 多人依次审批
|
||||
*/
|
||||
SEQUENTIAL_APPROVE = 4
|
||||
}
|
||||
|
||||
// 候选人策略 ( 用于审批节点。抄送节点 )
|
||||
// 候选人策略枚举 ( 用于审批节点。抄送节点 )
|
||||
export enum CandidateStrategy {
|
||||
/**
|
||||
* 指定角色
|
||||
|
@ -147,12 +118,41 @@ export enum CandidateStrategy {
|
|||
EXPRESSION = 60
|
||||
}
|
||||
|
||||
export type RejectHandler = {
|
||||
type: RejectHandlerType
|
||||
// 多人审批方式类型枚举 ( 用于审批节点 )
|
||||
export enum ApproveMethodType {
|
||||
/**
|
||||
* 随机挑选一人审批
|
||||
*/
|
||||
RRANDOM_SELECT_ONE_APPROVE = 1,
|
||||
|
||||
/**
|
||||
* 多人会签(按通过比例)
|
||||
*/
|
||||
APPROVE_BY_RATIO = 2,
|
||||
|
||||
/**
|
||||
* 多人或签(通过只需一人,拒绝只需一人)
|
||||
*/
|
||||
ANY_APPROVE = 3,
|
||||
/**
|
||||
* 多人依次审批
|
||||
*/
|
||||
SEQUENTIAL_APPROVE = 4
|
||||
}
|
||||
|
||||
/**
|
||||
* 审批拒绝结构定义
|
||||
*/
|
||||
export type RejectHandler = {
|
||||
// 审批拒绝类型
|
||||
type: RejectHandlerType
|
||||
// 回退节点 Id
|
||||
returnNodeId?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* 审批超时结构定义
|
||||
*/
|
||||
export type TimeoutHandler = {
|
||||
//是否开启超时处理
|
||||
enable: boolean
|
||||
|
@ -163,60 +163,57 @@ export type TimeoutHandler = {
|
|||
// 执行动作是自动提醒, 最大提醒次数
|
||||
maxRemindCount?: number
|
||||
}
|
||||
|
||||
export type SimpleFlowNode = {
|
||||
id: string
|
||||
type: NodeType
|
||||
name: string
|
||||
showText?: string
|
||||
attributes?: any
|
||||
// 孩子节点
|
||||
childNode?: SimpleFlowNode
|
||||
// 条件节点
|
||||
conditionNodes?: SimpleFlowNode[]
|
||||
// 候选人策略
|
||||
candidateStrategy?: number
|
||||
// 候选人参数
|
||||
candidateParam?: string
|
||||
// 多人审批方式
|
||||
approveMethod?: ApproveMethodType
|
||||
//通过比例
|
||||
approveRatio?: number
|
||||
// 审批按钮设置
|
||||
buttonsSetting?: any[]
|
||||
// 表单权限
|
||||
fieldsPermission?: any[]
|
||||
// 审批任务超时处理
|
||||
timeoutHandler?: TimeoutHandler
|
||||
// 审批任务拒绝处理
|
||||
rejectHandler?: RejectHandler
|
||||
// 审批拒绝类型枚举
|
||||
export enum RejectHandlerType {
|
||||
/**
|
||||
* 结束流程
|
||||
*/
|
||||
FINISH_PROCESS = 1,
|
||||
/**
|
||||
* 驳回到指定节点
|
||||
*/
|
||||
RETURN_USER_TASK = 2
|
||||
}
|
||||
|
||||
// 条件组
|
||||
export type ConditionGroup = {
|
||||
// 条件组的逻辑关系是否为且
|
||||
and: boolean
|
||||
// 条件数组
|
||||
conditions: Condition[]
|
||||
// 时间单位枚举
|
||||
export enum TimeUnitType {
|
||||
/**
|
||||
* 分钟
|
||||
*/
|
||||
MINUTE = 1,
|
||||
/**
|
||||
* 小时
|
||||
*/
|
||||
HOUR = 2,
|
||||
/**
|
||||
* 天
|
||||
*/
|
||||
DAY = 3
|
||||
}
|
||||
|
||||
// 条件
|
||||
export type Condition = {
|
||||
// 条件规则的逻辑关系是否为且
|
||||
and: boolean
|
||||
rules: ConditionRule[]
|
||||
// 条件配置类型 ( 用于条件节点配置 )
|
||||
export enum ConditionConfigType {
|
||||
/**
|
||||
* 条件表达式
|
||||
*/
|
||||
EXPRESSION = 1,
|
||||
|
||||
/**
|
||||
* 条件规则
|
||||
*/
|
||||
RULE = 2
|
||||
}
|
||||
|
||||
// 条件规则
|
||||
export type ConditionRule = {
|
||||
type: number
|
||||
opName: string
|
||||
opCode: string
|
||||
leftSide: string
|
||||
rightSide: string
|
||||
/**
|
||||
* 操作按钮权限结构定义
|
||||
*/
|
||||
export type ButtonSetting = {
|
||||
id: OpsButtonType
|
||||
displayName: string
|
||||
enable: boolean
|
||||
}
|
||||
|
||||
// 审批操作按钮类型
|
||||
// 操作按钮类型枚举 (用于审批节点)
|
||||
export enum OpsButtonType {
|
||||
/**
|
||||
* 通过
|
||||
|
@ -243,11 +240,34 @@ export enum OpsButtonType {
|
|||
*/
|
||||
RETURN = 6
|
||||
}
|
||||
/**
|
||||
* 条件规则结构定义
|
||||
*/
|
||||
export type ConditionRule = {
|
||||
type: number
|
||||
opName: string
|
||||
opCode: string
|
||||
leftSide: string
|
||||
rightSide: string
|
||||
}
|
||||
|
||||
export type ButtonSetting = {
|
||||
id: OpsButtonType
|
||||
displayName: string
|
||||
enable: boolean
|
||||
/**
|
||||
* 条件组结构定义
|
||||
*/
|
||||
export type ConditionGroup = {
|
||||
// 条件组的逻辑关系是否为且
|
||||
and: boolean
|
||||
// 条件数组
|
||||
conditions: Condition[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件结构定义
|
||||
*/
|
||||
export type Condition = {
|
||||
// 条件规则的逻辑关系是否为且
|
||||
and: boolean
|
||||
rules: ConditionRule[]
|
||||
}
|
||||
|
||||
export const NODE_DEFAULT_TEXT = new Map<number, string>()
|
||||
|
|
|
@ -0,0 +1,260 @@
|
|||
import { cloneDeep } from 'lodash-es'
|
||||
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'
|
||||
import {
|
||||
SimpleFlowNode,
|
||||
CandidateStrategy,
|
||||
NodeType,
|
||||
ApproveMethodType,
|
||||
RejectHandlerType,
|
||||
NODE_DEFAULT_NAME
|
||||
} from './consts'
|
||||
export function useWatchNode(props: { flowNode: SimpleFlowNode }): Ref<SimpleFlowNode> {
|
||||
const node = ref<SimpleFlowNode>(props.flowNode)
|
||||
watch(
|
||||
() => props.flowNode,
|
||||
(newValue) => {
|
||||
node.value = newValue
|
||||
}
|
||||
)
|
||||
return node
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 表单数据权限配置,用于审批节点、抄送节点
|
||||
*/
|
||||
export function useFormFieldsPermission() {
|
||||
// 字段权限配置. 需要有 field, title, permissioin 属性
|
||||
const fieldsPermissionConfig = ref<Array<Record<string, string>>>([])
|
||||
|
||||
const formType = inject<Ref<number>>('formType') // 表单类型
|
||||
|
||||
const formFields = inject<Ref<string[]>>('formFields') // 流程表单字段
|
||||
|
||||
const getNodeConfigFormFields = (nodeFormFields?: Array<Record<string, string>>) => {
|
||||
nodeFormFields = toRaw(nodeFormFields)
|
||||
fieldsPermissionConfig.value =
|
||||
cloneDeep(nodeFormFields) || getDefaultFieldsPermission(unref(formFields))
|
||||
}
|
||||
// 获取默认的表单权限。 所有字段只读
|
||||
const getDefaultFieldsPermission = (formFields?: string[]) => {
|
||||
const defaultFieldsPermission: Array<Record<string, string>> = []
|
||||
if (formFields) {
|
||||
formFields.forEach((fieldStr: string) => {
|
||||
const { field, title } = JSON.parse(fieldStr)
|
||||
defaultFieldsPermission.push({
|
||||
field,
|
||||
title,
|
||||
permission: '1' // 只读
|
||||
})
|
||||
})
|
||||
}
|
||||
return defaultFieldsPermission
|
||||
}
|
||||
|
||||
return {
|
||||
formType,
|
||||
fieldsPermissionConfig,
|
||||
getNodeConfigFormFields
|
||||
}
|
||||
}
|
||||
|
||||
export type UserTaskFormType = {
|
||||
candidateParamArray: any[]
|
||||
candidateStrategy: CandidateStrategy
|
||||
approveMethod: ApproveMethodType
|
||||
approveRatio?: number
|
||||
rejectHandlerType?: RejectHandlerType
|
||||
returnNodeId?: string
|
||||
timeoutHandlerEnable?: boolean
|
||||
timeoutHandlerAction?: number
|
||||
timeDuration?: number
|
||||
maxRemindCount?: number
|
||||
buttonsSetting: any[]
|
||||
}
|
||||
|
||||
export type CopyTaskFormType = {
|
||||
candidateParamArray: any[]
|
||||
candidateStrategy: CandidateStrategy
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 节点表单数据。 用于审批节点、抄送节点
|
||||
*/
|
||||
export function useNodeForm(nodeType: NodeType) {
|
||||
const roleOptions = inject<Ref<RoleApi.RoleVO[]>>('roleList') // 角色列表
|
||||
const postOptions = inject<Ref<PostApi.PostVO[]>>('postList') // 岗位列表
|
||||
const userOptions = inject<Ref<UserApi.UserVO[]>>('userList') // 用户列表
|
||||
const deptOptions = inject<Ref<DeptApi.DeptVO[]>>('deptList') // 部门列表
|
||||
const userGroupOptions = inject<Ref<UserGroupApi.UserGroupVO[]>>('userGroupList') // 用户组列表
|
||||
const deptTreeOptions = inject('deptTree') // 部门树
|
||||
const configForm = ref<UserTaskFormType | CopyTaskFormType>()
|
||||
if (nodeType === NodeType.USER_TASK_NODE) {
|
||||
configForm.value = {
|
||||
candidateParamArray: [],
|
||||
candidateStrategy: CandidateStrategy.USER,
|
||||
approveMethod: ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE,
|
||||
approveRatio: 100,
|
||||
rejectHandlerType: RejectHandlerType.FINISH_PROCESS,
|
||||
returnNodeId: '',
|
||||
timeoutHandlerEnable: false,
|
||||
timeoutHandlerAction: 1,
|
||||
timeDuration: 6, // 默认 6小时
|
||||
maxRemindCount: 1, // 默认 提醒 1次
|
||||
buttonsSetting: []
|
||||
}
|
||||
} else {
|
||||
configForm.value = {
|
||||
candidateParamArray: [],
|
||||
candidateStrategy: CandidateStrategy.USER
|
||||
}
|
||||
}
|
||||
|
||||
const getShowText = (): string => {
|
||||
let showText = ''
|
||||
// 指定成员
|
||||
if (configForm.value?.candidateStrategy === CandidateStrategy.USER) {
|
||||
if (configForm.value.candidateParamArray?.length > 0) {
|
||||
const candidateNames: string[] = []
|
||||
userOptions?.value.forEach((item) => {
|
||||
if (configForm.value?.candidateParamArray.includes(item.id)) {
|
||||
candidateNames.push(item.nickname)
|
||||
}
|
||||
})
|
||||
showText = `指定成员:${candidateNames.join(',')}`
|
||||
}
|
||||
}
|
||||
// 指定角色
|
||||
if (configForm.value?.candidateStrategy === CandidateStrategy.ROLE) {
|
||||
if (configForm.value.candidateParamArray?.length > 0) {
|
||||
const candidateNames: string[] = []
|
||||
roleOptions?.value.forEach((item) => {
|
||||
if (configForm.value?.candidateParamArray.includes(item.id)) {
|
||||
candidateNames.push(item.name)
|
||||
}
|
||||
})
|
||||
showText = `指定角色:${candidateNames.join(',')}`
|
||||
}
|
||||
}
|
||||
// 指定部门
|
||||
if (
|
||||
configForm.value?.candidateStrategy === CandidateStrategy.DEPT_MEMBER ||
|
||||
configForm.value?.candidateStrategy === CandidateStrategy.DEPT_LEADER
|
||||
) {
|
||||
if (configForm.value?.candidateParamArray?.length > 0) {
|
||||
const candidateNames: string[] = []
|
||||
deptOptions?.value.forEach((item) => {
|
||||
if (configForm.value?.candidateParamArray.includes(item.id)) {
|
||||
candidateNames.push(item.name)
|
||||
}
|
||||
})
|
||||
if (configForm.value.candidateStrategy === CandidateStrategy.DEPT_MEMBER) {
|
||||
showText = `部门成员:${candidateNames.join(',')}`
|
||||
} else {
|
||||
showText = `部门的负责人:${candidateNames.join(',')}`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 指定岗位
|
||||
if (configForm.value?.candidateStrategy === CandidateStrategy.POST) {
|
||||
if (configForm.value.candidateParamArray?.length > 0) {
|
||||
const candidateNames: string[] = []
|
||||
postOptions?.value.forEach((item) => {
|
||||
if (configForm.value?.candidateParamArray.includes(item.id)) {
|
||||
candidateNames.push(item.name)
|
||||
}
|
||||
})
|
||||
showText = `指定岗位: ${candidateNames.join(',')}`
|
||||
}
|
||||
}
|
||||
// 指定用户组
|
||||
if (configForm.value?.candidateStrategy === CandidateStrategy.USER_GROUP) {
|
||||
if (configForm.value?.candidateParamArray?.length > 0) {
|
||||
const candidateNames: string[] = []
|
||||
userGroupOptions?.value.forEach((item) => {
|
||||
if (configForm.value?.candidateParamArray.includes(item.id)) {
|
||||
candidateNames.push(item.name)
|
||||
}
|
||||
})
|
||||
showText = `指定用户组: ${candidateNames.join(',')}`
|
||||
}
|
||||
}
|
||||
|
||||
// 发起人自选
|
||||
if (configForm.value?.candidateStrategy === CandidateStrategy.START_USER_SELECT) {
|
||||
showText = `发起人自选`
|
||||
}
|
||||
// 发起人自己
|
||||
if (configForm.value?.candidateStrategy === CandidateStrategy.START_USER) {
|
||||
showText = `发起人自己`
|
||||
}
|
||||
|
||||
// 流程表达式
|
||||
if (configForm.value?.candidateStrategy === CandidateStrategy.EXPRESSION) {
|
||||
if (configForm.value.candidateParamArray?.length > 0) {
|
||||
showText = `流程表达式:${configForm.value.candidateParamArray[0]}`
|
||||
}
|
||||
}
|
||||
return showText
|
||||
}
|
||||
|
||||
return {
|
||||
configForm,
|
||||
roleOptions,
|
||||
postOptions,
|
||||
userOptions,
|
||||
userGroupOptions,
|
||||
deptTreeOptions,
|
||||
getShowText
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 抽屉配置
|
||||
*/
|
||||
export function useDrawer() {
|
||||
// 抽屉配置是否可见
|
||||
const settingVisible = ref(false)
|
||||
// 关闭配置抽屉
|
||||
const closeDrawer = () => {
|
||||
settingVisible.value = false
|
||||
}
|
||||
// 打开配置抽屉
|
||||
const openDrawer = () => {
|
||||
settingVisible.value = true
|
||||
}
|
||||
return {
|
||||
settingVisible,
|
||||
closeDrawer,
|
||||
openDrawer
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 节点名称配置
|
||||
*/
|
||||
export function useNodeName(nodeType: NodeType) {
|
||||
// 节点名称
|
||||
const nodeName = ref<string>()
|
||||
// 节点名称输入框
|
||||
const showInput = ref(false)
|
||||
// 点击节点名称编辑图标
|
||||
const clickIcon = () => {
|
||||
showInput.value = true
|
||||
}
|
||||
// 节点名称输入框失去焦点
|
||||
const blurEvent = () => {
|
||||
showInput.value = false
|
||||
nodeName.value = nodeName.value || (NODE_DEFAULT_NAME.get(nodeType) as string)
|
||||
}
|
||||
return {
|
||||
nodeName,
|
||||
showInput,
|
||||
clickIcon,
|
||||
blurEvent
|
||||
}
|
||||
}
|
|
@ -14,14 +14,12 @@
|
|||
class="config-editable-input"
|
||||
@blur="blurEvent()"
|
||||
v-mountedFocus
|
||||
v-model="configForm.name"
|
||||
:placeholder="configForm.name"
|
||||
v-model="nodeName"
|
||||
:placeholder="nodeName"
|
||||
/>
|
||||
<div v-else class="node-name"
|
||||
>{{ configForm.name }}
|
||||
<Icon class="ml-1" icon="ep:edit-pen" :size="16" @click="clickIcon()"
|
||||
/></div>
|
||||
|
||||
<div v-else class="node-name">
|
||||
{{ nodeName }} <Icon class="ml-1" icon="ep:edit-pen" :size="16" @click="clickIcon()" />
|
||||
</div>
|
||||
<div class="divide-line"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -173,7 +171,7 @@
|
|||
</div>
|
||||
<div
|
||||
class="field-setting-item"
|
||||
v-for="(item, index) in configForm.fieldsPermission"
|
||||
v-for="(item, index) in fieldsPermissionConfig"
|
||||
:key="index"
|
||||
>
|
||||
<div class="field-setting-item-label"> {{ item.title }} </div>
|
||||
|
@ -202,16 +200,17 @@
|
|||
</el-drawer>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { SimpleFlowNode, CandidateStrategy, NodeType, NODE_DEFAULT_NAME } from '../consts'
|
||||
import { getDefaultFieldsPermission } from '../utils'
|
||||
import { SimpleFlowNode, CandidateStrategy, NodeType } from '../consts'
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
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'
|
||||
import {
|
||||
useWatchNode,
|
||||
useDrawer,
|
||||
useNodeName,
|
||||
useFormFieldsPermission,
|
||||
useNodeForm,
|
||||
CopyTaskFormType
|
||||
} from '../node'
|
||||
import { defaultProps } from '@/utils/tree'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
defineOptions({
|
||||
name: 'CopyTaskNodeConfig'
|
||||
})
|
||||
|
@ -221,26 +220,34 @@ const props = defineProps({
|
|||
required: true
|
||||
}
|
||||
})
|
||||
// 是否可见
|
||||
const settingVisible = ref(false)
|
||||
// 抽屉配置
|
||||
const { settingVisible, closeDrawer, openDrawer } = useDrawer()
|
||||
// 当前节点
|
||||
const currentNode = ref<SimpleFlowNode>(props.flowNode)
|
||||
// 监控节点变化
|
||||
watch(
|
||||
() => props.flowNode,
|
||||
(newValue) => {
|
||||
currentNode.value = newValue
|
||||
}
|
||||
)
|
||||
const roleOptions = inject<Ref<RoleApi.RoleVO[]>>('roleList') // 角色列表
|
||||
const postOptions = inject<Ref<PostApi.PostVO[]>>('postList') // 岗位列表
|
||||
const userOptions = inject<Ref<UserApi.UserVO[]>>('userList') // 用户列表
|
||||
const deptOptions = inject<Ref<DeptApi.DeptVO[]>>('deptList') // 部门列表
|
||||
const userGroupOptions = inject<Ref<UserGroupApi.UserGroupVO[]>>('userGroupList') // 用户组列表
|
||||
const deptTreeOptions = inject('deptTree') // 部门树
|
||||
const formType = inject('formType') // 表单类型
|
||||
const formFields = inject<Ref<string[]>>('formFields')
|
||||
const currentNode = useWatchNode(props)
|
||||
// 节点名称
|
||||
const { nodeName, showInput, clickIcon, blurEvent } = useNodeName(NodeType.COPY_TASK_NODE)
|
||||
// 激活的 Tab 标签页
|
||||
const activeTabName = ref('user')
|
||||
// 表单字段权限配置
|
||||
const { formType, fieldsPermissionConfig, getNodeConfigFormFields } = useFormFieldsPermission()
|
||||
// 抄送人表单配置
|
||||
const formRef = ref() // 表单 Ref
|
||||
// 表单校验规则
|
||||
const formRules = reactive({
|
||||
candidateStrategy: [{ required: true, message: '抄送人设置不能为空', trigger: 'change' }],
|
||||
candidateParamArray: [{ required: true, message: '选项不能为空', trigger: 'blur' }]
|
||||
})
|
||||
|
||||
const {
|
||||
configForm: tempConfigForm,
|
||||
roleOptions,
|
||||
postOptions,
|
||||
userOptions,
|
||||
userGroupOptions,
|
||||
deptTreeOptions,
|
||||
getShowText
|
||||
} = useNodeForm(NodeType.COPY_TASK_NODE)
|
||||
const configForm = tempConfigForm as Ref<CopyTaskFormType>
|
||||
// 抄送人策略, 去掉发起人自选 和 发起人自己
|
||||
const copyUserStrategies = computed(() => {
|
||||
return getIntDictOptions(DICT_TYPE.BPM_TASK_CANDIDATE_STRATEGY).filter(
|
||||
|
@ -249,25 +256,9 @@ const copyUserStrategies = computed(() => {
|
|||
item.value !== CandidateStrategy.START_USER
|
||||
)
|
||||
})
|
||||
// 激活的 Tab 标签页
|
||||
const activeTabName = ref('user')
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
const configForm = ref<any>({
|
||||
name: NODE_DEFAULT_NAME.get(NodeType.COPY_TASK_NODE),
|
||||
candidateParamArray: [],
|
||||
candidateStrategy: CandidateStrategy.USER,
|
||||
fieldsPermission: []
|
||||
})
|
||||
// 表单校验规则
|
||||
const formRules = reactive({
|
||||
candidateStrategy: [{ required: true, message: '抄送人设置不能为空', trigger: 'change' }],
|
||||
candidateParamArray: [{ required: true, message: '选项不能为空', trigger: 'blur' }]
|
||||
})
|
||||
|
||||
// 关闭
|
||||
const closeDrawer = () => {
|
||||
settingVisible.value = false
|
||||
// 改变抄送人设置策略
|
||||
const changeCandidateStrategy = () => {
|
||||
configForm.value.candidateParamArray = []
|
||||
}
|
||||
// 保存配置
|
||||
const saveConfig = async () => {
|
||||
|
@ -277,23 +268,19 @@ const saveConfig = async () => {
|
|||
if (!valid) return false
|
||||
const showText = getShowText()
|
||||
if (!showText) return false
|
||||
currentNode.value.name = configForm.value.name
|
||||
currentNode.value.name = nodeName.value!
|
||||
currentNode.value.candidateParam = configForm.value.candidateParamArray?.join(',')
|
||||
currentNode.value.candidateStrategy = configForm.value.candidateStrategy
|
||||
currentNode.value.showText = showText
|
||||
currentNode.value.fieldsPermission = configForm.value.fieldsPermission
|
||||
currentNode.value.fieldsPermission = fieldsPermissionConfig.value
|
||||
settingVisible.value = false
|
||||
return true
|
||||
}
|
||||
|
||||
const open = () => {
|
||||
settingVisible.value = true
|
||||
}
|
||||
// 设置抄送节点
|
||||
const setCurrentNode = (node: SimpleFlowNode) => {
|
||||
configForm.value.name = node.name
|
||||
// 显示抄送节点配置, 由父组件传过来
|
||||
const showCopyTaskNodeConfig = (node: SimpleFlowNode) => {
|
||||
nodeName.value = node.name
|
||||
// 抄送人设置
|
||||
configForm.value.candidateStrategy = node.candidateStrategy
|
||||
configForm.value.candidateStrategy = node.candidateStrategy!
|
||||
const strCandidateParam = node?.candidateParam
|
||||
if (node.candidateStrategy === CandidateStrategy.EXPRESSION) {
|
||||
configForm.value.candidateParamArray[0] = strCandidateParam
|
||||
|
@ -303,104 +290,10 @@ const setCurrentNode = (node: SimpleFlowNode) => {
|
|||
}
|
||||
}
|
||||
// 表单字段权限
|
||||
configForm.value.fieldsPermission =
|
||||
cloneDeep(node.fieldsPermission) || getDefaultFieldsPermission(formFields?.value)
|
||||
getNodeConfigFormFields(node.fieldsPermission)
|
||||
}
|
||||
|
||||
defineExpose({ open, setCurrentNode }) // 暴露方法给父组件
|
||||
const changeCandidateStrategy = () => {
|
||||
configForm.value.candidateParamArray = []
|
||||
}
|
||||
// TODO 貌似可以和 UserTaskNodeConfig 重复了, 如何共用??
|
||||
const getShowText = (): string => {
|
||||
let showText = ''
|
||||
// 指定成员
|
||||
if (configForm.value.candidateStrategy === CandidateStrategy.USER) {
|
||||
if (configForm.value.candidateParamArray?.length > 0) {
|
||||
const candidateNames: string[] = []
|
||||
userOptions?.value.forEach((item) => {
|
||||
if (configForm.value.candidateParamArray.includes(item.id)) {
|
||||
candidateNames.push(item.nickname)
|
||||
}
|
||||
})
|
||||
showText = `指定成员:${candidateNames.join(',')}`
|
||||
}
|
||||
}
|
||||
// 指定角色
|
||||
if (configForm.value.candidateStrategy === CandidateStrategy.ROLE) {
|
||||
if (configForm.value.candidateParamArray?.length > 0) {
|
||||
const candidateNames: string[] = []
|
||||
roleOptions?.value.forEach((item) => {
|
||||
if (configForm.value.candidateParamArray.includes(item.id)) {
|
||||
candidateNames.push(item.name)
|
||||
}
|
||||
})
|
||||
showText = `指定角色:${candidateNames.join(',')}`
|
||||
}
|
||||
}
|
||||
// 指定部门
|
||||
if (
|
||||
configForm.value.candidateStrategy === CandidateStrategy.DEPT_MEMBER ||
|
||||
configForm.value.candidateStrategy === CandidateStrategy.DEPT_LEADER
|
||||
) {
|
||||
if (configForm.value.candidateParamArray?.length > 0) {
|
||||
const candidateNames: string[] = []
|
||||
deptOptions?.value.forEach((item) => {
|
||||
if (configForm.value.candidateParamArray.includes(item.id)) {
|
||||
candidateNames.push(item.name)
|
||||
}
|
||||
})
|
||||
if (currentNode.value.candidateStrategy === CandidateStrategy.DEPT_MEMBER) {
|
||||
showText = `部门成员:${candidateNames.join(',')}`
|
||||
} else {
|
||||
showText = `部门的负责人:${candidateNames.join(',')}`
|
||||
}
|
||||
}
|
||||
}
|
||||
// 指定岗位
|
||||
if (configForm.value.candidateStrategy === CandidateStrategy.POST) {
|
||||
if (configForm.value.candidateParamArray?.length > 0) {
|
||||
const candidateNames: string[] = []
|
||||
postOptions?.value.forEach((item) => {
|
||||
if (configForm.value.candidateParamArray.includes(item.id)) {
|
||||
candidateNames.push(item.name)
|
||||
}
|
||||
})
|
||||
showText = `指定岗位: ${candidateNames.join(',')}`
|
||||
}
|
||||
}
|
||||
// 指定用户组
|
||||
if (configForm.value.candidateStrategy === CandidateStrategy.USER_GROUP) {
|
||||
if (configForm.value.candidateParamArray?.length > 0) {
|
||||
const candidateNames: string[] = []
|
||||
userGroupOptions?.value.forEach((item) => {
|
||||
if (configForm.value.candidateParamArray.includes(item.id)) {
|
||||
candidateNames.push(item.name)
|
||||
}
|
||||
})
|
||||
showText = `指定用户组: ${candidateNames.join(',')}`
|
||||
}
|
||||
}
|
||||
// 流程表达式
|
||||
if (configForm.value.candidateStrategy === CandidateStrategy.EXPRESSION) {
|
||||
if (configForm.value.candidateParamArray?.length > 0) {
|
||||
showText = `流程表达式:${configForm.value.candidateParamArray[0]}`
|
||||
}
|
||||
}
|
||||
return showText
|
||||
}
|
||||
// 显示名称输入框
|
||||
const showInput = ref(false)
|
||||
|
||||
const clickIcon = () => {
|
||||
showInput.value = true
|
||||
}
|
||||
// 输入框失去焦点
|
||||
const blurEvent = () => {
|
||||
showInput.value = false
|
||||
configForm.value.name =
|
||||
configForm.value.name || (NODE_DEFAULT_NAME.get(NodeType.COPY_TASK_NODE) as string)
|
||||
}
|
||||
defineExpose({ openDrawer, showCopyTaskNodeConfig }) // 暴露方法给父组件
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
|
@ -15,14 +15,12 @@
|
|||
class="config-editable-input"
|
||||
@blur="blurEvent()"
|
||||
v-mountedFocus
|
||||
v-model="configForm.name"
|
||||
:placeholder="configForm.name"
|
||||
v-model="nodeName"
|
||||
:placeholder="nodeName"
|
||||
/>
|
||||
<div v-else class="node-name"
|
||||
>{{ configForm.name }}
|
||||
<Icon class="ml-1" icon="ep:edit-pen" :size="16" @click="clickIcon()"
|
||||
/></div>
|
||||
|
||||
<div v-else class="node-name">
|
||||
{{ nodeName }} <Icon class="ml-1" icon="ep:edit-pen" :size="16" @click="clickIcon()" />
|
||||
</div>
|
||||
<div class="divide-line"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -280,7 +278,7 @@
|
|||
</el-form>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="操作按钮设置" name="buttons" v-if="formType === 10">
|
||||
<el-tab-pane label="操作按钮设置" name="buttons">
|
||||
<div class="button-setting-pane">
|
||||
<div class="button-setting-desc">操作按钮</div>
|
||||
<div class="button-setting-title">
|
||||
|
@ -288,11 +286,7 @@
|
|||
<div class="pl-4 button-title-label">显示名称</div>
|
||||
<div class="button-title-label">启用</div>
|
||||
</div>
|
||||
<div
|
||||
class="button-setting-item"
|
||||
v-for="(item, index) in configForm.buttonsSetting"
|
||||
:key="index"
|
||||
>
|
||||
<div class="button-setting-item" v-for="(item, index) in buttonsSetting" :key="index">
|
||||
<div class="button-setting-item-label"> {{ OPERATION_BUTTON_NAME.get(item.id) }} </div>
|
||||
<div class="button-setting-item-label">
|
||||
<input
|
||||
|
@ -327,7 +321,7 @@
|
|||
</div>
|
||||
<div
|
||||
class="field-setting-item"
|
||||
v-for="(item, index) in configForm.fieldsPermission"
|
||||
v-for="(item, index) in fieldsPermissionConfig"
|
||||
:key="index"
|
||||
>
|
||||
<div class="field-setting-item-label"> {{ item.title }} </div>
|
||||
|
@ -368,19 +362,22 @@ import {
|
|||
TIMEOUT_HANDLER_ACTION_TYPES,
|
||||
TIME_UNIT_TYPES,
|
||||
REJECT_HANDLER_TYPES,
|
||||
NODE_DEFAULT_NAME,
|
||||
DEFAULT_BUTTON_SETTING,
|
||||
OPERATION_BUTTON_NAME
|
||||
OPERATION_BUTTON_NAME,
|
||||
ButtonSetting
|
||||
} from '../consts'
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import { getDefaultFieldsPermission } from '../utils'
|
||||
import {
|
||||
useWatchNode,
|
||||
useNodeName,
|
||||
useFormFieldsPermission,
|
||||
useNodeForm,
|
||||
UserTaskFormType,
|
||||
useDrawer
|
||||
} from '../node'
|
||||
import { defaultProps } 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'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { convertTimeUnit } from '../utils'
|
||||
defineOptions({
|
||||
name: 'UserTaskNodeConfig'
|
||||
})
|
||||
|
@ -393,44 +390,22 @@ const props = defineProps({
|
|||
const emits = defineEmits<{
|
||||
'find:returnTaskNodes': [nodeList: SimpleFlowNode[]]
|
||||
}>()
|
||||
// 监控节点的变化
|
||||
const currentNode = useWatchNode(props)
|
||||
// 抽屉配置
|
||||
const { settingVisible, closeDrawer, openDrawer } = useDrawer()
|
||||
// 节点名称配置
|
||||
const { nodeName, showInput, clickIcon, blurEvent } = useNodeName(NodeType.USER_TASK_NODE)
|
||||
// 激活的 Tab 标签页
|
||||
const activeTabName = ref('user')
|
||||
// 表单字段权限设置
|
||||
const { formType, fieldsPermissionConfig, getNodeConfigFormFields } = useFormFieldsPermission()
|
||||
// 操作按钮设置
|
||||
const { buttonsSetting, btnDisplayNameEdit, changeBtnDisplayName, btnDisplayNameBlurEvent } =
|
||||
useButtonsSetting()
|
||||
|
||||
const currentNode = ref<SimpleFlowNode>(props.flowNode)
|
||||
// 监控节点变化
|
||||
watch(
|
||||
() => props.flowNode,
|
||||
(newValue) => {
|
||||
currentNode.value = newValue
|
||||
}
|
||||
)
|
||||
const notAllowedMultiApprovers = ref(false)
|
||||
const settingVisible = ref(false)
|
||||
const roleOptions = inject<Ref<RoleApi.RoleVO[]>>('roleList') // 角色列表
|
||||
const postOptions = inject<Ref<PostApi.PostVO[]>>('postList') // 岗位列表
|
||||
const userOptions = inject<Ref<UserApi.UserVO[]>>('userList') // 用户列表
|
||||
const deptOptions = inject<Ref<DeptApi.DeptVO[]>>('deptList') // 部门列表
|
||||
const userGroupOptions = inject<Ref<UserGroupApi.UserGroupVO[]>>('userGroupList') // 用户组列表
|
||||
const deptTreeOptions = inject('deptTree') // 部门树
|
||||
const formType = inject('formType') // 表单类型
|
||||
const formFields = inject<Ref<string[]>>('formFields')
|
||||
const returnTaskList = ref<SimpleFlowNode[]>([])
|
||||
|
||||
// 审批人表单设置
|
||||
const formRef = ref() // 表单 Ref
|
||||
const activeTabName = ref('user') // 激活的 Tab 标签页
|
||||
const configForm = ref<any>({
|
||||
name: NODE_DEFAULT_NAME.get(NodeType.USER_TASK_NODE),
|
||||
candidateParamArray: [],
|
||||
candidateStrategy: CandidateStrategy.USER,
|
||||
approveMethod: ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE,
|
||||
approveRatio: 100,
|
||||
rejectHandlerType: RejectHandlerType.FINISH_PROCESS,
|
||||
returnNodeId: '',
|
||||
timeoutHandlerEnable: false,
|
||||
timeoutHandlerAction: 1,
|
||||
timeDuration: 6, // 默认 6小时
|
||||
maxRemindCount: 1, // 默认 提醒 1次
|
||||
fieldsPermission: [],
|
||||
buttonsSetting: []
|
||||
})
|
||||
// 表单校验规则
|
||||
const formRules = reactive({
|
||||
candidateStrategy: [{ required: true, message: '审批人设置不能为空', trigger: 'change' }],
|
||||
|
@ -443,10 +418,66 @@ const formRules = reactive({
|
|||
timeDuration: [{ required: true, message: '超时时间不能为空', trigger: 'blur' }],
|
||||
maxRemindCount: [{ required: true, message: '提醒次数不能为空', trigger: 'blur' }]
|
||||
})
|
||||
// 关闭
|
||||
const closeDrawer = () => {
|
||||
settingVisible.value = false
|
||||
|
||||
const {
|
||||
configForm: tempConfigForm,
|
||||
roleOptions,
|
||||
postOptions,
|
||||
userOptions,
|
||||
userGroupOptions,
|
||||
deptTreeOptions,
|
||||
getShowText
|
||||
} = useNodeForm(NodeType.USER_TASK_NODE)
|
||||
const configForm = tempConfigForm as Ref<UserTaskFormType>
|
||||
// 不允许多人审批
|
||||
const notAllowedMultiApprovers = ref(false)
|
||||
// 改变审批人设置策略
|
||||
const changeCandidateStrategy = () => {
|
||||
configForm.value.candidateParamArray = []
|
||||
configForm.value.approveMethod = ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE
|
||||
if (
|
||||
configForm.value.candidateStrategy === CandidateStrategy.START_USER ||
|
||||
configForm.value.candidateStrategy === CandidateStrategy.USER
|
||||
) {
|
||||
notAllowedMultiApprovers.value = true
|
||||
} else {
|
||||
notAllowedMultiApprovers.value = false
|
||||
}
|
||||
}
|
||||
// 改变审批候选人
|
||||
const changedCandidateUsers = () => {
|
||||
if (
|
||||
configForm.value.candidateParamArray?.length <= 1 &&
|
||||
configForm.value.candidateStrategy === CandidateStrategy.USER
|
||||
) {
|
||||
configForm.value.approveMethod = ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE
|
||||
configForm.value.rejectHandlerType = RejectHandlerType.FINISH_PROCESS
|
||||
notAllowedMultiApprovers.value = true
|
||||
} else {
|
||||
notAllowedMultiApprovers.value = false
|
||||
}
|
||||
}
|
||||
// 审批方式改变
|
||||
const approveMethodChanged = () => {
|
||||
configForm.value.rejectHandlerType = RejectHandlerType.FINISH_PROCESS
|
||||
if (configForm.value.approveMethod === ApproveMethodType.APPROVE_BY_RATIO) {
|
||||
configForm.value.approveRatio = 100
|
||||
}
|
||||
formRef.value.clearValidate('approveRatio')
|
||||
}
|
||||
// 审批拒绝 可回退的节点
|
||||
const returnTaskList = ref<SimpleFlowNode[]>([])
|
||||
// 审批人超时未处理设置
|
||||
const {
|
||||
timeoutHandlerChange,
|
||||
cTimeoutAction,
|
||||
timeoutActionChanged,
|
||||
timeUnit,
|
||||
timeUnitChange,
|
||||
isoTimeDuration,
|
||||
cTimeoutMaxRemindCount
|
||||
} = useTimeoutHandler()
|
||||
|
||||
// 保存配置
|
||||
const saveConfig = async () => {
|
||||
activeTabName.value = 'user'
|
||||
|
@ -455,7 +486,7 @@ const saveConfig = async () => {
|
|||
if (!valid) return false
|
||||
const showText = getShowText()
|
||||
if (!showText) return false
|
||||
currentNode.value.name = configForm.value.name
|
||||
currentNode.value.name = nodeName.value!
|
||||
currentNode.value.candidateStrategy = configForm.value.candidateStrategy
|
||||
currentNode.value.candidateParam = configForm.value.candidateParamArray?.join(',')
|
||||
// 设置审批方式
|
||||
|
@ -465,121 +496,31 @@ const saveConfig = async () => {
|
|||
}
|
||||
// 设置拒绝处理
|
||||
currentNode.value.rejectHandler = {
|
||||
type: configForm.value.rejectHandlerType,
|
||||
type: configForm.value.rejectHandlerType!,
|
||||
returnNodeId: configForm.value.returnNodeId
|
||||
}
|
||||
// 设置超时处理
|
||||
currentNode.value.timeoutHandler = {
|
||||
enable: configForm.value.timeoutHandlerEnable,
|
||||
enable: configForm.value.timeoutHandlerEnable!,
|
||||
action: cTimeoutAction.value,
|
||||
timeDuration: isoTimeDuration.value,
|
||||
maxRemindCount: cTimeoutMaxRemindCount.value
|
||||
}
|
||||
// 设置表单权限
|
||||
currentNode.value.fieldsPermission = configForm.value.fieldsPermission
|
||||
currentNode.value.fieldsPermission = fieldsPermissionConfig.value
|
||||
// 设置按钮权限
|
||||
currentNode.value.buttonsSetting = configForm.value.buttonsSetting
|
||||
currentNode.value.buttonsSetting = buttonsSetting.value
|
||||
|
||||
currentNode.value.showText = getShowText()
|
||||
currentNode.value.showText = showText
|
||||
settingVisible.value = false
|
||||
return true
|
||||
}
|
||||
const getShowText = (): string => {
|
||||
let showText = ''
|
||||
// 指定成员
|
||||
if (configForm.value.candidateStrategy === CandidateStrategy.USER) {
|
||||
if (configForm.value.candidateParamArray?.length > 0) {
|
||||
const candidateNames: string[] = []
|
||||
userOptions?.value.forEach((item) => {
|
||||
if (configForm.value.candidateParamArray.includes(item.id)) {
|
||||
candidateNames.push(item.nickname)
|
||||
}
|
||||
})
|
||||
showText = `指定成员:${candidateNames.join(',')}`
|
||||
}
|
||||
}
|
||||
// 指定角色
|
||||
if (configForm.value.candidateStrategy === CandidateStrategy.ROLE) {
|
||||
if (configForm.value.candidateParamArray?.length > 0) {
|
||||
const candidateNames: string[] = []
|
||||
roleOptions?.value.forEach((item) => {
|
||||
if (configForm.value.candidateParamArray.includes(item.id)) {
|
||||
candidateNames.push(item.name)
|
||||
}
|
||||
})
|
||||
showText = `指定角色:${candidateNames.join(',')}`
|
||||
}
|
||||
}
|
||||
// 指定部门
|
||||
if (
|
||||
configForm.value.candidateStrategy === CandidateStrategy.DEPT_MEMBER ||
|
||||
configForm.value.candidateStrategy === CandidateStrategy.DEPT_LEADER
|
||||
) {
|
||||
if (configForm.value.candidateParamArray?.length > 0) {
|
||||
const candidateNames: string[] = []
|
||||
deptOptions?.value.forEach((item) => {
|
||||
if (configForm.value.candidateParamArray.includes(item.id)) {
|
||||
candidateNames.push(item.name)
|
||||
}
|
||||
})
|
||||
if (configForm.value.candidateStrategy === CandidateStrategy.DEPT_MEMBER) {
|
||||
showText = `部门成员:${candidateNames.join(',')}`
|
||||
} else {
|
||||
showText = `部门的负责人:${candidateNames.join(',')}`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 指定岗位
|
||||
if (configForm.value.candidateStrategy === CandidateStrategy.POST) {
|
||||
if (configForm.value.candidateParamArray?.length > 0) {
|
||||
const candidateNames: string[] = []
|
||||
postOptions?.value.forEach((item) => {
|
||||
if (configForm.value.candidateParamArray.includes(item.id)) {
|
||||
candidateNames.push(item.name)
|
||||
}
|
||||
})
|
||||
showText = `指定岗位: ${candidateNames.join(',')}`
|
||||
}
|
||||
}
|
||||
// 指定用户组
|
||||
if (configForm.value.candidateStrategy === CandidateStrategy.USER_GROUP) {
|
||||
if (configForm.value.candidateParamArray?.length > 0) {
|
||||
const candidateNames: string[] = []
|
||||
userGroupOptions?.value.forEach((item) => {
|
||||
if (configForm.value.candidateParamArray.includes(item.id)) {
|
||||
candidateNames.push(item.name)
|
||||
}
|
||||
})
|
||||
showText = `指定用户组: ${candidateNames.join(',')}`
|
||||
}
|
||||
}
|
||||
|
||||
// 发起人自选
|
||||
if (configForm.value.candidateStrategy === CandidateStrategy.START_USER_SELECT) {
|
||||
showText = `发起人自选`
|
||||
}
|
||||
// 发起人自己
|
||||
if (configForm.value.candidateStrategy === CandidateStrategy.START_USER) {
|
||||
showText = `发起人自己`
|
||||
}
|
||||
|
||||
// 流程表达式
|
||||
if (configForm.value.candidateStrategy === CandidateStrategy.EXPRESSION) {
|
||||
if (configForm.value.candidateParamArray?.length > 0) {
|
||||
showText = `流程表达式:${configForm.value.candidateParamArray[0]}`
|
||||
}
|
||||
}
|
||||
return showText
|
||||
}
|
||||
const open = () => {
|
||||
settingVisible.value = true
|
||||
}
|
||||
// 配置审批节点, 由父组件传过来
|
||||
const setCurrentNode = (node: SimpleFlowNode) => {
|
||||
configForm.value.name = node.name
|
||||
// 显示审批节点配置, 由父组件传过来
|
||||
const showUserTaskNodeConfig = (node: SimpleFlowNode) => {
|
||||
nodeName.value = node.name
|
||||
//1.1 审批人设置
|
||||
configForm.value.candidateStrategy = node.candidateStrategy
|
||||
configForm.value.candidateStrategy = node.candidateStrategy!
|
||||
const strCandidateParam = node?.candidateParam
|
||||
if (node.candidateStrategy === CandidateStrategy.EXPRESSION) {
|
||||
configForm.value.candidateParamArray[0] = strCandidateParam
|
||||
|
@ -598,18 +539,18 @@ const setCurrentNode = (node: SimpleFlowNode) => {
|
|||
notAllowedMultiApprovers.value = false
|
||||
}
|
||||
//1.2 设置审批方式
|
||||
configForm.value.approveMethod = node.approveMethod
|
||||
configForm.value.approveMethod = node.approveMethod!
|
||||
if (node.approveMethod == ApproveMethodType.APPROVE_BY_RATIO) {
|
||||
configForm.value.approveRatio = node.approveRatio
|
||||
configForm.value.approveRatio = node.approveRatio!
|
||||
}
|
||||
// 1.3 设置审批拒绝处理
|
||||
configForm.value.rejectHandlerType = node.rejectHandler?.type
|
||||
configForm.value.rejectHandlerType = node.rejectHandler!.type
|
||||
configForm.value.returnNodeId = node.rejectHandler?.returnNodeId
|
||||
const matchNodeList = []
|
||||
emits('find:returnTaskNodes', matchNodeList)
|
||||
returnTaskList.value = matchNodeList
|
||||
// 1.4 设置审批超时处理
|
||||
configForm.value.timeoutHandlerEnable = node.timeoutHandler?.enable
|
||||
configForm.value.timeoutHandlerEnable = node.timeoutHandler!.enable
|
||||
if (node.timeoutHandler?.enable && node.timeoutHandler?.timeDuration) {
|
||||
const strTimeDuration = node.timeoutHandler.timeDuration
|
||||
let parseTime = strTimeDuration.slice(2, strTimeDuration.length - 1)
|
||||
|
@ -620,152 +561,121 @@ const setCurrentNode = (node: SimpleFlowNode) => {
|
|||
configForm.value.timeoutHandlerAction = node.timeoutHandler?.action
|
||||
configForm.value.maxRemindCount = node.timeoutHandler?.maxRemindCount
|
||||
// 2. 操作按钮设置
|
||||
configForm.value.buttonsSetting = cloneDeep(node.buttonsSetting) || DEFAULT_BUTTON_SETTING
|
||||
buttonsSetting.value = cloneDeep(node.buttonsSetting) || DEFAULT_BUTTON_SETTING
|
||||
// 3. 表单字段权限配置
|
||||
configForm.value.fieldsPermission =
|
||||
cloneDeep(node.fieldsPermission) || getDefaultFieldsPermission(formFields?.value)
|
||||
getNodeConfigFormFields(node.fieldsPermission)
|
||||
}
|
||||
|
||||
defineExpose({ open, setCurrentNode }) // 暴露方法给父组件
|
||||
defineExpose({ openDrawer, showUserTaskNodeConfig }) // 暴露方法给父组件
|
||||
|
||||
const changeCandidateStrategy = () => {
|
||||
configForm.value.candidateParamArray = []
|
||||
configForm.value.approveMethod = ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE
|
||||
if (
|
||||
configForm.value.candidateStrategy === CandidateStrategy.START_USER ||
|
||||
configForm.value.candidateStrategy === CandidateStrategy.USER
|
||||
) {
|
||||
notAllowedMultiApprovers.value = true
|
||||
} else {
|
||||
notAllowedMultiApprovers.value = false
|
||||
/**
|
||||
* @description 操作按钮设置
|
||||
*/
|
||||
function useButtonsSetting() {
|
||||
const buttonsSetting = ref<ButtonSetting[]>()
|
||||
// 操作按钮显示名称可编辑
|
||||
const btnDisplayNameEdit = ref<boolean[]>([])
|
||||
const changeBtnDisplayName = (index: number) => {
|
||||
btnDisplayNameEdit.value[index] = true
|
||||
}
|
||||
const btnDisplayNameBlurEvent = (index: number) => {
|
||||
btnDisplayNameEdit.value[index] = false
|
||||
const buttonItem = buttonsSetting.value![index]
|
||||
buttonItem.displayName = buttonItem.displayName || OPERATION_BUTTON_NAME.get(buttonItem.id)!
|
||||
}
|
||||
return {
|
||||
buttonsSetting,
|
||||
btnDisplayNameEdit,
|
||||
changeBtnDisplayName,
|
||||
btnDisplayNameBlurEvent
|
||||
}
|
||||
}
|
||||
|
||||
const changedCandidateUsers = () => {
|
||||
if (
|
||||
configForm.value.candidateParamArray?.length <= 1 &&
|
||||
configForm.value.candidateStrategy === CandidateStrategy.USER
|
||||
) {
|
||||
configForm.value.approveMethod = ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE
|
||||
configForm.value.rejectHandlerType = RejectHandlerType.FINISH_PROCESS
|
||||
notAllowedMultiApprovers.value = true
|
||||
} else {
|
||||
notAllowedMultiApprovers.value = false
|
||||
}
|
||||
}
|
||||
// 显示名称输入框
|
||||
const showInput = ref(false)
|
||||
/**
|
||||
* @description 审批人超时未处理配置
|
||||
*/
|
||||
function useTimeoutHandler() {
|
||||
// 时间单位
|
||||
const timeUnit = ref(TimeUnitType.HOUR)
|
||||
|
||||
const clickIcon = () => {
|
||||
showInput.value = true
|
||||
}
|
||||
// 节点名称输入框失去焦点
|
||||
const blurEvent = () => {
|
||||
showInput.value = false
|
||||
configForm.value.name =
|
||||
configForm.value.name || (NODE_DEFAULT_NAME.get(NodeType.USER_TASK_NODE) as string)
|
||||
}
|
||||
// 超时开关改变
|
||||
const timeoutHandlerChange = () => {
|
||||
if (configForm.value.timeoutHandlerEnable) {
|
||||
timeUnit.value = 2
|
||||
configForm.value.timeDuration = 6
|
||||
configForm.value.timeoutHandlerAction = 1
|
||||
configForm.value.maxRemindCount = 1
|
||||
}
|
||||
}
|
||||
// 超时执行的动作
|
||||
const cTimeoutAction = computed(() => {
|
||||
if (!configForm.value.timeoutHandlerEnable) {
|
||||
return undefined
|
||||
}
|
||||
return configForm.value.timeoutHandlerAction
|
||||
})
|
||||
|
||||
const approveMethodChanged = () => {
|
||||
configForm.value.rejectHandlerType = RejectHandlerType.FINISH_PROCESS
|
||||
if (configForm.value.approveMethod === ApproveMethodType.APPROVE_BY_RATIO) {
|
||||
configForm.value.approveRatio = 100
|
||||
// 超时处理动作改变
|
||||
const timeoutActionChanged = () => {
|
||||
if (configForm.value.timeoutHandlerAction === 1) {
|
||||
configForm.value.maxRemindCount = 1 // 超时提醒次数,默认为1
|
||||
}
|
||||
}
|
||||
formRef.value.clearValidate('approveRatio')
|
||||
}
|
||||
|
||||
const timeUnit = ref(TimeUnitType.HOUR)
|
||||
// 时间单位改变
|
||||
const timeUnitChange = () => {
|
||||
// 分钟,默认是 60 分钟
|
||||
if (timeUnit.value === TimeUnitType.MINUTE) {
|
||||
configForm.value.timeDuration = 60
|
||||
}
|
||||
// 小时,默认是 6 个小时
|
||||
if (timeUnit.value === TimeUnitType.HOUR) {
|
||||
configForm.value.timeDuration = 6
|
||||
}
|
||||
// 天, 默认 1天
|
||||
if (timeUnit.value === TimeUnitType.DAY) {
|
||||
configForm.value.timeDuration = 1
|
||||
}
|
||||
}
|
||||
// 超时时间的 ISO 表示
|
||||
const isoTimeDuration = computed(() => {
|
||||
if (!configForm.value.timeoutHandlerEnable) {
|
||||
return undefined
|
||||
}
|
||||
let strTimeDuration = 'PT'
|
||||
if (timeUnit.value === TimeUnitType.MINUTE) {
|
||||
strTimeDuration += configForm.value.timeDuration + 'M'
|
||||
}
|
||||
if (timeUnit.value === TimeUnitType.HOUR) {
|
||||
strTimeDuration += configForm.value.timeDuration + 'H'
|
||||
}
|
||||
if (timeUnit.value === TimeUnitType.DAY) {
|
||||
strTimeDuration += configForm.value.timeDuration + 'D'
|
||||
}
|
||||
return strTimeDuration
|
||||
})
|
||||
|
||||
// 超时时间的 ISO 表示
|
||||
const isoTimeDuration = computed(() => {
|
||||
if (!configForm.value.timeoutHandlerEnable) {
|
||||
return undefined
|
||||
}
|
||||
let strTimeDuration = 'PT'
|
||||
if (timeUnit.value === TimeUnitType.MINUTE) {
|
||||
strTimeDuration += configForm.value.timeDuration + 'M'
|
||||
}
|
||||
if (timeUnit.value === TimeUnitType.HOUR) {
|
||||
strTimeDuration += configForm.value.timeDuration + 'H'
|
||||
}
|
||||
if (timeUnit.value === TimeUnitType.DAY) {
|
||||
strTimeDuration += configForm.value.timeDuration + 'D'
|
||||
}
|
||||
return strTimeDuration
|
||||
})
|
||||
// 超时执行的动作
|
||||
const cTimeoutAction = computed(() => {
|
||||
if (!configForm.value.timeoutHandlerEnable) {
|
||||
return undefined
|
||||
}
|
||||
return configForm.value.timeoutHandlerAction
|
||||
})
|
||||
// 超时最大提醒次数
|
||||
const cTimeoutMaxRemindCount = computed(() => {
|
||||
if (!configForm.value.timeoutHandlerEnable) {
|
||||
return undefined
|
||||
}
|
||||
if (configForm.value.timeoutHandlerAction !== 1) {
|
||||
return undefined
|
||||
}
|
||||
return configForm.value.maxRemindCount
|
||||
})
|
||||
// 超时最大提醒次数
|
||||
const cTimeoutMaxRemindCount = computed(() => {
|
||||
if (!configForm.value.timeoutHandlerEnable) {
|
||||
return undefined
|
||||
}
|
||||
if (configForm.value.timeoutHandlerAction !== 1) {
|
||||
return undefined
|
||||
}
|
||||
return configForm.value.maxRemindCount
|
||||
})
|
||||
|
||||
// 超时开关改变
|
||||
const timeoutHandlerChange = () => {
|
||||
if (configForm.value.timeoutHandlerEnable) {
|
||||
timeUnit.value = 2
|
||||
configForm.value.timeDuration = 6
|
||||
configForm.value.timeoutHandlerAction = 1
|
||||
configForm.value.maxRemindCount = 1
|
||||
return {
|
||||
timeoutHandlerChange,
|
||||
cTimeoutAction,
|
||||
timeoutActionChanged,
|
||||
timeUnit,
|
||||
timeUnitChange,
|
||||
isoTimeDuration,
|
||||
cTimeoutMaxRemindCount
|
||||
}
|
||||
}
|
||||
// 超时处理动作改变
|
||||
const timeoutActionChanged = () => {
|
||||
if (configForm.value.timeoutHandlerAction === 1) {
|
||||
configForm.value.maxRemindCount = 1 // 超时提醒次数,默认为1
|
||||
}
|
||||
}
|
||||
|
||||
// 时间单位改变
|
||||
const timeUnitChange = () => {
|
||||
// 分钟,默认是 60 分钟
|
||||
if (timeUnit.value === TimeUnitType.MINUTE) {
|
||||
configForm.value.timeDuration = 60
|
||||
}
|
||||
// 小时,默认是 6 个小时
|
||||
if (timeUnit.value === TimeUnitType.HOUR) {
|
||||
configForm.value.timeDuration = 6
|
||||
}
|
||||
// 天, 默认 1天
|
||||
if (timeUnit.value === TimeUnitType.DAY) {
|
||||
configForm.value.timeDuration = 1
|
||||
}
|
||||
}
|
||||
|
||||
const convertTimeUnit = (strTimeUnit: string) => {
|
||||
if (strTimeUnit === 'M') {
|
||||
return TimeUnitType.MINUTE
|
||||
}
|
||||
if (strTimeUnit === 'H') {
|
||||
return TimeUnitType.HOUR
|
||||
}
|
||||
if (strTimeUnit === 'D') {
|
||||
return TimeUnitType.DAY
|
||||
}
|
||||
return TimeUnitType.HOUR
|
||||
}
|
||||
|
||||
// 操作按钮显示名称可编辑
|
||||
const btnDisplayNameEdit = ref<boolean[]>([])
|
||||
const changeBtnDisplayName = (index: number) => {
|
||||
btnDisplayNameEdit.value[index] = true
|
||||
}
|
||||
const btnDisplayNameBlurEvent = (index: number) => {
|
||||
btnDisplayNameEdit.value[index] = false
|
||||
const buttonItem = configForm.value.buttonPermission[index]
|
||||
buttonItem.displayName = buttonItem.displayName || OPERATION_BUTTON_NAME.get(buttonItem.id)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT, NODE_DEFAULT_NAME } from '../consts'
|
||||
import NodeHandler from '../NodeHandler.vue'
|
||||
import CopyTaskNodeConfig from '../nodes-config/CopyTaskNodeConfig.vue'
|
||||
import { generateUUID } from '@/utils'
|
||||
defineOptions({
|
||||
name: 'CopyTaskNode'
|
||||
})
|
||||
|
@ -81,8 +80,8 @@ const clickEvent = () => {
|
|||
const nodeSetting = ref()
|
||||
// 打开节点配置
|
||||
const openNodeConfig = () => {
|
||||
nodeSetting.value.setCurrentNode(currentNode.value)
|
||||
nodeSetting.value.open()
|
||||
nodeSetting.value.showCopyTaskNodeConfig(currentNode.value)
|
||||
nodeSetting.value.openDrawer()
|
||||
}
|
||||
|
||||
// 删除节点。更新当前节点为孩子节点
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
</template>
|
||||
<script setup lang="ts">
|
||||
import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT, NODE_DEFAULT_NAME } from '../consts'
|
||||
import { useWatchNode } from '../node'
|
||||
import NodeHandler from '../NodeHandler.vue'
|
||||
import UserTaskNodeConfig from '../nodes-config/UserTaskNodeConfig.vue'
|
||||
defineOptions({
|
||||
|
@ -61,21 +62,16 @@ const emits = defineEmits<{
|
|||
'find:parentNode': [nodeList: SimpleFlowNode[], nodeType: NodeType]
|
||||
}>()
|
||||
|
||||
const currentNode = ref<SimpleFlowNode>(props.flowNode)
|
||||
const currentNode = useWatchNode(props)
|
||||
|
||||
const nodeSetting = ref()
|
||||
// 打开节点配置
|
||||
const openNodeConfig = () => {
|
||||
// 把当前节点传递给配置组件
|
||||
nodeSetting.value.setCurrentNode(currentNode.value)
|
||||
nodeSetting.value.open()
|
||||
nodeSetting.value.showUserTaskNodeConfig(currentNode.value)
|
||||
nodeSetting.value.openDrawer()
|
||||
}
|
||||
// 监控节点变化
|
||||
watch(
|
||||
() => props.flowNode,
|
||||
(newValue) => {
|
||||
currentNode.value = newValue
|
||||
}
|
||||
)
|
||||
|
||||
// 显示节点名称输入框
|
||||
const showInput = ref(false)
|
||||
// 节点名称输入框失去焦点
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { TimeUnitType } from './consts'
|
||||
|
||||
// 获取条件节点默认的名称
|
||||
export const getDefaultConditionNodeName = (index: number, defaultFlow: boolean): string => {
|
||||
if (defaultFlow) {
|
||||
|
@ -6,18 +8,15 @@ export const getDefaultConditionNodeName = (index: number, defaultFlow: boolean)
|
|||
return '条件' + (index + 1)
|
||||
}
|
||||
|
||||
// 获得默认的表单字段权限.
|
||||
export const getDefaultFieldsPermission = (formFields: string[] | undefined) => {
|
||||
const defaultFieldsPermission: any[] = []
|
||||
if (formFields) {
|
||||
formFields.forEach((fieldStr: string) => {
|
||||
const { field, title } = JSON.parse(fieldStr)
|
||||
defaultFieldsPermission.push({
|
||||
field,
|
||||
title,
|
||||
permission: '1' // 只读
|
||||
})
|
||||
})
|
||||
export const convertTimeUnit = (strTimeUnit: string) => {
|
||||
if (strTimeUnit === 'M') {
|
||||
return TimeUnitType.MINUTE
|
||||
}
|
||||
return defaultFieldsPermission
|
||||
if (strTimeUnit === 'H') {
|
||||
return TimeUnitType.HOUR
|
||||
}
|
||||
if (strTimeUnit === 'D') {
|
||||
return TimeUnitType.DAY
|
||||
}
|
||||
return TimeUnitType.HOUR
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue