NodeUtil.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. package jnpf.flowable.util;
  2. import cn.hutool.core.collection.CollectionUtil;
  3. import cn.hutool.core.util.ObjectUtil;
  4. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5. import com.google.common.collect.ImmutableList;
  6. import jnpf.exception.WorkFlowException;
  7. import jnpf.flowable.entity.*;
  8. import jnpf.flowable.enums.*;
  9. import jnpf.flowable.model.flowable.FlowAbleUrl;
  10. import jnpf.flowable.model.flowable.FlowableHistoricModel;
  11. import jnpf.flowable.model.task.FlowMethod;
  12. import jnpf.flowable.model.task.FlowModel;
  13. import jnpf.flowable.model.templatenode.TaskNodeModel;
  14. import jnpf.flowable.model.templatenode.nodejson.AuxiliaryInfo;
  15. import jnpf.flowable.model.templatenode.nodejson.AuxiliaryInfoConfig;
  16. import jnpf.flowable.model.templatenode.nodejson.NodeModel;
  17. import jnpf.flowable.model.util.FlowNature;
  18. import jnpf.flowable.service.*;
  19. import jnpf.model.document.FlowFileModel;
  20. import jnpf.permission.entity.UserEntity;
  21. import jnpf.util.JsonUtil;
  22. import jnpf.util.StringUtil;
  23. import jnpf.util.UserProvider;
  24. import org.springframework.beans.factory.annotation.Autowired;
  25. import org.springframework.stereotype.Component;
  26. import java.util.*;
  27. import java.util.stream.Collectors;
  28. /**
  29. * 类的描述
  30. *
  31. * @author JNPF@YinMai Info. Co., Ltd
  32. * @version 5.0.x
  33. * @since 2024/4/29 10:29
  34. */
  35. @Component
  36. public class NodeUtil {
  37. @Autowired
  38. private FlowAbleUrl flowAbleUrl;
  39. @Autowired
  40. private ServiceUtil serviceUtil;
  41. @Autowired
  42. private TaskUtil taskUtil;
  43. @Autowired
  44. private OperatorService operatorService;
  45. @Autowired
  46. private OperatorUtil operatorUtil;
  47. @Autowired
  48. private TaskService taskService;
  49. @Autowired
  50. private RevokeService revokeService;
  51. @Autowired
  52. private EventLogService eventLogService;
  53. @Autowired
  54. private TriggerRecordService triggerRecordService;
  55. public List<TaskNodeModel> getNodeList(FlowModel flowModel) throws WorkFlowException {
  56. List<TaskNodeModel> nodeList = new ArrayList<>();
  57. TaskEntity taskEntity = flowModel.getTaskEntity();
  58. // 终止后 任务详情的流程图,需全部置灰
  59. if (ObjectUtil.equals(TaskStatusEnum.CANCEL.getCode(), taskEntity.getStatus())) {
  60. return nodeList;
  61. }
  62. RevokeEntity revokeEntity = revokeService.getRevokeTask(taskEntity.getId());
  63. boolean isRevoke = revokeEntity != null;
  64. List<TemplateNodeEntity> nodeEntities = flowModel.getNodeEntityList();
  65. // 当前节点
  66. String currentNodeCode = StringUtil.isNotEmpty(taskEntity.getCurrentNodeCode()) ? taskEntity.getCurrentNodeCode() : "";
  67. List<String> currentNodes = new ArrayList<>(Arrays.asList(currentNodeCode.split(",")));
  68. // 未经过的节点
  69. List<String> tobePass = flowAbleUrl.getTobePass(taskEntity.getInstanceId());
  70. if (currentNodeCode.equals(FlowNature.END_CODE)) {
  71. currentNodes = nodeEntities.stream()
  72. .filter(t -> NodeEnum.end.getType().equals(t.getNodeType())).map(TemplateNodeEntity::getNodeCode).collect(Collectors.toList());
  73. }
  74. // 经过的节点
  75. FlowMethod flowMethod = new FlowMethod();
  76. flowMethod.setTobePass(tobePass);
  77. flowMethod.setCurrentNodes(currentNodes);
  78. flowMethod.setTaskId(taskEntity.getId());
  79. flowMethod.setTaskEntity(taskEntity);
  80. flowMethod.setNodeEntityList(nodeEntities);
  81. List<String> passed = this.getPassed(flowMethod);
  82. TemplateNodeEntity start = nodeEntities.stream().filter(e -> e.getNodeType().equals(NodeEnum.start.getType())).findFirst().orElse(null);
  83. if (start != null) {
  84. passed.add(start.getNodeCode());
  85. }
  86. List<TriggerRecordEntity> triggerRecordList = triggerRecordService.getListByTaskId(taskEntity.getId());
  87. List<String> typeList = ImmutableList.of(NodeEnum.global.getType(), NodeEnum.connect.getType());
  88. List<String> divideList = Arrays.stream(DivideRuleEnum.values()).map(DivideRuleEnum::getType).collect(Collectors.toList());
  89. divideList.addAll(typeList);
  90. flowMethod.setFlowModel(flowModel);
  91. flowMethod.setErrorRule(false);
  92. flowMethod.setExtraRule(true);
  93. // 节点 (-1没有经过,0.经过 1.当前 2.未经过)
  94. for (TemplateNodeEntity node : nodeEntities) {
  95. String nodeCode = node.getNodeCode();
  96. // 跳过全局节点、连接线
  97. if (divideList.contains(node.getNodeType())) {
  98. continue;
  99. }
  100. TaskNodeModel model = JsonUtil.getJsonToBean(node, TaskNodeModel.class);
  101. // 节点名称
  102. NodeModel nodeModel = JsonUtil.getJsonToBean(node.getNodeJson(), NodeModel.class);
  103. model.setNodeName(nodeModel.getNodeName());
  104. if (CollectionUtil.isNotEmpty(currentNodes)) {
  105. if (currentNodes.contains(nodeCode)) {
  106. model.setType(NodeTypeEnum.current.getType());
  107. if (NodeEnum.end.getType().equals(node.getNodeType())) {
  108. model.setType(NodeTypeEnum.pass.getType());
  109. }
  110. }
  111. }
  112. if (CollectionUtil.isNotEmpty(passed)) {
  113. if (passed.contains(nodeCode)) {
  114. model.setType(NodeTypeEnum.pass.getType());
  115. }
  116. }
  117. TriggerRecordEntity triggerRecord = triggerRecordList.stream()
  118. .filter(e -> ObjectUtil.equals(e.getNodeCode(), nodeModel.getNodeId())).findFirst().orElse(null);
  119. if (null != triggerRecord) {
  120. String type = NodeTypeEnum.current.getType();
  121. if (ObjectUtil.equals(triggerRecord.getStatus(), TriggerRecordEnum.PASSED.getCode())) {
  122. type = NodeTypeEnum.pass.getType();
  123. } else if (ObjectUtil.equals(triggerRecord.getStatus(), TriggerRecordEnum.EXCEPTION.getCode())) {
  124. type = NodeTypeEnum.exception.getType();
  125. }
  126. model.setType(type);
  127. }
  128. List<String> userNameList = new ArrayList<>();
  129. if (StringUtil.equals(node.getNodeType(), NodeEnum.start.getType())) {
  130. List<String> userIds = new ArrayList<>();
  131. userIds.add(taskEntity.getCreatorUserId());
  132. List<UserEntity> users = serviceUtil.getUserName(userIds);
  133. UserEntity user = users.get(0);
  134. userNameList.add(user.getRealName() + "/" + user.getAccount());
  135. if (!TaskStatusEnum.TO_BE_SUBMIT.getCode().equals(taskEntity.getStatus())) {
  136. model.setType(NodeTypeEnum.pass.getType());
  137. }
  138. } else if (StringUtil.equals(node.getNodeType(), NodeEnum.subFlow.getType())) {
  139. QueryWrapper<TaskEntity> queryWrapper = new QueryWrapper<>();
  140. queryWrapper.lambda().eq(TaskEntity::getParentId, taskEntity.getId()).eq(TaskEntity::getSubCode, node.getNodeCode());
  141. List<TaskEntity> list = taskService.list(queryWrapper);
  142. List<String> userIds;
  143. if (CollectionUtil.isNotEmpty(list)) {
  144. userIds = list.stream().map(TaskEntity::getCreatorUserId).collect(Collectors.toList());
  145. } else {
  146. flowMethod.setNodeEntity(node);
  147. userIds = taskUtil.userListAll(flowMethod);
  148. }
  149. List<UserEntity> users = serviceUtil.getUserName(userIds);
  150. if (CollectionUtil.isNotEmpty(users)) {
  151. for (UserEntity user : users) {
  152. userNameList.add(user.getRealName() + "/" + user.getAccount());
  153. }
  154. }
  155. } else if (StringUtil.equals(node.getNodeType(), NodeEnum.approver.getType()) || StringUtil.equals(node.getNodeType(), NodeEnum.processing.getType())) {
  156. List<String> userIds;
  157. List<OperatorEntity> operatorList = operatorUtil.getByNodeCode(isRevoke ? revokeEntity.getTaskId() : taskEntity.getId(), node.getNodeCode());
  158. Integer counterSign = nodeModel.getCounterSign();
  159. // 获取生成经办的人
  160. List<Integer> statusList = ImmutableList.of(OperatorStateEnum.Revoke.getCode(), OperatorStateEnum.AddSign.getCode(), OperatorStateEnum.Assist.getCode());
  161. List<OperatorEntity> list = operatorList.stream().filter(e -> !statusList.contains(e.getStatus()) && ObjectUtil.equals(e.getParentId(), FlowNature.ParentId)).collect(Collectors.toList());
  162. userIds = list.stream().map(OperatorEntity::getHandleId).collect(Collectors.toList());
  163. // 依次审批
  164. if (counterSign.equals(FlowNature.ImproperApprover)) {
  165. OperatorEntity last = list.stream().filter(e -> e.getCompletion().equals(FlowNature.Normal)).findFirst().orElse(null);
  166. if (null != last && StringUtil.isNotBlank(last.getHandleAll())) {
  167. String[] split = last.getHandleAll().split(",");
  168. userIds = Arrays.stream(split).collect(Collectors.toList());
  169. }
  170. }
  171. // 经办处理人的id为0,为系统自动通过
  172. if (userIds.contains(FlowNature.SYSTEM_CODE)) {
  173. // model.setUserName(FlowNature.SYSTEM_NAME);
  174. nodeList.add(model);
  175. continue;
  176. }
  177. if (CollectionUtil.isEmpty(userIds)) {
  178. flowMethod.setNodeEntity(node);
  179. userIds = taskUtil.userListAll(flowMethod);
  180. }
  181. if (CollectionUtil.isEmpty(userIds)) {
  182. nodeList.add(model);
  183. continue;
  184. }
  185. userIds = userIds.stream().distinct().sorted().collect(Collectors.toList());
  186. List<UserEntity> users = serviceUtil.getUserName(userIds);
  187. if (CollectionUtil.isNotEmpty(users)) {
  188. for (String userId : userIds) {
  189. UserEntity user = users.stream().filter(e -> e.getId().equals(userId)).findFirst().orElse(null);
  190. if (null != user) {
  191. userNameList.add(user.getRealName() + "/" + user.getAccount());
  192. }
  193. }
  194. }
  195. }
  196. model.setUserName(String.join(",", userNameList));
  197. nodeList.add(model);
  198. }
  199. return nodeList;
  200. }
  201. /**
  202. * 经过的节点
  203. */
  204. public List<String> getPassed(FlowMethod flowMethod) {
  205. List<String> tobePass = flowMethod.getTobePass();
  206. List<String> currentNodes = flowMethod.getCurrentNodes();
  207. TaskEntity taskEntity = flowMethod.getTaskEntity();
  208. String taskId = flowMethod.getTaskId();
  209. List<TemplateNodeEntity> nodeEntityList = flowMethod.getNodeEntityList();
  210. List<String> resList = new ArrayList<>();
  211. QueryWrapper<OperatorEntity> wrapper = new QueryWrapper<>();
  212. wrapper.lambda().eq(OperatorEntity::getTaskId, taskId).ne(OperatorEntity::getStatus, OperatorStateEnum.Futility.getCode());
  213. List<OperatorEntity> operatorList = operatorService.list(wrapper);
  214. if (CollectionUtil.isNotEmpty(operatorList)) {
  215. List<String> nodeCodes = operatorList.stream().map(OperatorEntity::getNodeCode)
  216. .filter(e -> !currentNodes.contains(e)).collect(Collectors.toList());
  217. resList.addAll(nodeCodes);
  218. }
  219. QueryWrapper<EventLogEntity> eventLogWrapper = new QueryWrapper<>();
  220. eventLogWrapper.lambda().eq(EventLogEntity::getTaskId, taskId);
  221. eventLogWrapper.lambda().select(EventLogEntity::getId, EventLogEntity::getNodeCode);
  222. List<EventLogEntity> eventLogList = eventLogService.list(eventLogWrapper);
  223. if (CollectionUtil.isNotEmpty(eventLogList)) {
  224. List<String> nodeCodes = eventLogList.stream().map(EventLogEntity::getNodeCode)
  225. .filter(e -> !currentNodes.contains(e)).collect(Collectors.toList());
  226. resList.addAll(nodeCodes);
  227. }
  228. RevokeEntity revokeEntity = revokeService.getRevokeTask(taskEntity.getId());
  229. if (null != revokeEntity) {
  230. taskId = revokeEntity.getTaskId();
  231. }
  232. if (!ObjectUtil.equals(TaskStatusEnum.BACKED.getCode(), taskEntity.getStatus())) {
  233. QueryWrapper<TaskEntity> taskWrapper = new QueryWrapper<>();
  234. taskWrapper.lambda().eq(TaskEntity::getParentId, taskId);
  235. List<TaskEntity> subFlowList = taskService.list(taskWrapper);
  236. List<String> historic = new ArrayList<>();
  237. try {
  238. historic = flowAbleUrl.getHistoric(taskEntity.getInstanceId()).stream().map(FlowableHistoricModel::getCode).collect(Collectors.toList());
  239. } catch (Exception e) {
  240. e.printStackTrace();
  241. }
  242. if (CollectionUtil.isNotEmpty(subFlowList)) {
  243. List<String> subCodes = subFlowList.stream().map(TaskEntity::getSubCode)
  244. .filter(e -> !currentNodes.contains(e) && !tobePass.contains(e))
  245. .collect(Collectors.toList());
  246. if (null != revokeEntity) {
  247. subCodes = subCodes.stream().filter(historic::contains).collect(Collectors.toList());
  248. }
  249. resList.addAll(subCodes);
  250. }
  251. QueryWrapper<EventLogEntity> eventWrapper = new QueryWrapper<>();
  252. eventWrapper.lambda().eq(EventLogEntity::getTaskId, taskId);
  253. List<EventLogEntity> eventList = eventLogService.list(eventWrapper);
  254. if (CollectionUtil.isNotEmpty(eventList)) {
  255. List<String> eventCodes = eventList.stream().map(EventLogEntity::getNodeCode)
  256. .filter(e -> !currentNodes.contains(e) && !tobePass.contains(e))
  257. .collect(Collectors.toList());
  258. if (null != revokeEntity) {
  259. eventCodes = eventCodes.stream().filter(historic::contains).collect(Collectors.toList());
  260. }
  261. resList.addAll(eventCodes);
  262. }
  263. // 撤销会跳过办理节点
  264. if (null != revokeEntity) {
  265. List<String> finalHistoric = historic;
  266. List<String> processingList = nodeEntityList.stream()
  267. .filter(e -> ObjectUtil.equals(e.getNodeType(), NodeEnum.processing.getType())
  268. && !currentNodes.contains(e.getNodeCode()) && finalHistoric.contains(e.getNodeCode()))
  269. .map(TemplateNodeEntity::getNodeCode).collect(Collectors.toList());
  270. if (CollectionUtil.isNotEmpty(processingList)) {
  271. resList.addAll(processingList);
  272. }
  273. }
  274. }
  275. return resList;
  276. }
  277. /**
  278. * 辅助信息 添加归档文件信息
  279. */
  280. public void setFlowFile(NodeModel currentNode, TaskEntity taskEntity, Map<String, Object> nodeProperties) {
  281. List<AuxiliaryInfo> auxiliaryList = currentNode.getAuxiliaryInfo();
  282. if (auxiliaryList.isEmpty()) {
  283. return;
  284. }
  285. long count = auxiliaryList.stream().filter(e -> ObjectUtil.equals(e.getConfig().getOn(), 0)).count();
  286. if (count == auxiliaryList.size()) {
  287. nodeProperties.put("auxiliaryInfo", null);
  288. return;
  289. }
  290. AuxiliaryInfo auxiliary = auxiliaryList.stream().filter(e -> ObjectUtil.equals(e.getId(), 3)).findFirst().orElse(null);
  291. if (null == auxiliary) {
  292. return;
  293. }
  294. AuxiliaryInfoConfig auxiliaryConfig = auxiliary.getConfig();
  295. if (!ObjectUtil.equals(auxiliaryConfig.getOn(), 1)) {
  296. return;
  297. }
  298. String templateId = taskEntity.getTemplateId();
  299. FlowFileModel flowFileModel = FlowFileModel.builder().templateId(templateId).userId(UserProvider.getLoginUserId())
  300. .dataRange(auxiliaryConfig.getDataRange()).build();
  301. List<Map<String, Object>> flowFile = serviceUtil.getFlowFile(flowFileModel);
  302. if (CollectionUtil.isEmpty(flowFile)) {
  303. return;
  304. }
  305. Object auxiliaryInfo = nodeProperties.get("auxiliaryInfo");
  306. if (auxiliaryInfo instanceof List) {
  307. List<Map<String, Object>> list = (List<Map<String, Object>>) auxiliaryInfo;
  308. for (Map<String, Object> map : list) {
  309. if (ObjectUtil.equals(map.get("id"), 3)) {
  310. Map<String, Object> config = (Map<String, Object>) map.get("config");
  311. config.put("fileList", flowFile);
  312. }
  313. }
  314. }
  315. }
  316. }