308 lines
13 KiB
Java
308 lines
13 KiB
Java
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<ActTaskDef> findByProcDefId(String procDefId) {
|
||
List<ActTaskDef> 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<String> userIdList = new ArrayList<>();
|
||
if (StringUtils.isNotBlank(candidateUsers)) {
|
||
userIdList = Arrays.asList(candidateUsers.split("#"));
|
||
}
|
||
actTaskDef.setCandidateUserList(userIdList);
|
||
|
||
String candidateRoles = actTaskDef.getCandidateRoles();
|
||
List<String> roleIdList = new ArrayList<>();
|
||
if (StringUtils.isNotBlank(candidateRoles)) {
|
||
roleIdList = Arrays.asList(candidateRoles.split("#"));
|
||
}
|
||
actTaskDef.setCandidateRoleList(roleIdList);
|
||
}
|
||
|
||
|
||
public Set<String> 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<String> res = new HashSet<>(1);
|
||
logger.info("findCandidateUsers-0-task:{}, startUserId:{}", taskDef.getTaskName(), startUserId);
|
||
res.add(startUserId);
|
||
return res;
|
||
}
|
||
|
||
List<String> resList = new ArrayList<>();
|
||
List<String> candidateUserList = taskDef.getCandidateUserList();
|
||
logger.info("findCandidateUsers-1-task:{}, userList:{}", taskDef.getTaskName(), candidateUserList);
|
||
if (!candidateUserList.isEmpty()) {
|
||
resList.addAll(candidateUserList);
|
||
}
|
||
|
||
List<String> candidateRoleList = taskDef.getCandidateRoleList();
|
||
logger.info("findCandidateUsers-2-task:{}, roleList:{}", taskDef.getTaskName(), candidateRoleList);
|
||
List<String> list = accountService.getUserIsByRole(candidateRoleList);
|
||
logger.info("findCandidateUsers-3-task:{}, userIdListByRole:{}", taskDef.getTaskName(), list);
|
||
if (!list.isEmpty()) {
|
||
resList.addAll(list);
|
||
}
|
||
|
||
Set<String> 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<String, Object> map = new HashMap<>();
|
||
map.put(ActConstant.PROC_INS_ID, procInsId);
|
||
List<Record> 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<ActHisTask> 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<ActHisTask> 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<IdentityLink> 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;
|
||
}
|
||
}
|