ActivitiService.java 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. package com.common.workflow.service.activiti;
  2. import java.awt.image.BufferedImage;
  3. import java.io.File;
  4. import java.io.FileOutputStream;
  5. import java.io.InputStream;
  6. import java.io.OutputStream;
  7. import java.text.SimpleDateFormat;
  8. import java.util.ArrayList;
  9. import java.util.Arrays;
  10. import java.util.HashMap;
  11. import java.util.List;
  12. import java.util.Map;
  13. import javax.annotation.Resource;
  14. import javax.imageio.ImageIO;
  15. import javax.servlet.http.HttpServletResponse;
  16. import com.common.workflow.service.dto.ActiHistoricTaskDTO;
  17. import org.activiti.bpmn.model.BpmnModel;
  18. import org.activiti.bpmn.model.FlowNode;
  19. import org.activiti.bpmn.model.SequenceFlow;
  20. import org.activiti.engine.*;
  21. import org.activiti.engine.delegate.DelegateExecution;
  22. import org.activiti.engine.history.*;
  23. import org.activiti.engine.impl.RepositoryServiceImpl;
  24. import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
  25. import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
  26. import org.activiti.engine.runtime.ProcessInstance;
  27. import org.activiti.engine.task.Task;
  28. import org.activiti.engine.task.TaskQuery;
  29. import org.activiti.image.ProcessDiagramGenerator;
  30. import org.apache.commons.lang3.StringUtils;
  31. import org.springframework.beans.factory.annotation.Autowired;
  32. import org.springframework.stereotype.Service;
  33. @Service
  34. public class ActivitiService {
  35. @Autowired
  36. private RuntimeService runtimeService;
  37. @Autowired
  38. private TaskService taskService;
  39. @Autowired
  40. private HistoryService historyService;
  41. @Autowired
  42. private ProcessEngine processEngine;
  43. @Autowired
  44. private RepositoryService repositoryService;
  45. @Autowired
  46. private ProcessEngineConfigurationImpl processEngineConfiguration;
  47. /**
  48. * 启动流程
  49. * @param businessKey 业务id
  50. */
  51. public String startProcesses(String processKey, String businessKey, String userNames) {
  52. Map<String, Object> variables = new HashMap<String, Object>();
  53. variables.put("businessKey", businessKey);
  54. variables.put("recorder", userNames);
  55. ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processKey, variables);
  56. System.out.println("流程启动成功,流程id:"+processInstance.getId());
  57. return processInstance.getProcessInstanceId();
  58. }
  59. /**
  60. *
  61. * <p>描述: 根据工作流Key, 用户id, 业务表Key 查询待办任务列表</p>
  62. */
  63. public void completeTask(String processKey, String businessKey, String userNames, String userId, String result, String remarks) {
  64. Task myTask = taskService.createTaskQuery()
  65. .processDefinitionKey(processKey)
  66. .taskCandidateOrAssigned(userId)
  67. //.taskAssignee(userId)
  68. .processVariableValueEquals("businessKey", businessKey)
  69. .singleResult();
  70. /*List<Task> testTasks = taskService.createTaskQuery()
  71. .processDefinitionKey(processKey)
  72. .taskCandidateOrAssigned(userId)
  73. //.taskAssignee(userId)
  74. .processVariableValueEquals("businessKey", businessKey)
  75. .list();*/
  76. //获取流程实例
  77. taskService.claim(myTask.getId(), userId);
  78. Map<String,Object> vars = new HashMap<String,Object>();
  79. vars.put("users", userNames);
  80. vars.put("result", Integer.parseInt(result));
  81. List<String> assigneeList = Arrays.asList(userNames.split(","));
  82. vars.put("assigneeList", assigneeList);
  83. //设置流程变量【基本类型】
  84. taskService.setVariableLocal(myTask.getId(), "businessKey", businessKey);
  85. taskService.setVariableLocal(myTask.getId(), "users", userNames);
  86. taskService.setVariableLocal(myTask.getId(), "result", Integer.parseInt(result));
  87. taskService.setVariableLocal(myTask.getId(), "remarks", remarks);
  88. taskService.complete(myTask.getId(), vars);
  89. //taskService.complete(myTask.getId(), vars, true);
  90. }
  91. /**
  92. *
  93. * <p>描述:任务审批 (通过/拒接) </p>
  94. * @author 范相如
  95. * @date 2018年2月25日
  96. * @param taskId 任务id
  97. * @param userId 用户id
  98. * @param result false OR true
  99. */
  100. /*public void completeTask(String taskId,String userId,String result, String comments) {
  101. //获取流程实例
  102. taskService.claim(taskId, userId);
  103. Map<String,Object> vars = new HashMap<String,Object>();
  104. vars.put("sign", "true");
  105. taskService.complete(taskId, vars);
  106. }*/
  107. /**
  108. *
  109. * <p>描述: 根据工作流Key 和 用户id查询待办任务列表</p>
  110. */
  111. public String findTasksByUserId(String processKey, String userId) {
  112. List<Task> resultTasks = taskService.createTaskQuery().processDefinitionKey(processKey).taskCandidateOrAssigned(userId).list();
  113. String businessKeys = "";
  114. int i = 0;
  115. for (Task myTask : resultTasks) {
  116. if(resultTasks.size()-1 == i) {
  117. businessKeys += taskService.getVariable(myTask.getId(), "businessKey").toString();
  118. } else {
  119. businessKeys += taskService.getVariable(myTask.getId(), "businessKey").toString()+ ",";
  120. }
  121. i++;
  122. }
  123. return businessKeys;
  124. }
  125. /**
  126. *
  127. * <p>描述: 根据工作流Key 和 用户id查询已办任务列表</p>
  128. */
  129. public String findTaskHistByUserId(String processKey, String userId) {
  130. List<HistoricTaskInstance> hisTaskList = historyService.createHistoricTaskInstanceQuery()
  131. .processDefinitionKey(processKey)
  132. .taskAssignee(userId)
  133. .orderByTaskId()
  134. .desc()
  135. .list();
  136. List<String> businessKeyList = new ArrayList<>();
  137. String businessKeys = "";
  138. for (HistoricTaskInstance myTask : hisTaskList) {
  139. List<HistoricVariableInstance> varList = historyService.createHistoricVariableInstanceQuery()
  140. .processInstanceId(myTask.getProcessInstanceId())
  141. .list();
  142. for(HistoricVariableInstance hisvar : varList) {
  143. if(hisvar.getVariableName().equals("businessKey") && !businessKeyList.contains(hisvar.getValue().toString())) {
  144. businessKeyList.add(hisvar.getValue().toString());
  145. break;
  146. }
  147. }
  148. }
  149. businessKeys = StringUtils.join(businessKeyList.toArray(), ",");
  150. return businessKeys;
  151. }
  152. /**
  153. * 查询当前用户的待办任务
  154. * @param processDefinitionKey 流程定义key(流程定义的标识)
  155. * @param assignee 任务负责人
  156. * @return
  157. */
  158. /*public List<Task> findTasks(String processDefinitionKey, String assignee) {
  159. //创建查询对象
  160. TaskQuery taskQuery = taskService.createTaskQuery();
  161. //设置查询条件
  162. taskQuery.taskAssignee(assignee);
  163. //指定流程定义key,只查询某个流程的任务
  164. taskQuery.processDefinitionKey(processDefinitionKey);
  165. //获取查询列表
  166. List<Task> list = taskQuery.list();
  167. return list;
  168. }*/
  169. public List<ActiHistoricTaskDTO> getHistoricTasks(String processDefinitionKey, String businessKey, String processInstanceId) {
  170. List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
  171. .processInstanceId(processInstanceId)
  172. .list();
  173. List<HistoricVariableInstance> varList = historyService.createHistoricVariableInstanceQuery()
  174. .processInstanceId(processInstanceId)
  175. .list();
  176. List<ActiHistoricTaskDTO> historicTaskDTOS = new ArrayList<>();
  177. if (list != null && list.size() > 0) {
  178. for(HistoricTaskInstance histTask : list) {
  179. ActiHistoricTaskDTO historicTask = new ActiHistoricTaskDTO();
  180. for(HistoricVariableInstance hvi : varList){
  181. if(hvi.getTaskId() != null && hvi.getTaskId().equals(histTask.getId())) {
  182. if(hvi.getVariableName().equals("businessKey")) {
  183. historicTask.setBusinessKey(hvi.getValue().toString());
  184. } else if(hvi.getVariableName().equals("result")) {
  185. historicTask.setResult(hvi.getValue().toString());
  186. } else if(hvi.getVariableName().equals("remarks")) {
  187. historicTask.setRemarks(hvi.getValue().toString());
  188. } else if( hvi.getVariableName().equals("users")) {
  189. historicTask.setUsers(hvi.getValue().toString());
  190. }
  191. }
  192. }
  193. //当前未完成的步骤,取出当前操作人
  194. if ( histTask.getClaimTime() == null || histTask.getEndTime() == null ) {
  195. List<HistoricVariableInstance> varListTmp = historyService.createHistoricVariableInstanceQuery()
  196. .processInstanceId(processInstanceId)
  197. .executionId(histTask.getExecutionId())
  198. .list();
  199. for(HistoricVariableInstance hvi : varListTmp){
  200. if(hvi.getVariableName().equals("businessKey")) {
  201. historicTask.setBusinessKey(hvi.getValue().toString());
  202. } else if(hvi.getVariableName().equals("result")) {
  203. historicTask.setResult(hvi.getValue().toString());
  204. } else if(hvi.getVariableName().equals("remarks")) {
  205. historicTask.setRemarks(hvi.getValue().toString());
  206. } else if( hvi.getVariableName().equals("users")) {
  207. historicTask.setUsers(hvi.getValue().toString());
  208. }
  209. }
  210. }
  211. historicTask.setAssignee(histTask.getAssignee());
  212. historicTask.setTaskName(histTask.getName());
  213. if(histTask.getStartTime() != null) {
  214. historicTask.setStartTime(histTask.getStartTime().getTime());
  215. }
  216. if(histTask.getEndTime() != null) {
  217. historicTask.setEndTime(histTask.getEndTime().getTime());
  218. }
  219. historicTask.setProcessInstanceId(histTask.getProcessInstanceId());
  220. historicTaskDTOS.add(historicTask);
  221. }
  222. }
  223. return historicTaskDTOS;
  224. }
  225. /**
  226. * 更改业务流程状态#{ActivityDemoServiceImpl.updateBizStatus(execution,"tj")}
  227. * @param execution
  228. * @param status
  229. */
  230. /*public void updateBizStatus(DelegateExecution execution,String status) {
  231. String bizId = execution.getProcessBusinessKey();
  232. //根据业务id自行处理业务表
  233. System.out.println("业务表["+bizId+"]状态更改成功,状态更改为:"+status);
  234. }*/
  235. //流程节点权限用户列表${ActivityDemoServiceImpl.findUsers(execution,sign)}
  236. /*public List<String> findUsersForSL(DelegateExecution execution){
  237. return Arrays.asList("sly1","sly2");
  238. }*/
  239. //流程节点权限用户列表${ActivityDemoServiceImpl.findUsers(execution,sign)}
  240. /*public List<String> findUsersForSP(DelegateExecution execution){
  241. return Arrays.asList("spy1","uspy2");
  242. }*/
  243. /**
  244. *
  245. * <p>描述: 生成流程图
  246. * 首先启动流程,获取processInstanceId,替换即可生成</p>
  247. * @author 范相如
  248. * @date 2018年2月25日
  249. * @param processInstanceId
  250. * @throws Exception
  251. */
  252. /*public void queryProImg(String processInstanceId) throws Exception {
  253. //获取历史流程实例
  254. HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
  255. //根据流程定义获取输入流
  256. InputStream is = repositoryService.getProcessDiagram(processInstance.getProcessDefinitionId());
  257. BufferedImage bi = ImageIO.read(is);
  258. File file = new File("demo2.png");
  259. if(!file.exists()) file.createNewFile();
  260. FileOutputStream fos = new FileOutputStream(file);
  261. ImageIO.write(bi, "png", fos);
  262. fos.close();
  263. is.close();
  264. System.out.println("图片生成成功");
  265. List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("userId").list();
  266. for(Task t : tasks) {
  267. System.out.println(t.getName());
  268. }
  269. }*/
  270. /**
  271. * 获取流程图像,已执行节点和流程线高亮显示
  272. */
  273. public void getActivitiProccessImage(String pProcessInstanceId, HttpServletResponse response)
  274. {
  275. //logger.info("[开始]-获取流程图图像");
  276. try {
  277. // 获取历史流程实例
  278. HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
  279. .processInstanceId(pProcessInstanceId).singleResult();
  280. if (historicProcessInstance == null) {
  281. //throw new BusinessException("获取流程实例ID[" + pProcessInstanceId + "]对应的历史流程实例失败!");
  282. }
  283. else
  284. {
  285. // 获取流程定义
  286. ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
  287. .getDeployedProcessDefinition(historicProcessInstance.getProcessDefinitionId());
  288. // 获取流程历史中已执行节点,并按照节点在流程中执行先后顺序排序
  289. List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
  290. .processInstanceId(pProcessInstanceId).orderByHistoricActivityInstanceId().asc().list();
  291. // 已执行的节点ID集合
  292. List<String> executedActivityIdList = new ArrayList<String>();
  293. int index = 1;
  294. //logger.info("获取已经执行的节点ID");
  295. for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
  296. executedActivityIdList.add(activityInstance.getActivityId());
  297. //logger.info("第[" + index + "]个已执行节点=" + activityInstance.getActivityId() + " : " +activityInstance.getActivityName());
  298. index++;
  299. }
  300. BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
  301. // 已执行的线集合
  302. List<String> flowIds = new ArrayList<String>();
  303. // 获取流程走过的线 (getHighLightedFlows是下面的方法)
  304. flowIds = getHighLightedFlows(bpmnModel,processDefinition, historicActivityInstanceList);
  305. // 获取流程图图像字符流
  306. ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
  307. ProcessDiagramGenerator pec = processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator();
  308. //配置字体
  309. InputStream imageStream = pec.generateDiagram(bpmnModel, "png", executedActivityIdList, flowIds,"宋体","微软雅黑","黑体",null,2.0);
  310. response.setContentType("image/png");
  311. OutputStream os = response.getOutputStream();
  312. int bytesRead = 0;
  313. byte[] buffer = new byte[8192];
  314. while ((bytesRead = imageStream.read(buffer, 0, 8192)) != -1) {
  315. os.write(buffer, 0, bytesRead);
  316. }
  317. os.close();
  318. imageStream.close();
  319. }
  320. //logger.info("[完成]-获取流程图图像");
  321. } catch (Exception e) {
  322. System.out.println(e.getMessage());
  323. //logger.error("【异常】-获取流程图失败!" + e.getMessage());
  324. //throw new BusinessException("获取流程图失败!" + e.getMessage());
  325. }
  326. }
  327. public List<String> getHighLightedFlows(BpmnModel bpmnModel,ProcessDefinitionEntity processDefinitionEntity,List<HistoricActivityInstance> historicActivityInstances)
  328. {
  329. SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //24小时制
  330. List<String> highFlows = new ArrayList<String>();// 用以保存高亮的线flowId
  331. for (int i = 0; i < historicActivityInstances.size() - 1; i++)
  332. {
  333. // 对历史流程节点进行遍历
  334. // 得到节点定义的详细信息
  335. FlowNode activityImpl = (FlowNode)bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(i).getActivityId());
  336. List<FlowNode> sameStartTimeNodes = new ArrayList<FlowNode>();// 用以保存后续开始时间相同的节点
  337. FlowNode sameActivityImpl1 = null;
  338. HistoricActivityInstance activityImpl_ = historicActivityInstances.get(i);// 第一个节点
  339. HistoricActivityInstance activityImp2_ ;
  340. for(int k = i + 1 ; k <= historicActivityInstances.size() - 1; k++)
  341. {
  342. activityImp2_ = historicActivityInstances.get(k);// 后续第1个节点
  343. if ( activityImpl_.getActivityType().equals("userTask") && activityImp2_.getActivityType().equals("userTask") &&
  344. df.format(activityImpl_.getStartTime()).equals(df.format(activityImp2_.getStartTime())) ) //都是usertask,且主节点与后续节点的开始时间相同,说明不是真实的后继节点
  345. {
  346. }
  347. else
  348. {
  349. sameActivityImpl1 = (FlowNode)bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(k).getActivityId());//找到紧跟在后面的一个节点
  350. break;
  351. }
  352. }
  353. sameStartTimeNodes.add(sameActivityImpl1); // 将后面第一个节点放在时间相同节点的集合里
  354. for (int j = i + 1; j < historicActivityInstances.size() - 1; j++)
  355. {
  356. HistoricActivityInstance activityImpl1 = historicActivityInstances.get(j);// 后续第一个节点
  357. HistoricActivityInstance activityImpl2 = historicActivityInstances.get(j + 1);// 后续第二个节点
  358. if (df.format(activityImpl1.getStartTime()).equals(df.format(activityImpl2.getStartTime())) )
  359. {// 如果第一个节点和第二个节点开始时间相同保存
  360. FlowNode sameActivityImpl2 = (FlowNode)bpmnModel.getMainProcess().getFlowElement(activityImpl2.getActivityId());
  361. sameStartTimeNodes.add(sameActivityImpl2);
  362. }
  363. else
  364. {// 有不相同跳出循环
  365. break;
  366. }
  367. }
  368. List<SequenceFlow> pvmTransitions = activityImpl.getOutgoingFlows() ; // 取出节点的所有出去的线
  369. for (SequenceFlow pvmTransition : pvmTransitions)
  370. {// 对所有的线进行遍历
  371. FlowNode pvmActivityImpl = (FlowNode)bpmnModel.getMainProcess().getFlowElement( pvmTransition.getTargetRef());// 如果取出的线的目标节点存在时间相同的节点里,保存该线的id,进行高亮显示
  372. if (sameStartTimeNodes.contains(pvmActivityImpl)) {
  373. highFlows.add(pvmTransition.getId());
  374. }
  375. }
  376. }
  377. return highFlows;
  378. }
  379. }