mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-10-31 18:49:06 +08:00 
			
		
		
		
	| @ -32,6 +32,7 @@ public enum BpmReasonEnum { | |||||||
|     ASSIGN_EMPTY_REJECT("审批人为空,自动不通过"), |     ASSIGN_EMPTY_REJECT("审批人为空,自动不通过"), | ||||||
|     APPROVE_TYPE_AUTO_APPROVE("非人工审核,自动通过"), |     APPROVE_TYPE_AUTO_APPROVE("非人工审核,自动通过"), | ||||||
|     APPROVE_TYPE_AUTO_REJECT("非人工审核,自动不通过"), |     APPROVE_TYPE_AUTO_REJECT("非人工审核,自动不通过"), | ||||||
|  |     CANCEL_BY_PROCESS_CLEAN("进程清理自动取消"), | ||||||
|     ; |     ; | ||||||
|  |  | ||||||
|     private final String reason; |     private final String reason; | ||||||
|  | |||||||
| @ -9,7 +9,10 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |||||||
| import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO; | import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO; | ||||||
| import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.cc.BpmProcessInstanceCopyRespVO; | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.cc.BpmProcessInstanceCopyRespVO; | ||||||
| import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyPageReqVO; | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyPageReqVO; | ||||||
|  | import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO; | ||||||
| import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceCopyDO; | import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceCopyDO; | ||||||
|  | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; | ||||||
|  | import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; | ||||||
| import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceCopyService; | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceCopyService; | ||||||
| import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; | ||||||
| import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||||||
| @ -42,6 +45,8 @@ public class BpmProcessInstanceCopyController { | |||||||
|     private BpmProcessInstanceCopyService processInstanceCopyService; |     private BpmProcessInstanceCopyService processInstanceCopyService; | ||||||
|     @Resource |     @Resource | ||||||
|     private BpmProcessInstanceService processInstanceService; |     private BpmProcessInstanceService processInstanceService; | ||||||
|  |     @Resource | ||||||
|  |     private BpmProcessDefinitionService processDefinitionService; | ||||||
|  |  | ||||||
|     @Resource |     @Resource | ||||||
|     private AdminUserApi adminUserApi; |     private AdminUserApi adminUserApi; | ||||||
| @ -62,6 +67,8 @@ public class BpmProcessInstanceCopyController { | |||||||
|                 convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getProcessInstanceId)); |                 convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getProcessInstanceId)); | ||||||
|         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(pageResult.getList(), |         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(pageResult.getList(), | ||||||
|                 copy -> Stream.of(copy.getStartUserId(), Long.parseLong(copy.getCreator())))); |                 copy -> Stream.of(copy.getStartUserId(), Long.parseLong(copy.getCreator())))); | ||||||
|  |         Map<String, BpmProcessDefinitionInfoDO> processDefinitionInfoMap = processDefinitionService.getProcessDefinitionInfoMap( | ||||||
|  |                 convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getProcessDefinitionId)); | ||||||
|         return success(convertPage(pageResult, copy -> { |         return success(convertPage(pageResult, copy -> { | ||||||
|             BpmProcessInstanceCopyRespVO copyVO = BeanUtils.toBean(copy, BpmProcessInstanceCopyRespVO.class); |             BpmProcessInstanceCopyRespVO copyVO = BeanUtils.toBean(copy, BpmProcessInstanceCopyRespVO.class); | ||||||
|             MapUtils.findAndThen(userMap, Long.valueOf(copy.getCreator()), |             MapUtils.findAndThen(userMap, Long.valueOf(copy.getCreator()), | ||||||
| @ -69,7 +76,12 @@ public class BpmProcessInstanceCopyController { | |||||||
|             MapUtils.findAndThen(userMap, copy.getStartUserId(), |             MapUtils.findAndThen(userMap, copy.getStartUserId(), | ||||||
|                     user -> copyVO.setCreateUser(BeanUtils.toBean(user, UserSimpleBaseVO.class))); |                     user -> copyVO.setCreateUser(BeanUtils.toBean(user, UserSimpleBaseVO.class))); | ||||||
|             MapUtils.findAndThen(processInstanceMap, copyVO.getProcessInstanceId(), |             MapUtils.findAndThen(processInstanceMap, copyVO.getProcessInstanceId(), | ||||||
|                     processInstance -> copyVO.setProcessInstanceStartTime(DateUtils.of(processInstance.getStartTime()))); |                     processInstance -> { | ||||||
|  |                         copyVO.setSummary(FlowableUtils.getSummary( | ||||||
|  |                                 processDefinitionInfoMap.get(processInstance.getProcessDefinitionId()), | ||||||
|  |                                 processInstance.getProcessVariables())); | ||||||
|  |                         copyVO.setProcessInstanceStartTime(DateUtils.of(processInstance.getStartTime())); | ||||||
|  |                     }); | ||||||
|             return copyVO; |             return copyVO; | ||||||
|         })); |         })); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -1,10 +1,12 @@ | |||||||
| package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.cc; | package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.cc; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.common.core.KeyValue; | ||||||
| import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO; | import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO; | ||||||
| import io.swagger.v3.oas.annotations.media.Schema; | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
| import lombok.Data; | import lombok.Data; | ||||||
|  |  | ||||||
| import java.time.LocalDateTime; | import java.time.LocalDateTime; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
| @Schema(description = "管理后台 - 流程实例抄送的分页 Item Response VO") | @Schema(description = "管理后台 - 流程实例抄送的分页 Item Response VO") | ||||||
| @Data | @Data | ||||||
| @ -40,4 +42,7 @@ public class BpmProcessInstanceCopyRespVO { | |||||||
|     @Schema(description = "抄送时间", requiredMode = Schema.RequiredMode.REQUIRED) |     @Schema(description = "抄送时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||||||
|     private LocalDateTime createTime; |     private LocalDateTime createTime; | ||||||
|  |  | ||||||
|  |     @Schema(description = "流程摘要", example = "[]") | ||||||
|  |     private List<KeyValue<String, String>> summary; | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -85,10 +85,6 @@ public class BpmTaskRespVO { | |||||||
|     @Schema(description = "是否填写审批意见", example = "false") |     @Schema(description = "是否填写审批意见", example = "false") | ||||||
|     private Boolean reasonRequire; |     private Boolean reasonRequire; | ||||||
|  |  | ||||||
|     // TODO @lesan:要不放到 processInstance 里面?因为摘要是流程实例的,不是流程任务的 |  | ||||||
|     @Schema(description = "流程摘要", example = "[]") |  | ||||||
|     private List<KeyValue<String, String>> summary; // 只有流程表单,才有摘要! |  | ||||||
|  |  | ||||||
|     @Data |     @Data | ||||||
|     @Schema(description = "流程实例") |     @Schema(description = "流程实例") | ||||||
|     public static class ProcessInstance { |     public static class ProcessInstance { | ||||||
| @ -105,6 +101,9 @@ public class BpmTaskRespVO { | |||||||
|         @Schema(description = "流程定义的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") |         @Schema(description = "流程定义的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") | ||||||
|         private String processDefinitionId; |         private String processDefinitionId; | ||||||
|  |  | ||||||
|  |         @Schema(description = "流程摘要", example = "[]") | ||||||
|  |         private List<KeyValue<String, String>> summary; // 只有流程表单,才有摘要! | ||||||
|  |  | ||||||
|         /** |         /** | ||||||
|          * 发起人的用户信息 |          * 发起人的用户信息 | ||||||
|          */ |          */ | ||||||
|  | |||||||
| @ -54,7 +54,7 @@ public interface BpmTaskConvert { | |||||||
|             AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId())); |             AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId())); | ||||||
|             taskVO.getProcessInstance().setStartUser(BeanUtils.toBean(startUser, UserSimpleBaseVO.class)); |             taskVO.getProcessInstance().setStartUser(BeanUtils.toBean(startUser, UserSimpleBaseVO.class)); | ||||||
|             // 摘要 |             // 摘要 | ||||||
|             taskVO.setSummary(FlowableUtils.getSummary(processDefinitionInfoMap.get(processInstance.getProcessDefinitionId()), |             taskVO.getProcessInstance().setSummary(FlowableUtils.getSummary(processDefinitionInfoMap.get(processInstance.getProcessDefinitionId()), | ||||||
|                     processInstance.getProcessVariables())); |                     processInstance.getProcessVariables())); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| @ -80,7 +80,7 @@ public interface BpmTaskConvert { | |||||||
|                 taskVO.setProcessInstance(BeanUtils.toBean(processInstance, BpmTaskRespVO.ProcessInstance.class)); |                 taskVO.setProcessInstance(BeanUtils.toBean(processInstance, BpmTaskRespVO.ProcessInstance.class)); | ||||||
|                 taskVO.getProcessInstance().setStartUser(BeanUtils.toBean(startUser, UserSimpleBaseVO.class)); |                 taskVO.getProcessInstance().setStartUser(BeanUtils.toBean(startUser, UserSimpleBaseVO.class)); | ||||||
|                 // 摘要 |                 // 摘要 | ||||||
|                 taskVO.setSummary(FlowableUtils.getSummary(processDefinitionInfoMap.get(processInstance.getProcessDefinitionId()), |                 taskVO.getProcessInstance().setSummary(FlowableUtils.getSummary(processDefinitionInfoMap.get(processInstance.getProcessDefinitionId()), | ||||||
|                         processInstance.getProcessVariables())); |                         processInstance.getProcessVariables())); | ||||||
|             } |             } | ||||||
|             return taskVO; |             return taskVO; | ||||||
|  | |||||||
| @ -49,6 +49,12 @@ public class BpmProcessInstanceCopyDO extends BaseDO { | |||||||
|      * 关联 ProcessInstance 的 id 属性 |      * 关联 ProcessInstance 的 id 属性 | ||||||
|      */ |      */ | ||||||
|     private String processInstanceId; |     private String processInstanceId; | ||||||
|  |     /** | ||||||
|  |      * 流程实例的流程定义编号 | ||||||
|  |      * | ||||||
|  |      * 关联 ProcessInstance 的 processDefinitionId 属性 | ||||||
|  |      */ | ||||||
|  |     private String processDefinitionId; | ||||||
|     /** |     /** | ||||||
|      * 流程分类 |      * 流程分类 | ||||||
|      * |      * | ||||||
|  | |||||||
| @ -27,6 +27,8 @@ import org.flowable.task.api.TaskInfo; | |||||||
| import java.util.*; | import java.util.*; | ||||||
| import java.util.concurrent.Callable; | import java.util.concurrent.Callable; | ||||||
|  |  | ||||||
|  | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Flowable 相关的工具方法 |  * Flowable 相关的工具方法 | ||||||
|  * |  * | ||||||
| @ -193,7 +195,6 @@ public class FlowableUtils { | |||||||
|                 BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES); |                 BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // TODO @lesan:如果值是 null 的情况,可能要调研下飞书、钉钉,是不是不返回哈! |  | ||||||
|     /** |     /** | ||||||
|      * 获得流程实例的摘要 |      * 获得流程实例的摘要 | ||||||
|      * |      * | ||||||
| @ -206,53 +207,39 @@ public class FlowableUtils { | |||||||
|      */ |      */ | ||||||
|     public static List<KeyValue<String, String>> getSummary(BpmProcessDefinitionInfoDO processDefinitionInfo, |     public static List<KeyValue<String, String>> getSummary(BpmProcessDefinitionInfoDO processDefinitionInfo, | ||||||
|                                                             Map<String, Object> processVariables) { |                                                             Map<String, Object> processVariables) { | ||||||
|         // TODO @lesan:建议 if return,减少 { 层级 |         // 只有流程表单才会显示摘要! | ||||||
|         if (ObjectUtil.isNotNull(processDefinitionInfo) |         if (ObjectUtil.isNull(processDefinitionInfo) | ||||||
|                 && BpmModelFormTypeEnum.NORMAL.getType().equals(processDefinitionInfo.getFormType())) { |                 || !BpmModelFormTypeEnum.NORMAL.getType().equals(processDefinitionInfo.getFormType())) { | ||||||
|             List<KeyValue<String, String>> summaryList = new ArrayList<>(); |             return null; | ||||||
|             // TODO @lesan:可以使用 CollUtils.convertMap 简化工作量哈。 |  | ||||||
|             Map<String, BpmFormFieldVO> formFieldsMap = new HashMap<>(); |  | ||||||
|             processDefinitionInfo.getFormFields().forEach(formFieldStr -> { |  | ||||||
|                 BpmFormFieldVO formField = JsonUtils.parseObject(formFieldStr, BpmFormFieldVO.class); |  | ||||||
|                 if (formField != null) { |  | ||||||
|                     formFieldsMap.put(formField.getField(), formField); |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|  |  | ||||||
|             // TODO @lesan:这里也可以 if return,还是为了减少括号哈。这样,就可以写注释,情况一:;情况二: |  | ||||||
|             if (ObjectUtil.isNotNull(processDefinitionInfo.getSummarySetting()) |  | ||||||
|                     && Boolean.TRUE.equals(processDefinitionInfo.getSummarySetting().getEnable())) { |  | ||||||
|                 // TODO @lesan:这里,也可以通过 CollUtils.convertList 简化哈。 |  | ||||||
|                 for (String item : processDefinitionInfo.getSummarySetting().getSummary()) { |  | ||||||
|                     BpmFormFieldVO formField = formFieldsMap.get(item); |  | ||||||
|                     if (formField != null) { |  | ||||||
|                         summaryList.add(new KeyValue<>(formField.getTitle(), |  | ||||||
|                                 processVariables.getOrDefault(item, "").toString())); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } else { |  | ||||||
|                 // 默认展示前三个 |  | ||||||
|                 /* TODO @lesan:stream 简化 |  | ||||||
|                  * summaryList.addAll(formFieldsMap.entrySet().stream() |  | ||||||
|                  *         .limit(3) |  | ||||||
|                  *         .map(entry -> new KeyValue<>(entry.getValue().getTitle(), |  | ||||||
|                  *                 processVariables.getOrDefault(entry.getValue().getField(), "").toString())) |  | ||||||
|                  *         .collect(Collectors.toList())); |  | ||||||
|                  */ |  | ||||||
|                 int j = 0; |  | ||||||
|                 for (Map.Entry<String, BpmFormFieldVO> entry : formFieldsMap.entrySet()) { |  | ||||||
|                     BpmFormFieldVO formField = entry.getValue(); |  | ||||||
|                     if (j > 2) { |  | ||||||
|                         break; |  | ||||||
|                     } |  | ||||||
|                     summaryList.add(new KeyValue<>(formField.getTitle(), |  | ||||||
|                             processVariables.getOrDefault(formField.getField(), "").toString())); |  | ||||||
|                     j++; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             return summaryList; |  | ||||||
|         } |         } | ||||||
|         return null; |         List<KeyValue<String, String>> summaryList; | ||||||
|  |         Map<String, BpmFormFieldVO> formFieldsMap = new HashMap<>(); | ||||||
|  |         processDefinitionInfo.getFormFields().forEach(formFieldStr -> { | ||||||
|  |             BpmFormFieldVO formField = JsonUtils.parseObject(formFieldStr, BpmFormFieldVO.class); | ||||||
|  |             if (formField != null) { | ||||||
|  |                 formFieldsMap.put(formField.getField(), formField); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |         if (ObjectUtil.isNotNull(processDefinitionInfo.getSummarySetting()) | ||||||
|  |                 && Boolean.TRUE.equals(processDefinitionInfo.getSummarySetting().getEnable())) { | ||||||
|  |             // 情况一:当自定义了摘要 | ||||||
|  |             summaryList = convertList(processDefinitionInfo.getSummarySetting().getSummary(), item -> { | ||||||
|  |                 BpmFormFieldVO formField = formFieldsMap.get(item); | ||||||
|  |                 if (formField != null) { | ||||||
|  |                     return new KeyValue<String, String>(formField.getTitle(), | ||||||
|  |                             processVariables.getOrDefault(item, "").toString()); | ||||||
|  |                 } | ||||||
|  |                 return null; | ||||||
|  |             }); | ||||||
|  |         } else { | ||||||
|  |             // 情况二:默认摘要展示前三个表单字段 | ||||||
|  |             summaryList = new ArrayList<>(formFieldsMap.entrySet().stream() | ||||||
|  |                     .limit(3) | ||||||
|  |                     .map(entry -> new KeyValue<>(entry.getValue().getTitle(), | ||||||
|  |                             processVariables.getOrDefault(entry.getValue().getField(), "").toString())) | ||||||
|  |                     .toList()); | ||||||
|  |         } | ||||||
|  |         return summaryList; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // ========== Task 相关的工具方法 ========== |     // ========== Task 相关的工具方法 ========== | ||||||
| @ -317,9 +304,9 @@ public class FlowableUtils { | |||||||
|  |  | ||||||
|     private static Object getExpressionValue(VariableContainer variableContainer, String expressionString, |     private static Object getExpressionValue(VariableContainer variableContainer, String expressionString, | ||||||
|                                              ProcessEngineConfigurationImpl processEngineConfiguration) { |                                              ProcessEngineConfigurationImpl processEngineConfiguration) { | ||||||
|         assert processEngineConfiguration!= null; |         assert processEngineConfiguration != null; | ||||||
|         ExpressionManager expressionManager = processEngineConfiguration.getExpressionManager(); |         ExpressionManager expressionManager = processEngineConfiguration.getExpressionManager(); | ||||||
|         assert expressionManager!= null; |         assert expressionManager != null; | ||||||
|         Expression expression = expressionManager.createExpression(expressionString); |         Expression expression = expressionManager.createExpression(expressionString); | ||||||
|         return expression.getValue(variableContainer); |         return expression.getValue(variableContainer); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -288,8 +288,7 @@ public class BpmModelServiceImpl implements BpmModelService { | |||||||
|         // 2.3 清理所有 Task |         // 2.3 清理所有 Task | ||||||
|         List<Task> tasks = taskService.createTaskQuery() |         List<Task> tasks = taskService.createTaskQuery() | ||||||
|                 .processDefinitionKey(model.getKey()).list(); |                 .processDefinitionKey(model.getKey()).list(); | ||||||
|         // TODO @lesan:貌似传递一个 reason 会好点! |         tasks.forEach(task -> taskService.deleteTask(task.getId(),BpmReasonEnum.CANCEL_BY_PROCESS_CLEAN.getReason())); | ||||||
|         tasks.forEach(task -> taskService.deleteTask(task.getId())); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|  | |||||||
| @ -77,7 +77,8 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy | |||||||
|                 .setUserId(userId).setReason(reason).setStartUserId(Long.valueOf(processInstance.getStartUserId())) |                 .setUserId(userId).setReason(reason).setStartUserId(Long.valueOf(processInstance.getStartUserId())) | ||||||
|                 .setProcessInstanceId(processInstanceId).setProcessInstanceName(processInstance.getName()) |                 .setProcessInstanceId(processInstanceId).setProcessInstanceName(processInstance.getName()) | ||||||
|                 .setCategory(processDefinition.getCategory()).setTaskId(taskId) |                 .setCategory(processDefinition.getCategory()).setTaskId(taskId) | ||||||
|                 .setActivityId(activityId).setActivityName(activityName)); |                 .setActivityId(activityId).setActivityName(activityName) | ||||||
|  |                 .setProcessDefinitionId(processInstance.getProcessDefinitionId())); | ||||||
|         processInstanceCopyMapper.insertBatch(copyList); |         processInstanceCopyMapper.insertBatch(copyList); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 芋道源码
					芋道源码