FlowTaskServiceImpl.java 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263
  1. package com.ruoyi.flowable.service.impl;
  2. import com.alibaba.fastjson2.JSON;
  3. import com.alibaba.fastjson2.JSONArray;
  4. import com.alibaba.fastjson2.JSONObject;
  5. import com.alibaba.fastjson2.TypeReference;
  6. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  7. import com.ruoyi.common.core.domain.model.LoginUser;
  8. import com.ruoyi.flowable.common.constant.ProcessConstants;
  9. import com.ruoyi.common.core.domain.AjaxResult;
  10. import com.ruoyi.common.core.domain.entity.SysRole;
  11. import com.ruoyi.common.core.domain.entity.SysUser;
  12. import com.ruoyi.flowable.common.enums.FlowComment;
  13. import com.ruoyi.common.exception.CustomException;
  14. import com.ruoyi.common.utils.SecurityUtils;
  15. import com.ruoyi.flowable.domain.dto.FlowCommentDto;
  16. import com.ruoyi.flowable.domain.dto.FlowNextDto;
  17. import com.ruoyi.flowable.domain.dto.FlowTaskDto;
  18. import com.ruoyi.flowable.domain.dto.FlowViewerDto;
  19. import com.ruoyi.flowable.domain.vo.FlowQueryVo;
  20. import com.ruoyi.flowable.domain.vo.FlowTaskVo;
  21. import com.ruoyi.flowable.factory.FlowServiceFactory;
  22. import com.ruoyi.flowable.flow.CustomProcessDiagramGenerator;
  23. import com.ruoyi.flowable.flow.FindNextNodeUtil;
  24. import com.ruoyi.flowable.flow.FlowableUtils;
  25. import com.ruoyi.flowable.service.IFlowTaskService;
  26. import com.ruoyi.flowable.service.ISysDeployFormService;
  27. import com.ruoyi.flowable.service.ISysFormService;
  28. import com.ruoyi.system.domain.SysForm;
  29. import com.ruoyi.system.service.ISysRoleService;
  30. import com.ruoyi.system.service.ISysUserService;
  31. import lombok.extern.slf4j.Slf4j;
  32. import org.apache.commons.collections4.CollectionUtils;
  33. import org.apache.commons.io.IOUtils;
  34. import org.apache.commons.lang3.StringUtils;
  35. import org.flowable.bpmn.model.Process;
  36. import org.flowable.bpmn.model.*;
  37. import org.flowable.common.engine.api.FlowableException;
  38. import org.flowable.common.engine.api.FlowableObjectNotFoundException;
  39. import org.flowable.common.engine.impl.identity.Authentication;
  40. import org.flowable.engine.ProcessEngineConfiguration;
  41. import org.flowable.engine.history.HistoricActivityInstance;
  42. import org.flowable.engine.history.HistoricProcessInstance;
  43. import org.flowable.engine.history.HistoricProcessInstanceQuery;
  44. import org.flowable.engine.repository.ProcessDefinition;
  45. import org.flowable.engine.runtime.ActivityInstance;
  46. import org.flowable.engine.runtime.Execution;
  47. import org.flowable.engine.runtime.ProcessInstance;
  48. import org.flowable.engine.task.Comment;
  49. import org.flowable.identitylink.api.history.HistoricIdentityLink;
  50. import org.flowable.image.ProcessDiagramGenerator;
  51. import org.flowable.task.api.DelegationState;
  52. import org.flowable.task.api.Task;
  53. import org.flowable.task.api.TaskQuery;
  54. import org.flowable.task.api.history.HistoricTaskInstance;
  55. import org.flowable.task.api.history.HistoricTaskInstanceQuery;
  56. import org.flowable.engine.impl.cmd.AddMultiInstanceExecutionCmd;
  57. import org.flowable.engine.impl.cmd.DeleteMultiInstanceExecutionCmd;
  58. import org.springframework.stereotype.Service;
  59. import org.springframework.transaction.annotation.Transactional;
  60. import javax.annotation.Resource;
  61. import java.io.InputStream;
  62. import java.lang.reflect.Field;
  63. import java.nio.charset.StandardCharsets;
  64. import java.util.*;
  65. import java.util.concurrent.ConcurrentHashMap;
  66. import java.util.function.Function;
  67. import java.util.function.Predicate;
  68. import java.util.stream.Collectors;
  69. /**
  70. * @author Tony
  71. * @date 2021-04-03
  72. **/
  73. @Service
  74. @Slf4j
  75. public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTaskService {
  76. @Resource
  77. private ISysUserService sysUserService;
  78. @Resource
  79. private ISysRoleService sysRoleService;
  80. @Resource
  81. private ISysDeployFormService sysInstanceFormService;
  82. @Resource
  83. private ISysFormService sysFormService;
  84. /**
  85. * 完成任务
  86. *
  87. * @param taskVo 请求实体参数
  88. */
  89. @Transactional(rollbackFor = Exception.class)
  90. @Override
  91. public AjaxResult complete(FlowTaskVo taskVo) {
  92. Task task = taskService.createTaskQuery().taskId(taskVo.getTaskId()).singleResult();
  93. if (Objects.isNull(task)) {
  94. return AjaxResult.error("任务不存在");
  95. }
  96. if (DelegationState.PENDING.equals(task.getDelegationState())) {
  97. taskService.addComment(taskVo.getTaskId(), taskVo.getInstanceId(), FlowComment.DELEGATE.getType(), taskVo.getComment());
  98. taskService.resolveTask(taskVo.getTaskId(), taskVo.getVariables());
  99. } else {
  100. taskService.addComment(taskVo.getTaskId(), taskVo.getInstanceId(), FlowComment.NORMAL.getType(), taskVo.getComment());
  101. Long userId = SecurityUtils.getLoginUser().getUser().getUserId();
  102. taskService.setAssignee(taskVo.getTaskId(), userId.toString());
  103. taskService.complete(taskVo.getTaskId(), taskVo.getVariables());
  104. }
  105. return AjaxResult.success();
  106. }
  107. /**
  108. * 驳回任务
  109. *
  110. * @param flowTaskVo
  111. */
  112. @Override
  113. public void taskReject(FlowTaskVo flowTaskVo) {
  114. if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) {
  115. throw new CustomException("任务处于挂起状态!");
  116. }
  117. // 当前任务 task
  118. Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
  119. // 获取流程定义信息
  120. ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
  121. // 获取所有节点信息
  122. Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
  123. // 获取全部节点列表,包含子节点
  124. Collection<FlowElement> allElements = FlowableUtils.getAllElements(process.getFlowElements(), null);
  125. // 获取当前任务节点元素
  126. FlowElement source = null;
  127. if (allElements != null) {
  128. for (FlowElement flowElement : allElements) {
  129. // 类型为用户节点
  130. if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
  131. // 获取节点信息
  132. source = flowElement;
  133. }
  134. }
  135. }
  136. // 目的获取所有跳转到的节点 targetIds
  137. // 获取当前节点的所有父级用户任务节点
  138. // 深度优先算法思想:延边迭代深入
  139. List<UserTask> parentUserTaskList = FlowableUtils.iteratorFindParentUserTasks(source, null, null);
  140. if (parentUserTaskList == null || parentUserTaskList.size() == 0) {
  141. throw new CustomException("当前节点为初始任务节点,不能驳回");
  142. }
  143. // 获取活动 ID 即节点 Key
  144. List<String> parentUserTaskKeyList = new ArrayList<>();
  145. parentUserTaskList.forEach(item -> parentUserTaskKeyList.add(item.getId()));
  146. // 获取全部历史节点活动实例,即已经走过的节点历史,数据采用开始时间升序
  147. List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(task.getProcessInstanceId()).orderByHistoricTaskInstanceStartTime().asc().list();
  148. // 数据清洗,将回滚导致的脏数据清洗掉
  149. List<String> lastHistoricTaskInstanceList = FlowableUtils.historicTaskInstanceClean(allElements, historicTaskInstanceList);
  150. // 此时历史任务实例为倒序,获取最后走的节点
  151. List<String> targetIds = new ArrayList<>();
  152. // 循环结束标识,遇到当前目标节点的次数
  153. int number = 0;
  154. StringBuilder parentHistoricTaskKey = new StringBuilder();
  155. for (String historicTaskInstanceKey : lastHistoricTaskInstanceList) {
  156. // 当会签时候会出现特殊的,连续都是同一个节点历史数据的情况,这种时候跳过
  157. if (parentHistoricTaskKey.toString().equals(historicTaskInstanceKey)) {
  158. continue;
  159. }
  160. parentHistoricTaskKey = new StringBuilder(historicTaskInstanceKey);
  161. if (historicTaskInstanceKey.equals(task.getTaskDefinitionKey())) {
  162. number++;
  163. }
  164. // 在数据清洗后,历史节点就是唯一一条从起始到当前节点的历史记录,理论上每个点只会出现一次
  165. // 在流程中如果出现循环,那么每次循环中间的点也只会出现一次,再出现就是下次循环
  166. // number == 1,第一次遇到当前节点
  167. // number == 2,第二次遇到,代表最后一次的循环范围
  168. if (number == 2) {
  169. break;
  170. }
  171. // 如果当前历史节点,属于父级的节点,说明最后一次经过了这个点,需要退回这个点
  172. if (parentUserTaskKeyList.contains(historicTaskInstanceKey)) {
  173. targetIds.add(historicTaskInstanceKey);
  174. }
  175. }
  176. // 目的获取所有需要被跳转的节点 currentIds
  177. // 取其中一个父级任务,因为后续要么存在公共网关,要么就是串行公共线路
  178. UserTask oneUserTask = parentUserTaskList.get(0);
  179. // 获取所有正常进行的任务节点 Key,这些任务不能直接使用,需要找出其中需要撤回的任务
  180. List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
  181. List<String> runTaskKeyList = new ArrayList<>();
  182. runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey()));
  183. // 需驳回任务列表
  184. List<String> currentIds = new ArrayList<>();
  185. // 通过父级网关的出口连线,结合 runTaskList 比对,获取需要撤回的任务
  186. List<UserTask> currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(oneUserTask, runTaskKeyList, null, null);
  187. currentUserTaskList.forEach(item -> currentIds.add(item.getId()));
  188. // 规定:并行网关之前节点必须需存在唯一用户任务节点,如果出现多个任务节点,则并行网关节点默认为结束节点,原因为不考虑多对多情况
  189. if (targetIds.size() > 1 && currentIds.size() > 1) {
  190. throw new CustomException("任务出现多对多情况,无法撤回");
  191. }
  192. // 循环获取那些需要被撤回的节点的ID,用来设置驳回原因
  193. List<String> currentTaskIds = new ArrayList<>();
  194. currentIds.forEach(currentId -> runTaskList.forEach(runTask -> {
  195. if (currentId.equals(runTask.getTaskDefinitionKey())) {
  196. currentTaskIds.add(runTask.getId());
  197. }
  198. }));
  199. // 设置驳回意见
  200. currentTaskIds.forEach(item -> taskService.addComment(item, task.getProcessInstanceId(), FlowComment.REJECT.getType(), flowTaskVo.getComment()));
  201. try {
  202. // 如果父级任务多于 1 个,说明当前节点不是并行节点,原因为不考虑多对多情况
  203. if (targetIds.size() > 1) {
  204. // 1 对 多任务跳转,currentIds 当前节点(1),targetIds 跳转到的节点(多)
  205. runtimeService.createChangeActivityStateBuilder()
  206. .processInstanceId(task.getProcessInstanceId()).
  207. moveSingleActivityIdToActivityIds(currentIds.get(0), targetIds).changeState();
  208. }
  209. // 如果父级任务只有一个,因此当前任务可能为网关中的任务
  210. if (targetIds.size() == 1) {
  211. // 1 对 1 或 多 对 1 情况,currentIds 当前要跳转的节点列表(1或多),targetIds.get(0) 跳转到的节点(1)
  212. runtimeService.createChangeActivityStateBuilder()
  213. .processInstanceId(task.getProcessInstanceId())
  214. .moveActivityIdsToSingleActivityId(currentIds, targetIds.get(0)).changeState();
  215. }
  216. } catch (FlowableObjectNotFoundException e) {
  217. throw new CustomException("未找到流程实例,流程可能已发生变化");
  218. } catch (FlowableException e) {
  219. throw new CustomException("无法取消或开始活动");
  220. }
  221. }
  222. /**
  223. * 退回任务
  224. *
  225. * @param flowTaskVo 请求实体参数
  226. */
  227. @Transactional(rollbackFor = Exception.class)
  228. @Override
  229. public void taskReturn(FlowTaskVo flowTaskVo) {
  230. if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) {
  231. throw new CustomException("任务处于挂起状态");
  232. }
  233. // 当前任务 task
  234. Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
  235. // 获取流程定义信息
  236. ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
  237. // 获取所有节点信息
  238. Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
  239. // 获取全部节点列表,包含子节点
  240. Collection<FlowElement> allElements = FlowableUtils.getAllElements(process.getFlowElements(), null);
  241. // 获取当前任务节点元素
  242. FlowElement source = null;
  243. // 获取跳转的节点元素
  244. FlowElement target = null;
  245. if (allElements != null) {
  246. for (FlowElement flowElement : allElements) {
  247. // 当前任务节点元素
  248. if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
  249. source = flowElement;
  250. }
  251. // 跳转的节点元素
  252. if (flowElement.getId().equals(flowTaskVo.getTargetKey())) {
  253. target = flowElement;
  254. }
  255. }
  256. }
  257. // 从当前节点向前扫描
  258. // 如果存在路线上不存在目标节点,说明目标节点是在网关上或非同一路线上,不可跳转
  259. // 否则目标节点相对于当前节点,属于串行
  260. Boolean isSequential = FlowableUtils.iteratorCheckSequentialReferTarget(source, flowTaskVo.getTargetKey(), null, null);
  261. if (!isSequential) {
  262. throw new CustomException("当前节点相对于目标节点,不属于串行关系,无法回退");
  263. }
  264. // 获取所有正常进行的任务节点 Key,这些任务不能直接使用,需要找出其中需要撤回的任务
  265. List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
  266. List<String> runTaskKeyList = new ArrayList<>();
  267. runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey()));
  268. // 需退回任务列表
  269. List<String> currentIds = new ArrayList<>();
  270. // 通过父级网关的出口连线,结合 runTaskList 比对,获取需要撤回的任务
  271. List<UserTask> currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(target, runTaskKeyList, null, null);
  272. currentUserTaskList.forEach(item -> currentIds.add(item.getId()));
  273. // 循环获取那些需要被撤回的节点的ID,用来设置驳回原因
  274. List<String> currentTaskIds = new ArrayList<>();
  275. currentIds.forEach(currentId -> runTaskList.forEach(runTask -> {
  276. if (currentId.equals(runTask.getTaskDefinitionKey())) {
  277. currentTaskIds.add(runTask.getId());
  278. }
  279. }));
  280. // 设置回退意见
  281. currentTaskIds.forEach(currentTaskId -> taskService.addComment(currentTaskId, task.getProcessInstanceId(), FlowComment.REBACK.getType(), flowTaskVo.getComment()));
  282. try {
  283. // 1 对 1 或 多 对 1 情况,currentIds 当前要跳转的节点列表(1或多),targetKey 跳转到的节点(1)
  284. runtimeService.createChangeActivityStateBuilder()
  285. .processInstanceId(task.getProcessInstanceId())
  286. .moveActivityIdsToSingleActivityId(currentIds, flowTaskVo.getTargetKey()).changeState();
  287. } catch (FlowableObjectNotFoundException e) {
  288. throw new CustomException("未找到流程实例,流程可能已发生变化");
  289. } catch (FlowableException e) {
  290. throw new CustomException("无法取消或开始活动");
  291. }
  292. }
  293. /**
  294. * 获取所有可回退的节点
  295. *
  296. * @param flowTaskVo
  297. * @return
  298. */
  299. @Override
  300. public AjaxResult findReturnTaskList(FlowTaskVo flowTaskVo) {
  301. // // 当前任务 task
  302. // Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
  303. // // 从流程历史任务中获取可退回节点
  304. //// List<HistoricActivityInstance> hisActIns = historyService.createHistoricActivityInstanceQuery()
  305. //// .executionId(task.getExecutionId())
  306. //// .activityType("userTask")
  307. //// .orderByHistoricActivityInstanceStartTime()
  308. //// .finished()
  309. //// .desc()
  310. //// .list();
  311. ////
  312. //// // 可回退的节点列表
  313. //// List<ReturnTaskNodeVo> returnTaskNodeList = new ArrayList<>();
  314. //// ReturnTaskNodeVo returnTaskNodeVo;
  315. //// for (HistoricActivityInstance activityInstance : hisActIns) {
  316. //// returnTaskNodeVo = new ReturnTaskNodeVo();
  317. //// returnTaskNodeVo.setId(activityInstance.getActivityId());
  318. //// // 根据流程节点处理时间校验改节点是否已完成
  319. //// returnTaskNodeVo.setName(activityInstance.getActivityName());
  320. //// returnTaskNodeList.add(returnTaskNodeVo);
  321. //// }
  322. // List<UserTask> userTaskList = new ArrayList<>();
  323. // // 获取流程定义信息
  324. // ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
  325. // // 获取所有节点信息,暂不考虑子流程情况
  326. // Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
  327. // Collection<FlowElement> flowElements = process.getFlowElements();
  328. // // 获取当前任务节点元素
  329. // UserTask source = null;
  330. // if (flowElements != null) {
  331. // for (FlowElement flowElement : flowElements) {
  332. // // 类型为用户节点
  333. // if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
  334. // source = (UserTask) flowElement;
  335. // }
  336. // }
  337. // }
  338. // // 获取节点的所有路线
  339. // List<List<UserTask>> roads = FlowableUtils.findRoad(source, null, null, null);
  340. //
  341. // for (List<UserTask> road : roads) {
  342. // if (userTaskList.size() == 0) {
  343. // // 还没有可回退节点直接添加
  344. // userTaskList = road;
  345. // } else {
  346. // // 如果已有回退节点,则比对取交集部分
  347. // userTaskList.retainAll(road);
  348. // }
  349. // }
  350. // return AjaxResult.success(userTaskList);
  351. // 当前任务 task
  352. Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
  353. // 获取流程定义信息
  354. ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
  355. // 获取所有节点信息,暂不考虑子流程情况
  356. Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
  357. Collection<FlowElement> flowElements = process.getFlowElements();
  358. // 获取当前任务节点元素
  359. UserTask source = null;
  360. if (flowElements != null) {
  361. for (FlowElement flowElement : flowElements) {
  362. // 类型为用户节点
  363. if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
  364. source = (UserTask) flowElement;
  365. }
  366. }
  367. }
  368. // 获取节点的所有路线
  369. List<List<UserTask>> roads = FlowableUtils.findRoad(source, null, null, null);
  370. // 可回退的节点列表
  371. List<UserTask> userTaskList = new ArrayList<>();
  372. for (List<UserTask> road : roads) {
  373. if (userTaskList.size() == 0) {
  374. // 还没有可回退节点直接添加
  375. userTaskList = road;
  376. } else {
  377. // 如果已有回退节点,则比对取交集部分
  378. userTaskList.retainAll(road);
  379. }
  380. }
  381. return AjaxResult.success(userTaskList);
  382. }
  383. /**
  384. * 删除任务
  385. *
  386. * @param flowTaskVo 请求实体参数
  387. */
  388. @Override
  389. public void deleteTask(FlowTaskVo flowTaskVo) {
  390. // todo 待确认删除任务是物理删除任务 还是逻辑删除,让这个任务直接通过?
  391. taskService.deleteTask(flowTaskVo.getTaskId(), flowTaskVo.getComment());
  392. }
  393. /**
  394. * 认领/签收任务
  395. * 认领以后,这个用户就会成为任务的执行人,任务会从其他成员的任务列表中消失
  396. *
  397. * @param flowTaskVo 请求实体参数
  398. */
  399. @Override
  400. @Transactional(rollbackFor = Exception.class)
  401. public void claim(FlowTaskVo flowTaskVo) {
  402. taskService.claim(flowTaskVo.getTaskId(), flowTaskVo.getUserId());
  403. }
  404. /**
  405. * 取消认领/签收任务
  406. *
  407. * @param flowTaskVo 请求实体参数
  408. */
  409. @Override
  410. @Transactional(rollbackFor = Exception.class)
  411. public void unClaim(FlowTaskVo flowTaskVo) {
  412. taskService.unclaim(flowTaskVo.getTaskId());
  413. }
  414. /**
  415. * 委派任务
  416. * 任务委派只是委派人将当前的任务交给被委派人进行审批,处理任务后又重新回到委派人身上。
  417. *
  418. * @param flowTaskVo 请求实体参数
  419. */
  420. @Override
  421. @Transactional(rollbackFor = Exception.class)
  422. public void delegateTask(FlowTaskVo flowTaskVo) {
  423. taskService.delegateTask(flowTaskVo.getTaskId(), flowTaskVo.getAssignee());
  424. }
  425. /**
  426. * 任务归还
  427. * 被委派人完成任务之后,将任务归还委派人
  428. *
  429. * @param flowTaskVo 请求实体参数
  430. */
  431. @Override
  432. @Transactional(rollbackFor = Exception.class)
  433. public void resolveTask(FlowTaskVo flowTaskVo) {
  434. taskService.resolveTask(flowTaskVo.getTaskId());
  435. }
  436. /**
  437. * 转办任务
  438. * 直接将办理人换成别人,这时任务的拥有者不再是转办人
  439. *
  440. * @param flowTaskVo 请求实体参数
  441. */
  442. @Override
  443. @Transactional(rollbackFor = Exception.class)
  444. public void assignTask(FlowTaskVo flowTaskVo) {
  445. // 直接转派就可以覆盖掉之前的
  446. taskService.setAssignee(flowTaskVo.getTaskId(), flowTaskVo.getAssignee());
  447. // // 删除指派人重新指派
  448. // taskService.deleteCandidateUser(flowTaskVo.getTaskId(),flowTaskVo.getAssignee());
  449. // taskService.addCandidateUser(flowTaskVo.getTaskId(),flowTaskVo.getAssignee());
  450. // // 如果要查询转给他人处理的任务,可以同时将OWNER进行设置:
  451. // taskService.setOwner(flowTaskVo.getTaskId(), flowTaskVo.getAssignee());
  452. }
  453. /**
  454. * 多实例加签
  455. * act_ru_task、act_ru_identitylink各生成一条记录
  456. *
  457. * @param flowTaskVo
  458. */
  459. @Override
  460. public void addMultiInstanceExecution(FlowTaskVo flowTaskVo) {
  461. managementService.executeCommand(new AddMultiInstanceExecutionCmd(flowTaskVo.getDefId(), flowTaskVo.getInstanceId(), flowTaskVo.getVariables()));
  462. }
  463. /**
  464. * 多实例减签
  465. * act_ru_task减1、act_ru_identitylink不变
  466. *
  467. * @param flowTaskVo
  468. */
  469. @Override
  470. public void deleteMultiInstanceExecution(FlowTaskVo flowTaskVo) {
  471. managementService.executeCommand(new DeleteMultiInstanceExecutionCmd(flowTaskVo.getCurrentChildExecutionId(), flowTaskVo.getFlag()));
  472. }
  473. /**
  474. * 我发起的流程
  475. *
  476. * @param queryVo 请求参数
  477. * @return
  478. */
  479. @Override
  480. public AjaxResult myProcess(FlowQueryVo queryVo) {
  481. Page<FlowTaskDto> page = new Page<>();
  482. Long userId = SecurityUtils.getLoginUser().getUser().getUserId();
  483. HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery()
  484. .startedBy(userId.toString())
  485. .orderByProcessInstanceStartTime()
  486. .desc();
  487. List<HistoricProcessInstance> historicProcessInstances = historicProcessInstanceQuery.listPage(queryVo.getPageSize() * (queryVo.getPageNum() - 1), queryVo.getPageSize());
  488. page.setTotal(historicProcessInstanceQuery.count());
  489. List<FlowTaskDto> flowList = new ArrayList<>();
  490. for (HistoricProcessInstance hisIns : historicProcessInstances) {
  491. FlowTaskDto flowTask = new FlowTaskDto();
  492. flowTask.setCreateTime(hisIns.getStartTime());
  493. flowTask.setFinishTime(hisIns.getEndTime());
  494. flowTask.setProcInsId(hisIns.getId());
  495. // 计算耗时
  496. if (Objects.nonNull(hisIns.getEndTime())) {
  497. long time = hisIns.getEndTime().getTime() - hisIns.getStartTime().getTime();
  498. flowTask.setDuration(getDate(time));
  499. } else {
  500. long time = System.currentTimeMillis() - hisIns.getStartTime().getTime();
  501. flowTask.setDuration(getDate(time));
  502. }
  503. // 流程定义信息
  504. ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
  505. .processDefinitionId(hisIns.getProcessDefinitionId())
  506. .singleResult();
  507. flowTask.setDeployId(pd.getDeploymentId());
  508. flowTask.setProcDefName(pd.getName());
  509. flowTask.setProcDefVersion(pd.getVersion());
  510. flowTask.setCategory(pd.getCategory());
  511. flowTask.setProcDefVersion(pd.getVersion());
  512. // 当前所处流程
  513. List<Task> taskList = taskService.createTaskQuery().processInstanceId(hisIns.getId()).list();
  514. if (CollectionUtils.isNotEmpty(taskList)) {
  515. flowTask.setTaskId(taskList.get(0).getId());
  516. flowTask.setTaskName(taskList.get(0).getName());
  517. if (StringUtils.isNotBlank(taskList.get(0).getAssignee())) {
  518. // 当前任务节点办理人信息
  519. SysUser sysUser = sysUserService.selectUserById(Long.parseLong(taskList.get(0).getAssignee()));
  520. if (Objects.nonNull(sysUser)) {
  521. flowTask.setAssigneeId(sysUser.getUserId());
  522. flowTask.setAssigneeName(sysUser.getNickName());
  523. flowTask.setAssigneeDeptName(Objects.nonNull(sysUser.getDept()) ? sysUser.getDept().getDeptName() : "");
  524. }
  525. }
  526. } else {
  527. List<HistoricTaskInstance> historicTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(hisIns.getId()).orderByHistoricTaskInstanceEndTime().desc().list();
  528. if(historicTaskInstance!=null && historicTaskInstance.size() > 0){
  529. flowTask.setTaskId(historicTaskInstance.get(0).getId());
  530. flowTask.setTaskName(historicTaskInstance.get(0).getName());
  531. if (StringUtils.isNotBlank(historicTaskInstance.get(0).getAssignee())) {
  532. // 当前任务节点办理人信息
  533. SysUser sysUser = sysUserService.selectUserById(Long.parseLong(historicTaskInstance.get(0).getAssignee()));
  534. if (Objects.nonNull(sysUser)) {
  535. flowTask.setAssigneeId(sysUser.getUserId());
  536. flowTask.setAssigneeName(sysUser.getNickName());
  537. flowTask.setAssigneeDeptName(Objects.nonNull(sysUser.getDept()) ? sysUser.getDept().getDeptName() : "");
  538. }
  539. }
  540. }
  541. }
  542. flowList.add(flowTask);
  543. }
  544. page.setRecords(flowList);
  545. return AjaxResult.success(page);
  546. }
  547. /**
  548. * 取消申请
  549. * 目前实现方式: 直接将当前流程变更为已完成
  550. *
  551. * @param flowTaskVo
  552. * @return
  553. */
  554. @Override
  555. public AjaxResult stopProcess(FlowTaskVo flowTaskVo) {
  556. List<Task> task = taskService.createTaskQuery().processInstanceId(flowTaskVo.getInstanceId()).list();
  557. if (CollectionUtils.isEmpty(task)) {
  558. throw new CustomException("流程未启动或已执行完成,取消申请失败");
  559. }
  560. // 获取当前流程实例
  561. ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
  562. .processInstanceId(flowTaskVo.getInstanceId())
  563. .singleResult();
  564. BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
  565. if (Objects.nonNull(bpmnModel)) {
  566. Process process = bpmnModel.getMainProcess();
  567. List<EndEvent> endNodes = process.findFlowElementsOfType(EndEvent.class, false);
  568. if (CollectionUtils.isNotEmpty(endNodes)) {
  569. // TODO 取消流程为什么要设置流程发起人?
  570. // SysUser loginUser = SecurityUtils.getLoginUser().getUser();
  571. // Authentication.setAuthenticatedUserId(loginUser.getUserId().toString());
  572. // taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.STOP.getType(),
  573. // StringUtils.isBlank(flowTaskVo.getComment()) ? "取消申请" : flowTaskVo.getComment());
  574. // 获取当前流程最后一个节点
  575. String endId = endNodes.get(0).getId();
  576. List<Execution> executions = runtimeService.createExecutionQuery()
  577. .parentId(processInstance.getProcessInstanceId()).list();
  578. List<String> executionIds = new ArrayList<>();
  579. executions.forEach(execution -> executionIds.add(execution.getId()));
  580. // 变更流程为已结束状态
  581. runtimeService.createChangeActivityStateBuilder()
  582. .moveExecutionsToSingleActivityId(executionIds, endId).changeState();
  583. }
  584. }
  585. return AjaxResult.success();
  586. }
  587. /**
  588. * 撤回流程 目前存在错误
  589. *
  590. * @param flowTaskVo
  591. * @return
  592. */
  593. @Override
  594. public AjaxResult revokeProcess(FlowTaskVo flowTaskVo) {
  595. Task task = taskService.createTaskQuery().processInstanceId(flowTaskVo.getInstanceId()).singleResult();
  596. if (task == null) {
  597. throw new CustomException("流程未启动或已执行完成,无法撤回");
  598. }
  599. SysUser loginUser = SecurityUtils.getLoginUser().getUser();
  600. List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
  601. .processInstanceId(task.getProcessInstanceId())
  602. .orderByTaskCreateTime()
  603. .asc()
  604. .list();
  605. String myTaskId = null;
  606. HistoricTaskInstance myTask = null;
  607. for (HistoricTaskInstance hti : htiList) {
  608. if (loginUser.getUserId().toString().equals(hti.getAssignee())) {
  609. myTaskId = hti.getId();
  610. myTask = hti;
  611. break;
  612. }
  613. }
  614. if (null == myTaskId) {
  615. throw new CustomException("该任务非当前用户提交,无法撤回");
  616. }
  617. String processDefinitionId = myTask.getProcessDefinitionId();
  618. BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
  619. //变量
  620. // Map<String, VariableInstance> variables = runtimeService.getVariableInstances(currentTask.getExecutionId());
  621. String myActivityId = null;
  622. List<HistoricActivityInstance> haiList = historyService.createHistoricActivityInstanceQuery()
  623. .executionId(myTask.getExecutionId()).finished().list();
  624. for (HistoricActivityInstance hai : haiList) {
  625. if (myTaskId.equals(hai.getTaskId())) {
  626. myActivityId = hai.getActivityId();
  627. break;
  628. }
  629. }
  630. FlowNode myFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(myActivityId);
  631. Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
  632. String activityId = execution.getActivityId();
  633. FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
  634. //记录原活动方向
  635. List<SequenceFlow> oriSequenceFlows = new ArrayList<>(flowNode.getOutgoingFlows());
  636. return AjaxResult.success();
  637. }
  638. /**
  639. * 代办任务列表
  640. *
  641. * @param queryVo 请求参数
  642. * @return
  643. */
  644. @Override
  645. public AjaxResult todoList(FlowQueryVo queryVo) {
  646. Page<FlowTaskDto> page = new Page<>();
  647. // 只查看自己的数据
  648. SysUser sysUser = SecurityUtils.getLoginUser().getUser();
  649. TaskQuery taskQuery = taskService.createTaskQuery()
  650. .active()
  651. .includeProcessVariables()
  652. .taskCandidateGroupIn(sysUser.getRoles().stream().map(role -> role.getRoleId().toString()).collect(Collectors.toList()))
  653. .taskCandidateOrAssigned(sysUser.getUserId().toString())
  654. .orderByTaskCreateTime().desc();
  655. // TODO 传入名称查询不到数据?
  656. // if (StringUtils.isNotBlank(queryVo.getName())){
  657. // taskQuery.processDefinitionNameLike(queryVo.getName());
  658. // }
  659. page.setTotal(taskQuery.count());
  660. List<Task> taskList = taskQuery.listPage(queryVo.getPageSize() * (queryVo.getPageNum() - 1), queryVo.getPageSize());
  661. List<FlowTaskDto> flowList = new ArrayList<>();
  662. for (Task task : taskList) {
  663. FlowTaskDto flowTask = new FlowTaskDto();
  664. // 当前流程信息
  665. flowTask.setTaskId(task.getId());
  666. flowTask.setTaskDefKey(task.getTaskDefinitionKey());
  667. flowTask.setCreateTime(task.getCreateTime());
  668. flowTask.setProcDefId(task.getProcessDefinitionId());
  669. flowTask.setExecutionId(task.getExecutionId());
  670. flowTask.setTaskName(task.getName());
  671. // 流程定义信息
  672. ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
  673. .processDefinitionId(task.getProcessDefinitionId())
  674. .singleResult();
  675. flowTask.setDeployId(pd.getDeploymentId());
  676. flowTask.setProcDefName(pd.getName());
  677. flowTask.setProcDefVersion(pd.getVersion());
  678. flowTask.setProcInsId(task.getProcessInstanceId());
  679. // 流程发起人信息
  680. HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
  681. .processInstanceId(task.getProcessInstanceId())
  682. .singleResult();
  683. SysUser startUser = sysUserService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
  684. flowTask.setStartUserId(startUser.getUserId().toString());
  685. flowTask.setStartUserName(startUser.getNickName());
  686. flowTask.setStartDeptName(Objects.nonNull(startUser.getDept()) ? startUser.getDept().getDeptName() : "");
  687. flowList.add(flowTask);
  688. }
  689. page.setRecords(flowList);
  690. return AjaxResult.success(page);
  691. }
  692. /**
  693. * 已办任务列表
  694. *
  695. * @param queryVo 请求参数
  696. * @return
  697. */
  698. @Override
  699. public AjaxResult finishedList(FlowQueryVo queryVo) {
  700. Page<FlowTaskDto> page = new Page<>();
  701. Long userId = SecurityUtils.getLoginUser().getUser().getUserId();
  702. HistoricTaskInstanceQuery taskInstanceQuery = historyService.createHistoricTaskInstanceQuery()
  703. .includeProcessVariables()
  704. .finished()
  705. .taskAssignee(userId.toString())
  706. .orderByHistoricTaskInstanceEndTime()
  707. .desc();
  708. List<HistoricTaskInstance> historicTaskInstanceList = taskInstanceQuery.listPage(queryVo.getPageSize() * (queryVo.getPageNum() - 1), queryVo.getPageSize());
  709. List<FlowTaskDto> hisTaskList = new ArrayList<>();
  710. for (HistoricTaskInstance histTask : historicTaskInstanceList) {
  711. FlowTaskDto flowTask = new FlowTaskDto();
  712. // 当前流程信息
  713. flowTask.setTaskId(histTask.getId());
  714. // 审批人员信息
  715. flowTask.setCreateTime(histTask.getCreateTime());
  716. flowTask.setFinishTime(histTask.getEndTime());
  717. flowTask.setDuration(getDate(histTask.getDurationInMillis()));
  718. flowTask.setProcDefId(histTask.getProcessDefinitionId());
  719. flowTask.setTaskDefKey(histTask.getTaskDefinitionKey());
  720. flowTask.setTaskName(histTask.getName());
  721. // 流程定义信息
  722. ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
  723. .processDefinitionId(histTask.getProcessDefinitionId())
  724. .singleResult();
  725. flowTask.setDeployId(pd.getDeploymentId());
  726. flowTask.setProcDefName(pd.getName());
  727. flowTask.setProcDefVersion(pd.getVersion());
  728. flowTask.setProcInsId(histTask.getProcessInstanceId());
  729. flowTask.setHisProcInsId(histTask.getProcessInstanceId());
  730. // 流程发起人信息
  731. HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
  732. .processInstanceId(histTask.getProcessInstanceId())
  733. .singleResult();
  734. SysUser startUser = sysUserService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
  735. flowTask.setStartUserId(startUser.getNickName());
  736. flowTask.setStartUserName(startUser.getNickName());
  737. flowTask.setStartDeptName(startUser.getDept().getDeptName());
  738. hisTaskList.add(flowTask);
  739. }
  740. page.setTotal(taskInstanceQuery.count());
  741. page.setRecords(hisTaskList);
  742. return AjaxResult.success(page);
  743. }
  744. private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
  745. Set<Object> seen = ConcurrentHashMap.newKeySet();
  746. return t -> seen.add(keyExtractor.apply(t));
  747. }
  748. /**
  749. * 流程历史流转记录
  750. *
  751. * @param procInsId 流程实例Id
  752. * @return
  753. */
  754. @Override
  755. public AjaxResult flowRecord(String procInsId, String deployId) {
  756. Map<String, Object> map = new HashMap<String, Object>();
  757. if (StringUtils.isNotBlank(procInsId)) {
  758. List<HistoricActivityInstance> list = historyService
  759. .createHistoricActivityInstanceQuery()
  760. .processInstanceId(procInsId)
  761. .orderByHistoricActivityInstanceStartTime()
  762. .desc().list();
  763. List<FlowTaskDto> hisFlowList = new ArrayList<>();
  764. for (HistoricActivityInstance histIns : list) {
  765. // 展示开始节点
  766. // if ("startEvent".equals(histIns.getActivityType())) {
  767. // FlowTaskDto flowTask = new FlowTaskDto();
  768. // // 流程发起人信息
  769. // HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
  770. // .processInstanceId(histIns.getProcessInstanceId())
  771. // .singleResult();
  772. // SysUser startUser = sysUserService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
  773. // flowTask.setTaskName(startUser.getNickName() + "(" + startUser.getDept().getDeptName() + ")发起申请");
  774. // flowTask.setFinishTime(histIns.getEndTime());
  775. // hisFlowList.add(flowTask);
  776. // } else if ("endEvent".equals(histIns.getActivityType())) {
  777. // FlowTaskDto flowTask = new FlowTaskDto();
  778. // flowTask.setTaskName(StringUtils.isNotBlank(histIns.getActivityName()) ? histIns.getActivityName() : "结束");
  779. // flowTask.setFinishTime(histIns.getEndTime());
  780. // hisFlowList.add(flowTask);
  781. // } else
  782. if (StringUtils.isNotBlank(histIns.getTaskId())) {
  783. FlowTaskDto flowTask = new FlowTaskDto();
  784. flowTask.setTaskId(histIns.getTaskId());
  785. flowTask.setTaskName(histIns.getActivityName());
  786. flowTask.setCreateTime(histIns.getStartTime());
  787. flowTask.setFinishTime(histIns.getEndTime());
  788. if (StringUtils.isNotBlank(histIns.getAssignee())) {
  789. SysUser sysUser = sysUserService.selectUserById(Long.parseLong(histIns.getAssignee()));
  790. flowTask.setAssigneeId(sysUser.getUserId());
  791. flowTask.setAssigneeName(sysUser.getNickName());
  792. flowTask.setDeptName(Objects.nonNull(sysUser.getDept()) ? sysUser.getDept().getDeptName() : "");
  793. }
  794. // 展示审批人员
  795. List<HistoricIdentityLink> linksForTask = historyService.getHistoricIdentityLinksForTask(histIns.getTaskId());
  796. StringBuilder stringBuilder = new StringBuilder();
  797. for (HistoricIdentityLink identityLink : linksForTask) {
  798. // 获选人,候选组/角色(多个)
  799. if ("candidate".equals(identityLink.getType())) {
  800. if (StringUtils.isNotBlank(identityLink.getUserId())) {
  801. SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId()));
  802. stringBuilder.append(sysUser.getNickName()).append(",");
  803. }
  804. if (StringUtils.isNotBlank(identityLink.getGroupId())) {
  805. SysRole sysRole = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId()));
  806. stringBuilder.append(sysRole.getRoleName()).append(",");
  807. }
  808. }
  809. }
  810. if (StringUtils.isNotBlank(stringBuilder)) {
  811. flowTask.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1));
  812. }
  813. flowTask.setDuration(histIns.getDurationInMillis() == null || histIns.getDurationInMillis() == 0 ? null : getDate(histIns.getDurationInMillis()));
  814. // 获取意见评论内容
  815. List<Comment> commentList = taskService.getProcessInstanceComments(histIns.getProcessInstanceId());
  816. commentList.forEach(comment -> {
  817. if (histIns.getTaskId().equals(comment.getTaskId())) {
  818. flowTask.setComment(FlowCommentDto.builder().type(comment.getType()).comment(comment.getFullMessage()).build());
  819. }
  820. });
  821. hisFlowList.add(flowTask);
  822. }
  823. }
  824. map.put("flowList", hisFlowList);
  825. }
  826. // 第一次申请获取初始化表单
  827. if (StringUtils.isNotBlank(deployId)) {
  828. SysForm sysForm = sysInstanceFormService.selectSysDeployFormByDeployId(deployId);
  829. if (Objects.isNull(sysForm)) {
  830. return AjaxResult.error("请先配置流程表单");
  831. }
  832. map.put("formData", JSONObject.parseObject(sysForm.getFormContent()));
  833. }
  834. return AjaxResult.success(map);
  835. }
  836. /**
  837. * 根据任务ID查询挂载的表单信息
  838. *
  839. * @param taskId 任务Id
  840. * @return
  841. */
  842. @Override
  843. public Task getTaskForm(String taskId) {
  844. Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
  845. return task;
  846. }
  847. /**
  848. * 获取流程过程图
  849. *
  850. * @param processId
  851. * @return
  852. */
  853. @Override
  854. public InputStream diagram(String processId) {
  855. String processDefinitionId;
  856. // 获取当前的流程实例
  857. ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
  858. // 如果流程已经结束,则得到结束节点
  859. if (Objects.isNull(processInstance)) {
  860. HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processId).singleResult();
  861. processDefinitionId = pi.getProcessDefinitionId();
  862. } else {// 如果流程没有结束,则取当前活动节点
  863. // 根据流程实例ID获得当前处于活动状态的ActivityId合集
  864. ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
  865. processDefinitionId = pi.getProcessDefinitionId();
  866. }
  867. // 获得活动的节点
  868. List<HistoricActivityInstance> highLightedFlowList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processId).orderByHistoricActivityInstanceStartTime().asc().list();
  869. List<String> highLightedFlows = new ArrayList<>();
  870. List<String> highLightedNodes = new ArrayList<>();
  871. //高亮线
  872. for (HistoricActivityInstance tempActivity : highLightedFlowList) {
  873. if ("sequenceFlow".equals(tempActivity.getActivityType())) {
  874. //高亮线
  875. highLightedFlows.add(tempActivity.getActivityId());
  876. } else {
  877. //高亮节点
  878. highLightedNodes.add(tempActivity.getActivityId());
  879. }
  880. }
  881. //获取流程图
  882. BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
  883. ProcessEngineConfiguration configuration = processEngine.getProcessEngineConfiguration();
  884. //获取自定义图片生成器
  885. ProcessDiagramGenerator diagramGenerator = new CustomProcessDiagramGenerator();
  886. InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", highLightedNodes, highLightedFlows, configuration.getActivityFontName(),
  887. configuration.getLabelFontName(), configuration.getAnnotationFontName(), configuration.getClassLoader(), 1.0, true);
  888. return in;
  889. }
  890. /**
  891. * 获取流程执行节点
  892. *
  893. * @param procInsId 流程实例id
  894. * @return
  895. */
  896. @Override
  897. public AjaxResult getFlowViewer(String procInsId, String executionId) {
  898. List<FlowViewerDto> flowViewerList = new ArrayList<>();
  899. FlowViewerDto flowViewerDto;
  900. // 获取任务开始节点(临时处理方式)
  901. List<HistoricActivityInstance> startNodeList = historyService.createHistoricActivityInstanceQuery()
  902. .processInstanceId(procInsId)
  903. .orderByHistoricActivityInstanceStartTime()
  904. .asc().listPage(0, 3);
  905. for (HistoricActivityInstance startInstance : startNodeList) {
  906. if (!"sequenceFlow".equals(startInstance.getActivityType())) {
  907. flowViewerDto = new FlowViewerDto();
  908. if (!"sequenceFlow".equals(startInstance.getActivityType())) {
  909. flowViewerDto.setKey(startInstance.getActivityId());
  910. // 根据流程节点处理时间校验改节点是否已完成
  911. flowViewerDto.setCompleted(!Objects.isNull(startInstance.getEndTime()));
  912. flowViewerList.add(flowViewerDto);
  913. }
  914. }
  915. }
  916. // 历史节点
  917. List<HistoricActivityInstance> hisActIns = historyService.createHistoricActivityInstanceQuery()
  918. .executionId(executionId)
  919. .orderByHistoricActivityInstanceStartTime()
  920. .asc().list();
  921. for (HistoricActivityInstance activityInstance : hisActIns) {
  922. if (!"sequenceFlow".equals(activityInstance.getActivityType())) {
  923. flowViewerDto = new FlowViewerDto();
  924. flowViewerDto.setKey(activityInstance.getActivityId());
  925. // 根据流程节点处理时间校验改节点是否已完成
  926. flowViewerDto.setCompleted(!Objects.isNull(activityInstance.getEndTime()));
  927. flowViewerList.add(flowViewerDto);
  928. }
  929. }
  930. return AjaxResult.success(flowViewerList);
  931. }
  932. /**
  933. * 获取流程变量
  934. *
  935. * @param taskId
  936. * @return
  937. */
  938. @Override
  939. public AjaxResult processVariables(String taskId) {
  940. // HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
  941. // .processInstanceId(task.getProcessInstanceId())
  942. // .singleResult();
  943. // SysUser startUser = sysUserService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
  944. // 流程变量
  945. HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().finished().taskId(taskId).singleResult();
  946. if (Objects.nonNull(historicTaskInstance)) {
  947. return AjaxResult.success(historicTaskInstance.getProcessVariables());
  948. } else {
  949. Map<String, Object> variables = taskService.getVariables(taskId);
  950. return AjaxResult.success(variables);
  951. }
  952. }
  953. /**
  954. * 获取下一节点
  955. *
  956. * @param flowTaskVo 任务
  957. * @return
  958. */
  959. @Override
  960. public AjaxResult getNextFlowNode(FlowTaskVo flowTaskVo) {
  961. // Step 1. 获取当前节点并找到下一步节点
  962. Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
  963. FlowNextDto flowNextDto = new FlowNextDto();
  964. if (Objects.nonNull(task)) {
  965. // Step 2. 获取当前流程所有流程变量(网关节点时需要校验表达式)
  966. Map<String, Object> variables = taskService.getVariables(task.getId());
  967. List<UserTask> nextUserTask = FindNextNodeUtil.getNextUserTasks(repositoryService, task, variables);
  968. if (CollectionUtils.isNotEmpty(nextUserTask)) {
  969. for (UserTask userTask : nextUserTask) {
  970. MultiInstanceLoopCharacteristics multiInstance = userTask.getLoopCharacteristics();
  971. // 会签节点
  972. if (Objects.nonNull(multiInstance)) {
  973. flowNextDto.setVars(multiInstance.getInputDataItem());
  974. flowNextDto.setType(ProcessConstants.PROCESS_MULTI_INSTANCE);
  975. flowNextDto.setDataType(ProcessConstants.DYNAMIC);
  976. } else {
  977. // 读取自定义节点属性 判断是否是否需要动态指定任务接收人员、组
  978. String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE);
  979. String userType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE);
  980. flowNextDto.setVars(ProcessConstants.PROCESS_APPROVAL);
  981. flowNextDto.setType(userType);
  982. flowNextDto.setDataType(dataType);
  983. }
  984. }
  985. } else {
  986. return AjaxResult.success("流程已完结", null);
  987. }
  988. }
  989. return AjaxResult.success(flowNextDto);
  990. }
  991. /**
  992. * 获取下一节点
  993. *
  994. * @param flowTaskVo 任务
  995. * @return
  996. */
  997. @Override
  998. public AjaxResult getNextFlowNodeByStart(FlowTaskVo flowTaskVo) {
  999. ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(flowTaskVo.getDeploymentId()).singleResult();
  1000. // Step 1. 获取当前节点并找到下一步节点
  1001. FlowNextDto flowNextDto = new FlowNextDto();
  1002. // Step 2. 获取当前流程所有流程变量(网关节点时需要校验表达式)
  1003. List<UserTask> nextUserTask = FindNextNodeUtil.getNextUserTasksByStart(repositoryService, processDefinition, flowTaskVo.getVariables());
  1004. if (CollectionUtils.isNotEmpty(nextUserTask)) {
  1005. for (UserTask userTask : nextUserTask) {
  1006. MultiInstanceLoopCharacteristics multiInstance = userTask.getLoopCharacteristics();
  1007. // 会签节点
  1008. if (Objects.nonNull(multiInstance)) {
  1009. flowNextDto.setVars(multiInstance.getInputDataItem());
  1010. flowNextDto.setType(ProcessConstants.PROCESS_MULTI_INSTANCE);
  1011. flowNextDto.setDataType(ProcessConstants.DYNAMIC);
  1012. } else {
  1013. // 读取自定义节点属性 判断是否是否需要动态指定任务接收人员、组
  1014. String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE);
  1015. String userType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE);
  1016. flowNextDto.setVars(ProcessConstants.PROCESS_APPROVAL);
  1017. flowNextDto.setType(userType);
  1018. flowNextDto.setDataType(dataType);
  1019. }
  1020. }
  1021. }
  1022. return AjaxResult.success(flowNextDto);
  1023. }
  1024. /**
  1025. * 流程初始化表单
  1026. *
  1027. * @param deployId
  1028. * @return
  1029. */
  1030. @Override
  1031. public AjaxResult flowFormData(String deployId) {
  1032. // 第一次申请获取初始化表单
  1033. if (StringUtils.isNotBlank(deployId)) {
  1034. SysForm sysForm = sysInstanceFormService.selectSysDeployFormByDeployId(deployId);
  1035. if (Objects.isNull(sysForm)) {
  1036. return AjaxResult.error("请先配置流程表单!");
  1037. }
  1038. return AjaxResult.success(JSONObject.parseObject(sysForm.getFormContent()));
  1039. } else {
  1040. return AjaxResult.error("参数错误!");
  1041. }
  1042. }
  1043. /**
  1044. * 流程节点信息
  1045. *
  1046. * @param procInsId
  1047. * @return
  1048. */
  1049. @Override
  1050. public AjaxResult flowXmlAndNode(String procInsId, String deployId) {
  1051. try {
  1052. List<FlowViewerDto> flowViewerList = new ArrayList<>();
  1053. // 获取已经完成的节点
  1054. List<HistoricActivityInstance> listFinished = historyService.createHistoricActivityInstanceQuery()
  1055. .processInstanceId(procInsId)
  1056. .finished()
  1057. .list();
  1058. // 保存已经完成的流程节点编号
  1059. listFinished.forEach(s -> {
  1060. FlowViewerDto flowViewerDto = new FlowViewerDto();
  1061. flowViewerDto.setKey(s.getActivityId());
  1062. flowViewerDto.setCompleted(true);
  1063. flowViewerList.add(flowViewerDto);
  1064. });
  1065. // 获取代办节点
  1066. List<HistoricActivityInstance> listUnFinished = historyService.createHistoricActivityInstanceQuery()
  1067. .processInstanceId(procInsId)
  1068. .unfinished()
  1069. .list();
  1070. // 保存需要代办的节点编号
  1071. listUnFinished.forEach(s -> {
  1072. FlowViewerDto flowViewerDto = new FlowViewerDto();
  1073. flowViewerDto.setKey(s.getActivityId());
  1074. flowViewerDto.setCompleted(false);
  1075. flowViewerList.add(flowViewerDto);
  1076. });
  1077. Map<String, Object> result = new HashMap();
  1078. // xmlData 数据
  1079. ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult();
  1080. InputStream inputStream = repositoryService.getResourceAsStream(definition.getDeploymentId(), definition.getResourceName());
  1081. String xmlData = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
  1082. result.put("nodeData", flowViewerList);
  1083. result.put("xmlData", xmlData);
  1084. return AjaxResult.success(result);
  1085. } catch (Exception e) {
  1086. return AjaxResult.error("高亮历史任务失败");
  1087. }
  1088. }
  1089. /**
  1090. * 流程节点表单
  1091. *
  1092. * @param taskId 流程任务编号
  1093. * @return
  1094. */
  1095. @Override
  1096. public AjaxResult flowTaskForm(String taskId) throws Exception {
  1097. JSONObject result = new JSONObject();
  1098. result.put("formKeyExist", false);
  1099. Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
  1100. BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
  1101. FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey());
  1102. // 流程变量
  1103. Map<String, Object> parameters = new HashMap<>();
  1104. HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().finished().taskId(taskId).singleResult();
  1105. if (Objects.nonNull(historicTaskInstance)) {
  1106. parameters = historicTaskInstance.getProcessVariables();
  1107. } else {
  1108. parameters = taskService.getVariables(taskId);
  1109. }
  1110. // TODO 暂时只处理用户任务上的表单
  1111. if (flowElement instanceof UserTask) {
  1112. String formKey = ((UserTask) flowElement).getFormKey();
  1113. if (StringUtils.isNotBlank(formKey)) {
  1114. SysForm sysForm = sysFormService.selectSysFormById(Long.parseLong(formKey));
  1115. JSONObject oldVariables = JSONObject.parseObject(JSON.toJSONString(parameters.get("variables")));
  1116. List<JSONObject> oldFields = JSON.parseObject(JSON.toJSONString(oldVariables.get("fields")), new TypeReference<List<JSONObject>>() {
  1117. });
  1118. oldFields.forEach(obj -> obj.put("disabled", true));
  1119. JSONObject data = JSONObject.parseObject(sysForm.getFormContent());
  1120. List<JSONObject> newFields = JSON.parseObject(JSON.toJSONString(data.get("fields")), new TypeReference<List<JSONObject>>() {
  1121. });
  1122. oldFields.addAll(newFields);
  1123. oldVariables.put("fields", oldFields);
  1124. oldVariables.put("disabled", false);
  1125. oldVariables.put("formBtns", true);
  1126. result.put("formData", oldVariables);
  1127. result.put("formKeyExist", true);
  1128. return AjaxResult.success("", result);
  1129. } else {
  1130. result.put("formData", parameters.get("variables"));
  1131. return AjaxResult.success("", result);
  1132. }
  1133. } else {
  1134. result.put("formData", parameters.get("variables"));
  1135. return AjaxResult.success("", result);
  1136. }
  1137. }
  1138. /**
  1139. * 将Object类型的数据转化成Map<String,Object>
  1140. *
  1141. * @param obj
  1142. * @return
  1143. * @throws Exception
  1144. */
  1145. public Map<String, Object> obj2Map(Object obj) throws Exception {
  1146. Map<String, Object> map = new HashMap<String, Object>();
  1147. Field[] fields = obj.getClass().getDeclaredFields();
  1148. for (Field field : fields) {
  1149. field.setAccessible(true);
  1150. map.put(field.getName(), field.get(obj));
  1151. }
  1152. return map;
  1153. }
  1154. /**
  1155. * 流程完成时间处理
  1156. *
  1157. * @param ms
  1158. * @return
  1159. */
  1160. private String getDate(long ms) {
  1161. long day = ms / (24 * 60 * 60 * 1000);
  1162. long hour = (ms / (60 * 60 * 1000) - day * 24);
  1163. long minute = ((ms / (60 * 1000)) - day * 24 * 60 - hour * 60);
  1164. long second = (ms / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60);
  1165. if (day > 0) {
  1166. return day + "天" + hour + "小时" + minute + "分钟";
  1167. }
  1168. if (hour > 0) {
  1169. return hour + "小时" + minute + "分钟";
  1170. }
  1171. if (minute > 0) {
  1172. return minute + "分钟";
  1173. }
  1174. if (second > 0) {
  1175. return second + "秒";
  1176. } else {
  1177. return 0 + "秒";
  1178. }
  1179. }
  1180. }