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.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; 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 public class ActTaskDefService { private static final Logger logger = LoggerFactory.getLogger(ActTaskDefService.class); @Autowired private RepositoryService repositoryService; //管理流程定义 与流程定义和部署对象相关的Service @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; } /** * 处理任务 * * @param json */ public void completeTask(JSONObject json) { String taskId = json.getString("taskId"); String procInsId = json.getString("procInsId"); String message = json.getString("message"); int type = json.getInteger("type"); String userId = InterfaceUtil.getAdminId() + ""; taskService.addComment(taskId, procInsId, message); actTaskDefRepository.updateHiTaskAssign(userId, procInsId, taskId); actTaskDefRepository.updateHiActAssign(userId, procInsId, taskId); Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult(); ActTaskDef actTaskDef = findFirstByProcDefIdAndTaskKey(currentTask.getProcessDefinitionId(), currentTask.getTaskDefinitionKey()); if (ActConstant.TYPE_APPROVE == type) { taskService.setAssignee(taskId, userId); //审批通过 taskService.complete(taskId); //执行配置的审批通过脚本 int endScript = actTaskDef.getEndScript(); if (endScript != 0) { invokeEventScript(endScript, procInsId); } else { logger.info("未配置审批通过脚本 task:{}", actTaskDef.getTaskName()); } } else if (ActConstant.TYPE_ROLLBACK == type) { //驳回 String rollbackTaskKey = actTaskDef.getRollbackTaskKey(); jumpToTargetTask(taskId, rollbackTaskKey); //执行配置的驳回脚本 int rollbackScript = actTaskDef.getRollbackScript(); if (rollbackScript != 0) { invokeEventScript(rollbackScript, procInsId); } else { logger.info("未配置驳回脚本 task:{}", actTaskDef.getTaskName()); } } } /** * 反射执行脚本 * * @param scriptId * @param procInsId */ 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"); 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); } } } } 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); Long hour = (ztime % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60); Long minute = (ztime % (1000 * 60 * 60 * 24)) % (1000 * 60 * 60) / (1000 * 60); Long second = (ztime % (1000 * 60 * 60 * 24)) % (1000 * 60 * 60) % (1000 * 60) / 1000; actHisTask.setDuration(day + "天" + hour + "时" + minute + "分" + second + "秒"); } else { actHisTask.setDuration("正在处理。。。"); } } return taskList; } }