From f6ecfcc120ab20703c0e24659b18a6634b6d3e35 Mon Sep 17 00:00:00 2001 From: pengqiang Date: Wed, 10 Nov 2021 11:24:49 +0800 Subject: [PATCH] activiti --- .../config/activiti/DeleteTaskCommand.java | 2 +- .../backend/ActModelController.java | 9 +- .../backend/ActModelEditorController.java | 2 +- .../backend/ActProcDefController.java | 6 +- .../backend/ActProcInsController.java | 11 +- .../java/cn/palmte/work/pojo/ActHisTask.java | 3 +- .../work/service/ActListenerService.java | 9 +- .../work/service/ActProcDefService.java | 69 +--- .../work/service/ActProcInsService.java | 144 +++---- .../work/service/ActTaskDefService.java | 364 ++++++++---------- .../java/cn/palmte/work/utils/ActUtil.java | 250 ++++++++++++ .../templates/admin/act_his_task_list.ftl | 10 +- .../templates/admin/act_proc_def_list.ftl | 2 +- .../templates/admin/act_proc_ins_list.ftl | 28 +- .../templates/admin/act_script_list.ftl | 2 +- 15 files changed, 545 insertions(+), 366 deletions(-) create mode 100644 src/main/java/cn/palmte/work/utils/ActUtil.java diff --git a/src/main/java/cn/palmte/work/config/activiti/DeleteTaskCommand.java b/src/main/java/cn/palmte/work/config/activiti/DeleteTaskCommand.java index e29a1e1..964bf1e 100644 --- a/src/main/java/cn/palmte/work/config/activiti/DeleteTaskCommand.java +++ b/src/main/java/cn/palmte/work/config/activiti/DeleteTaskCommand.java @@ -21,7 +21,7 @@ public class DeleteTaskCommand extends NeedsActiveTaskCmd { //获取当前任务的来源任务及来源节点信息 ExecutionEntity executionEntity = currentTask.getExecution(); //删除当前任务,来源任务 - taskEntityManager.deleteTask(currentTask, "jumpReason", false, false); + taskEntityManager.deleteTask(currentTask, "驳回", false, false); return executionEntity.getId(); } diff --git a/src/main/java/cn/palmte/work/controller/backend/ActModelController.java b/src/main/java/cn/palmte/work/controller/backend/ActModelController.java index b625664..611e067 100644 --- a/src/main/java/cn/palmte/work/controller/backend/ActModelController.java +++ b/src/main/java/cn/palmte/work/controller/backend/ActModelController.java @@ -36,8 +36,9 @@ public class ActModelController extends BaseController { return "/admin/act_model_list"; } + @GetMapping(value = "/add") - public String add(Map model) { + public String add() { return "/admin/act_model_input"; } @@ -67,6 +68,12 @@ public class ActModelController extends BaseController { } + /** + * 部署流程 + * + * @param id + * @return + */ @ResponseBody @GetMapping(value = "/deploy") public ResponseMsg deploy(@RequestParam("id") String id) { diff --git a/src/main/java/cn/palmte/work/controller/backend/ActModelEditorController.java b/src/main/java/cn/palmte/work/controller/backend/ActModelEditorController.java index 9a1e038..4912840 100644 --- a/src/main/java/cn/palmte/work/controller/backend/ActModelEditorController.java +++ b/src/main/java/cn/palmte/work/controller/backend/ActModelEditorController.java @@ -96,7 +96,7 @@ public class ActModelEditorController implements ModelDataJsonConstants { /** - * 报错模型数据 + * 保存模型数据 * * @param modelId * @param values diff --git a/src/main/java/cn/palmte/work/controller/backend/ActProcDefController.java b/src/main/java/cn/palmte/work/controller/backend/ActProcDefController.java index e1d6625..7b6b928 100644 --- a/src/main/java/cn/palmte/work/controller/backend/ActProcDefController.java +++ b/src/main/java/cn/palmte/work/controller/backend/ActProcDefController.java @@ -3,6 +3,7 @@ package cn.palmte.work.controller.backend; import cn.palmte.work.bean.ResponseMsg; import cn.palmte.work.service.ActProcDefService; +import cn.palmte.work.utils.ActUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -25,6 +26,9 @@ public class ActProcDefController extends BaseController { @Autowired private ActProcDefService actProcDefService; + @Autowired + private ActUtil actUtil; + @RequestMapping("/list") public String list(@RequestParam(value = "keywords", required = false) String keywords, @RequestParam(value = PAGE_NUMBER, defaultValue = DEFAULT_PAGE_NUMBER) int pageNumber, @@ -57,7 +61,7 @@ public class ActProcDefController extends BaseController { */ @RequestMapping("/xml/{deploymentId}") public void xml(HttpServletResponse response, @PathVariable("deploymentId") String deploymentId) throws Exception { - actProcDefService.getXmlByDeploymentId(response, deploymentId); + actUtil.responseXml(response, deploymentId); } diff --git a/src/main/java/cn/palmte/work/controller/backend/ActProcInsController.java b/src/main/java/cn/palmte/work/controller/backend/ActProcInsController.java index 49ca359..5db6987 100644 --- a/src/main/java/cn/palmte/work/controller/backend/ActProcInsController.java +++ b/src/main/java/cn/palmte/work/controller/backend/ActProcInsController.java @@ -30,6 +30,7 @@ public class ActProcInsController extends BaseController { /** * 列表 + * * @param keywords * @param pageNumber * @param pageSize @@ -81,10 +82,16 @@ public class ActProcInsController extends BaseController { */ @ResponseBody @GetMapping(value = "/startProcIns") - public ResponseMsg startProcessInstance(@RequestParam String procDefKey) throws Exception{ + public ResponseMsg startProcessInstance(@RequestParam String procDefKey) { Map variables = new HashMap<>(); variables.put(ActConstant.START_PROCESS_USERID, InterfaceUtil.getAdminId()); - String procInsId = actProcInsService.startProcessInstance(procDefKey, variables); + String procInsId = null; + try { + procInsId = actProcInsService.startProcessInstance(procDefKey, variables); + } catch (Exception e) { + logger.error("", e); + return ResponseMsg.buildFailedMsg("流程启动失败:" + e.getMessage()); + } return ResponseMsg.buildSuccessMsg("流程启动成功", procInsId); } diff --git a/src/main/java/cn/palmte/work/pojo/ActHisTask.java b/src/main/java/cn/palmte/work/pojo/ActHisTask.java index 258b83e..8623d1c 100644 --- a/src/main/java/cn/palmte/work/pojo/ActHisTask.java +++ b/src/main/java/cn/palmte/work/pojo/ActHisTask.java @@ -7,11 +7,12 @@ import java.util.Date; @Data public class ActHisTask { private String taskId; - private String actName; + private String taskName; private String assign; private Date startTime; private Date endTime; private String duration; private String comments; + private String deleteReason; } diff --git a/src/main/java/cn/palmte/work/service/ActListenerService.java b/src/main/java/cn/palmte/work/service/ActListenerService.java index 3b063c5..9053e80 100644 --- a/src/main/java/cn/palmte/work/service/ActListenerService.java +++ b/src/main/java/cn/palmte/work/service/ActListenerService.java @@ -13,7 +13,7 @@ import java.util.Set; /** - * 流程节点创建监听 + * 流程节点监听 */ @Service public class ActListenerService { @@ -23,10 +23,15 @@ public class ActListenerService { @Autowired private ActTaskDefService actTaskDefService; + /** + * 节点创建监听 动态设置审批人 + * + * @param delegateTask + * @throws Exception + */ public void create(DelegateTask delegateTask) throws Exception { logger.info("--- {}", JSONObject.toJSONString(delegateTask)); - // 每一个任务节点监听运行时都要初始化流程定义规则数据到 流程引擎中 String procDefId = delegateTask.getProcessDefinitionId(); String procInsId = delegateTask.getProcessInstanceId(); String taskDefKey = delegateTask.getTaskDefinitionKey(); diff --git a/src/main/java/cn/palmte/work/service/ActProcDefService.java b/src/main/java/cn/palmte/work/service/ActProcDefService.java index 7d232ca..cb3fcd1 100644 --- a/src/main/java/cn/palmte/work/service/ActProcDefService.java +++ b/src/main/java/cn/palmte/work/service/ActProcDefService.java @@ -2,11 +2,10 @@ package cn.palmte.work.service; import cn.palmte.work.model.ActTaskDefRepository; import cn.palmte.work.pojo.ActProcDef; +import cn.palmte.work.utils.ActUtil; import org.activiti.bpmn.model.BpmnModel; -import org.activiti.engine.ProcessEngine; import org.activiti.engine.RepositoryService; import org.activiti.engine.repository.ProcessDefinition; -import org.activiti.image.ProcessDiagramGenerator; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -16,29 +15,22 @@ import org.springframework.transaction.annotation.Transactional; import top.jfunc.common.db.QueryHelper; import top.jfunc.common.db.bean.Page; import top.jfunc.common.db.utils.Pagination; -import top.jfunc.common.utils.IoUtil; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; -import java.util.List; import java.util.concurrent.ConcurrentHashMap; @Service public class ActProcDefService { private static final Logger logger = LoggerFactory.getLogger(ActProcDefService.class); - - @Autowired - private ProcessEngine processEngine; //流程引擎对象 @Autowired private RepositoryService repositoryService; //管理流程定义 与流程定义和部署对象相关的Service - @Autowired private ActTaskDefRepository actTaskDefRepository; - - + @Autowired + private ActUtil actUtil; @Autowired Pagination pagination; @@ -53,35 +45,6 @@ public class ActProcDefService { return pagination.paginate(queryHelper.getSql(), ActProcDef.class, pageNumber, pageSize); } - public void getXmlByDeploymentId(HttpServletResponse response, String deploymentId) throws IOException { - InputStream pic=null; - try { - pic= getXmlStreamByDeploymentId(deploymentId); - byte[] b = new byte[1024]; - int len = -1; - while ((len = pic.read(b, 0, 1024)) != -1) { - response.getOutputStream().write(b, 0, len); - } - }catch (Exception e){ - logger.error("an exception happens in try catch statement", e); - }finally { - if(pic!=null) { - pic.close(); - } - } - } - - public InputStream getXmlStreamByDeploymentId(String deploymentId) throws IOException{ - List names = repositoryService.getDeploymentResourceNames(deploymentId); - for (String name : names) { - if(name.contains("xml") ) { - return repositoryService.getResourceAsStream(deploymentId, name); - } - } - return null; - } - - /** * 创建默认的png @@ -94,22 +57,11 @@ public class ActProcDefService { ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult(); // 获取bpmnModel BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId()); - try (InputStream inputStream = generateDiagramInputStream(bpmnModel, new ArrayList<>(), new ArrayList<>())){ - IoUtil.copy(inputStream, response.getOutputStream()); - } + actUtil.responsePng(response, bpmnModel, new ArrayList<>(), new ArrayList<>()); } - public InputStream generateDiagramInputStream(BpmnModel bpmnModel, List executedActivityIdList, List flowIds) { - try { - ProcessDiagramGenerator processDiagramGenerator = processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator(); - return processDiagramGenerator.generateDiagram(bpmnModel, "png", executedActivityIdList, - flowIds, "宋体", "微软雅黑", "黑体", null, 2.0); //使用默认配置获得流程图表生成器,并生成追踪图片字符流 - } catch (Exception e) { - logger.error("an exception happens in try catch statement", e); - return null; - } - } + @Transactional(rollbackFor = Exception.class) public void deleteDeployment(String deploymentId) { @@ -117,13 +69,20 @@ public class ActProcDefService { actTaskDefRepository.deleteByProcDefId(processDefinition.getId()); //repositoryService.deleteDeployment(deploymentId); //不带级联的删除,此删除只能删除没有启动的流程,否则抛出异常 .act_re_deployment,act_re_procdef 和 act_ge_bytearray 三张表中相关数据都删除 - repositoryService.deleteDeployment(deploymentId, true); //级联删除,不管流程是否启动,都可以删除 + repositoryService.deleteDeployment(deploymentId, true); //级联删除,不管流程是否启动,都可以删除 } + + /** + * 挂起与激活 + * + * @param procDefId + * @param status + */ public void suspend(String procDefId, int status) { if (1 == status) { repositoryService.activateProcessDefinitionById(procDefId, true, null); - }else{ + } else { repositoryService.suspendProcessDefinitionById(procDefId, true, null); } } diff --git a/src/main/java/cn/palmte/work/service/ActProcInsService.java b/src/main/java/cn/palmte/work/service/ActProcInsService.java index 0b02e0f..8363493 100644 --- a/src/main/java/cn/palmte/work/service/ActProcInsService.java +++ b/src/main/java/cn/palmte/work/service/ActProcInsService.java @@ -1,8 +1,9 @@ package cn.palmte.work.service; -import cn.palmte.work.config.activiti.ActConstant; -import cn.palmte.work.exception.ResponseException; + +import cn.palmte.work.model.ActTaskDefRepository; import cn.palmte.work.pojo.ActProcIns; +import cn.palmte.work.utils.ActUtil; import cn.palmte.work.utils.InterfaceUtil; import org.activiti.bpmn.model.BpmnModel; import org.activiti.bpmn.model.FlowNode; @@ -15,9 +16,7 @@ import org.activiti.engine.history.HistoricActivityInstance; import org.activiti.engine.history.HistoricProcessInstance; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.runtime.ProcessInstance; -import org.activiti.engine.task.IdentityLink; import org.activiti.engine.task.Task; -import org.activiti.image.ProcessDiagramGenerator; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,13 +24,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import top.jfunc.common.db.QueryHelper; import top.jfunc.common.db.bean.Page; -import top.jfunc.common.db.bean.Record; import top.jfunc.common.db.utils.Pagination; -import top.jfunc.common.utils.IoUtil; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import java.io.InputStream; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -54,12 +50,65 @@ public class ActProcInsService { Pagination pagination; @Autowired - private ActProcDefService actProcDefService; + private ActTaskDefService actTaskDefService; @Autowired private HistoryService historyService; //历史管理(执行完的数据的管理) + @Autowired + private ActTaskDefRepository actTaskDefRepository; + @Autowired + private ActUtil actUtil; + + + /** + * 启动流程实列 + * + * @param procDefKey + * @param variables + * @return + */ + public String startProcessInstance(String procDefKey, Map variables) throws Exception{ + List list = repositoryService.createProcessDefinitionQuery().processDefinitionKey(procDefKey).active().orderByProcessDefinitionVersion().desc().list(); + if (list == null || list.isEmpty()) { + throw new Exception("procDefKey(" + procDefKey + ")未定义"); + } + + //取最新版本的流程定义进行启动流程实列 + ProcessDefinition processDefinition = list.get(0); + + //启动流程 + ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId(), variables); + + String procInsId = processInstance.getProcessInstanceId(); + Task task = taskService.createTaskQuery().processInstanceId(procInsId).singleResult(); + if (task == null) { + throw new Exception("procDefKey(" + procDefKey + ")启动异常"); + } + + //设置发起人为办理人 然后完成任务 任务转入下一个审批节点 + String assignee = InterfaceUtil.getAdminId() + ""; + task.setAssignee(assignee); + String taskId = task.getId(); + taskService.addComment(taskId, procInsId, "提交审批"); + taskService.complete(taskId); + + actTaskDefRepository.updateHiTaskAssign(assignee, procInsId, taskId); + actTaskDefRepository.updateHiActAssign(assignee, procInsId, taskId); + + return processInstance.getId(); + } + + + /** + * 流程实列列表 + * + * @param searchInfo + * @param pageNumber + * @param pageSize + * @return + */ public Page list(ConcurrentHashMap searchInfo, int pageNumber, int pageSize) { String select = "select h.proc_inst_id_ as procInsId,h.proc_def_id_ as procDefId," + "h.start_time_ as startTime,h.end_time_ as endTime,p.key_ as procKey," + @@ -74,12 +123,8 @@ public class ActProcInsService { for (ActProcIns ins : list) { //查询流程发起人 - Record record = getVariable(ActConstant.START_PROCESS_USERID, ins.getProcInsId()); - if (record != null) { - String userId = getStartUserId(ins.getProcInsId()); - ins.setUser(accountService.getNameById(Integer.parseInt(userId))); - } - + String userId = actUtil.getStartUserId(ins.getProcInsId()); + ins.setUser(accountService.getNameById(Integer.parseInt(userId))); //查询当前任务审批人 String currentTaskId = ins.getCurrentTaskId(); @@ -87,56 +132,18 @@ public class ActProcInsService { String[] split = currentTaskId.split(","); String candidateUsers = ""; for (String taskId : split) { - List identityLinksForTask = taskService.getIdentityLinksForTask(taskId); - for (IdentityLink identityLink : identityLinksForTask) { - if ("assignee".equals(identityLink.getType()) || "candidate".equals(identityLink.getType())) { - String userId = identityLink.getUserId(); - if (StringUtils.isNotBlank(candidateUsers)) { - candidateUsers = candidateUsers + ","; - } - candidateUsers += accountService.getNameById(Integer.parseInt(userId)); - } - } + candidateUsers = actUtil.getAssigneeByIdentityLink(taskId); } ins.setCandidateUsers(candidateUsers); } } - return paginate; } - /** - * 获取流程实例里的变量 - * - * @param variableName - * @param procInsId - * @return - */ - public Record getVariable(String variableName, String procInsId) { - String sql = "select TEXT_ as text from ACT_HI_VARINST where NAME_=? and PROC_INST_ID_=?"; - return pagination.findFirst(sql, variableName, procInsId); - } - - - public String getStartUserId(String procInsId) { - Record record = getVariable(ActConstant.START_PROCESS_USERID, procInsId); - if (record != null) { - return record.getStr("text"); - } - return "0"; - } - - - public List getVariables(String procInsId) { - String sql = "select NAME_ as name, TEXT_ as text from ACT_HI_VARINST where PROC_INST_ID_=?"; - return pagination.find(sql, procInsId); - } - - public void deleteProcessInstance(String procInsId, String reason) { - runtimeService.deleteProcessInstance(procInsId, reason); //作废流程 + runtimeService.deleteProcessInstance(procInsId, reason); } @@ -184,10 +191,7 @@ public class ActProcInsService { } BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId()); // 获取bpmnModel List flowIds = this.getExecutedFlows(bpmnModel, newHisTaskInstanceList); // 获取流程已发生流转的线ID集合 - try (InputStream inputStream = actProcDefService.generateDiagramInputStream(bpmnModel, executedActivityIdList, flowIds)){ - IoUtil.copy(inputStream, response.getOutputStream()); - } - + actUtil.responsePng(response, bpmnModel, executedActivityIdList, flowIds); } catch (Exception e) { logger.error("an exception happens in try catch statement", e); } @@ -274,28 +278,4 @@ public class ActProcInsService { } return flowIdList; } - - public String startProcessInstance(String procDefKey, Map variables) { - List list = repositoryService.createProcessDefinitionQuery().processDefinitionKey(procDefKey).active().orderByProcessDefinitionVersion().desc().list(); - if (list == null || list.isEmpty()) { - throw new ResponseException("procDefKey:" + procDefKey + " 未定义"); - } - - //取最新版本的流程定义进行启动流程实列 - ProcessDefinition processDefinition = list.get(0); - - //启动流程 - ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId(), variables); - - Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).singleResult(); - if (task == null) { - throw new ResponseException("procDefKey:" + procDefKey + " 启动异常"); - } - - //设置发起人为办理人 然后完成任务 任务转入下一个审批节点 - task.setAssignee(InterfaceUtil.getAdminId() + ""); - taskService.complete(task.getId()); - return processInstance.getId(); - } - } diff --git a/src/main/java/cn/palmte/work/service/ActTaskDefService.java b/src/main/java/cn/palmte/work/service/ActTaskDefService.java index c645819..09a584c 100644 --- a/src/main/java/cn/palmte/work/service/ActTaskDefService.java +++ b/src/main/java/cn/palmte/work/service/ActTaskDefService.java @@ -1,13 +1,12 @@ package cn.palmte.work.service; import cn.palmte.work.config.activiti.ActConstant; -import cn.palmte.work.config.activiti.DeleteTaskCommand; -import cn.palmte.work.config.activiti.JumpCommand; + import cn.palmte.work.model.*; import cn.palmte.work.pojo.ActHisTask; +import cn.palmte.work.utils.ActUtil; import cn.palmte.work.utils.InterfaceUtil; import com.alibaba.fastjson.JSONObject; -import org.activiti.bpmn.model.FlowNode; import org.activiti.engine.*; import org.activiti.engine.task.IdentityLink; import org.activiti.engine.task.Task; @@ -15,19 +14,11 @@ import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.data.jpa.repository.Modifying; import org.springframework.stereotype.Service; import top.jfunc.common.db.QueryHelper; -import top.jfunc.common.db.bean.Record; import top.jfunc.common.db.utils.Pagination; -import javax.annotation.Resource; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; -import java.lang.reflect.Method; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; @Service @@ -38,107 +29,19 @@ public class ActTaskDefService { @Autowired private ProcessEngine processEngine; //流程引擎对象 @Autowired - private RuntimeService runtimeService; //与正在执行的流程实例和执行对象相关的Service(执行管理,包括启动、推进、删除流程实例等操作) - @Autowired private TaskService taskService; //任务管理 与正在执行的任务管理相关的Service - @Autowired private ActTaskDefRepository actTaskDefRepository; - @Autowired private AccountService accountService; - - @Autowired - private ActProcInsService actProcInsService; - - @Resource - private ApplicationContext applicationContext; - - @Autowired - private ActScriptRepository actScriptRepository; @Autowired Pagination pagination; - - public List findByProcDefId(String procDefId) { - List list = actTaskDefRepository.findByProcDefId(procDefId); - for (ActTaskDef actTaskDef : list) { - ids2List(actTaskDef); - } - return list; - } - - - public ActTaskDef findFirstByProcDefIdAndTaskKey(String procDefId, String taskKey) { - ActTaskDef def = actTaskDefRepository.findFirstByProcDefIdAndTaskKey(procDefId, taskKey); - ids2List(def); - return def; - } - - - public void saveConfig(ActTaskDef taskDef) { - ActTaskDef one = actTaskDefRepository.findOne(taskDef.getId()); - one.setCandidateUsers(taskDef.getCandidateUsers()); - one.setCandidateRoles(taskDef.getCandidateRoles()); - one.setRollbackTaskKey(taskDef.getRollbackTaskKey()); - one.setEndScript(taskDef.getEndScript()); - one.setRollbackScript(taskDef.getRollbackScript()); - one.setLastUpdatedTime(new Date()); - - actTaskDefRepository.save(one); - logger.info("saveTaskConfig uerId:{}, config:{}", InterfaceUtil.getAdminId(), JSONObject.toJSONString(one)); - } - - - private void ids2List(ActTaskDef actTaskDef) { - String candidateUsers = actTaskDef.getCandidateUsers(); - List userIdList = new ArrayList<>(); - if (StringUtils.isNotBlank(candidateUsers)) { - userIdList = Arrays.asList(candidateUsers.split("#")); - } - actTaskDef.setCandidateUserList(userIdList); - - String candidateRoles = actTaskDef.getCandidateRoles(); - List roleIdList = new ArrayList<>(); - if (StringUtils.isNotBlank(candidateRoles)) { - roleIdList = Arrays.asList(candidateRoles.split("#")); - } - actTaskDef.setCandidateRoleList(roleIdList); - } - - - public Set findCandidateUsers(String procDefId, String procInsId, String taskDefKey) { - ActTaskDef taskDef = findFirstByProcDefIdAndTaskKey(procDefId, taskDefKey); - if (taskDef.getTaskIndex() == ActConstant.TASK_INDEX_FIRST_USER_TASK) { - String startUserId = actProcInsService.getStartUserId(procInsId); - Set res = new HashSet<>(1); - logger.info("findCandidateUsers-0-task:{}, startUserId:{}", taskDef.getTaskName(), startUserId); - res.add(startUserId); - return res; - } - - List resList = new ArrayList<>(); - List candidateUserList = taskDef.getCandidateUserList(); - logger.info("findCandidateUsers-1-task:{}, userList:{}", taskDef.getTaskName(), candidateUserList); - if (!candidateUserList.isEmpty()) { - resList.addAll(candidateUserList); - } - - List candidateRoleList = taskDef.getCandidateRoleList(); - logger.info("findCandidateUsers-2-task:{}, roleList:{}", taskDef.getTaskName(), candidateRoleList); - List list = accountService.getUserIsByRole(candidateRoleList); - logger.info("findCandidateUsers-3-task:{}, userIdListByRole:{}", taskDef.getTaskName(), list); - if (!list.isEmpty()) { - resList.addAll(list); - } - - Set res = new HashSet<>(resList); - logger.info("findCandidateUsers-4-task:{}, resIds:{}", taskDef.getTaskName(), res); - return res; - } + @Autowired + private ActUtil actUtil; /** - * 处理任务 + * 审批任务 * * @param json */ @@ -165,7 +68,7 @@ public class ActTaskDefService { //执行配置的审批通过脚本 int endScript = actTaskDef.getEndScript(); if (endScript != 0) { - invokeEventScript(endScript, procInsId); + actUtil.invokeEventScript(endScript, procInsId); } else { logger.info("未配置审批通过脚本 task:{}", actTaskDef.getTaskName()); } @@ -173,12 +76,12 @@ public class ActTaskDefService { } else if (ActConstant.TYPE_ROLLBACK == type) { //驳回 String rollbackTaskKey = actTaskDef.getRollbackTaskKey(); - jumpToTargetTask(taskId, rollbackTaskKey); + actUtil.jumpToTargetTask(taskId, rollbackTaskKey); //执行配置的驳回脚本 int rollbackScript = actTaskDef.getRollbackScript(); if (rollbackScript != 0) { - invokeEventScript(rollbackScript, procInsId); + actUtil.invokeEventScript(rollbackScript, procInsId); } else { logger.info("未配置驳回脚本 task:{}", actTaskDef.getTaskName()); } @@ -186,110 +89,27 @@ public class ActTaskDefService { } - /** - * 反射执行脚本 + * 审批过程任务查询 * - * @param scriptId - * @param procInsId + * @param procIncId + * @return */ - private void invokeEventScript(int scriptId, String procInsId) { - ActScript actScript = actScriptRepository.findOne(scriptId); - if (actScript == null) { - logger.info("脚本配置错误"); - return; - } - - Map map = new HashMap<>(); - map.put(ActConstant.PROC_INS_ID, procInsId); - List variables = actProcInsService.getVariables(procInsId); - for (Record variable : variables) { - map.put(variable.getStr("name"), variable.get("text")); - } - - //调用方法传递的参数 - Object[] args = new Object[1]; - args[0] = map; - - logger.info("invokeEventScript class:{}, methond:{}, param:{}", actScript.getClassName(), actScript.getClassMethod(), map); - try { - Class ownerClass = Class.forName(actScript.getClassName()); - Object bean = applicationContext.getBean(ownerClass); - Class[] paramsType = new Class[1]; - paramsType[0] = Class.forName("java.util.Map"); - //找到脚本方法对应的方法 注意:有且只有一个以Map为参数的方法 - Method method = ownerClass.getDeclaredMethod(actScript.getClassMethod(), paramsType); - method.invoke(bean, args); - } catch (Exception e) { - logger.error("", e); - } - - } - - /** - * 跳转到指定任务节点 - * - * @param currentTaskId 当前任务id - * @param targetTaskDefKey 跳转目的任务key - */ - public void jumpToTargetTask(String currentTaskId, String targetTaskDefKey) { - Task currentTask = taskService.createTaskQuery().taskId(currentTaskId).singleResult(); - // 获取流程定义 - org.activiti.bpmn.model.Process process = repositoryService.getBpmnModel(currentTask.getProcessDefinitionId()).getMainProcess(); - //获取目标节点定义 - FlowNode targetNode = (FlowNode) process.getFlowElement(targetTaskDefKey); - - ManagementService managementService = processEngine.getManagementService(); - //删除当前运行任务 - String executionEntityId = managementService.executeCommand(new DeleteTaskCommand(currentTask.getId())); - //流程执行到来源节点 - managementService.executeCommand(new JumpCommand(targetNode, executionEntityId)); - - Task singleResult = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).singleResult(); - singleResult.setParentTaskId(currentTask.getTaskDefinitionKey()); - taskService.saveTask(singleResult); - } - - public List hisTaskList(String procIncId) { - String select = "select ht.ID_ as hisInstanceId, ht.PROC_DEF_ID_ as procDefinitionId, ht.PROC_INST_ID_ as procInstanceId, ht.EXECUTION_ID_ as executionId," + - " ht.ACT_ID_ as actId, ht.TASK_ID_ as taskId, ht.CALL_PROC_INST_ID_ as callProcInstanceId, ht.ACT_NAME_ as actName, " + - "ht.ACT_TYPE_ as actType, ht.ASSIGNEE_ as assignee, ht.START_TIME_ as startTime, ht.END_TIME_ as endTime, " + - "ht.DURATION_ as duration, ht.DELETE_REASON_ as deleteReason, ht.TENANT_ID_ as tenantId, hc.MESSAGE_ AS comments"; - QueryHelper queryHelper = new QueryHelper(select, " ACT_HI_ACTINST ht " + - " LEFT JOIN ACT_HI_COMMENT hc on ht.TASK_ID_ = hc.TASK_ID_ and hc.type_='comment' "); - queryHelper.addCondition("ht.TASK_ID_ is not null"); + String select = "select ht.PROC_DEF_ID_ as procDefId, ht.PROC_INST_ID_ as procInsId, ht.EXECUTION_ID_ as executionId," + + " ht.ID_ as taskId, ht.NAME_ as taskName, " + + " ht.ASSIGNEE_ as assign, ht.START_TIME_ as startTime, ht.END_TIME_ as endTime, " + + "ht.DURATION_ as duration, ht.DELETE_REASON_ as deleteReason, hc.MESSAGE_ AS comments"; + QueryHelper queryHelper = new QueryHelper(select, " ACT_HI_TASKINST ht " + + " LEFT JOIN ACT_HI_COMMENT hc on ht.ID_ = hc.TASK_ID_ and hc.type_='comment' "); queryHelper.addCondition("ht.PROC_INST_ID_ =?", procIncId); queryHelper.addOrderProperty("ht.start_time_", true); List taskList = pagination.find(queryHelper.getSql(), ActHisTask.class); for (ActHisTask actHisTask : taskList) { - if (StringUtils.isBlank(actHisTask.getAssign())) { - Task task = taskService.createTaskQuery().taskId(actHisTask.getTaskId()).singleResult(); - if (task != null) { - if (StringUtils.isNotBlank(task.getAssignee())) { - actHisTask.setAssign(task.getAssignee()); - } else { - List identityLinkList = taskService.getIdentityLinksForTask(task.getId()); - if (identityLinkList != null && !identityLinkList.isEmpty()) { - String name = ""; - for (IdentityLink identityLink : identityLinkList) { - if ("assignee".equals(identityLink.getType()) || "candidate".equals(identityLink.getType())) { - String assigneeUserId = identityLink.getUserId(); - if (StringUtils.isNotBlank(name)) { - name = name + ","; - } - name += accountService.getNameById(Integer.parseInt(assigneeUserId)); - } - } - actHisTask.setAssign(name); - } - } - } - } + setAssign(actHisTask); + //办理用时 String duration = actHisTask.getDuration(); - /*Date startTime = actHisTask.getStartTime(); - Date endTime = actHisTask.getEndTime();*/ if (StringUtils.isNotBlank(duration)) { Long ztime = Long.parseLong(duration); Long day = ztime / (1000 * 60 * 60 * 24); @@ -300,8 +120,154 @@ public class ActTaskDefService { } else { actHisTask.setDuration("正在处理。。。"); } + + if (StringUtils.isNotBlank(actHisTask.getDeleteReason())) { + actHisTask.setComments("【驳回】" + actHisTask.getComments()); + } } return taskList; } + + + /** + * 根据流程定义查询任务 + * + * @param procDefId + * @return + */ + public List findByProcDefId(String procDefId) { + List list = actTaskDefRepository.findByProcDefId(procDefId); + for (ActTaskDef actTaskDef : list) { + candidatesHandle(actTaskDef); + } + return list; + } + + + /** + * 根据流程定义和任务key查询任务 + * + * @param procDefId + * @param taskKey + * @return + */ + public ActTaskDef findFirstByProcDefIdAndTaskKey(String procDefId, String taskKey) { + ActTaskDef def = actTaskDefRepository.findFirstByProcDefIdAndTaskKey(procDefId, taskKey); + candidatesHandle(def); + return def; + } + + + /** + * 保存任务配置 + * + * @param taskDef + */ + public void saveConfig(ActTaskDef taskDef) { + ActTaskDef one = actTaskDefRepository.findOne(taskDef.getId()); + one.setCandidateUsers(taskDef.getCandidateUsers()); + one.setCandidateRoles(taskDef.getCandidateRoles()); + one.setRollbackTaskKey(taskDef.getRollbackTaskKey()); + one.setEndScript(taskDef.getEndScript()); + one.setRollbackScript(taskDef.getRollbackScript()); + one.setLastUpdatedTime(new Date()); + + actTaskDefRepository.save(one); + logger.info("saveTaskConfig uerId:{}, config:{}", InterfaceUtil.getAdminId(), JSONObject.toJSONString(one)); + } + + + /** + * 查找任务配置的审批人 + * + * @param procDefId + * @param procInsId + * @param taskDefKey + * @return + */ + public Set findCandidateUsers(String procDefId, String procInsId, String taskDefKey) { + ActTaskDef taskDef = findFirstByProcDefIdAndTaskKey(procDefId, taskDefKey); + if (taskDef.getTaskIndex() == ActConstant.TASK_INDEX_FIRST_USER_TASK) { + //任务驳回到发起节点 审批人设置为发起人 + String startUserId = actUtil.getStartUserId(procInsId); + Set res = new HashSet<>(1); + logger.info("findCandidateUsers-0-task:{}, startUserId:{}", taskDef.getTaskName(), startUserId); + res.add(startUserId); + return res; + } + + List resList = new ArrayList<>(); + + //通过人员id查询 + List candidateUserList = taskDef.getCandidateUserList(); + logger.info("findCandidateUsers-1-task:{}, userList:{}", taskDef.getTaskName(), candidateUserList); + if (!candidateUserList.isEmpty()) { + resList.addAll(candidateUserList); + } + + //通过角色id查询 + List candidateRoleList = taskDef.getCandidateRoleList(); + logger.info("findCandidateUsers-2-task:{}, roleList:{}", taskDef.getTaskName(), candidateRoleList); + List list = accountService.getUserIsByRole(candidateRoleList); + logger.info("findCandidateUsers-3-task:{}, userIdListByRole:{}", taskDef.getTaskName(), list); + if (!list.isEmpty()) { + resList.addAll(list); + } + + //去重 + Set res = new HashSet<>(resList); + logger.info("findCandidateUsers-4-task:{}, resIds:{}", taskDef.getTaskName(), res); + return res; + } + + + /** + * 任务审批人列表从sring转成list + * + * @param actTaskDef + */ + private void candidatesHandle(ActTaskDef actTaskDef) { + String candidateUsers = actTaskDef.getCandidateUsers(); + List userIdList = new ArrayList<>(); + if (StringUtils.isNotBlank(candidateUsers)) { + userIdList = Arrays.asList(candidateUsers.split("#")); + } + actTaskDef.setCandidateUserList(userIdList); + + String candidateRoles = actTaskDef.getCandidateRoles(); + List roleIdList = new ArrayList<>(); + if (StringUtils.isNotBlank(candidateRoles)) { + roleIdList = Arrays.asList(candidateRoles.split("#")); + } + actTaskDef.setCandidateRoleList(roleIdList); + } + + + /** + * 设置历史任务审批人 + * + * @param actHisTask + */ + private void setAssign(ActHisTask actHisTask) { + if (StringUtils.isNotBlank(actHisTask.getAssign())) { + String userName = accountService.getNameById(Integer.parseInt(actHisTask.getAssign())); + actHisTask.setAssign(userName); + return; + } + + Task task = taskService.createTaskQuery().taskId(actHisTask.getTaskId()).singleResult(); + if (task == null) { + return; + } + + if (StringUtils.isNotBlank(task.getAssignee())) { + actHisTask.setAssign(task.getAssignee()); + return; + } + + actHisTask.setAssign(actUtil.getAssigneeByIdentityLink(task.getId())); + } + + } diff --git a/src/main/java/cn/palmte/work/utils/ActUtil.java b/src/main/java/cn/palmte/work/utils/ActUtil.java new file mode 100644 index 0000000..0a9e6b2 --- /dev/null +++ b/src/main/java/cn/palmte/work/utils/ActUtil.java @@ -0,0 +1,250 @@ +package cn.palmte.work.utils; + +import cn.palmte.work.config.activiti.ActConstant; +import cn.palmte.work.config.activiti.DeleteTaskCommand; +import cn.palmte.work.config.activiti.JumpCommand; +import cn.palmte.work.model.ActScript; +import cn.palmte.work.model.ActScriptRepository; +import cn.palmte.work.service.AccountService; +import org.activiti.bpmn.model.BpmnModel; +import org.activiti.bpmn.model.FlowNode; +import org.activiti.engine.ManagementService; +import org.activiti.engine.ProcessEngine; +import org.activiti.engine.RepositoryService; +import org.activiti.engine.TaskService; +import org.activiti.engine.task.IdentityLink; +import org.activiti.engine.task.Task; +import org.activiti.image.ProcessDiagramGenerator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; +import top.jfunc.common.db.bean.Record; +import top.jfunc.common.db.utils.Pagination; +import top.jfunc.common.utils.IoUtil; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class ActUtil { + private static final Logger logger = LoggerFactory.getLogger(ActUtil.class); + @Autowired + private ProcessEngine processEngine; + @Autowired + private RepositoryService repositoryService; + @Autowired + Pagination pagination; + @Autowired + private ActScriptRepository actScriptRepository; + @Resource + private ApplicationContext applicationContext; + @Autowired + private TaskService taskService; + @Autowired + private AccountService accountService; + + + /** + * 获取流程实例里的变量 + * + * @param variableName + * @param procInsId + * @return + */ + public Record getVariable(String variableName, String procInsId) { + String sql = "select TEXT_ as text from ACT_HI_VARINST where NAME_=? and PROC_INST_ID_=?"; + return pagination.findFirst(sql, variableName, procInsId); + } + + + public String getStartUserId(String procInsId) { + Record record = getVariable(ActConstant.START_PROCESS_USERID, procInsId); + if (record != null) { + return record.getStr("text"); + } + return "0"; + } + + + /** + * 获取流程实列里的所有变量 + * + * @param procInsId + * @return + */ + public List getVariables(String procInsId) { + String sql = "select NAME_ as name, TEXT_ as text from ACT_HI_VARINST where PROC_INST_ID_=?"; + return pagination.find(sql, procInsId); + } + + + /** + * 反射执行脚本 + * + * @param scriptId + * @param procInsId + */ + public void invokeEventScript(int scriptId, String procInsId) { + ActScript actScript = actScriptRepository.findOne(scriptId); + if (actScript == null) { + logger.info("脚本配置错误"); + return; + } + + Map map = new HashMap<>(); + map.put(ActConstant.PROC_INS_ID, procInsId); + List variables = getVariables(procInsId); + for (Record variable : variables) { + map.put(variable.getStr("name"), variable.get("text")); + } + + //调用方法传递的参数 + Object[] args = new Object[1]; + args[0] = map; + + logger.info("invokeEventScript class:{}, methond:{}, param:{}", actScript.getClassName(), actScript.getClassMethod(), map); + try { + Class ownerClass = Class.forName(actScript.getClassName()); + Object bean = applicationContext.getBean(ownerClass); + Class[] paramsType = new Class[1]; + paramsType[0] = Class.forName("java.util.Map"); + //找到脚本方法对应的方法 注意:有且只有一个以Map为参数的方法 + Method method = ownerClass.getDeclaredMethod(actScript.getClassMethod(), paramsType); + method.invoke(bean, args); + } catch (Exception e) { + logger.error("", e); + } + + } + + + /** + * 跳转到指定任务节点 + * + * @param currentTaskId 当前任务id + * @param targetTaskDefKey 跳转目的任务key + */ + public void jumpToTargetTask(String currentTaskId, String targetTaskDefKey) { + Task currentTask = taskService.createTaskQuery().taskId(currentTaskId).singleResult(); + // 获取流程定义 + org.activiti.bpmn.model.Process process = repositoryService.getBpmnModel(currentTask.getProcessDefinitionId()).getMainProcess(); + //获取目标节点定义 + FlowNode targetNode = (FlowNode) process.getFlowElement(targetTaskDefKey); + + ManagementService managementService = processEngine.getManagementService(); + //删除当前运行任务 + String executionEntityId = managementService.executeCommand(new DeleteTaskCommand(currentTask.getId())); + //流程执行到来源节点 + managementService.executeCommand(new JumpCommand(targetNode, executionEntityId)); + + Task singleResult = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).singleResult(); + singleResult.setParentTaskId(currentTask.getTaskDefinitionKey()); + taskService.saveTask(singleResult); + } + + /** + * 响应图片 + * + * @param response + * @param bpmnModel + * @param executedActivityIdList + * @param flowIds + * @throws IOException + */ + public void responsePng(HttpServletResponse response, BpmnModel bpmnModel, List executedActivityIdList, List flowIds) throws IOException { + try (InputStream inputStream = generateDiagramInputStream(bpmnModel, executedActivityIdList, flowIds)) { + IoUtil.copy(inputStream, response.getOutputStream()); + } + } + + + /** + * 查看流程xml + * + * @param response + * @param deploymentId + * @throws IOException + */ + public void responseXml(HttpServletResponse response, String deploymentId) throws IOException { + try (InputStream inputStream = getXmlStreamByDeploymentId(deploymentId)) { + IoUtil.copy(inputStream, response.getOutputStream()); + } + } + + + /** + * 查询任务审批人 + * + * @param taskId + * @return + */ + public String getAssigneeByIdentityLink(String taskId) { + List identityLinkList = taskService.getIdentityLinksForTask(taskId); + if (identityLinkList == null || identityLinkList.isEmpty()) { + return ""; + } + + StringBuilder namesBuilder = new StringBuilder(); + for (IdentityLink identityLink : identityLinkList) { + if ("assignee".equals(identityLink.getType()) || "candidate".equals(identityLink.getType())) { + String assigneeUserId = identityLink.getUserId(); + namesBuilder.append(accountService.getNameById(Integer.parseInt(assigneeUserId))); + namesBuilder.append(","); + } + } + String names = namesBuilder.toString(); + if (names.endsWith(",")) { + names = names.substring(0, names.length() - 1); + } + return names; + } + + + + /** + * 生成xml流 + * + * @param deploymentId + * @return + * @throws IOException + */ + private InputStream getXmlStreamByDeploymentId(String deploymentId) throws IOException { + List names = repositoryService.getDeploymentResourceNames(deploymentId); + for (String name : names) { + if (name.contains("xml")) { + return repositoryService.getResourceAsStream(deploymentId, name); + } + } + return null; + } + + + /** + * 生成流程图片流 + * + * @param bpmnModel + * @param executedActivityIdList + * @param flowIds + * @return + */ + private InputStream generateDiagramInputStream(BpmnModel bpmnModel, List executedActivityIdList, List flowIds) { + try { + ProcessDiagramGenerator processDiagramGenerator = processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator(); + return processDiagramGenerator.generateDiagram(bpmnModel, "png", executedActivityIdList, + flowIds, "宋体", "微软雅黑", "黑体", null, 2.0); //使用默认配置获得流程图表生成器,并生成追踪图片字符流 + } catch (Exception e) { + logger.error("an exception happens in try catch statement", e); + return null; + } + } + + +} diff --git a/src/main/resources/templates/admin/act_his_task_list.ftl b/src/main/resources/templates/admin/act_his_task_list.ftl index 3253c5f..0bd4ea6 100644 --- a/src/main/resources/templates/admin/act_his_task_list.ftl +++ b/src/main/resources/templates/admin/act_his_task_list.ftl @@ -18,11 +18,11 @@ 序号 任务节点 - 办理人 - 审批开始时间 - 审批结束时间 + 处理人 + 开始时间 + 结束时间 用时 - 审批意见 + 意见 @@ -30,7 +30,7 @@ <#list taskList as list> ${list_index+1!} - ${list.actName!} + ${list.taskName!} ${list.assign!} ${list.startTime?datetime} <#if list.endTime??> diff --git a/src/main/resources/templates/admin/act_proc_def_list.ftl b/src/main/resources/templates/admin/act_proc_def_list.ftl index 49510ba..15fc261 100644 --- a/src/main/resources/templates/admin/act_proc_def_list.ftl +++ b/src/main/resources/templates/admin/act_proc_def_list.ftl @@ -6,7 +6,7 @@
工作流程 / - 流程定义管理 + 流程定义
diff --git a/src/main/resources/templates/admin/act_proc_ins_list.ftl b/src/main/resources/templates/admin/act_proc_ins_list.ftl index 2cd9e71..f4b9afc 100644 --- a/src/main/resources/templates/admin/act_proc_ins_list.ftl +++ b/src/main/resources/templates/admin/act_proc_ins_list.ftl @@ -63,21 +63,21 @@ 驳回 - - - - + + + + diff --git a/src/main/resources/templates/admin/act_script_list.ftl b/src/main/resources/templates/admin/act_script_list.ftl index 89d299e..0c4a424 100644 --- a/src/main/resources/templates/admin/act_script_list.ftl +++ b/src/main/resources/templates/admin/act_script_list.ftl @@ -6,7 +6,7 @@
工作流程 / - 模型管理 + 脚本管理