gaoluyang
5 天以前 defe1e1c3ade87de0a7990f565f08f93aeb2decc
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
@@ -5,6 +5,7 @@
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;
@@ -15,13 +16,16 @@
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;
@@ -37,6 +41,8 @@
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;
@@ -123,6 +129,11 @@
    @Resource
    private BpmProcessIdRedisDAO processIdRedisDAO;
    @Resource
    private BpmBusinessAttachService businessAttachService;
    @Resource
    private BpmFormService formService;
    // ========== Query 查询相关方法 ==========
@@ -389,9 +400,38 @@
        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());
        }
    }
    /**
@@ -805,10 +845,8 @@
        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());
@@ -875,6 +913,11 @@
        }
        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);
@@ -1016,8 +1059,11 @@
        }
        // 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())) {