2021-11-09 07:26:08 +00:00
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 ;
2021-11-09 10:45:12 +00:00
import cn.palmte.work.model.* ;
import cn.palmte.work.pojo.ActHisTask ;
2021-11-09 07:26:08 +00:00
import cn.palmte.work.utils.InterfaceUtil ;
import com.alibaba.fastjson.JSONObject ;
import org.activiti.bpmn.model.FlowNode ;
import org.activiti.engine.* ;
2021-11-09 10:45:12 +00:00
import org.activiti.engine.task.IdentityLink ;
2021-11-09 07:26:08 +00:00
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 ;
2021-11-09 10:45:12 +00:00
import org.springframework.data.jpa.repository.Modifying ;
2021-11-09 07:26:08 +00:00
import org.springframework.stereotype.Service ;
2021-11-09 10:45:12 +00:00
import top.jfunc.common.db.QueryHelper ;
2021-11-09 07:26:08 +00:00
import top.jfunc.common.db.bean.Record ;
2021-11-09 10:45:12 +00:00
import top.jfunc.common.db.utils.Pagination ;
2021-11-09 07:26:08 +00:00
import javax.annotation.Resource ;
2021-11-09 10:45:12 +00:00
import javax.persistence.EntityManager ;
import javax.transaction.Transactional ;
2021-11-09 07:26:08 +00:00
import java.lang.reflect.Method ;
import java.util.* ;
2021-11-09 10:45:12 +00:00
import java.util.concurrent.ConcurrentHashMap ;
2021-11-09 07:26:08 +00:00
@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 ;
2021-11-09 10:45:12 +00:00
@Autowired
Pagination pagination ;
2021-11-09 07:26:08 +00:00
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 ;
}
/ * *
* 处 理 任 务
2021-11-09 10:45:12 +00:00
*
2021-11-09 07:26:08 +00:00
* @param json
* /
public void completeTask ( JSONObject json ) {
String taskId = json . getString ( "taskId" ) ;
2021-11-09 10:45:12 +00:00
String procInsId = json . getString ( "procInsId" ) ;
2021-11-09 07:26:08 +00:00
String message = json . getString ( "message" ) ;
int type = json . getInteger ( "type" ) ;
2021-11-09 10:45:12 +00:00
String userId = InterfaceUtil . getAdminId ( ) + "" ;
taskService . addComment ( taskId , procInsId , message ) ;
actTaskDefRepository . updateHiTaskAssign ( userId , procInsId , taskId ) ;
actTaskDefRepository . updateHiActAssign ( userId , procInsId , taskId ) ;
2021-11-09 07:26:08 +00:00
Task currentTask = taskService . createTaskQuery ( ) . taskId ( taskId ) . singleResult ( ) ;
ActTaskDef actTaskDef = findFirstByProcDefIdAndTaskKey ( currentTask . getProcessDefinitionId ( ) , currentTask . getTaskDefinitionKey ( ) ) ;
if ( ActConstant . TYPE_APPROVE = = type ) {
2021-11-09 10:45:12 +00:00
taskService . setAssignee ( taskId , userId ) ;
2021-11-09 07:26:08 +00:00
//审批通过
taskService . complete ( taskId ) ;
//执行配置的审批通过脚本
int endScript = actTaskDef . getEndScript ( ) ;
if ( endScript ! = 0 ) {
2021-11-09 10:45:12 +00:00
invokeEventScript ( endScript , procInsId ) ;
2021-11-09 07:26:08 +00:00
} 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 ) {
2021-11-09 10:45:12 +00:00
invokeEventScript ( rollbackScript , procInsId ) ;
2021-11-09 07:26:08 +00:00
} else {
logger . info ( "未配置驳回脚本 task:{}" , actTaskDef . getTaskName ( ) ) ;
}
}
}
2021-11-09 10:45:12 +00:00
2021-11-09 07:26:08 +00:00
/ * *
* 反 射 执 行 脚 本
*
* @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 ) ;
}
2021-11-09 10:45:12 +00:00
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 ;
}
2021-11-09 07:26:08 +00:00
}