| | |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.date.DateUtil; |
| | | import cn.hutool.core.lang.Assert; |
| | | import cn.hutool.core.map.MapUtil; |
| | | import cn.hutool.core.util.*; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.date.DateUtils; |
| | |
| | | import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; |
| | | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModelMetaInfoVO; |
| | | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; |
| | | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO; |
| | | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; |
| | | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO.ActivityNodeTask; |
| | | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO; |
| | | import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; |
| | | import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; |
| | | import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO; |
| | | import cn.iocoder.yudao.module.bpm.dal.redis.BpmProcessIdRedisDAO; |
| | | import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants; |
| | | import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum; |
| | | import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelTypeEnum; |
| | | import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeTypeEnum; |
| | | import cn.iocoder.yudao.module.bpm.enums.task.BpmAttachmentTypeEnum; |
| | |
| | | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; |
| | | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; |
| | | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils; |
| | | import cn.iocoder.yudao.module.bpm.service.attach.BpmBusinessAttachService; |
| | | import cn.iocoder.yudao.module.bpm.service.definition.BpmFormService; |
| | | import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; |
| | | import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; |
| | | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| | |
| | | * <p> |
| | | * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 |
| | | * |
| | | * @author 芋道源码 |
| | | * @author 超级管理员 |
| | | */ |
| | | @Service |
| | | @Validated |
| | |
| | | |
| | | @Resource |
| | | private BpmProcessIdRedisDAO processIdRedisDAO; |
| | | |
| | | @Resource |
| | | private BpmBusinessAttachService businessAttachService; |
| | | @Resource |
| | | private BpmFormService formService; |
| | | |
| | | // ========== Query 查询相关方法 ========== |
| | | |
| | |
| | | Map<String, String> formFieldsPermission = getFormFieldsPermission(bpmnModel, reqVO.getActivityId(), taskId); |
| | | |
| | | // 3. 拼接数据 |
| | | return BpmProcessInstanceConvert.INSTANCE.buildApprovalDetail(bpmnModel, processDefinition, |
| | | processDefinitionInfo, processInstance, |
| | | BpmApprovalDetailRespVO detailRespVO = BpmProcessInstanceConvert.INSTANCE.buildApprovalDetail(bpmnModel, |
| | | processDefinition, processDefinitionInfo, processInstance, |
| | | processInstanceStatus, approveNodes, todoTask, formFieldsPermission, userMap, deptMap); |
| | | |
| | | // 3.1 普通表单兜底:历史部署 / 配置导入的数据,bpm_process_definition_info 可能没有 formConf、formFields, |
| | | // 此时按 formId 回读 bpm_form,避免审批详情页表单区域空白 |
| | | fillNormalForm(detailRespVO.getProcessDefinition(), processDefinitionInfo); |
| | | |
| | | // 4. 填充业务附件配置,实现审批详情自动展示外部业务信息 |
| | | businessAttachService.fillBusinessForm(detailRespVO.getProcessDefinition(), processDefinition.getKey(), |
| | | processInstance != null ? processInstance.getBusinessKey() : null); |
| | | return detailRespVO; |
| | | } |
| | | |
| | | /** |
| | | * 普通表单兜底填充:历史部署或配置导入的流程定义,可能只有 formId 而缺失 formConf、formFields, |
| | | * 导致审批详情页的表单区域空白。这里按 formId 回读 bpm_form 补齐。 |
| | | */ |
| | | private void fillNormalForm(BpmProcessDefinitionRespVO definition, BpmProcessDefinitionInfoDO processDefinitionInfo) { |
| | | if (definition == null || !Objects.equals(definition.getFormType(), BpmModelFormTypeEnum.NORMAL.getType())) { |
| | | return; |
| | | } |
| | | Long formId = definition.getFormId() != null ? definition.getFormId() |
| | | : (processDefinitionInfo != null ? processDefinitionInfo.getFormId() : null); |
| | | if (formId == null |
| | | || (StrUtil.isNotBlank(definition.getFormConf()) && CollUtil.isNotEmpty(definition.getFormFields()))) { |
| | | return; |
| | | } |
| | | BpmFormDO form = formService.getForm(formId); |
| | | if (form != null) { |
| | | definition.setFormConf(form.getConf()).setFormFields(form.getFields()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | validateStartUserSelectAssignees(userId, definition, startUserSelectAssignees, variables); |
| | | |
| | | // 2. 创建流程实例 |
| | | if (variables == null) { |
| | | variables = new HashMap<>(); |
| | | } |
| | | FlowableUtils.filterProcessInstanceFormVariable(variables); // 过滤一下,避免 ProcessInstance 系统级的变量被占用 |
| | | variables = FlowableUtils.filterProcessInstanceFormVariable( |
| | | variables == null ? new HashMap<>() : variables); // 复制并过滤,避免修改调用方的变量 |
| | | variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, userId); // 设置流程变量,发起人 ID |
| | | variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, // 流程实例状态:审批中 |
| | | BpmProcessInstanceStatusEnum.RUNNING.getStatus()); |
| | |
| | | } |
| | | BpmModelMetaInfoVO.TitleSetting titleSetting = definitionInfo.getTitleSetting(); |
| | | if (titleSetting == null || !BooleanUtil.isTrue(titleSetting.getEnable())) { |
| | | String businessNo = MapUtil.getStr(variables, |
| | | BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_BUSINESS_NO); |
| | | if (StrUtil.isNotBlank(businessNo)) { |
| | | return definition.getName() + "-" + businessNo; |
| | | } |
| | | return definition.getName(); |
| | | } |
| | | AdminUserRespDTO user = adminUserApi.getUser(userId); |
| | |
| | | } |
| | | |
| | | // 3. 发送流程实例的状态事件 |
| | | // 带上流程分类:自定义流程模型的 key 可能是随机值(如 C000_abc.),业务监听器需要按分类兜底匹配 |
| | | ProcessDefinition processDefinition = processDefinitionService.getProcessDefinition(instance.getProcessDefinitionId()); |
| | | processInstanceEventPublisher.sendProcessInstanceResultEvent( |
| | | BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceStatusEvent(this, instance, status, reason)); |
| | | BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceStatusEvent(this, instance, |
| | | processDefinition != null ? processDefinition.getCategory() : null, status, reason)); |
| | | |
| | | // 4. 流程后置通知 |
| | | if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) { |