feat(REQ-3769) - 增加签署业务下,审批待办中,获取最新的渲染文档

This commit is contained in:
wangli 2025-04-03 18:06:29 +08:00
parent 5693083be1
commit ff0d0b6cdd
6 changed files with 122 additions and 10 deletions

View File

@ -14,6 +14,7 @@ import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceLog
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceMyPageReqVO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.SuperBpmnProcessInstanceCancelDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ProcessDocQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskButtonSearchDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormVariablesUpdateDTO;
import cn.axzo.workflow.common.model.response.BpmPageResult;
@ -24,6 +25,7 @@ import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstancePa
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.process.NodesByModelVO;
import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO;
import cn.axzo.workflow.common.model.response.bpmn.process.doc.DocPendingVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskButtonVo;
import cn.azxo.framework.common.model.CommonResponse;
import com.fasterxml.jackson.databind.node.ObjectNode;
@ -286,15 +288,14 @@ public interface ProcessInstanceApi {
@InvokeMode(SYNC)
CommonResponse<Boolean> updateInstanceFormVariables(@Validated @RequestBody FormVariablesUpdateDTO dto);
// /**
// * 获取指定流程的变量集合, 用于打印模板中暂时系统字段
// *
// * @return
// */
// @Operation(summary = "获取指定流程的变量集合,用于打印")
// @PostMapping("/api/process/instance/variables")
// @InvokeMode(SYNC)
// CommonResponse<?> getProcessInstanceVariables();
/**
* 签署业务流程实例在审批待办中查询使用的文档列表
*
* @return
*/
@Operation(summary = "签署业务流程实例在审批待办中查询使用的文档列表")
@PostMapping("/api/process/instance/select/doc/list")
@InvokeMode(SYNC)
CommonResponse<List<DocPendingVO>> processInstanceSelectDocs(@Validated @RequestBody ProcessDocQueryDTO dto);
}

View File

@ -0,0 +1,20 @@
package cn.axzo.workflow.common.model.response.bpmn.process.doc;
import cn.axzo.workflow.common.model.response.bpmn.model.doc.DocBaseVO;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 基础的流程关联文档待办中的响应模型
*
* @author wangli
* @since 2025-03-31 09:49
*/
@ApiModel("基础的流程关联文档待办中的响应模型")
@Data
@NoArgsConstructor
public class DocPendingVO extends DocBaseVO {
private String ossUrl;
}

View File

