diff --git a/workflow-engine-api/src/main/java/cn/axzo/workflow/client/feign/manage/PrintAdminApi.java b/workflow-engine-api/src/main/java/cn/axzo/workflow/client/feign/manage/PrintAdminApi.java index a3b91683f..79ce4d9d5 100644 --- a/workflow-engine-api/src/main/java/cn/axzo/workflow/client/feign/manage/PrintAdminApi.java +++ b/workflow-engine-api/src/main/java/cn/axzo/workflow/client/feign/manage/PrintAdminApi.java @@ -6,6 +6,7 @@ import cn.axzo.workflow.common.annotation.Manageable; import cn.axzo.workflow.common.model.dto.print.PrintFieldDTO; import cn.axzo.workflow.common.model.request.bpmn.print.Print4ProcessLogDTO; import cn.axzo.workflow.common.model.request.bpmn.print.PrintFieldQueryDTO; +import cn.axzo.workflow.common.model.request.bpmn.print.PrintProcessLogPdfDTO; import cn.axzo.workflow.common.model.request.bpmn.print.PrintTemplateConfigUpsertDTO; import cn.axzo.workflow.common.model.response.bpmn.process.PrintData4LogVO; import cn.azxo.framework.common.model.CommonResponse; @@ -88,4 +89,14 @@ public interface PrintAdminApi { @Manageable @InvokeMode(SYNC) CommonResponse getPrintDataForProcessLog(@Validated @RequestBody Print4ProcessLogDTO dto); + + /** + * 后端请求指定流程日志 PDF 文件生成 + * + * @return + */ + @Operation(summary = "后端请求指定流程日志 PDF 文件生成") + @PostMapping("/api/print/admin/process/log/pdf") + @InvokeMode(SYNC) + CommonResponse createProcessLogPdf(@Validated @RequestBody PrintProcessLogPdfDTO dto); } diff --git a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/code/BpmnTaskRespCode.java b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/code/BpmnTaskRespCode.java index 07d01a019..1968f7e27 100644 --- a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/code/BpmnTaskRespCode.java +++ b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/code/BpmnTaskRespCode.java @@ -44,6 +44,7 @@ public enum BpmnTaskRespCode implements IModuleRespCode { REMIND_TASK_TOO_MANY("027", "催办任务数据异常"), PROCESS_SET_ASSIGNEE_PARAM_ERROR("028", "当前审批业务审批人模型中 NodeId 必传(topNodeId/nodeId均可), 触发 ID: 【{}】"), TASK_OPERATION_PARAM_INVALID("029", "流程实例 ID 与任务 ID 必须二选一"), + COOPERATION_NOT_EXIST_WITH_NODE("030", "查询审批人时,组织不存在"), ; private final String code; diff --git a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/constant/BpmnConstants.java b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/constant/BpmnConstants.java index 0daac19ab..f86508f1d 100644 --- a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/constant/BpmnConstants.java +++ b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/constant/BpmnConstants.java @@ -160,6 +160,7 @@ public interface BpmnConstants { String NUMBER_OF_INSTANCES = "nrOfInstances"; String MULTI_INSTANCE_LOOP_COUNTER = "loopCounter"; String TASK_COMPLETE_OPERATION_TYPE = "_TASK_COMPLETE_TYPE"; + String TASK_LOG_NODE_HAS_BEEN_HIDDEN = "_TASK_LOG_HIDDEN"; String TASK_ATTACHMENTS_VAR_NAME = "TASK_ATTACHMENTS"; /** diff --git a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/enums/BpmnProcessInstanceResultEnum.java b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/enums/BpmnProcessInstanceResultEnum.java index 4ae46cef7..a819d30e2 100644 --- a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/enums/BpmnProcessInstanceResultEnum.java +++ b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/enums/BpmnProcessInstanceResultEnum.java @@ -19,6 +19,7 @@ public enum BpmnProcessInstanceResultEnum { UPGRADED("UPGRADED", "已提级"), COMMENTED("COMMENTED", "已评论"), DELETED("DELETED", "已删除"), + HIDDEN("HIDDEN", "已隐藏"), @JsonEnumDefaultValue UNKNOWN("UNKNOWN", "未知"), ; diff --git a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/exception/WorkflowApproverCalcException.java b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/exception/WorkflowApproverCalcException.java new file mode 100644 index 000000000..8956569cc --- /dev/null +++ b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/exception/WorkflowApproverCalcException.java @@ -0,0 +1,75 @@ +package cn.axzo.workflow.common.exception; + +import cn.axzo.framework.domain.ServiceException; +import cn.axzo.framework.domain.web.code.IRespCode; +import com.google.common.annotations.VisibleForTesting; +import lombok.extern.slf4j.Slf4j; + +/** + * 流程内部计算审批人的异常 + * + * @author wangli + * @since 2025-11-03 10:11 + */ +@Slf4j +public class WorkflowApproverCalcException extends ServiceException { + + private String code; + + public WorkflowApproverCalcException(IRespCode code) { + super(code.getMessage()); + this.code = code.getRespCode(); + } + + public WorkflowApproverCalcException(IRespCode code, String... params) { + super(doFormat(code.getCode(), code.getMessage(), params)); + this.code = code.getRespCode(); + } + + public WorkflowApproverCalcException(IRespCode code, Throwable cause, String... params) { + super(doFormat(code.getCode(), code.getMessage(), params), cause); + this.code = code.getRespCode(); + } + + @Override + public String getCode() { + return this.code; + } + + /** + * 将错误编号对应的消息使用 params 进行格式化。 + * + * @param code 错误编号 + * @param messagePattern 消息模版 + * @param params 参数 + * @return 格式化后的提示 + */ + @VisibleForTesting + private static String doFormat(String code, String messagePattern, Object... params) { + StringBuilder sbuf = new StringBuilder(messagePattern.length() + 50); + int i = 0; + int j; + int l; + for (l = 0; l < params.length; l++) { + j = messagePattern.indexOf("{}", i); + if (j == -1) { + log.warn("[doFormat][参数过多:错误码({})|错误内容({})|参数({})", code, messagePattern, params); + if (i == 0) { + return messagePattern; + } else { + sbuf.append(messagePattern.substring(i)); + return sbuf.toString(); + } + } else { + sbuf.append(messagePattern, i, j); + sbuf.append(params[l]); + i = j + 2; + } + } + if (messagePattern.indexOf("{}", i) != -1) { + log.warn("[doFormat][参数过少:错误码({})|错误内容({})|参数({})", code, messagePattern, params); + } + sbuf.append(messagePattern.substring(i)); + return sbuf.toString(); + } +} diff --git a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/dto/CustomDocDTO.java b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/dto/CustomDocDTO.java index c61b3b7ef..748b25ba2 100644 --- a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/dto/CustomDocDTO.java +++ b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/dto/CustomDocDTO.java @@ -53,7 +53,7 @@ public class CustomDocDTO implements Serializable { private String fileKey; /** - * 文件的类型 + * 文件的类型,如果要替换变量,支持 docx 格式,doc 格式不支持。 */ @NotNull(message = "业务自定义文件的类型不能为空") private FileTypeEnum fileType; diff --git a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/print/PrintProcessLogPdfDTO.java b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/print/PrintProcessLogPdfDTO.java new file mode 100644 index 000000000..2c48315a0 --- /dev/null +++ b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/print/PrintProcessLogPdfDTO.java @@ -0,0 +1,36 @@ +package cn.axzo.workflow.common.model.request.bpmn.print; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; + +/** + * 请求审批日志转 pdf 的入参模型 + * + * @author wangli + * @since 2025-10-31 17:15 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class PrintProcessLogPdfDTO { + + /** + * 审批实例 ID + */ + @ApiModelProperty(value = "审批实例 ID") + @NotBlank(message = "审批实例 ID 不能为空") + private String processInstanceId; + + /** + * 实例日志访问者的personId + */ + @ApiModelProperty(value = "访问者的 PersonId") + @NotBlank(message = "访问者的 personId 不能为空") + private String personId; +} diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/SupportRefreshProperties.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/SupportRefreshProperties.java index b57a30193..9f4f247c8 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/SupportRefreshProperties.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/SupportRefreshProperties.java @@ -109,4 +109,7 @@ public class SupportRefreshProperties { @Value("${workflow.ignoreMqAlterApplicationNames:}") private List ignoreMqAlterApplicationNames; + @Value("${workflow.processLogHtmlUrl:https://taskflow-web.axzo.cn/#/document/log?processInstanceId=%s&personId=%d}") + private String processLogHtmlUrl; + } diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomApproveTaskCmd.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomApproveTaskCmd.java index 99992115d..614088a31 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomApproveTaskCmd.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomApproveTaskCmd.java @@ -42,7 +42,9 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_OPERAT import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_SPECIFY_NEXT_APPROVER; import static cn.axzo.workflow.common.constant.BpmnConstants.SIGNATURE_COLLECTION; import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_COMPLETE_OPERATION_TYPE; +import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_LOG_NODE_HAS_BEEN_HIDDEN; import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.APPROVED; +import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.HIDDEN; import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.PROCESSING; import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.addComment; import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.batchAddAttachment; @@ -159,7 +161,12 @@ public class CustomApproveTaskCmd extends AbstractCommand implements Seria runtimeService.setVariable(task.getProcessInstanceId(), INTERNAL_SPECIFY_NEXT_APPROVER, nextApprover); } - task.setTransientVariable(TASK_COMPLETE_OPERATION_TYPE + taskId, APPROVED.getStatus()); + Boolean logNodeHidden = (Boolean) task.getTransientVariable(TASK_LOG_NODE_HAS_BEEN_HIDDEN); + if (logNodeHidden) { + task.setTransientVariable(TASK_COMPLETE_OPERATION_TYPE + taskId, HIDDEN.getStatus()); + } else { + task.setTransientVariable(TASK_COMPLETE_OPERATION_TYPE + taskId, APPROVED.getStatus()); + } // 更新流程内的变量 runtimeService.setVariables(task.getProcessInstanceId(), variables); diff --git a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/AbstractBpmnTaskAssigneeSelector.java b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/AbstractBpmnTaskAssigneeSelector.java index 880a0138c..682da5d49 100644 --- a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/AbstractBpmnTaskAssigneeSelector.java +++ b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/AbstractBpmnTaskAssigneeSelector.java @@ -7,6 +7,7 @@ import cn.axzo.karma.client.model.response.PersonProfileResp; import cn.axzo.orggateway.api.nodeuser.resp.FlowTaskAssignerV2Resp; import cn.axzo.workflow.common.enums.ApproverScopeEnum; import cn.axzo.workflow.common.enums.CarbonCopyObjectType; +import cn.axzo.workflow.common.exception.WorkflowApproverCalcException; import cn.axzo.workflow.common.exception.WorkflowEngineException; import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner; import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper; @@ -45,6 +46,7 @@ import java.util.function.Supplier; import java.util.stream.Collectors; import static cn.axzo.workflow.common.code.BpmnTaskRespCode.CALC_TASK_ASSIGNEE_ERROR; +import static cn.axzo.workflow.common.code.BpmnTaskRespCode.COOPERATION_NOT_EXIST_WITH_NODE; import static cn.axzo.workflow.common.code.ConvertorRespCode.CONVERTOR_META_DATA_FORMAT_ERROR; import static cn.axzo.workflow.common.code.FlowableEngineRespCode.ENGINE_USER_TASK_CALC_ERROR; import static cn.axzo.workflow.common.code.FlowableEngineRespCode.ENGINE_USER_TASK_PARAM_ERROR; @@ -122,6 +124,40 @@ public abstract class AbstractBpmnTaskAssigneeSelector implements BpmnTaskAssign return Collections.emptyList(); } + protected final T parseFoundationApiResultWithErrCode(Supplier> supplier, String operatorDesc, + String extInfo, Object... param) { + StopWatch stopWatch = new StopWatch(operatorDesc); + log.info("{}-Param: {}", operatorDesc, JSONUtil.toJsonStr(param)); + stopWatch.start(); + cn.axzo.foundation.result.ApiResult result = supplier.get(); + stopWatch.stop(); + log.info("{}-Cost:{}, Result: {}", operatorDesc, + "API StopWatch '" + stopWatch.getId() + "': running time = " + stopWatch.getTotalTimeSeconds() + " 's", + JSONUtil.toJsonStr(result)); + try { + if (stopWatch.getTotalTimeSeconds() > refreshProperties.getApiTimeout() && Boolean.TRUE.equals(refreshProperties.getSendDingTalk())) { + DingTalkUtils.sendDingTalkForSlowUrl(applicationContext.getEnvironment() + .getProperty("spring.profiles.active"), + stopWatch.getTotalTimeSeconds(), + extInfo, + param, + result); + } + } catch (Exception e) { + // ignore + } + Assert.notNull(result, "服务调用异常"); + if (Objects.equals(30022100, result.getCode())) { + // 特殊需求,组织不存在时抛得的异常码 + throw new WorkflowApproverCalcException(COOPERATION_NOT_EXIST_WITH_NODE); + } + // 200自定义处理 + if (HttpStatus.HTTP_OK != result.getCode()) { + throw new WorkflowEngineException(CALC_TASK_ASSIGNEE_ERROR, "[API:" + extInfo + "]" + result.getMsg()); + } + return result.getData(); + } + protected final T parseFoundationApiResult(Supplier> supplier, String operatorDesc, String extInfo, Object... param) { StopWatch stopWatch = new StopWatch(operatorDesc); diff --git a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BasedIdentityV2TaskAssigneeSelector.java b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BasedIdentityV2TaskAssigneeSelector.java index f86d05307..1a68aa9e8 100644 --- a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BasedIdentityV2TaskAssigneeSelector.java +++ b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BasedIdentityV2TaskAssigneeSelector.java @@ -9,9 +9,11 @@ import cn.axzo.orggateway.api.nodeuser.resp.FlowTaskAssignerV2Resp; import cn.axzo.workflow.common.enums.ApproverSpecifyEnum; import cn.axzo.workflow.common.enums.ApproverSpecifyRangeEnum; import cn.axzo.workflow.common.enums.SignApproverOrgLimitEnum; +import cn.axzo.workflow.common.exception.WorkflowApproverCalcException; import cn.axzo.workflow.common.exception.WorkflowEngineException; import cn.axzo.workflow.common.model.dto.CooperationOrgDTO; import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner; +import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSON; import com.google.common.collect.Sets; import lombok.extern.slf4j.Slf4j; @@ -21,6 +23,7 @@ import org.flowable.engine.delegate.DelegateExecution; import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -33,6 +36,7 @@ import static cn.axzo.workflow.common.code.FlowableEngineRespCode.ENGINE_USER_TA import static cn.axzo.workflow.common.constant.BpmnConstants.BIZ_ORG_RELATION; import static cn.axzo.workflow.common.constant.BpmnConstants.CLOSE_PROCESS_ASSIGNER; import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_INITIATOR; +import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_LOG_NODE_HAS_BEEN_HIDDEN; import static cn.axzo.workflow.common.enums.ApproverEmptyHandleTypeEnum.transferToAdmin; import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getApproverEmptyHandleType; import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getApproverSpecifyRange; @@ -120,8 +124,14 @@ public class BasedIdentityV2TaskAssigneeSelector extends AbstractBpmnTaskAssigne break; } FlowTaskAssignerV2Req request = v2ReqBuilder.build(); - List apiResultUsers = parseFoundationApiResult(() -> orgNodeUserApi.listFlowTaskAssignerV2(request), "新版查询身份下的人" + execution.getProcessInstanceId() + flowElement.getId(), - "cn.axzo.orggateway.api.nodeuser.OrgNodeUserApi.listFlowTaskAssignerV2", request); + List apiResultUsers = new ArrayList<>(); + try { + apiResultUsers.addAll(parseFoundationApiResultWithErrCode(() -> orgNodeUserApi.listFlowTaskAssignerV2(request), "新版查询身份下的人" + execution.getProcessInstanceId() + flowElement.getId(), + "cn.axzo.orggateway.api.nodeuser.OrgNodeUserApi.listFlowTaskAssignerV2", request)); + } catch (WorkflowApproverCalcException e) { + log.warn("组织节点不存在, 入参:{}; 错误信息:{}", JSONUtil.toJsonStr(request), e.getMessage(), e); + execution.setVariable(TASK_LOG_NODE_HAS_BEEN_HIDDEN, true); + } return convertApprover(apiResultUsers); } diff --git a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BasedInitiatorLeaderV2TaskAssigneeSelector.java b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BasedInitiatorLeaderV2TaskAssigneeSelector.java index 9161ef04c..f01df895a 100644 --- a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BasedInitiatorLeaderV2TaskAssigneeSelector.java +++ b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BasedInitiatorLeaderV2TaskAssigneeSelector.java @@ -7,8 +7,10 @@ import cn.axzo.orggateway.api.nodeuser.req.FlowTaskAssignerV2Req; import cn.axzo.orggateway.api.nodeuser.resp.FlowTaskAssignerV2Resp; import cn.axzo.workflow.common.enums.ApproverSpecifyEnum; import cn.axzo.workflow.common.enums.SignApproverOrgLimitEnum; +import cn.axzo.workflow.common.exception.WorkflowApproverCalcException; import cn.axzo.workflow.common.model.dto.CooperationOrgDTO; import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner; +import cn.hutool.json.JSONUtil; import com.google.common.collect.Sets; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.ListUtils; @@ -17,12 +19,14 @@ import org.flowable.engine.delegate.DelegateExecution; import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; import static cn.axzo.workflow.common.constant.BpmnConstants.BIZ_ORG_RELATION; import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_INITIATOR; +import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_LOG_NODE_HAS_BEEN_HIDDEN; import static cn.axzo.workflow.common.enums.ApproverEmptyHandleTypeEnum.transferToAdmin; import static cn.axzo.workflow.common.enums.ApproverSpecifyRangeUnitEnum.in_project; import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getApproverEmptyHandleType; @@ -74,8 +78,14 @@ public class BasedInitiatorLeaderV2TaskAssigneeSelector extends AbstractBpmnTask .querySupervisorWhileMissMatched(getApproverEmptyHandleType(flowElement).filter(type -> Objects.equals(type, transferToAdmin)).isPresent()); FlowTaskAssignerV2Req request = v2ReqBuilder.build(); - List apiResultUsers = parseFoundationApiResult(() -> orgNodeUserApi.listFlowTaskAssignerV2(request), "新版查询发起人主管的审批人" + execution.getProcessInstanceId() + flowElement.getId(), - "cn.axzo.orggateway.api.nodeuser.OrgNodeUserApi.listFlowTaskAssignerV2", request); + List apiResultUsers = new ArrayList<>(); + try { + apiResultUsers.addAll(parseFoundationApiResultWithErrCode(() -> orgNodeUserApi.listFlowTaskAssignerV2(request), "新版查询发起人主管的审批人" + execution.getProcessInstanceId() + flowElement.getId(), + "cn.axzo.orggateway.api.nodeuser.OrgNodeUserApi.listFlowTaskAssignerV2", request)); + } catch (WorkflowApproverCalcException e) { + log.warn("组织节点不存在, 入参:{}; 错误信息:{}", JSONUtil.toJsonStr(request), e.getMessage(), e); + execution.setVariable(TASK_LOG_NODE_HAS_BEEN_HIDDEN, true); + } return convertApprover(apiResultUsers); } diff --git a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BasedPositionV2TaskAssigneeSelector.java b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BasedPositionV2TaskAssigneeSelector.java index 31eed2e82..f7adc6cfb 100644 --- a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BasedPositionV2TaskAssigneeSelector.java +++ b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BasedPositionV2TaskAssigneeSelector.java @@ -10,9 +10,11 @@ import cn.axzo.workflow.common.enums.ApproverSpecifyRangeEnum; import cn.axzo.workflow.common.enums.ApproverSpecifyRangeUnitEnum; import cn.axzo.workflow.common.enums.CooperateShipTypeEnum; import cn.axzo.workflow.common.enums.SignApproverOrgLimitEnum; +import cn.axzo.workflow.common.exception.WorkflowApproverCalcException; import cn.axzo.workflow.common.exception.WorkflowEngineException; import cn.axzo.workflow.common.model.dto.CooperationOrgDTO; import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner; +import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSON; import com.google.common.collect.Sets; import lombok.extern.slf4j.Slf4j; @@ -22,6 +24,7 @@ import org.flowable.engine.delegate.DelegateExecution; import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -33,6 +36,7 @@ import static cn.axzo.workflow.common.code.FlowableEngineRespCode.ENGINE_POSITIO import static cn.axzo.workflow.common.constant.BpmnConstants.BIZ_ORG_RELATION; import static cn.axzo.workflow.common.constant.BpmnConstants.CLOSE_PROCESS_ASSIGNER; import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_INITIATOR; +import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_LOG_NODE_HAS_BEEN_HIDDEN; import static cn.axzo.workflow.common.enums.ApproverEmptyHandleTypeEnum.transferToAdmin; import static cn.axzo.workflow.common.enums.ApproverSpecifyRangeUnitEnum.in_project; import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getApproverEmptyHandleType; @@ -143,8 +147,14 @@ public class BasedPositionV2TaskAssigneeSelector extends AbstractBpmnTaskAssigne break; } FlowTaskAssignerV2Req request = v2ReqBuilder.build(); - List apiResultUsers = parseFoundationApiResult(() -> orgNodeUserApi.listFlowTaskAssignerV2(request), "新版查询岗位下的人" + execution.getProcessInstanceId() + flowElement.getId(), - "cn.axzo.orggateway.api.nodeuser.OrgNodeUserApi.listFlowTaskAssignerV2", request); + List apiResultUsers = new ArrayList<>(); + try { + apiResultUsers.addAll(parseFoundationApiResultWithErrCode(() -> orgNodeUserApi.listFlowTaskAssignerV2(request), "新版查询岗位下的人" + execution.getProcessInstanceId() + flowElement.getId(), + "cn.axzo.orggateway.api.nodeuser.OrgNodeUserApi.listFlowTaskAssignerV2", request)); + } catch (WorkflowApproverCalcException e) { + log.warn("组织节点不存在, 入参:{}; 错误信息:{}", JSONUtil.toJsonStr(request), e.getMessage(), e); + execution.setVariable(TASK_LOG_NODE_HAS_BEEN_HIDDEN, true); + } return convertApprover(apiResultUsers); } diff --git a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BasedRoleV2TaskAssigneeSelector.java b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BasedRoleV2TaskAssigneeSelector.java index c4f3574a6..7f297388b 100644 --- a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BasedRoleV2TaskAssigneeSelector.java +++ b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BasedRoleV2TaskAssigneeSelector.java @@ -10,9 +10,11 @@ import cn.axzo.workflow.common.enums.ApproverSpecifyRangeEnum; import cn.axzo.workflow.common.enums.ApproverSpecifyRangeUnitEnum; import cn.axzo.workflow.common.enums.CooperateShipTypeEnum; import cn.axzo.workflow.common.enums.SignApproverOrgLimitEnum; +import cn.axzo.workflow.common.exception.WorkflowApproverCalcException; import cn.axzo.workflow.common.exception.WorkflowEngineException; import cn.axzo.workflow.common.model.dto.CooperationOrgDTO; import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner; +import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSON; import com.google.common.collect.Sets; import lombok.extern.slf4j.Slf4j; @@ -23,6 +25,7 @@ import org.flowable.engine.delegate.DelegateExecution; import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -34,6 +37,7 @@ import static cn.axzo.workflow.common.code.FlowableEngineRespCode.ENGINE_ROLE_V2 import static cn.axzo.workflow.common.constant.BpmnConstants.BIZ_ORG_RELATION; import static cn.axzo.workflow.common.constant.BpmnConstants.CLOSE_PROCESS_ASSIGNER; import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_INITIATOR; +import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_LOG_NODE_HAS_BEEN_HIDDEN; import static cn.axzo.workflow.common.enums.ApproverEmptyHandleTypeEnum.transferToAdmin; import static cn.axzo.workflow.common.enums.ApproverSpecifyRangeUnitEnum.in_project; import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getApproverEmptyHandleType; @@ -146,8 +150,14 @@ public class BasedRoleV2TaskAssigneeSelector extends AbstractBpmnTaskAssigneeSel break; } FlowTaskAssignerV2Req request = v2ReqBuilder.build(); - List apiResultUsers = parseFoundationApiResult(() -> orgNodeUserApi.listFlowTaskAssignerV2(request), "新版查询角色下的人" + execution.getProcessInstanceId() + flowElement.getId(), - "cn.axzo.orggateway.api.nodeuser.OrgNodeUserApi.listFlowTaskAssignerV2", request); + List apiResultUsers = new ArrayList<>(); + try { + apiResultUsers.addAll(parseFoundationApiResultWithErrCode(() -> orgNodeUserApi.listFlowTaskAssignerV2(request), "新版查询角色下的人" + execution.getProcessInstanceId() + flowElement.getId(), + "cn.axzo.orggateway.api.nodeuser.OrgNodeUserApi.listFlowTaskAssignerV2", request)); + } catch (WorkflowApproverCalcException e) { + log.warn("组织节点不存在, 入参:{}; 错误信息:{}", JSONUtil.toJsonStr(request), e.getMessage(), e); + execution.setVariable(TASK_LOG_NODE_HAS_BEEN_HIDDEN, true); + } return convertApprover(apiResultUsers); } diff --git a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/web/manage/PrintAdminController.java b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/web/manage/PrintAdminController.java index e4c0d54f6..56029b3b1 100644 --- a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/web/manage/PrintAdminController.java +++ b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/web/manage/PrintAdminController.java @@ -3,6 +3,9 @@ package cn.axzo.workflow.server.controller.web.manage; import cn.axzo.maokai.api.client.OrganizationalNodeUserQueryApi; import cn.axzo.maokai.api.vo.request.OrgNodeUserBriefInfoListReq; import cn.axzo.maokai.api.vo.response.OrgNodeUserBriefInfoResp; +import cn.axzo.nanopart.doc.api.conversion.DocConversionApi; +import cn.axzo.nanopart.doc.api.conversion.req.SubmitConversionTaskRequest; +import cn.axzo.nanopart.doc.api.enums.DocConversionTypeEnum; import cn.axzo.oss.http.api.ServerFileServiceApi; import cn.axzo.oss.http.model.ApiSignUrlDownloadRequest; import cn.axzo.oss.http.model.ApiSignUrlDownloadResponse; @@ -16,6 +19,7 @@ import cn.axzo.workflow.common.model.dto.print.FieldAttributeDTO; import cn.axzo.workflow.common.model.dto.print.PrintFieldDTO; import cn.axzo.workflow.common.model.request.bpmn.print.Print4ProcessLogDTO; import cn.axzo.workflow.common.model.request.bpmn.print.PrintFieldQueryDTO; +import cn.axzo.workflow.common.model.request.bpmn.print.PrintProcessLogPdfDTO; import cn.axzo.workflow.common.model.request.bpmn.print.PrintTemplateConfigUpsertDTO; import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceLogQueryDTO; import cn.axzo.workflow.common.model.request.bpmn.task.AttachmentDTO; @@ -28,6 +32,7 @@ import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceLo import cn.axzo.workflow.common.model.response.bpmn.process.PrintData4LogVO; import cn.axzo.workflow.common.model.response.category.CategoryGroupVarItemVo; import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper; +import cn.axzo.workflow.core.conf.SupportRefreshProperties; import cn.axzo.workflow.core.engine.cmd.CustomGetFormInstanceLatestValuesCmd; import cn.axzo.workflow.core.engine.cmd.CustomGetProcessInstanceVariablesCmd; import cn.axzo.workflow.core.repository.entity.ExtAxProcessLog; @@ -46,7 +51,6 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.google.common.collect.Lists; import io.swagger.v3.oas.annotations.Operation; -import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.ListUtils; import org.flowable.common.engine.api.FlowableObjectNotFoundException; import org.flowable.common.engine.impl.interceptor.CommandExecutor; @@ -59,6 +63,7 @@ import org.flowable.form.model.FormField; import org.flowable.form.model.FormFieldTypes; import org.flowable.form.model.SimpleFormModel; import org.flowable.spring.SpringProcessEngineConfiguration; +import org.slf4j.Logger; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -139,13 +144,13 @@ import static cn.azxo.framework.common.model.CommonResponse.success; * @author wangli * @since 2025-01-16 17:48 */ -@Slf4j @RequestMapping({"/web/v1/api/print/admin", "/api/print/admin"}) @RestController @ErrorReporter @Validated public class PrintAdminController implements PrintAdminApi { + private static final Logger log = org.slf4j.LoggerFactory.getLogger(PrintAdminController.class); @Resource private FormRepositoryService formRepositoryService; @Resource @@ -168,6 +173,10 @@ public class PrintAdminController implements PrintAdminApi { private TaskService taskService; @Resource private ServerFileServiceApi serverFileServiceApi; + @Resource + private DocConversionApi docConversionApi; + @Resource + private SupportRefreshProperties refreshProperties; /** * 查询指定流程实例是否能使用打印 @@ -575,4 +584,17 @@ public class PrintAdminController implements PrintAdminApi { return RpcExternalUtil.rpcProcessor(() -> serverFileServiceApi.signUrlFetchDownload(request), "批量获取手写签私有访问地址", request); } + @Operation(summary = "后端请求指定流程日志 PDF 文件生成") + @PostMapping("/process/log/pdf") + @Override + public CommonResponse createProcessLogPdf(@Validated @RequestBody PrintProcessLogPdfDTO dto) { + SubmitConversionTaskRequest request = new SubmitConversionTaskRequest(); + request.setBizCode("workflow-process-log"); + request.setBizKey(dto.getProcessInstanceId()); + request.setConversionType(DocConversionTypeEnum.HTML_URL_TO_PDF); + request.setFileName(String.format(refreshProperties.getProcessLogHtmlUrl(), dto.getProcessInstanceId(), dto.getPersonId())); + request.setFileKey(dto.getPersonId()); + String taskId = RpcExternalUtil.rpcApiResultProcessor(() -> docConversionApi.submitConvertTask(request), "创建网页转 PDF 的异步任务", request); + return CommonResponse.success(taskId); + } } diff --git a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/engine/ext/listener/TaskEntityEventHandle.java b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/engine/ext/listener/TaskEntityEventHandle.java index 228eedc08..22ea57fbb 100644 --- a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/engine/ext/listener/TaskEntityEventHandle.java +++ b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/engine/ext/listener/TaskEntityEventHandle.java @@ -59,6 +59,7 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_TASK_RELAT import static cn.axzo.workflow.common.constant.BpmnConstants.NO_ASSIGNEE; import static cn.axzo.workflow.common.constant.BpmnConstants.SUPPORT_UPGRADE_VARIABLE; import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_COMPLETE_OPERATION_TYPE; +import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_LOG_NODE_HAS_BEEN_HIDDEN; import static cn.axzo.workflow.common.enums.ApprovalMethodEnum.nobody; import static cn.axzo.workflow.common.enums.BpmnCountersignTypeEnum.BACK_COUNTERSIGN; import static cn.axzo.workflow.common.enums.BpmnCountersignTypeEnum.FORWARD_COUNTERSIGN; @@ -291,6 +292,8 @@ public class TaskEntityEventHandle implements EntityEventHandle { needDelete = true; } } + // 重置日志隐藏的标识为 false + taskEntity.setVariable(TASK_LOG_NODE_HAS_BEEN_HIDDEN, false); update.setEndTime(new Date()); // 判断是否抄送节点,如果是的话,需要将抄送人集合放入对应字段