diff --git a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue index 25532344..25e4ed74 100644 --- a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue +++ b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue @@ -306,6 +306,9 @@ const addNode = (type: number) => { }, timeoutSetting: { enable: false + }, + multiInstanceSetting: { + enable: false } } } diff --git a/src/components/SimpleProcessDesignerV2/src/consts.ts b/src/components/SimpleProcessDesignerV2/src/consts.ts index 2b6ebce4..3ef47989 100644 --- a/src/components/SimpleProcessDesignerV2/src/consts.ts +++ b/src/components/SimpleProcessDesignerV2/src/consts.ts @@ -814,26 +814,84 @@ export const TRIGGER_TYPES: DictDataVO[] = [ export type ChildProcessSetting = { calledProcessDefinitionKey: string calledProcessDefinitionName: string - async: boolean, - inVariables?: IOParameter[], - outVariables?: IOParameter[], - skipStartUserNode: boolean, - startUserSetting: StartUserSetting, - timeoutSetting: TimeoutSetting, + async: boolean + inVariables?: IOParameter[] + outVariables?: IOParameter[] + skipStartUserNode: boolean + startUserSetting: StartUserSetting + timeoutSetting: TimeoutSetting + multiInstanceSetting: MultiInstanceSetting } export type IOParameter = { source: string - sourceExpression: string target: string - targetExpression: string } export type StartUserSetting = { - type: number + type: ChildProcessStartUserTypeEnum formField?: string - emptyType?: number + emptyType?: ChildProcessStartUserEmptyTypeEnum } export type TimeoutSetting = { - enable: boolean, - type?: DelayTypeEnum, - timeExpression?: string, + enable: boolean + type?: DelayTypeEnum + timeExpression?: string } +export type MultiInstanceSetting = { + enable: boolean + sequential?: boolean + completeRatio?: number + sourceType?: ChildProcessMultiInstanceSourceTypeEnum + source?: string +} +export enum ChildProcessStartUserTypeEnum { + /** + * 同主流程发起人 + */ + MAIN_PROCESS_START_USER = 1, + /** + * 表单 + */ + FROM_FORM = 2 +} +export const CHILD_PROCESS_START_USER_TYPE = [ + { label: '同主流程发起人', value: ChildProcessStartUserTypeEnum.MAIN_PROCESS_START_USER }, + { label: '表单', value: ChildProcessStartUserTypeEnum.FROM_FORM } +] +export enum ChildProcessStartUserEmptyTypeEnum { + /** + * 同主流程发起人 + */ + MAIN_PROCESS_START_USER = 1, + /** + * 子流程管理员 + */ + CHILD_PROCESS_ADMIN = 2, + /** + * 主流程管理员 + */ + MAIN_PROCESS_ADMIN = 3 +} +export const CHILD_PROCESS_START_USER_EMPTY_TYPE = [ + { label: '同主流程发起人', value: ChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_START_USER }, + { label: '子流程管理员', value: ChildProcessStartUserEmptyTypeEnum.CHILD_PROCESS_ADMIN }, + { label: '主流程管理员', value: ChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_ADMIN } +] +export enum ChildProcessMultiInstanceSourceTypeEnum { + /** + * 固定数量 + */ + FIXED_QUANTITY = 1, + /** + * 数字表单 + */ + DIGITAL_FORM = 2, + /** + * 多项表单 + */ + MULTI_FORM = 3 +} +export const CHILD_PROCESS_MULTI_INSTANCE_SOURCE_TYPE = [ + { label: '固定数量', value: ChildProcessMultiInstanceSourceTypeEnum.FIXED_QUANTITY }, + { label: '数字表单', value: ChildProcessMultiInstanceSourceTypeEnum.DIGITAL_FORM }, // TODO @lesan:DIGITAL 改成 NUMBER,和 Element plus 更接近? + { label: '多项表单', value: ChildProcessMultiInstanceSourceTypeEnum.MULTI_FORM } // TODO @lesan:多选表单?multiple 是这个解释。另外 MULTI => MULTIPLE +] diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/ChildProcessNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/ChildProcessNodeConfig.vue index 9e2ce4a2..abd3a310 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/ChildProcessNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/ChildProcessNodeConfig.vue @@ -95,7 +95,7 @@ @@ -103,7 +103,6 @@ 添加一行 - @@ -160,22 +159,30 @@ 添加一行 - - 同主流程发起人 - 表单 + + {{ item.label }} + - 同主流程发起人 - 子流程管理员 - 主流程管理员 + + {{ item.label }} + 后进入下一节点 + + 多实例设置 + + + +
+ + + + + 完成比例(%) + + + + 多实例来源 + + + + + + + + + + + + + + + + + + +
@@ -268,7 +342,14 @@ import { TIME_UNIT_TYPES, TimeUnitType, DelayTypeEnum, - DELAY_TYPE + DELAY_TYPE, + IOParameter, + ChildProcessStartUserTypeEnum, + CHILD_PROCESS_START_USER_TYPE, + ChildProcessStartUserEmptyTypeEnum, + CHILD_PROCESS_START_USER_EMPTY_TYPE, + CHILD_PROCESS_MULTI_INSTANCE_SOURCE_TYPE, + ChildProcessMultiInstanceSourceTypeEnum } from '../consts' import { useWatchNode, useDrawer, useNodeName, useFormFieldsAndStartUser } from '../node' import { parseFormFields } from '@/components/FormCreate/src/utils' @@ -307,25 +388,57 @@ const formRules = reactive({ timeoutEnable: [{ required: true, message: '超时设置是否开启不能为空', trigger: 'change' }], timeoutType: [{ required: true, message: '超时设置时间不能为空', trigger: 'change' }], timeDuration: [{ required: true, message: '超时设置时间不能为空', trigger: 'change' }], - dateTime: [{ required: true, message: '超时设置时间不能为空', trigger: 'change' }] + dateTime: [{ required: true, message: '超时设置时间不能为空', trigger: 'change' }], + multiInstanceEnable: [{ required: true, message: '多实例设置不能为空', trigger: 'change' }] }) -const configForm = ref({ +type ChildProcessFormType = { + async: boolean + calledProcessDefinitionKey: string + skipStartUserNode: boolean + inVariables?: IOParameter[] + outVariables?: IOParameter[] + startUserType: ChildProcessStartUserTypeEnum + startUserEmptyType: ChildProcessStartUserEmptyTypeEnum + startUserFormField: string + timeoutEnable: boolean + timeoutType: DelayTypeEnum + timeDuration: number + timeUnit: TimeUnitType + dateTime: string + multiInstanceEnable: boolean + sequential: boolean + completeRatio: number + multiInstanceSourceType: ChildProcessMultiInstanceSourceTypeEnum + multiInstanceSource: string +} +const configForm = ref({ async: false, calledProcessDefinitionKey: '', skipStartUserNode: false, inVariables: [], outVariables: [], - startUserType: 1, - startUserEmptyType: 1, + startUserType: ChildProcessStartUserTypeEnum.MAIN_PROCESS_START_USER, + startUserEmptyType: ChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_START_USER, startUserFormField: '', timeoutEnable: false, timeoutType: DelayTypeEnum.FIXED_TIME_DURATION, timeDuration: 1, timeUnit: TimeUnitType.HOUR, - dateTime: '' + dateTime: '', + multiInstanceEnable: false, + sequential: false, + completeRatio: 100, + multiInstanceSourceType: ChildProcessMultiInstanceSourceTypeEnum.FIXED_QUANTITY, + multiInstanceSource: '' }) const childProcessOptions = ref() const formFieldOptions = useFormFieldsAndStartUser() +const digitalFormFieldOptions = computed(() => { + return formFieldOptions.filter((item) => item.type === 'inputNumber') +}) +const multiFormFieldOptions = computed(() => { + return formFieldOptions.filter((item) => item.type === 'select' || item.type === 'checkbox') +}) const childFormFieldOptions = ref() // 保存配置 @@ -334,9 +447,8 @@ const saveConfig = async () => { if (!formRef) return false const valid = await formRef.value.validate() if (!valid) return false - // TODO @lesan:这里的 option 黄色告警,也处理下哈 const childInfo = childProcessOptions.value.find( - (option) => option.key === configForm.value.calledProcessDefinitionKey + (option: any) => option.key === configForm.value.calledProcessDefinitionKey ) currentNode.value.name = nodeName.value! if (currentNode.value.childProcessSetting) { @@ -371,6 +483,20 @@ const saveConfig = async () => { configForm.value.dateTime } } + // 8. 多实例设置 + currentNode.value.childProcessSetting.multiInstanceSetting = { + enable: configForm.value.multiInstanceEnable + } + if (configForm.value.multiInstanceEnable) { + currentNode.value.childProcessSetting.multiInstanceSetting.sequential = + configForm.value.sequential + currentNode.value.childProcessSetting.multiInstanceSetting.completeRatio = + configForm.value.completeRatio + currentNode.value.childProcessSetting.multiInstanceSetting.sourceType = + configForm.value.multiInstanceSourceType + currentNode.value.childProcessSetting.multiInstanceSetting.source = + configForm.value.multiInstanceSource + } } currentNode.value.showText = `调用子流程:${childInfo.name}` @@ -378,7 +504,6 @@ const saveConfig = async () => { return true } // 显示子流程节点配置, 由父组件传过来 -// TODO @lesan:inVariables、outVariables 红色告警 const showChildProcessNodeConfig = (node: SimpleFlowNode) => { nodeName.value = node.name if (node.childProcessSetting) { @@ -415,21 +540,34 @@ const showChildProcessNodeConfig = (node: SimpleFlowNode) => { configForm.value.dateTime = node.childProcessSetting.timeoutSetting.timeExpression ?? '' } } + // 8. 多实例设置 + configForm.value.multiInstanceEnable = + node.childProcessSetting.multiInstanceSetting.enable ?? false + if (configForm.value.multiInstanceEnable) { + configForm.value.sequential = + node.childProcessSetting.multiInstanceSetting.sequential ?? false + configForm.value.completeRatio = + node.childProcessSetting.multiInstanceSetting.completeRatio ?? 100 + configForm.value.multiInstanceSourceType = + node.childProcessSetting.multiInstanceSetting.sourceType ?? + ChildProcessMultiInstanceSourceTypeEnum.FIXED_QUANTITY + configForm.value.multiInstanceSource = + node.childProcessSetting.multiInstanceSetting.source ?? '' + } } loadFormInfo() } defineExpose({ openDrawer, showChildProcessNodeConfig }) // 暴露方法给父组件 -// TODO @lesan:这里的 arr 黄色告警,也处理下哈,可以用 cursor quick fix 哈 -const addVariable = (arr) => { - arr.push({ +const addVariable = (arr?: IOParameter[]) => { + arr?.push({ source: '', target: '' }) } -const deleteVariable = (arr, index: number) => { - arr.splice(index, 1) +const deleteVariable = (index: number, arr?: IOParameter[]) => { + arr?.splice(index, 1) } const handleCalledElementChange = () => { configForm.value.inVariables = [] @@ -461,6 +599,9 @@ const getIsoTimeDuration = () => { } return strTimeDuration } +const handleMultiInstanceSourceTypeChange = () => { + configForm.value.multiInstanceSource = '' +} onMounted(async () => { childProcessOptions.value = await getModelList(undefined) diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue index 63d80d60..9020d655 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue @@ -48,7 +48,7 @@ import { getDefaultConditionNodeName } from '../utils' import { useFormFieldsAndStartUser, getConditionShowText } from '../node' import Condition from './components/Condition.vue' import { cloneDeep } from 'lodash-es' -const message = useMessage() // 消息弹窗 + defineOptions({ name: 'ConditionNodeConfig' }) @@ -69,14 +69,18 @@ const condition = ref({ conditionExpression: '', conditionGroups: { and: true, - conditions: [{ - and: true, - rules: [{ - opCode: '==', - leftSide: '', - rightSide: '' - }] - }] + conditions: [ + { + and: true, + rules: [ + { + opCode: '==', + leftSide: '', + rightSide: '' + } + ] + } + ] } }) const open = () => { @@ -90,14 +94,18 @@ const open = () => { conditionExpression: '', conditionGroups: { and: true, - conditions: [{ - and: true, - rules: [{ - opCode: '==', - leftSide: '', - rightSide: '' - }] - }] + conditions: [ + { + and: true, + rules: [ + { + opCode: '==', + leftSide: '', + rightSide: '' + } + ] + } + ] } } } @@ -162,8 +170,14 @@ const saveConfig = async () => { currentNode.value.conditionSetting = cloneDeep({ ...currentNode.value.conditionSetting, conditionType: condition.value?.conditionType, - conditionExpression: condition.value?.conditionType === ConditionType.EXPRESSION ? condition.value?.conditionExpression : undefined, - conditionGroups: condition.value?.conditionType === ConditionType.RULE ? condition.value?.conditionGroups : undefined + conditionExpression: + condition.value?.conditionType === ConditionType.EXPRESSION + ? condition.value?.conditionExpression + : undefined, + conditionGroups: + condition.value?.conditionType === ConditionType.RULE + ? condition.value?.conditionGroups + : undefined }) } settingVisible.value = false diff --git a/src/views/bpm/processInstance/create/ProcessDefinitionDetail.vue b/src/views/bpm/processInstance/create/ProcessDefinitionDetail.vue index 5944c253..0bab7d44 100644 --- a/src/views/bpm/processInstance/create/ProcessDefinitionDetail.vue +++ b/src/views/bpm/processInstance/create/ProcessDefinitionDetail.vue @@ -157,25 +157,24 @@ const initProcessInfo = async (row: any, formVariables?: any) => { } /** 预测流程节点会因为输入的参数值而产生新的预测结果值,所以需重新预测一次 */ -// TODO @芋艿:这里我执行填写表单的时候不知道为啥一直报错,先注释了 @lesan:可以和群里的小北说下 -// watch( -// detailForm.value, -// (newValue) => { -// if (newValue && Object.keys(newValue.value).length > 0) { -// // 记录之前的节点审批人 -// tempStartUserSelectAssignees.value = startUserSelectAssignees.value -// startUserSelectAssignees.value = {} -// // 加载最新的审批详情 -// getApprovalDetail({ -// id: props.selectProcessDefinition.id, -// processVariablesStr: JSON.stringify(newValue.value) // 解决 GET 无法传递对象的问题,后端 String 再转 JSON -// }) -// } -// }, -// { -// immediate: true -// } -// ) +watch( + detailForm.value, + (newValue) => { + if (newValue && Object.keys(newValue.value).length > 0) { + // 记录之前的节点审批人 + tempStartUserSelectAssignees.value = startUserSelectAssignees.value + startUserSelectAssignees.value = {} + // 加载最新的审批详情 + getApprovalDetail({ + id: props.selectProcessDefinition.id, + processVariablesStr: JSON.stringify(newValue.value) // 解决 GET 无法传递对象的问题,后端 String 再转 JSON + }) + } + }, + { + immediate: true + } +) /** 获取审批详情 */ const getApprovalDetail = async (row: any) => {