@ -14,15 +14,20 @@ import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import static cn.axzo.workflow.common.code.BpmnModelRespCode.MODEL_FILE_QUERY_ERROR;
import static cn.axzo.workflow.common.code.BpmnProcessDefinitionRespCode.PROCESS_DEFINITION_ID_ILLEGAL;
import static cn.axzo.workflow.common.constant.BpmnConstants.NO_TENANT_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.SIGN_PROCESS_ENABLE_DOC_IDS;
import static cn.axzo.workflow.core.service.impl.ExtAxModelDocServiceImpl.buildQueryWrapper;
@ -40,10 +45,19 @@ public class CustomGetModelDocsCmd implements Command<List<DocBaseVO>> {
*/
private String processDefinitionId;
private String tenantId;
/**
* 该属性只对流程实例入参生效过滤出发起流程时勾选的文档
*/
private Boolean filterSelect = false;
private final ExtAxModelDocMapper extAxModelDocMapper;
public CustomGetModelDocsCmd(String processInstanceId, ExtAxModelDocMapper extAxModelDocMapper) {
this(processInstanceId, false, extAxModelDocMapper);
}
public CustomGetModelDocsCmd(String processInstanceId, Boolean filterSelect, ExtAxModelDocMapper extAxModelDocMapper) {
this.processInstanceId = processInstanceId;
this.filterSelect = filterSelect;
this.extAxModelDocMapper = extAxModelDocMapper;
}
@ -66,10 +80,17 @@ public class CustomGetModelDocsCmd implements Command<List<DocBaseVO>> {
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
RepositoryService repositoryService = processEngineConfiguration.getRepositoryService();
ProcessDefinition processDefinition;
List<Long> selectDocIds = new ArrayList<>();
if (StringUtils.hasText(processInstanceId)) {
HistoryService historyService = processEngineConfiguration.getHistoryService();
HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(instance.getProcessDefinitionId()).singleResult();
if (filterSelect) {
HistoricVariableInstance variableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(SIGN_PROCESS_ENABLE_DOC_IDS).singleResult();
if (Objects.nonNull(variableInstance)) {
selectDocIds.addAll((List<Long>) variableInstance.getValue());
}
}
} else {
List<ProcessDefinition> definitions = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey(parseProcessDefinitionKey())
@ -85,6 +106,10 @@ public class CustomGetModelDocsCmd implements Command<List<DocBaseVO>> {
query.setStatus(true);
query.setTenantId(processDefinition.getTenantId());
List<ExtAxModelDoc> docs = extAxModelDocMapper.selectList(buildQueryWrapper(query));
if (filterSelect) {
docs = docs.stream().filter(i -> selectDocIds.contains(i.getId())).collect(Collectors.toList());
}
return BeanMapper.copyList(docs, DocBaseVO.class, (s, t) -> t.setFileType(FileTypeEnum.valueOfType(s.getFileType())));
}

View File

@ -11,6 +11,7 @@ import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceMyP
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.HistoricProcessInstanceSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.SuperBpmnProcessInstanceCancelDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ProcessDocQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskButtonSearchDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormVariablesUpdateDTO;
import cn.axzo.workflow.common.model.response.BpmPageResult;
@ -22,6 +23,7 @@ import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO
import cn.axzo.workflow.common.model.response.bpmn.process.HistoricProcessInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.process.NodesByModelVO;
import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO;
import cn.axzo.workflow.common.model.response.bpmn.process.doc.DocPendingVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskButtonVo;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.flowable.engine.history.HistoricProcessInstance;
@ -197,4 +199,6 @@ public interface BpmnProcessInstanceService {
void overrideFormVariables(FormVariablesUpdateDTO dto);
boolean hasPrintTemplate(String processInstanceId, String processDefinitionId);
List<DocPendingVO> processInstanceSelectDocs(ProcessDocQueryDTO dto);
}

View File

@ -1,5 +1,6 @@
package cn.axzo.workflow.core.service.impl;
import cn.axzo.basics.common.BeanMapper;
import cn.axzo.basics.common.exception.ServiceException;
import cn.axzo.workflow.common.constant.BpmnConstants;
import cn.axzo.workflow.common.enums.ApprovalMethodEnum;
@ -13,6 +14,7 @@ import cn.axzo.workflow.common.enums.BusinessTypeEnum;
import cn.axzo.workflow.common.enums.ButtonVisibleScopeEnum;
import cn.axzo.workflow.common.enums.WorkspaceType;
import cn.axzo.workflow.common.exception.WorkflowEngineException;
import cn.axzo.workflow.common.model.dto.SignFileDTO;
import cn.axzo.workflow.common.model.request.BpmnApproveConf;
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonConf;
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonMetaInfo;
@ -27,6 +29,7 @@ import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceMyP
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.HistoricProcessInstanceSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.SuperBpmnProcessInstanceCancelDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ProcessDocQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.AttachmentDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskButtonSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
@ -36,6 +39,7 @@ import cn.axzo.workflow.common.model.request.form.instance.FormVariablesUpdateDT
import cn.axzo.workflow.common.model.response.BpmPageResult;
import cn.axzo.workflow.common.model.response.bpmn.BatchOperationItemResultVO;
import cn.axzo.workflow.common.model.response.bpmn.BatchOperationResultVO;
import cn.axzo.workflow.common.model.response.bpmn.model.doc.DocBaseVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnNodeConfigVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessDefinitionVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceAdminPageItemVO;
@ -45,6 +49,7 @@ import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO
import cn.axzo.workflow.common.model.response.bpmn.process.HistoricProcessInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.process.NodesByModelVO;
import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO;
import cn.axzo.workflow.common.model.response.bpmn.process.doc.DocPendingVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskButtonVo;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskInstanceLogVO;
import cn.axzo.workflow.common.model.response.category.CategoryItemVO;
@ -56,17 +61,21 @@ import cn.axzo.workflow.core.engine.cmd.CustomCancelProcessInstanceAsyncCmd;
import cn.axzo.workflow.core.engine.cmd.CustomCancelProcessInstanceCmd;
import cn.axzo.workflow.core.engine.cmd.CustomCarbonCopyUserSelectorCmd;
import cn.axzo.workflow.core.engine.cmd.CustomForecastUserTaskAssigneeCmd;
import cn.axzo.workflow.core.engine.cmd.CustomGetModelDocsCmd;
import cn.axzo.workflow.core.engine.cmd.CustomOverrideFormVariablesByLatestInstanceCmd;
import cn.axzo.workflow.core.engine.listener.EngineExecutionStartListener;
import cn.axzo.workflow.core.repository.entity.ExtAxBpmnFormRelation;
import cn.axzo.workflow.core.repository.entity.ExtAxHiTaskInst;
import cn.axzo.workflow.core.repository.entity.ExtAxProcessLog;
import cn.axzo.workflow.core.repository.entity.ExtAxProcessSign;
import cn.axzo.workflow.core.repository.mapper.ExtAxModelDocMapper;
import cn.axzo.workflow.core.service.BpmnProcessDefinitionService;
import cn.axzo.workflow.core.service.BpmnProcessInstanceService;
import cn.axzo.workflow.core.service.CategoryService;
import cn.axzo.workflow.core.service.ExtAxBpmnFormRelationService;
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
import cn.axzo.workflow.core.service.ExtAxProcessLogService;
import cn.axzo.workflow.core.service.ExtAxProcessSignService;
import cn.axzo.workflow.core.service.ExtAxReModelService;
import cn.axzo.workflow.core.service.converter.BpmnHistoricProcessInstanceConverter;
import cn.axzo.workflow.core.service.converter.BpmnHistoricTaskInstanceConverter;
@ -163,6 +172,7 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.FLOW_SERVER_VERSION
import static cn.axzo.workflow.common.constant.BpmnConstants.INITIATOR_SPECIFY;
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_INITIATOR;
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_PROCESS_AGENT;
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_PROCESS_BIZ_TYPE;
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_PROCESS_WORKSPACE_TYPE;
import static cn.axzo.workflow.common.constant.BpmnConstants.NO_TENANT_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.OLD_INTERNAL_INITIATOR;
@ -255,6 +265,10 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic
private ExtAxBpmnFormRelationService bpmnFormRelationService;
@Resource
private ExtAxReModelService extAxReModelService;
@Resource
private ExtAxModelDocMapper extAxModelDocMapper;
@Resource
private ExtAxProcessSignService extAxProcessSignService;
@Override
public HistoricProcessInstance getProcessInstanceByBusinessKey(String businessKey, @Nullable String tenantId,
@ -443,6 +457,7 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic
categoryItemVO.ifPresent(itemVO -> {
dto.getVariables().put(INTERNAL_PROCESS_WORKSPACE_TYPE, WorkspaceType.getType(Integer.valueOf(itemVO.getWorkspaceTypeCode())).getCode());
dto.getVariables().put(INTERNAL_PROCESS_BIZ_TYPE, itemVO.getBusinessType().getType());
if (Objects.equals(BusinessTypeEnum.SIGN, itemVO.getBusinessType())) {
// 签署业务
dto.getVariables().put(SIGN_PROCESS_ENABLE_DOC_IDS, dto.getDocIds());
@ -1713,4 +1728,17 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic
CommandExecutor commandExecutor = springProcessEngineConfiguration.getCommandExecutor();
commandExecutor.execute(new CustomOverrideFormVariablesByLatestInstanceCmd(dto.getProcessInstanceId(), dto.getFormVariables()));
}
@Override
public List<DocPendingVO> processInstanceSelectDocs(ProcessDocQueryDTO dto) {
CommandExecutor commandExecutor = springProcessEngineConfiguration.getCommandExecutor();
List<DocBaseVO> docs = commandExecutor.execute(new CustomGetModelDocsCmd(dto.getProcessInstanceId(), true, extAxModelDocMapper));
ExtAxProcessSign processSign = extAxProcessSignService.findByProcessInstanceId(dto.getProcessInstanceId());
Map<Long, String> archiveFileMap = processSign.getFileArchive().stream().collect(Collectors.toMap(SignFileDTO::getId, SignFileDTO::getFileCode));
return BeanMapper.copyList(docs, DocPendingVO.class, (s, t) -> {
t.setFileRelationId(archiveFileMap.getOrDefault(t.getId(), ""));
});
}
}

View File

@ -1,5 +1,7 @@
package cn.axzo.workflow.server.controller.web.bpmn;
import cn.axzo.nanopart.doc.api.anonymous.DocAnonymousDatabaseApi;
import cn.axzo.nanopart.doc.api.index.request.GetNodeInfoRequest;
import cn.axzo.oss.http.api.ServerFileServiceApi;
import cn.axzo.oss.http.model.ApiSignUrlDownloadRequest;
import cn.axzo.oss.http.model.ApiSignUrlDownloadResponse;
@ -16,6 +18,7 @@ import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceMyP
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.HistoricProcessInstanceSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.SuperBpmnProcessInstanceCancelDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ProcessDocQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskButtonSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.common.model.request.form.instance.FormVariablesUpdateDTO;
@ -28,6 +31,7 @@ import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO
import cn.axzo.workflow.common.model.response.bpmn.process.HistoricProcessInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.process.NodesByModelVO;
import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO;
import cn.axzo.workflow.common.model.response.bpmn.process.doc.DocPendingVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskButtonVo;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskInstanceLogVO;
import cn.axzo.workflow.common.valid.group.ValidGroup;
@ -39,6 +43,7 @@ import cn.axzo.workflow.server.controller.web.BasicPopulateAvatarController;
import cn.azxo.framework.common.model.CommonResponse;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Lists;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
@ -60,6 +65,7 @@ import javax.annotation.Nullable;
import javax.annotation.Resource;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@ -82,6 +88,8 @@ public class BpmnProcessInstanceController extends BasicPopulateAvatarController
private BpmnProcessInstanceService bpmnProcessInstanceService;
@Resource
private ServerFileServiceApi serverFileServiceApi;
@Resource
private DocAnonymousDatabaseApi docApi;
/**
* 超管查询所有流程实例
@ -427,4 +435,30 @@ public class BpmnProcessInstanceController extends BasicPopulateAvatarController
bpmnProcessInstanceService.overrideFormVariables(dto);
return CommonResponse.success(true);
}
@Override
@Operation(summary = "签署业务流程实例在审批待办中查询使用的文档列表")
@PostMapping("/select/doc/list")
public CommonResponse<List<DocPendingVO>> processInstanceSelectDocs(ProcessDocQueryDTO dto) {
List<DocPendingVO> docs = bpmnProcessInstanceService.processInstanceSelectDocs(dto);
GetNodeInfoRequest request = new GetNodeInfoRequest();
List<String> wpsCodes = docs.stream().map(DocPendingVO::getFileRelationId).distinct().collect(Collectors.toList());
// TODO 需要提供支持批量查询 fileKey 的接口
// request.setCode(wpsCodes);
docApi.getNodeInfo(request);
Map</*wpsCode*/String, /*fileKey*/String> wpsCodeWithFileKeyMap = new HashMap<>();
ApiSignUrlDownloadRequest ossRequest = new ApiSignUrlDownloadRequest();
ossRequest.setFileKeys(Lists.newArrayList(wpsCodeWithFileKeyMap.values()));
Map</*fileKey*/String, /*ossUrl*/String> ossUrlMap = RpcExternalUtil.rpcProcessor(() -> serverFileServiceApi.signUrlFetchDownload(ossRequest), "批量获取文件 OSS 地址", request)
.stream().collect(Collectors.toMap(ApiSignUrlDownloadResponse::getFileKey, ApiSignUrlDownloadResponse::getSignUrl, (s, t) -> s));
docs.forEach(i -> {
String fileKey = wpsCodeWithFileKeyMap.getOrDefault(i.getFileRelationId(), null);
if (!StringUtils.hasText(fileKey)) {
return;
}
i.setOssUrl(ossUrlMap.getOrDefault(fileKey, null));
});
return success(docs);
}
}