@@ -0,0 +1,27 @@ | |||||
package com.ningdatech.pmapi.common.model; | |||||
import io.swagger.annotations.ApiModel; | |||||
import io.swagger.annotations.ApiModelProperty; | |||||
import lombok.Data; | |||||
/** | |||||
* @author liuxinxin | |||||
* @date 2022/7/25 下午1:55 | |||||
* 用于包装使用 | |||||
*/ | |||||
@Data | |||||
@ApiModel("文件信息基类") | |||||
public class FileBasicInfo { | |||||
@ApiModelProperty("文件id") | |||||
private Long fileId; | |||||
@ApiModelProperty("文件名") | |||||
private String fileName; | |||||
@ApiModelProperty("文件类型") | |||||
private Integer fileType; | |||||
@ApiModelProperty("文件路径") | |||||
private String filePath; | |||||
} |
@@ -1,9 +1,6 @@ | |||||
package com.ningdatech.pmapi.sys.entity; | package com.ningdatech.pmapi.sys.entity; | ||||
import com.baomidou.mybatisplus.annotation.IdType; | |||||
import com.baomidou.mybatisplus.annotation.TableId; | |||||
import com.baomidou.mybatisplus.annotation.TableLogic; | |||||
import com.baomidou.mybatisplus.annotation.TableName; | |||||
import com.baomidou.mybatisplus.annotation.*; | |||||
import io.swagger.annotations.ApiModel; | import io.swagger.annotations.ApiModel; | ||||
import io.swagger.annotations.ApiModelProperty; | import io.swagger.annotations.ApiModelProperty; | ||||
import lombok.Data; | import lombok.Data; | ||||
@@ -46,15 +43,19 @@ public class Notice implements Serializable { | |||||
private String attachment; | private String attachment; | ||||
@ApiModelProperty("创建时间") | @ApiModelProperty("创建时间") | ||||
@TableField(fill = FieldFill.INSERT) | |||||
private LocalDateTime createOn; | private LocalDateTime createOn; | ||||
@ApiModelProperty("创建人id") | @ApiModelProperty("创建人id") | ||||
@TableField(fill = FieldFill.INSERT) | |||||
private Long createBy; | private Long createBy; | ||||
@ApiModelProperty("最后修改时间") | @ApiModelProperty("最后修改时间") | ||||
@TableField(fill = FieldFill.INSERT_UPDATE) | |||||
private LocalDateTime updateOn; | private LocalDateTime updateOn; | ||||
@ApiModelProperty("最后修改人") | @ApiModelProperty("最后修改人") | ||||
@TableField(fill = FieldFill.INSERT_UPDATE) | |||||
private Long updateBy; | private Long updateBy; | ||||
@ApiModelProperty("是否删除") | @ApiModelProperty("是否删除") | ||||
@@ -8,14 +8,14 @@ import lombok.EqualsAndHashCode; | |||||
/** | /** | ||||
* <p> | * <p> | ||||
* DashboardNoticeListPo | |||||
* NoticeListReq | |||||
* </p> | * </p> | ||||
* | * | ||||
* @author WendyYang | * @author WendyYang | ||||
* @since 00:32 2022/7/23 | * @since 00:32 2022/7/23 | ||||
*/ | */ | ||||
@Data | @Data | ||||
@ApiModel("工作台消息列表查询") | |||||
@ApiModel("公告查询参数类") | |||||
@EqualsAndHashCode(callSuper = true) | @EqualsAndHashCode(callSuper = true) | ||||
public class NoticeListReq extends PagePo { | public class NoticeListReq extends PagePo { | ||||
@@ -4,7 +4,6 @@ import io.swagger.annotations.ApiModel; | |||||
import io.swagger.annotations.ApiModelProperty; | import io.swagger.annotations.ApiModelProperty; | ||||
import lombok.Data; | import lombok.Data; | ||||
import javax.validation.Valid; | |||||
import javax.validation.constraints.NotBlank; | import javax.validation.constraints.NotBlank; | ||||
import javax.validation.constraints.NotNull; | import javax.validation.constraints.NotNull; | ||||
@@ -0,0 +1,68 @@ | |||||
package com.ningdatech.pmapi.todocenter.bean.entity; | |||||
import com.ningdatech.pmapi.todocenter.model.dto.req.ReqProcessHandlerDTO; | |||||
import com.wflow.workflow.bean.process.OrgUser; | |||||
import com.wflow.workflow.bean.process.enums.ApprovalModeEnum; | |||||
import com.wflow.workflow.bean.process.enums.NodeTypeEnum; | |||||
import com.wflow.workflow.bean.vo.ProcessHandlerParamsVo; | |||||
import com.wflow.workflow.bean.vo.TaskCommentVo; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Builder; | |||||
import lombok.Data; | |||||
import lombok.NoArgsConstructor; | |||||
import java.util.Date; | |||||
import java.util.List; | |||||
/** | |||||
* 流程节点实体 | |||||
* | |||||
* @author CMM | |||||
* @since 2023/01/31 12:24 | |||||
*/ | |||||
@Data | |||||
@Builder | |||||
@AllArgsConstructor | |||||
@NoArgsConstructor | |||||
public class ProgressNode { | |||||
/** | |||||
* 节点ID | |||||
*/ | |||||
private String nodeId; | |||||
/** | |||||
* 任务ID | |||||
*/ | |||||
private String taskId; | |||||
/** | |||||
* 审批类型 | |||||
*/ | |||||
private ApprovalModeEnum approvalMode; | |||||
/** | |||||
* 节点类型 | |||||
*/ | |||||
private NodeTypeEnum nodeType; | |||||
/** | |||||
* 节点名称 | |||||
*/ | |||||
private String name; | |||||
/** | |||||
* 节点相关人员 | |||||
*/ | |||||
private OrgUser user; | |||||
/** | |||||
* 该节点动作操作类型 | |||||
*/ | |||||
private ReqProcessHandlerDTO.Action action; | |||||
/** | |||||
* 处理结果 | |||||
*/ | |||||
private ReqProcessHandlerDTO.Action result; | |||||
/** | |||||
* 开始时间 | |||||
*/ | |||||
private Date startTime; | |||||
/** | |||||
* 结束时间 | |||||
*/ | |||||
private Date finishTime; | |||||
} |
@@ -0,0 +1,70 @@ | |||||
package com.ningdatech.pmapi.todocenter.bean.vo; | |||||
import com.ningdatech.pmapi.todocenter.bean.entity.ProgressNode; | |||||
import com.wflow.workflow.bean.process.OrgUser; | |||||
import com.wflow.workflow.bean.process.form.Form; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Builder; | |||||
import lombok.Data; | |||||
import lombok.NoArgsConstructor; | |||||
import java.util.Date; | |||||
import java.util.List; | |||||
import java.util.Map; | |||||
/** | |||||
* 流程进展详情实体 | |||||
* | |||||
* @author CMM | |||||
* @since 2023/01/30 17:21 | |||||
*/ | |||||
@Data | |||||
@Builder | |||||
@AllArgsConstructor | |||||
@NoArgsConstructor | |||||
public class ProcessProgressDetailVo { | |||||
/** | |||||
* 审批实例ID | |||||
*/ | |||||
private String instanceId; | |||||
/** | |||||
* 表单配置项 | |||||
*/ | |||||
private List<Form> formItems; | |||||
/** | |||||
* 表单值 | |||||
*/ | |||||
private Map<String, Object> formData; | |||||
/** | |||||
* 流程进度步骤 | |||||
*/ | |||||
private List<ProgressNode> progress; | |||||
/** | |||||
* 流程定义名称 | |||||
*/ | |||||
private String processDefName; | |||||
/** | |||||
* 版本 | |||||
*/ | |||||
private Integer version; | |||||
/** | |||||
* 流程状态 | |||||
*/ | |||||
private String status; | |||||
/** | |||||
* 流程结果 | |||||
*/ | |||||
private String result; | |||||
/** | |||||
* 发起人 | |||||
*/ | |||||
private OrgUser staterUser; | |||||
/** | |||||
* 发起人部门 | |||||
*/ | |||||
private String starterDept; | |||||
/** | |||||
* 发起时间 | |||||
*/ | |||||
private Date startTime; | |||||
} |
@@ -0,0 +1,25 @@ | |||||
package com.ningdatech.pmapi.todocenter.constant; | |||||
/** | |||||
* 历史流程实例终点活跃ID状态 | |||||
* @author CMM | |||||
* @since 2023/01/31 15:13 | |||||
*/ | |||||
public interface HisProInsEndActId { | |||||
/** | |||||
* 流程被驳回 | |||||
*/ | |||||
public static final String REJECT = "refuse-end"; | |||||
/** | |||||
* 流程被退回 | |||||
*/ | |||||
public static final String BACK = "back-end"; | |||||
/** | |||||
* 流程被撤回 | |||||
*/ | |||||
public static final String WITHDRAW = "cancel-end"; | |||||
/** | |||||
* 流程结束 | |||||
*/ | |||||
public static final String END = "process-end"; | |||||
} |
@@ -5,10 +5,11 @@ import javax.servlet.http.HttpServletResponse; | |||||
import javax.validation.Valid; | import javax.validation.Valid; | ||||
import com.ningdatech.pmapi.common.util.ExcelDownUtil; | import com.ningdatech.pmapi.common.util.ExcelDownUtil; | ||||
import org.springframework.web.bind.annotation.GetMapping; | |||||
import org.springframework.web.bind.annotation.ModelAttribute; | |||||
import org.springframework.web.bind.annotation.RequestMapping; | |||||
import org.springframework.web.bind.annotation.RestController; | |||||
import com.ningdatech.pmapi.todocenter.bean.vo.ProcessProgressDetailVo; | |||||
import com.ningdatech.pmapi.todocenter.model.dto.req.ReqProcessHandlerDTO; | |||||
import com.wflow.utils.R; | |||||
import com.wflow.workflow.bean.vo.ProcessHandlerParamsVo; | |||||
import org.springframework.web.bind.annotation.*; | |||||
import com.ningdatech.basic.model.ApiResponse; | import com.ningdatech.basic.model.ApiResponse; | ||||
import com.ningdatech.basic.model.PageVo; | import com.ningdatech.basic.model.PageVo; | ||||
@@ -40,7 +41,7 @@ public class TodoCenterController { | |||||
* @param param | * @param param | ||||
* @return | * @return | ||||
*/ | */ | ||||
@GetMapping("/NotAppendProjectList") | |||||
@GetMapping("/query-project-list") | |||||
public ApiResponse<PageVo<ResToBeProcessedDTO>> queryProjectList(@Valid @ModelAttribute ReqToBeProcessedDTO param){ | public ApiResponse<PageVo<ResToBeProcessedDTO>> queryProjectList(@Valid @ModelAttribute ReqToBeProcessedDTO param){ | ||||
PageVo<ResToBeProcessedDTO> result = todoCenterManage.queryProjectList(param); | PageVo<ResToBeProcessedDTO> result = todoCenterManage.queryProjectList(param); | ||||
return ApiResponse.ofSuccess(result); | return ApiResponse.ofSuccess(result); | ||||
@@ -58,4 +59,26 @@ public class TodoCenterController { | |||||
ExcelDownUtil.downXlsx(response,param,todoCenterManage::exportProjectList); | ExcelDownUtil.downXlsx(response,param,todoCenterManage::exportProjectList); | ||||
} | } | ||||
/** | |||||
* 查询流程表单数据及审批的进度步骤 | |||||
* @param instanceId 流程实例ID | |||||
* @param nodeId 当前获取流程人员关联的流程节点ID | |||||
* @return 流程进度及表单详情 | |||||
*/ | |||||
@GetMapping("progress/{instanceId}/{nodeId}") | |||||
public ApiResponse<ProcessProgressDetailVo> getProcessDetail(@PathVariable String instanceId, | |||||
@PathVariable(required = false) String nodeId) { | |||||
return ApiResponse.ofSuccess(todoCenterManage.getProcessDetail(nodeId, instanceId)); | |||||
} | |||||
/** | |||||
* 审核通过,盖章并通过、退回、撤回、驳回等操作 | |||||
* @param param 操作参数 | |||||
* @return 操作结果 | |||||
*/ | |||||
@PostMapping("/handler") | |||||
public ApiResponse<Object> handler(@Valid @RequestBody ReqProcessHandlerDTO param) { | |||||
todoCenterManage.handler(param); | |||||
return ApiResponse.ofSuccess(); | |||||
} | |||||
} | } |
@@ -27,7 +27,7 @@ public enum ProcessStatusEnum { | |||||
/** | /** | ||||
* 被退回 | * 被退回 | ||||
*/ | */ | ||||
BE_RETURNED(2, "被退回"), | |||||
BE_BACKED(2, "被退回"), | |||||
/** | /** | ||||
* 被驳回 | * 被驳回 | ||||
@@ -0,0 +1,189 @@ | |||||
package com.ningdatech.pmapi.todocenter.extension.cmd; | |||||
import java.io.Serializable; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
import java.util.Map; | |||||
import java.util.Set; | |||||
import java.util.stream.Collectors; | |||||
import org.assertj.core.util.Sets; | |||||
import org.flowable.bpmn.model.FlowNode; | |||||
import org.flowable.bpmn.model.Process; | |||||
import org.flowable.bpmn.model.UserTask; | |||||
import org.flowable.common.engine.api.FlowableException; | |||||
import org.flowable.common.engine.api.FlowableObjectNotFoundException; | |||||
import org.flowable.common.engine.impl.interceptor.Command; | |||||
import org.flowable.common.engine.impl.interceptor.CommandContext; | |||||
import org.flowable.engine.RuntimeService; | |||||
import org.flowable.engine.impl.delegate.ActivityBehavior; | |||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntity; | |||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager; | |||||
import org.flowable.engine.impl.util.CommandContextUtil; | |||||
import org.flowable.engine.impl.util.ExecutionGraphUtil; | |||||
import org.flowable.engine.impl.util.ProcessDefinitionUtil; | |||||
import org.flowable.task.api.Task; | |||||
import org.flowable.task.service.impl.persistence.entity.TaskEntity; | |||||
import com.wflow.workflow.utils.FlowableUtils; | |||||
/** | |||||
* @author : willian fu | |||||
* @date : 2022/10/14 | |||||
*/ | |||||
public class BackToHisApprovalNodeCmd implements Command<String>, Serializable { | |||||
private static final long serialVersionUID = -80075781855060928L; | |||||
protected RuntimeService runtimeService; | |||||
protected String taskId; | |||||
protected String targetNodeId; | |||||
public BackToHisApprovalNodeCmd(RuntimeService runtimeService, String taskId, String targetNodeId) { | |||||
this.runtimeService = runtimeService; | |||||
this.taskId = taskId; | |||||
this.targetNodeId = targetNodeId; | |||||
} | |||||
@Override | |||||
public String execute(CommandContext commandContext) { | |||||
if (targetNodeId == null || targetNodeId.length() == 0) { | |||||
throw new FlowableException("退回的目标节点不能为空"); | |||||
} | |||||
TaskEntity task = CommandContextUtil.getProcessEngineConfiguration().getTaskServiceConfiguration().getTaskService().getTask(taskId); | |||||
if (task == null) { | |||||
throw new FlowableObjectNotFoundException(taskId + " 任务不能为空", Task.class); | |||||
} | |||||
String sourceNodeId = task.getTaskDefinitionKey(); | |||||
String processInstanceId = task.getProcessInstanceId(); | |||||
String processDefinitionId = task.getProcessDefinitionId(); | |||||
//获取流程定义 | |||||
Process process = ProcessDefinitionUtil.getProcess(processDefinitionId); | |||||
FlowNode sourceFlowElement = (FlowNode) process.getFlowElement(sourceNodeId, true); | |||||
// 只支持从用户任务退回 | |||||
if (!(sourceFlowElement instanceof UserTask)) { | |||||
throw new FlowableException("只能从审批节点进行回退"); | |||||
} | |||||
FlowNode targetFlowElement = (FlowNode) process.getFlowElement(targetNodeId, true); | |||||
// 退回节点到当前节点不可达到,不允许退回 | |||||
if (!ExecutionGraphUtil.isReachable(processDefinitionId, targetNodeId, sourceNodeId)) { | |||||
throw new FlowableException("无法回退到目标节点"); | |||||
} | |||||
//目标节点如果相对当前节点是在子流程内部,则无法直接退回,目前处理是只能退回到子流程开始节点 | |||||
String[] sourceAndTargetRealActivityId = FlowableUtils.getSourceAndTargetRealActivityId(sourceFlowElement, targetFlowElement); | |||||
// 实际应操作的当前节点ID | |||||
String sourceRealActivityId = sourceAndTargetRealActivityId[0]; | |||||
// 实际应操作的目标节点ID | |||||
String targetRealActivityId = sourceAndTargetRealActivityId[1]; | |||||
Map<String, Set<String>> specialGatewayNodes = FlowableUtils.getSpecialGatewayElements(process); | |||||
// 当前节点处在的并行网关list | |||||
List<String> sourceInSpecialGatewayList = new ArrayList<>(); | |||||
// 目标节点处在的并行网关list | |||||
List<String> targetInSpecialGatewayList = new ArrayList<>(); | |||||
setSpecialGatewayList(sourceRealActivityId, targetRealActivityId, specialGatewayNodes, sourceInSpecialGatewayList, targetInSpecialGatewayList); | |||||
// 实际应筛选的节点ID | |||||
Set<String> sourceRealAcitivtyIds = null; | |||||
// 若退回目标节点相对当前节点在并行网关中,则要找到相对当前节点最近的这个并行网关,后续做特殊处理 | |||||
String targetRealSpecialGateway = null; | |||||
// 1.目标节点和当前节点都不在并行网关中 | |||||
if (targetInSpecialGatewayList.isEmpty() && sourceInSpecialGatewayList.isEmpty()) { | |||||
sourceRealAcitivtyIds = Sets.newLinkedHashSet(sourceRealActivityId); | |||||
} | |||||
// 2.目标节点不在并行网关中、当前节点在并行网关中 | |||||
else if (targetInSpecialGatewayList.isEmpty()) { | |||||
sourceRealAcitivtyIds = specialGatewayNodes.get(sourceInSpecialGatewayList.get(0)); | |||||
} | |||||
// 3.目标节点在并行网关中、当前节点不在并行网关中 | |||||
else if (sourceInSpecialGatewayList.isEmpty()) { | |||||
sourceRealAcitivtyIds = Sets.newLinkedHashSet(sourceRealActivityId); | |||||
targetRealSpecialGateway = targetInSpecialGatewayList.get(0); | |||||
} | |||||
// 4.目标节点和当前节点都在并行网关中 | |||||
else { | |||||
int diffSpecialGatewayLevel = FlowableUtils.getDiffLevel(sourceInSpecialGatewayList, targetInSpecialGatewayList); | |||||
// 在并行网关同一层且在同一分支 | |||||
if (diffSpecialGatewayLevel == -1) { | |||||
sourceRealAcitivtyIds = Sets.newLinkedHashSet(sourceRealActivityId); | |||||
} else { | |||||
// 当前节点最内层并行网关不被目标节点最内层并行网关包含 | |||||
// 或理解为当前节点相对目标节点在并行网关外 | |||||
// 只筛选当前节点的execution | |||||
if (sourceInSpecialGatewayList.size() == diffSpecialGatewayLevel) { | |||||
sourceRealAcitivtyIds = Sets.newLinkedHashSet(sourceRealActivityId); | |||||
} | |||||
// 当前节点相对目标节点在并行网关内,应筛选相对目标节点最近的并行网关的所有节点的execution | |||||
else { | |||||
sourceRealAcitivtyIds = specialGatewayNodes.get(sourceInSpecialGatewayList.get(diffSpecialGatewayLevel)); | |||||
} | |||||
// 目标节点最内层并行网关包含当前节点最内层并行网关 | |||||
// 或理解为目标节点相对当前节点在并行网关外 | |||||
// 不做处理 | |||||
if (targetInSpecialGatewayList.size() == diffSpecialGatewayLevel) { | |||||
} | |||||
// 目标节点相对当前节点在并行网关内 | |||||
else { | |||||
targetRealSpecialGateway = targetInSpecialGatewayList.get(diffSpecialGatewayLevel); | |||||
} | |||||
} | |||||
} | |||||
// 筛选需要处理的execution | |||||
List<ExecutionEntity> realExecutions = this.getRealExecutions(commandContext, processInstanceId, | |||||
task.getExecutionId(), sourceRealActivityId, sourceRealAcitivtyIds); | |||||
// 执行退回,直接跳转到实际的 targetRealActivityId | |||||
List<String> realExecutionIds = realExecutions.stream().map(ExecutionEntity::getId).collect(Collectors.toList()); | |||||
runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId).moveExecutionsToSingleActivityId(realExecutionIds, targetRealActivityId).changeState(); | |||||
// 目标节点相对当前节点处于并行网关内,需要特殊处理,需要手动生成并行网关汇聚节点(_end)的execution数据 | |||||
if (targetRealSpecialGateway != null) { | |||||
createTargetInSpecialGatewayEndExecutions(commandContext, realExecutions, process, targetInSpecialGatewayList, targetRealSpecialGateway); | |||||
} | |||||
return targetRealActivityId; | |||||
} | |||||
private void setSpecialGatewayList(String sourceNodeId, String targetNodeId, Map<String, Set<String>> specialGatewayNodes, | |||||
List<String> sourceInSpecialGatewayList, List<String> targetInSpecialGatewayList) { | |||||
for (Map.Entry<String, Set<String>> entry : specialGatewayNodes.entrySet()) { | |||||
if (entry.getValue().contains(sourceNodeId)) { | |||||
sourceInSpecialGatewayList.add(entry.getKey()); | |||||
} | |||||
if (entry.getValue().contains(targetNodeId)) { | |||||
targetInSpecialGatewayList.add(entry.getKey()); | |||||
} | |||||
} | |||||
} | |||||
private void createTargetInSpecialGatewayEndExecutions(CommandContext commandContext, List<ExecutionEntity> excutionEntitys, Process process, | |||||
List<String> targetInSpecialGatewayList, String targetRealSpecialGateway) { | |||||
// 目标节点相对当前节点处于并行网关,需要手动生成并行网关汇聚节点(_end)的execution数据 | |||||
String parentExecutionId = excutionEntitys.iterator().next().getParentId(); | |||||
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext); | |||||
ExecutionEntity parentExecutionEntity = executionEntityManager.findById(parentExecutionId); | |||||
int index = targetInSpecialGatewayList.indexOf(targetRealSpecialGateway); | |||||
for (; index < targetInSpecialGatewayList.size(); index++) { | |||||
String targetInSpecialGateway = targetInSpecialGatewayList.get(index); | |||||
FlowNode targetInSpecialGatewayEnd = (FlowNode) process.getFlowElement(targetInSpecialGateway + "_end", true); | |||||
int nbrOfExecutionsToJoin = targetInSpecialGatewayEnd.getIncomingFlows().size(); | |||||
// 处理目标节点所处的分支以外的分支,即 总分枝数-1 = nbrOfExecutionsToJoin - 1 | |||||
for (int i = 0; i < nbrOfExecutionsToJoin - 1; i++) { | |||||
ExecutionEntity childExecution = executionEntityManager.createChildExecution(parentExecutionEntity); | |||||
childExecution.setCurrentFlowElement(targetInSpecialGatewayEnd); | |||||
ActivityBehavior activityBehavior = (ActivityBehavior) targetInSpecialGatewayEnd.getBehavior(); | |||||
activityBehavior.execute(childExecution); | |||||
} | |||||
} | |||||
} | |||||
private List<ExecutionEntity> getRealExecutions(CommandContext commandContext, String processInstanceId, | |||||
String taskExecutionId, String sourceRealActivityId, Set<String> activityIds) { | |||||
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext); | |||||
ExecutionEntity taskExecution = executionEntityManager.findById(taskExecutionId); | |||||
List<ExecutionEntity> executions = executionEntityManager.findChildExecutionsByProcessInstanceId(processInstanceId); | |||||
Set<String> parentExecutionIds = FlowableUtils.getParentExecutionIdsByActivityId(executions, sourceRealActivityId); | |||||
String realParentExecutionId = FlowableUtils.getParentExecutionIdFromParentIds(taskExecution, parentExecutionIds); | |||||
return executionEntityManager.findExecutionsByParentExecutionAndActivityIds(realParentExecutionId, activityIds); | |||||
} | |||||
} |
@@ -1,28 +1,53 @@ | |||||
package com.ningdatech.pmapi.todocenter.manage; | package com.ningdatech.pmapi.todocenter.manage; | ||||
import cn.hutool.core.collection.CollectionUtil; | import cn.hutool.core.collection.CollectionUtil; | ||||
import cn.hutool.core.util.ObjectUtil; | |||||
import cn.hutool.core.util.StrUtil; | |||||
import com.alibaba.excel.EasyExcel; | import com.alibaba.excel.EasyExcel; | ||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | ||||
import com.ningdatech.basic.exception.BizException; | |||||
import com.ningdatech.basic.util.NdDateUtils; | import com.ningdatech.basic.util.NdDateUtils; | ||||
import com.ningdatech.pmapi.common.constant.ProjectDeclareConstants; | import com.ningdatech.pmapi.common.constant.ProjectDeclareConstants; | ||||
import com.ningdatech.pmapi.common.util.ExcelDownUtil; | import com.ningdatech.pmapi.common.util.ExcelDownUtil; | ||||
import com.ningdatech.pmapi.common.util.ExcelExportStyle; | import com.ningdatech.pmapi.common.util.ExcelExportStyle; | ||||
import com.ningdatech.pmapi.todocenter.bean.entity.ProgressNode; | |||||
import com.ningdatech.pmapi.todocenter.bean.vo.ProcessProgressDetailVo; | |||||
import com.ningdatech.pmapi.todocenter.constant.HisProInsEndActId; | |||||
import com.ningdatech.pmapi.todocenter.enums.ProcessStatusEnum; | import com.ningdatech.pmapi.todocenter.enums.ProcessStatusEnum; | ||||
import com.ningdatech.pmapi.todocenter.extension.cmd.BackToHisApprovalNodeCmd; | |||||
import com.ningdatech.pmapi.todocenter.model.dto.req.ReqProcessHandlerDTO; | |||||
import com.ningdatech.pmapi.todocenter.model.dto.res.ResToBeProjectListExportDTO; | import com.ningdatech.pmapi.todocenter.model.dto.res.ResToBeProjectListExportDTO; | ||||
import com.ningdatech.pmapi.user.util.LoginUserUtil; | import com.ningdatech.pmapi.user.util.LoginUserUtil; | ||||
import com.wflow.bean.do_.UserDo; | |||||
import com.wflow.bean.entity.WflowCcTasks; | |||||
import com.wflow.bean.entity.WflowModelHistorys; | |||||
import com.wflow.mapper.WflowCcTasksMapper; | |||||
import com.wflow.mapper.WflowModelHistorysMapper; | |||||
import com.wflow.service.OrgRepositoryService; | |||||
import com.wflow.workflow.bean.dto.ProcessInstanceOwnerDto; | import com.wflow.workflow.bean.dto.ProcessInstanceOwnerDto; | ||||
import com.wflow.workflow.bean.process.OrgUser; | import com.wflow.workflow.bean.process.OrgUser; | ||||
import com.wflow.workflow.bean.process.ProcessNode; | |||||
import com.wflow.workflow.bean.process.enums.ApprovalModeEnum; | |||||
import com.wflow.workflow.bean.process.enums.NodeTypeEnum; | |||||
import com.wflow.workflow.bean.process.form.Form; | |||||
import com.wflow.workflow.bean.process.props.ApprovalProps; | |||||
import com.wflow.workflow.bean.vo.ProcessProgressVo; | import com.wflow.workflow.bean.vo.ProcessProgressVo; | ||||
import com.wflow.workflow.bean.vo.ProcessTaskVo; | import com.wflow.workflow.bean.vo.ProcessTaskVo; | ||||
import com.wflow.workflow.service.ProcessInstanceService; | |||||
import com.wflow.workflow.service.UserDeptOrLeaderService; | |||||
import org.flowable.engine.RepositoryService; | |||||
import org.flowable.engine.RuntimeService; | |||||
import org.flowable.engine.TaskService; | |||||
import com.wflow.workflow.config.WflowGlobalVarDef; | |||||
import com.wflow.workflow.service.*; | |||||
import com.wflow.workflow.service.FormService; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.assertj.core.util.Maps; | |||||
import org.flowable.engine.*; | |||||
import org.flowable.engine.history.HistoricActivityInstance; | |||||
import org.flowable.engine.history.HistoricProcessInstance; | |||||
import org.flowable.engine.repository.ProcessDefinition; | import org.flowable.engine.repository.ProcessDefinition; | ||||
import org.flowable.engine.runtime.Execution; | |||||
import org.flowable.engine.runtime.ProcessInstance; | import org.flowable.engine.runtime.ProcessInstance; | ||||
import org.flowable.task.api.Task; | import org.flowable.task.api.Task; | ||||
import org.flowable.task.api.TaskQuery; | import org.flowable.task.api.TaskQuery; | ||||
import org.flowable.variable.api.history.HistoricVariableInstance; | |||||
import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||
import com.ningdatech.basic.model.PageVo; | import com.ningdatech.basic.model.PageVo; | ||||
@@ -33,10 +58,8 @@ import lombok.RequiredArgsConstructor; | |||||
import javax.servlet.http.HttpServletResponse; | import javax.servlet.http.HttpServletResponse; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.util.HashSet; | |||||
import java.util.List; | |||||
import java.util.Map; | |||||
import java.util.Set; | |||||
import java.time.LocalDateTime; | |||||
import java.util.*; | |||||
import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||
/** | /** | ||||
@@ -45,6 +68,7 @@ import java.util.stream.Collectors; | |||||
*/ | */ | ||||
@Component | @Component | ||||
@RequiredArgsConstructor | @RequiredArgsConstructor | ||||
@Slf4j | |||||
public class TodoCenterManage { | public class TodoCenterManage { | ||||
private final TaskService taskService; | private final TaskService taskService; | ||||
@@ -52,6 +76,14 @@ public class TodoCenterManage { | |||||
private final RuntimeService runtimeService; | private final RuntimeService runtimeService; | ||||
private final UserDeptOrLeaderService userDeptOrLeaderService; | private final UserDeptOrLeaderService userDeptOrLeaderService; | ||||
private final ProcessInstanceService processService; | private final ProcessInstanceService processService; | ||||
private final FormService formService; | |||||
private final ManagementService managementService; | |||||
private final HistoryService historyService; | |||||
private final WflowModelHistorysMapper modelHistorysMapper; | |||||
private final ProcessNodeCatchService nodeCatchService; | |||||
private final OrgRepositoryService orgRepositoryService; | |||||
private final ProcessTaskService processTaskService; | |||||
private final WflowCcTasksMapper ccTasksMapper; | |||||
public PageVo<ResToBeProcessedDTO> queryProjectList(ReqToBeProcessedDTO param) { | public PageVo<ResToBeProcessedDTO> queryProjectList(ReqToBeProcessedDTO param) { | ||||
// 获取登录用户ID | // 获取登录用户ID | ||||
Long userId = LoginUserUtil.getUserId(); | Long userId = LoginUserUtil.getUserId(); | ||||
@@ -99,7 +131,7 @@ public class TodoCenterManage { | |||||
.createTime(processInstance.getStartTime()) | .createTime(processInstance.getStartTime()) | ||||
.taskCreateTime(task.getCreateTime()) | .taskCreateTime(task.getCreateTime()) | ||||
.build(); | .build(); | ||||
res.setProcessTaskVo(processTaskVo); | |||||
res.setProcessTaskInfo(processTaskVo); | |||||
String projectName = (String) formData.get(ProjectDeclareConstants.BasicInformation.PROJECT_NAME); | String projectName = (String) formData.get(ProjectDeclareConstants.BasicInformation.PROJECT_NAME); | ||||
res.setProjectName(projectName); | res.setProjectName(projectName); | ||||
res.setReportUnitId(owner.getOwnerDeptId()); | res.setReportUnitId(owner.getOwnerDeptId()); | ||||
@@ -121,12 +153,11 @@ public class TodoCenterManage { | |||||
//取用户信息,减少数据库查询,一次构建 | //取用户信息,减少数据库查询,一次构建 | ||||
if (CollectionUtil.isNotEmpty(staterUsers)) { | if (CollectionUtil.isNotEmpty(staterUsers)) { | ||||
Map<String, OrgUser> userMap = userDeptOrLeaderService.getUserMapByIds(staterUsers); | Map<String, OrgUser> userMap = userDeptOrLeaderService.getUserMapByIds(staterUsers); | ||||
page.setRecords(result.stream().peek(v -> v.getProcessTaskVo().setOwner(userMap.get(v.getProcessTaskVo().getOwnerId()))).collect(Collectors.toList())); | |||||
page.setRecords(result.stream().peek(v -> v.getProcessTaskInfo().setOwner(userMap.get(v.getProcessTaskInfo().getOwnerId()))).collect(Collectors.toList())); | |||||
} | } | ||||
return PageVo.of(resVos,page.getTotal()); | return PageVo.of(resVos,page.getTotal()); | ||||
} | } | ||||
public void exportProjectList(HttpServletResponse response, ReqToBeProcessedDTO param) { | public void exportProjectList(HttpServletResponse response, ReqToBeProcessedDTO param) { | ||||
PageVo<ResToBeProcessedDTO> page = | PageVo<ResToBeProcessedDTO> page = | ||||
queryProjectList(param); | queryProjectList(param); | ||||
@@ -149,4 +180,283 @@ public class TodoCenterManage { | |||||
throw new RuntimeException(e); | throw new RuntimeException(e); | ||||
} | } | ||||
} | } | ||||
public void handler(ReqProcessHandlerDTO param) { | |||||
Long userId = LoginUserUtil.getUserId(); | |||||
Task task = taskService.createTaskQuery().taskId(param.getTaskId()).active().singleResult(); | |||||
HashMap<String, Object> formData = new HashMap<>(32); | |||||
String format = NdDateUtils.format(LocalDateTime.now(), "yyyy-MM-dd HH:mm"); | |||||
LocalDateTime auditTime = LocalDateTime.parse(format); | |||||
if (Objects.isNull(task)) { | |||||
throw new BizException("任务不存在"); | |||||
} | |||||
switch (param.getAction()) { | |||||
// 通过 | |||||
case pass: | |||||
formData.put("audit_pass_opinion",param.getAuditPassOpinion()); | |||||
formData.put("audit_pass_appendix",param.getAuditPassAppendix()); | |||||
formData.put("audit_pass_time", auditTime); | |||||
formService.updateInstanceFormData(param.getInstanceId(), formData); | |||||
doPass(task, param); | |||||
// 盖章并通过 | |||||
case seal_pass: | |||||
formData.put("seal_pass_opinion",param.getSealPassOpinion()); | |||||
formData.put("seal_pass_appendix",param.getSealPassAppendix()); | |||||
Date sealPassTime = NdDateUtils.localDateTime2Date(LocalDateTime.now()); | |||||
formData.put("seal_pass_time",sealPassTime); | |||||
formService.updateInstanceFormData(param.getInstanceId(), formData); | |||||
doSealPass(task, param); | |||||
// 驳回 | |||||
case reject: | |||||
formData.put("audit_reject_opinion",param.getAuditRejectOpinion()); | |||||
formData.put("audit_reject_appendix",param.getAuditRejectAppendix()); | |||||
formData.put("audit_reject_time", auditTime); | |||||
formService.updateInstanceFormData(param.getInstanceId(), formData); | |||||
doReject(task, param); | |||||
break; | |||||
// 退回 | |||||
case back: | |||||
formData.put("audit_back_opinion",param.getAuditBackOpinion()); | |||||
formData.put("audit_back_appendix",param.getAuditBackAppendix()); | |||||
formData.put("audit_back_time", auditTime); | |||||
formService.updateInstanceFormData(param.getInstanceId(), formData); | |||||
doBackTask(task.getTaskDefinitionKey(), userId, param); | |||||
break; | |||||
// 撤回 | |||||
case withdraw: | |||||
doWithDrawProcess(task); | |||||
break; | |||||
default: | |||||
throw new IllegalStateException("Unexpected value: " + param.getAction()); | |||||
} | |||||
} | |||||
/** | |||||
* 审批任务:驳回 | |||||
* | |||||
* @param task 当前任务 | |||||
* @param param 参数 | |||||
*/ | |||||
private void doReject(Task task, ReqProcessHandlerDTO param) { | |||||
Map<String, Object> var = new HashMap<>(16); | |||||
var.put("approve_" + task.getId(), param.getAction()); | |||||
// TODO 中止流程并使项目进入对应状态 | |||||
// TODO 给项目创建人、流程发起人发送浙政钉工作通知:【项目名称】的【流程名称】被驳回,请及时处理。 | |||||
taskService.complete(param.getTaskId(), var); | |||||
} | |||||
/** | |||||
* 审批任务:盖章并通过 | |||||
* | |||||
* @param task 当前任务 | |||||
* @param param 参数 | |||||
*/ | |||||
private void doSealPass(Task task, ReqProcessHandlerDTO param) { | |||||
Map<String, Object> var = new HashMap<>(16); | |||||
var.put("approve_" + task.getId(), param.getAction()); | |||||
// TODO 判断项目申报单位级别,区县单位申报有上级主管单位意见栏,市级单位没有 | |||||
// TODO 市级单位:为大数据局;区县单位:为大数据中心(根据附件区分?) | |||||
taskService.complete(param.getTaskId(), var); | |||||
} | |||||
/** | |||||
* 审批任务:通过 | |||||
* | |||||
* @param task 当前任务 | |||||
* @param param 参数 | |||||
*/ | |||||
private void doPass(Task task, ReqProcessHandlerDTO param) { | |||||
Map<String, Object> var = new HashMap<>(16); | |||||
var.put("approve_" + task.getId(), param.getAction()); | |||||
// TODO 获取流程下一个节点的审核人 | |||||
// TODO 若有下一个审核人,向其发送浙政钉工作通知:标题:审核任务 内容:【单位名称】的【项目名称】需要您审核。 | |||||
// TODO 若没有,向发起人发送浙政钉工作通知:【项目名称】已通过【流程名称】,请及时开始下一步操作。 | |||||
taskService.complete(param.getTaskId(), var); | |||||
} | |||||
/** | |||||
* 撤销流程处理 | |||||
* | |||||
* @param task 当前任务 | |||||
*/ | |||||
private void doWithDrawProcess(Task task) { | |||||
// TODO 若是流程发起人点击撤回,项目回到上一个状态,并删除当前审核人对应的待办记录 | |||||
// TODO 若是前一个审核人点击撤回,在审核记录中移除自己提交过的审核意见、待我处理中移除当前审核人的待办记录、待我处理中增加自己的待办记录、我已处理中去掉自己之前处理的记录 | |||||
List<Execution> executions = runtimeService.createExecutionQuery() | |||||
.processInstanceId(task.getProcessInstanceId()) | |||||
.onlyChildExecutions().list(); | |||||
// 强制流程指向撤回 | |||||
runtimeService.createChangeActivityStateBuilder() | |||||
.processInstanceId(task.getProcessInstanceId()) | |||||
.moveActivityIdTo(task.getTaskDefinitionKey(), HisProInsEndActId.WITHDRAW) | |||||
.moveExecutionsToSingleActivityId(executions.stream().map(Execution::getId) | |||||
.collect(Collectors.toList()), HisProInsEndActId.WITHDRAW) | |||||
.changeState(); | |||||
} | |||||
/** | |||||
* 退回流程处理 | |||||
* @param current 当前流程定义key | |||||
* @param userId 当前登录用户ID | |||||
* @param param 参数 | |||||
*/ | |||||
private void doBackTask(String current, Long userId, ReqProcessHandlerDTO param) { | |||||
// TODO 流程变成【被退回】状态 | |||||
// TODO 待我处理中,为流程发起人增加一条待办记录 | |||||
// TODO 给项目创建人、流程发起人发送浙政钉工作通知:【项目名称】的【流程名称】被退回,请及时处理。 | |||||
//执行自定义回退逻辑 | |||||
managementService.executeCommand(new BackToHisApprovalNodeCmd(runtimeService, param.getTaskId(), param.getTargetNode())); | |||||
runtimeService.setVariables(param.getInstanceId(), Maps.newHashMap("approve_" + param.getTaskId(), param.getAction())); | |||||
log.info("用户[{}] 退回流程[{}] [{} -> {}]", userId, param.getInstanceId(), current, param.getTargetNode()); | |||||
} | |||||
/** | |||||
* 查询流程表单数据及审批的进度步骤 | |||||
* @param instanceId 流程实例ID | |||||
* @param nodeId 当前获取流程人员关联的流程节点ID | |||||
* @return 流程进度及表单详情 | |||||
*/ | |||||
public ProcessProgressDetailVo getProcessDetail(String nodeId, String instanceId) { | |||||
HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(instanceId).singleResult(); | |||||
// 取表单及表单数据 | |||||
HistoricVariableInstance forms = historyService.createHistoricVariableInstanceQuery() | |||||
.processInstanceId(instanceId).variableName(WflowGlobalVarDef.WFLOW_FORMS).singleResult(); | |||||
List<HistoricVariableInstance> formDatas = historyService.createHistoricVariableInstanceQuery() | |||||
.processInstanceId(instanceId).variableNameLike("field%").list(); | |||||
// 取节点设置 | |||||
HistoricVariableInstance nodeProps = historyService.createHistoricVariableInstanceQuery() | |||||
.processInstanceId(instanceId).variableName(WflowGlobalVarDef.WFLOW_NODE_PROPS).singleResult(); | |||||
Map<String, Object> nodePropsValue = (Map<String, Object>) nodeProps.getValue(); | |||||
ProcessNode<?> currentNode = null; | |||||
if (StrUtil.isNotBlank(nodeId)) { | |||||
// 搜索当前版本流程的配置 | |||||
WflowModelHistorys modelHistory = modelHistorysMapper.selectOne(new QueryWrapper<>(WflowModelHistorys.builder() | |||||
.processDefId(instance.getProcessDefinitionId()).version(instance.getProcessDefinitionVersion()).build())); | |||||
currentNode = nodeCatchService.reloadProcessByStr(modelHistory.getProcess()).get(nodeId); | |||||
} | |||||
UserDo users = orgRepositoryService.getUserById(instance.getStartUserId()); | |||||
OrgUser startUser = OrgUser.builder().id(users.getUserId()).name(users.getUserName()).avatar(users.getAvatar()).build(); | |||||
List<ProgressNode> taskRecords = getHisTaskRecords(instanceId, nodePropsValue); | |||||
// 获取添加抄送任务 | |||||
taskRecords.addAll(getCcTaskRecords(instanceId)); | |||||
if (ObjectUtil.isNull(instance.getEndTime())) { | |||||
// TODO 下版实现 获取等待中且还未开始的任务,如果存在条件则需要直接解析条件 | |||||
taskRecords.addAll(getFutureTask(instanceId)); | |||||
} | |||||
taskRecords = taskRecords.stream() | |||||
.sorted(Comparator.comparing(ProgressNode::getStartTime)) | |||||
.collect(Collectors.toList()); | |||||
taskRecords.add(0, ProgressNode.builder() | |||||
.nodeId("root") | |||||
.name("提交申请") | |||||
.user(startUser) | |||||
.nodeType(NodeTypeEnum.ROOT) | |||||
.startTime(instance.getStartTime()) | |||||
.finishTime(instance.getStartTime()) | |||||
.taskId("root") | |||||
.result(ReqProcessHandlerDTO.Action.pass) | |||||
.build()); | |||||
// 提取全量表单数据 | |||||
Map<String, Object> formData = formDatas.stream().collect(Collectors.toMap(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue)); | |||||
HistoricVariableInstance variableInstance = historyService.createHistoricVariableInstanceQuery() | |||||
.processInstanceId(instanceId).variableName("owner").singleResult(); | |||||
ProcessInstanceOwnerDto owner = (ProcessInstanceOwnerDto) variableInstance.getValue(); | |||||
ProcessProgressDetailVo res = ProcessProgressDetailVo.builder() | |||||
.instanceId(instanceId) | |||||
.version(instance.getProcessDefinitionVersion()) | |||||
.formItems(formService.filterFormAndDataByPermConfig((List<Form>) forms.getValue(), formData, currentNode)) | |||||
.formData(formData) | |||||
.processDefName(instance.getProcessDefinitionName()) | |||||
.staterUser(startUser) | |||||
.starterDept(null == owner ? null : owner.getOwnerDeptName()) | |||||
.result(instance.getEndActivityId()) | |||||
.startTime(instance.getStartTime()) | |||||
.progress(taskRecords) | |||||
.build(); | |||||
if (Objects.isNull(instance.getEndActivityId())){ | |||||
res.setStatus(ProcessStatusEnum.UNDER_REVIEW.name()); | |||||
} else if (HisProInsEndActId.BACK.equals(instance.getEndActivityId())) { | |||||
res.setStatus(ProcessStatusEnum.BE_BACKED.name()); | |||||
} else if (HisProInsEndActId.REJECT.equals(instance.getEndActivityId())) { | |||||
res.setStatus(ProcessStatusEnum.BE_REJECTED.name()); | |||||
} else if (HisProInsEndActId.END.equals(instance.getEndActivityId())) { | |||||
res.setStatus(ProcessStatusEnum.APPROVED.name()); | |||||
} | |||||
return res; | |||||
} | |||||
/** | |||||
* 获取抄送的流程实例信息 | |||||
* | |||||
* @param instanceId 实例ID | |||||
* @return 抄送我的流程 | |||||
*/ | |||||
private List<ProgressNode> getCcTaskRecords(String instanceId) { | |||||
Set<String> ccUsers = new HashSet<>(); | |||||
List<ProgressNode> ccList = ccTasksMapper.selectList(new QueryWrapper<WflowCcTasks>() | |||||
.eq("instance_id", instanceId)).stream().map(task -> { | |||||
ccUsers.add(task.getUserId()); | |||||
return ProgressNode.builder() | |||||
.nodeId(task.getNodeId()) | |||||
.nodeType(NodeTypeEnum.CC) | |||||
.name(task.getNodeName()) | |||||
.user(OrgUser.builder().id(task.getUserId()).build()) | |||||
.startTime(task.getCreateTime()) | |||||
.finishTime(task.getCreateTime()) | |||||
.build(); | |||||
}).collect(Collectors.toList()); | |||||
if (CollectionUtil.isNotEmpty(ccUsers)) { | |||||
Map<String, OrgUser> userMap = userDeptOrLeaderService.getUserMapByIds(ccUsers); | |||||
ccList.stream().peek(v -> v.setUser(userMap.get(v.getUser().getId()))).collect(Collectors.toList()); | |||||
} | |||||
return ccList; | |||||
} | |||||
/** | |||||
* 获取流程的审批历史记录 | |||||
* | |||||
* @param instanceId 审批实例ID | |||||
* @param nodeProps 节点设置 | |||||
* @return 历史记录列表 | |||||
*/ | |||||
private List<ProgressNode> getHisTaskRecords(String instanceId, Map<String, Object> nodeProps) { | |||||
List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery() | |||||
.processInstanceId(instanceId).orderByHistoricActivityInstanceStartTime().asc().list(); | |||||
Set<String> userSet = new HashSet<>(); | |||||
//获取节点处理结果 | |||||
Map<String, ReqProcessHandlerDTO.Action> varMap = historyService.createHistoricVariableInstanceQuery() | |||||
.processInstanceId(instanceId).variableNameLike("approve_%").list().stream() | |||||
.collect(Collectors.toMap(HistoricVariableInstance::getVariableName, v -> (ReqProcessHandlerDTO.Action) v.getValue())); | |||||
List<ProgressNode> progressNodes = list.stream().filter(his -> ObjectUtil.isNotNull(his.getTaskId())).map(his -> { | |||||
Object props = nodeProps.get(his.getActivityId()); | |||||
ApprovalModeEnum approvalMode = null; | |||||
if (props instanceof ApprovalProps) { | |||||
approvalMode = ((ApprovalProps) props).getMode(); | |||||
} | |||||
userSet.add(his.getAssignee()); | |||||
return ProgressNode.builder() | |||||
.nodeId(his.getActivityId()) | |||||
.name(his.getActivityName()) | |||||
.nodeType(NodeTypeEnum.APPROVAL) | |||||
.user(OrgUser.builder().id(his.getAssignee()).build()) | |||||
.startTime(his.getStartTime()) | |||||
.finishTime(his.getEndTime()) | |||||
.taskId(his.getTaskId()) | |||||
.approvalMode(approvalMode) | |||||
.result(varMap.get("approve_" + his.getTaskId())) | |||||
.build(); | |||||
}).collect(Collectors.toList()); | |||||
if (CollectionUtil.isNotEmpty(userSet)) { | |||||
Map<String, OrgUser> map = userDeptOrLeaderService.getUserMapByIds(userSet); | |||||
progressNodes.forEach(n -> n.setUser(map.get(n.getUser().getId()))); | |||||
} | |||||
return progressNodes; | |||||
} | |||||
private List<ProgressNode> getFutureTask(String instanceId) { | |||||
//根据流程遍历后续节点,期间要穿越后续包含并行网关和条件网关的节点 | |||||
return Collections.emptyList(); | |||||
} | |||||
} | } |
@@ -0,0 +1,82 @@ | |||||
package com.ningdatech.pmapi.todocenter.model.dto.req; | |||||
import com.ningdatech.pmapi.common.model.FileBasicInfo; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Data; | |||||
import lombok.NoArgsConstructor; | |||||
import java.time.LocalDateTime; | |||||
/** | |||||
* 流程处理操作参数实体 | |||||
* | |||||
* @author CMM | |||||
* @since 2023/01/30 09:09 | |||||
*/ | |||||
@Data | |||||
@NoArgsConstructor | |||||
@AllArgsConstructor | |||||
public class ReqProcessHandlerDTO { | |||||
/** | |||||
* 实例ID | |||||
*/ | |||||
private String instanceId; | |||||
/** | |||||
* 任务ID | |||||
*/ | |||||
private String taskId; | |||||
/** | |||||
* 签名图片地址 | |||||
*/ | |||||
private String signature; | |||||
/** | |||||
* 操作类型 | |||||
*/ | |||||
private Action action; | |||||
/** | |||||
* 目标用户 | |||||
*/ | |||||
private String targetUser; | |||||
/** | |||||
* 目标节点 | |||||
*/ | |||||
private String targetNode; | |||||
/** | |||||
* 审核通过意见 | |||||
*/ | |||||
private String auditPassOpinion; | |||||
/** | |||||
* 审核通过附件 | |||||
*/ | |||||
private FileBasicInfo auditPassAppendix; | |||||
/** | |||||
* 盖章通过意见 | |||||
*/ | |||||
private String sealPassOpinion; | |||||
/** | |||||
* 盖章通过附件 | |||||
*/ | |||||
private FileBasicInfo sealPassAppendix; | |||||
/** | |||||
* 审核退回意见 | |||||
*/ | |||||
private String auditBackOpinion; | |||||
/** | |||||
* 审核退回附件 | |||||
*/ | |||||
private FileBasicInfo auditBackAppendix; | |||||
/** | |||||
* 审核驳回意见 | |||||
*/ | |||||
private String auditRejectOpinion; | |||||
/** | |||||
* 审核驳回附件 | |||||
*/ | |||||
private FileBasicInfo auditRejectAppendix; | |||||
public enum Action{ | |||||
//通过、盖章并通过、退回、撤回、驳回,审核意见类型 | |||||
pass, seal_pass ,back, withdraw, reject; | |||||
} | |||||
} |
@@ -49,5 +49,5 @@ public class ResToBeProcessedDTO implements Serializable { | |||||
private LocalDateTime processLaunchTime; | private LocalDateTime processLaunchTime; | ||||
@ApiModelProperty("流程任务信息") | @ApiModelProperty("流程任务信息") | ||||
private ProcessTaskVo processTaskVo; | |||||
private ProcessTaskVo processTaskInfo; | |||||
} | } |
@@ -1,8 +1,6 @@ | |||||
package com.ningdatech.pmapi.todocenter.model.dto.res; | package com.ningdatech.pmapi.todocenter.model.dto.res; | ||||
import com.alibaba.excel.annotation.ExcelProperty; | import com.alibaba.excel.annotation.ExcelProperty; | ||||
import com.wflow.workflow.bean.vo.ProcessTaskVo; | |||||
import io.swagger.annotations.ApiModelProperty; | |||||
import lombok.AllArgsConstructor; | import lombok.AllArgsConstructor; | ||||
import lombok.Data; | import lombok.Data; | ||||
import lombok.NoArgsConstructor; | import lombok.NoArgsConstructor; | ||||