|
|
@@ -82,7 +82,14 @@ import java.lang.reflect.Field;
|
|
|
import java.lang.reflect.Method;
|
|
|
|
|
|
/**
|
|
|
- * 流程定义相关Service
|
|
|
+ * 流程任务相关Service
|
|
|
+ *
|
|
|
+ * 【冷热数据分离说明】
|
|
|
+ * 历史数据采用冷热分离方案,解决历史表数据量过大导致OOM的问题:
|
|
|
+ * - 热表:act_hi_procinst / act_hi_actinst / act_hi_varinst 等(Flowable原生表,保留近6个月数据)
|
|
|
+ * - 冷表:act_hi_procinst_archive / act_hi_actinst_archive / act_hi_varinst_archive 等(归档表,存储老数据)
|
|
|
+ * - 查询逻辑:优先查热表(Flowable API),热表无数据时回查冷表(flowArchiveService)
|
|
|
+ * - 数据迁移:通过存储过程 sp_flow_archive 定时将3个月前的已结束流程迁移到归档表
|
|
|
*
|
|
|
* @author jeeplus
|
|
|
* @version 2021-09-03
|
|
|
@@ -122,6 +129,9 @@ public class FlowTaskService {
|
|
|
private DiscoveryClient discoveryClient;
|
|
|
@Autowired
|
|
|
private RestTemplate restTemplate;
|
|
|
+ /** 归档数据查询服务,用于冷表回查(热表无数据时从 act_hi_*_archive 归档表查询) */
|
|
|
+ @Autowired
|
|
|
+ private FlowArchiveService flowArchiveService;
|
|
|
|
|
|
private static final ConcurrentMap<String, Map<String, Object>> BATCH_AUDIT_JOBS = new ConcurrentHashMap<>();
|
|
|
|
|
|
@@ -144,6 +154,8 @@ public class FlowTaskService {
|
|
|
/**
|
|
|
* 获取流转历史任务列表
|
|
|
*
|
|
|
+ * 支持冷表回查:热表无数据时从归档表查询活动实例,归档模式使用 queryTaskStateArchive
|
|
|
+ *
|
|
|
* @param procInsId 流程实例
|
|
|
*/
|
|
|
public Map historicTaskList2(String procInsId) throws Exception {
|
|
|
@@ -151,6 +163,12 @@ public class FlowTaskService {
|
|
|
List<HistoricActivityInstance> list = Lists.newArrayList ();
|
|
|
List<HistoricActivityInstance> historicActivityInstances2 = historyService.createHistoricActivityInstanceQuery ().processInstanceId (procInsId)
|
|
|
.orderByHistoricActivityInstanceStartTime ().asc ().orderByHistoricActivityInstanceEndTime ().asc ().list ();
|
|
|
+ // 冷表回查:热表无数据时从归档表查询活动实例
|
|
|
+ boolean isArchive = false;
|
|
|
+ if ( historicActivityInstances2.isEmpty ( ) ) {
|
|
|
+ historicActivityInstances2 = flowArchiveService.findActivityInstances ( procInsId );
|
|
|
+ isArchive = !historicActivityInstances2.isEmpty ( );
|
|
|
+ }
|
|
|
for (HistoricActivityInstance historicActivityInstance : historicActivityInstances2) {
|
|
|
if (historicActivityInstance.getEndTime () != null) {
|
|
|
list.add (historicActivityInstance);
|
|
|
@@ -165,16 +183,25 @@ public class FlowTaskService {
|
|
|
|
|
|
for (int i = 0; i < list.size (); i++) {
|
|
|
HistoricActivityInstance histIns = list.get (i);
|
|
|
- // 只显示开始节点和结束节点,并且执行人不为空的任务
|
|
|
- if (StrUtil.isNotBlank (histIns.getAssignee ())
|
|
|
- && historyService.createHistoricTaskInstanceQuery ().taskId (histIns.getTaskId ()).count () != 0
|
|
|
- || BpmnXMLConstants.ELEMENT_TASK_USER.equals (histIns.getActivityType ()) && histIns.getEndTime () == null
|
|
|
- || BpmnXMLConstants.ELEMENT_EVENT_START.equals (histIns.getActivityType ())
|
|
|
- || BpmnXMLConstants.ELEMENT_EVENT_END.equals (histIns.getActivityType ())) {
|
|
|
- // 获取流程发起人名称
|
|
|
- Flow e = queryTaskState (histIns);
|
|
|
-
|
|
|
- actList.add (e);
|
|
|
+ if ( isArchive ) {
|
|
|
+ if (StrUtil.isNotBlank (histIns.getAssignee ())
|
|
|
+ || BpmnXMLConstants.ELEMENT_TASK_USER.equals (histIns.getActivityType ()) && histIns.getEndTime () == null
|
|
|
+ || BpmnXMLConstants.ELEMENT_EVENT_START.equals (histIns.getActivityType ())
|
|
|
+ || BpmnXMLConstants.ELEMENT_EVENT_END.equals (histIns.getActivityType ())) {
|
|
|
+ Flow e = queryTaskStateArchive (histIns);
|
|
|
+ actList.add (e);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 只显示开始节点和结束节点,并且执行人不为空的任务
|
|
|
+ if (StrUtil.isNotBlank (histIns.getAssignee ())
|
|
|
+ && historyService.createHistoricTaskInstanceQuery ().taskId (histIns.getTaskId ()).count () != 0
|
|
|
+ || BpmnXMLConstants.ELEMENT_TASK_USER.equals (histIns.getActivityType ()) && histIns.getEndTime () == null
|
|
|
+ || BpmnXMLConstants.ELEMENT_EVENT_START.equals (histIns.getActivityType ())
|
|
|
+ || BpmnXMLConstants.ELEMENT_EVENT_END.equals (histIns.getActivityType ())) {
|
|
|
+ // 获取流程发起人名称
|
|
|
+ Flow e = queryTaskState (histIns);
|
|
|
+ actList.add (e);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
|
|
|
@@ -251,6 +278,8 @@ public class FlowTaskService {
|
|
|
/**
|
|
|
* 获取流转历史任务列表
|
|
|
*
|
|
|
+ * 支持冷表回查:热表无数据时从归档表查询活动实例,归档模式使用 queryTaskStateArchive
|
|
|
+ *
|
|
|
* @param procInsId 流程实例
|
|
|
*/
|
|
|
public Map historicTaskList3(String procInsId) throws Exception {
|
|
|
@@ -258,6 +287,12 @@ public class FlowTaskService {
|
|
|
List<HistoricActivityInstance> list = Lists.newArrayList ();
|
|
|
List<HistoricActivityInstance> historicActivityInstances2 = historyService.createHistoricActivityInstanceQuery ().processInstanceId (procInsId)
|
|
|
.orderByHistoricActivityInstanceStartTime ().asc ().orderByHistoricActivityInstanceEndTime ().asc ().list ();
|
|
|
+ // 冷表回查:热表无数据时从归档表查询活动实例
|
|
|
+ boolean isArchive = false;
|
|
|
+ if ( historicActivityInstances2.isEmpty ( ) ) {
|
|
|
+ historicActivityInstances2 = flowArchiveService.findActivityInstances ( procInsId );
|
|
|
+ isArchive = !historicActivityInstances2.isEmpty ( );
|
|
|
+ }
|
|
|
for (HistoricActivityInstance historicActivityInstance : historicActivityInstances2) {
|
|
|
if (historicActivityInstance.getEndTime () != null) {
|
|
|
list.add (historicActivityInstance);
|
|
|
@@ -272,16 +307,25 @@ public class FlowTaskService {
|
|
|
|
|
|
for (int i = 0; i < list.size (); i++) {
|
|
|
HistoricActivityInstance histIns = list.get (i);
|
|
|
- // 只显示开始节点和结束节点,并且执行人不为空的任务
|
|
|
- if (StrUtil.isNotBlank (histIns.getAssignee ())
|
|
|
- && historyService.createHistoricTaskInstanceQuery ().taskId (histIns.getTaskId ()).count () != 0
|
|
|
- || BpmnXMLConstants.ELEMENT_TASK_USER.equals (histIns.getActivityType ()) && histIns.getEndTime () == null
|
|
|
- || BpmnXMLConstants.ELEMENT_EVENT_START.equals (histIns.getActivityType ())
|
|
|
- || BpmnXMLConstants.ELEMENT_EVENT_END.equals (histIns.getActivityType ())) {
|
|
|
- // 获取流程发起人名称
|
|
|
- Flow e = queryTaskState (histIns);
|
|
|
-
|
|
|
- actList.add (e);
|
|
|
+ if ( isArchive ) {
|
|
|
+ if (StrUtil.isNotBlank (histIns.getAssignee ())
|
|
|
+ || BpmnXMLConstants.ELEMENT_TASK_USER.equals (histIns.getActivityType ()) && histIns.getEndTime () == null
|
|
|
+ || BpmnXMLConstants.ELEMENT_EVENT_START.equals (histIns.getActivityType ())
|
|
|
+ || BpmnXMLConstants.ELEMENT_EVENT_END.equals (histIns.getActivityType ())) {
|
|
|
+ Flow e = queryTaskStateArchive (histIns);
|
|
|
+ actList.add (e);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 只显示开始节点和结束节点,并且执行人不为空的任务
|
|
|
+ if (StrUtil.isNotBlank (histIns.getAssignee ())
|
|
|
+ && historyService.createHistoricTaskInstanceQuery ().taskId (histIns.getTaskId ()).count () != 0
|
|
|
+ || BpmnXMLConstants.ELEMENT_TASK_USER.equals (histIns.getActivityType ()) && histIns.getEndTime () == null
|
|
|
+ || BpmnXMLConstants.ELEMENT_EVENT_START.equals (histIns.getActivityType ())
|
|
|
+ || BpmnXMLConstants.ELEMENT_EVENT_END.equals (histIns.getActivityType ())) {
|
|
|
+ // 获取流程发起人名称
|
|
|
+ Flow e = queryTaskState (histIns);
|
|
|
+ actList.add (e);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
Map data = new HashMap();
|
|
|
@@ -440,8 +484,8 @@ public class FlowTaskService {
|
|
|
|
|
|
List <Task> todoList;
|
|
|
// 查询列表
|
|
|
- if ( page.getSize ( ) == -1 ) {//不分页
|
|
|
- todoList = todoTaskQuery.list ( );
|
|
|
+ if ( page.getSize ( ) == -1 ) {//不分页,限制最多1000条防止OOM
|
|
|
+ todoList = todoTaskQuery.listPage ( 0, 1000 );
|
|
|
} else {
|
|
|
int start = (int) ((page.getCurrent ( ) - 1) * page.getSize ( ));
|
|
|
int size = (int) (page.getSize ( ));
|
|
|
@@ -528,7 +572,7 @@ public class FlowTaskService {
|
|
|
// 查询列表
|
|
|
List <HistoricTaskInstance> histList;
|
|
|
if ( page.getSize ( ) == -1 ) {
|
|
|
- histList = histTaskQuery.list ( );
|
|
|
+ histList = histTaskQuery.listPage ( 0, 1000 ); // 限制最多1000条防止OOM
|
|
|
} else {
|
|
|
int start = (int) ((page.getCurrent ( ) - 1) * page.getSize ( ));
|
|
|
int size = (int) (page.getSize ( ));
|
|
|
@@ -623,6 +667,8 @@ public class FlowTaskService {
|
|
|
/**
|
|
|
* 获取流转历史任务列表
|
|
|
*
|
|
|
+ * 支持冷表回查:热表无数据时从归档表查询活动实例,归档模式使用 queryTaskStateArchive
|
|
|
+ *
|
|
|
* @param procInsId 流程实例
|
|
|
*/
|
|
|
public List <Flow> historicTaskList(String procInsId) throws Exception {
|
|
|
@@ -630,6 +676,17 @@ public class FlowTaskService {
|
|
|
List <HistoricActivityInstance> list = Lists.newArrayList ( );
|
|
|
List <HistoricActivityInstance> historicActivityInstances2 = historyService.createHistoricActivityInstanceQuery ( ).processInstanceId ( procInsId )
|
|
|
.orderByHistoricActivityInstanceStartTime ( ).asc ( ).orderByHistoricActivityInstanceEndTime ( ).asc ( ).list ( );
|
|
|
+
|
|
|
+ // 冷表回查:热表无数据时从归档表查询活动实例
|
|
|
+ boolean isArchive = false;
|
|
|
+ if ( historicActivityInstances2.isEmpty ( ) ) {
|
|
|
+ historicActivityInstances2 = flowArchiveService.findActivityInstances ( procInsId );
|
|
|
+ isArchive = !historicActivityInstances2.isEmpty ( );
|
|
|
+ if ( isArchive ) {
|
|
|
+ log.info ( "流程[{}]数据在归档表中,从冷表查询", procInsId );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
for (HistoricActivityInstance historicActivityInstance : historicActivityInstances2) {
|
|
|
if ( historicActivityInstance.getEndTime ( ) != null ) {
|
|
|
list.add ( historicActivityInstance );
|
|
|
@@ -644,16 +701,26 @@ public class FlowTaskService {
|
|
|
|
|
|
for (int i = 0; i < list.size ( ); i++) {
|
|
|
HistoricActivityInstance histIns = list.get ( i );
|
|
|
- // 只显示开始节点和结束节点,并且执行人不为空的任务
|
|
|
- if ( StrUtil.isNotBlank ( histIns.getAssignee ( ) )
|
|
|
- && historyService.createHistoricTaskInstanceQuery ( ).taskId ( histIns.getTaskId ( ) ).count ( ) != 0
|
|
|
- || BpmnXMLConstants.ELEMENT_TASK_USER.equals ( histIns.getActivityType ( ) ) && histIns.getEndTime ( ) == null
|
|
|
- || BpmnXMLConstants.ELEMENT_EVENT_START.equals ( histIns.getActivityType ( ) )
|
|
|
- || BpmnXMLConstants.ELEMENT_EVENT_END.equals ( histIns.getActivityType ( ) ) ) {
|
|
|
- // 获取流程发起人名称
|
|
|
- Flow e = queryTaskState ( histIns );
|
|
|
-
|
|
|
- actList.add ( e );
|
|
|
+ // 对于归档数据,跳过热表中的任务实例检查
|
|
|
+ if ( isArchive ) {
|
|
|
+ if ( StrUtil.isNotBlank ( histIns.getAssignee ( ) )
|
|
|
+ || BpmnXMLConstants.ELEMENT_TASK_USER.equals ( histIns.getActivityType ( ) ) && histIns.getEndTime ( ) == null
|
|
|
+ || BpmnXMLConstants.ELEMENT_EVENT_START.equals ( histIns.getActivityType ( ) )
|
|
|
+ || BpmnXMLConstants.ELEMENT_EVENT_END.equals ( histIns.getActivityType ( ) ) ) {
|
|
|
+ Flow e = queryTaskStateArchive ( histIns );
|
|
|
+ actList.add ( e );
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 只显示开始节点和结束节点,并且执行人不为空的任务
|
|
|
+ if ( StrUtil.isNotBlank ( histIns.getAssignee ( ) )
|
|
|
+ && historyService.createHistoricTaskInstanceQuery ( ).taskId ( histIns.getTaskId ( ) ).count ( ) != 0
|
|
|
+ || BpmnXMLConstants.ELEMENT_TASK_USER.equals ( histIns.getActivityType ( ) ) && histIns.getEndTime ( ) == null
|
|
|
+ || BpmnXMLConstants.ELEMENT_EVENT_START.equals ( histIns.getActivityType ( ) )
|
|
|
+ || BpmnXMLConstants.ELEMENT_EVENT_END.equals ( histIns.getActivityType ( ) ) ) {
|
|
|
+ // 获取流程发起人名称
|
|
|
+ Flow e = queryTaskState ( histIns );
|
|
|
+ actList.add ( e );
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
return actList;
|
|
|
@@ -709,6 +776,10 @@ public class FlowTaskService {
|
|
|
/**
|
|
|
* 获取我发起的流程申请列表
|
|
|
*
|
|
|
+ * 优化说明:
|
|
|
+ * 1. page.getSize()==-1 时限制最多1000条,防止全量查询导致OOM
|
|
|
+ * 2. 按processDefinitionId分组后调用batchQueryProcessState批量查询,避免N+1查询问题
|
|
|
+ *
|
|
|
* @param user
|
|
|
* @return
|
|
|
*/
|
|
|
@@ -726,8 +797,8 @@ public class FlowTaskService {
|
|
|
|
|
|
page.setTotal ( query.count ( ) );
|
|
|
List <HistoricProcessInstance> histList;
|
|
|
- if ( page.getSize ( ) == -1 ) {//不分页
|
|
|
- histList = query.list ( );
|
|
|
+ if ( page.getSize ( ) == -1 ) {//不分页,限制最多1000条防止OOM
|
|
|
+ histList = query.listPage ( 0, 1000 );
|
|
|
} else {
|
|
|
int start = (int) ((page.getCurrent ( ) - 1) * page.getSize ( ));
|
|
|
int size = (int) (page.getSize ( ));
|
|
|
@@ -754,17 +825,30 @@ public class FlowTaskService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- List records = Lists.newArrayList ( );
|
|
|
+ // 按processDefinitionId分组,批量查询流程状态(避免N+1查询)
|
|
|
+ List records = Lists.newArrayList();
|
|
|
+ Map<String, List<HistoricProcessInstance>> groupedByDefId = new LinkedHashMap<>();
|
|
|
for (HistoricProcessInstance historicProcessInstance : histList) {
|
|
|
- ProcessVo processVo = flowProcessService.queryProcessState ( historicProcessInstance.getProcessDefinitionId ( ), historicProcessInstance.getId ( ) );
|
|
|
- processVo.setEndTime ( historicProcessInstance.getEndTime ( ) );
|
|
|
- processVo.setStartTime ( historicProcessInstance.getStartTime ( ) );
|
|
|
- processVo.setProcessDefinitionId ( historicProcessInstance.getProcessDefinitionId ( ) );
|
|
|
- processVo.setProcessInstanceId ( historicProcessInstance.getId ( ) );
|
|
|
- processVo.setVars ( historicProcessInstance.getProcessVariables ( ) );
|
|
|
- processVo.setProcessDefinitionName ( historicProcessInstance.getProcessDefinitionName ( ) );
|
|
|
- processVo.setVersion ( historicProcessInstance.getProcessDefinitionVersion ( ) );
|
|
|
- records.add ( processVo );
|
|
|
+ groupedByDefId.computeIfAbsent(historicProcessInstance.getProcessDefinitionId(), k -> new ArrayList<>()).add(historicProcessInstance);
|
|
|
+ }
|
|
|
+ for (Map.Entry<String, List<HistoricProcessInstance>> entry : groupedByDefId.entrySet()) {
|
|
|
+ String procDefId = entry.getKey();
|
|
|
+ List<String> procInsIds = entry.getValue().stream().map(HistoricProcessInstance::getId).collect(Collectors.toList());
|
|
|
+ Map<String, ProcessVo> stateMap = flowProcessService.batchQueryProcessState(procDefId, procInsIds);
|
|
|
+ for (HistoricProcessInstance historicProcessInstance : entry.getValue()) {
|
|
|
+ ProcessVo processVo = stateMap.get(historicProcessInstance.getId());
|
|
|
+ if (processVo == null) {
|
|
|
+ processVo = new ProcessVo();
|
|
|
+ }
|
|
|
+ processVo.setEndTime ( historicProcessInstance.getEndTime ( ) );
|
|
|
+ processVo.setStartTime ( historicProcessInstance.getStartTime ( ) );
|
|
|
+ processVo.setProcessDefinitionId ( historicProcessInstance.getProcessDefinitionId ( ) );
|
|
|
+ processVo.setProcessInstanceId ( historicProcessInstance.getId ( ) );
|
|
|
+ processVo.setVars ( historicProcessInstance.getProcessVariables ( ) );
|
|
|
+ processVo.setProcessDefinitionName ( historicProcessInstance.getProcessDefinitionName ( ) );
|
|
|
+ processVo.setVersion ( historicProcessInstance.getProcessDefinitionVersion ( ) );
|
|
|
+ records.add ( processVo );
|
|
|
+ }
|
|
|
}
|
|
|
page.setRecords ( records );
|
|
|
|
|
|
@@ -1073,9 +1157,100 @@ public class FlowTaskService {
|
|
|
return e;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 查询任务节点的状态(归档数据版本)
|
|
|
+ * 用于冷表回查场景,从归档表查询评论和变量
|
|
|
+ *
|
|
|
+ * 与 queryTaskState 的区别:
|
|
|
+ * - queryTaskState 从热表查询评论和流程发起人
|
|
|
+ * - queryTaskStateArchive 从归档表(act_hi_comment_archive / act_hi_procinst_archive)查询
|
|
|
+ */
|
|
|
+ public Flow queryTaskStateArchive(HistoricActivityInstance histIns) {
|
|
|
+ Flow e = new Flow ( );
|
|
|
+ e.setHistIns ( histIns );
|
|
|
+ if ( BpmnXMLConstants.ELEMENT_EVENT_START.equals ( histIns.getActivityType ( ) ) ) {
|
|
|
+ // 开始节点:获取流程发起人信息
|
|
|
+ // 先尝试热表查询,热表无数据则查归档表
|
|
|
+ List <HistoricProcessInstance> il = historyService.createHistoricProcessInstanceQuery ( ).processInstanceId ( histIns.getProcessInstanceId ( ) ).orderByProcessInstanceStartTime ( ).asc ( ).list ( );
|
|
|
+ if ( il.isEmpty ( ) ) {
|
|
|
+ // 热表无数据,从归档表获取流程发起人
|
|
|
+ Map<String, Object> archiveProcInst = flowArchiveService.findHistoricProcessInstance ( histIns.getProcessInstanceId ( ) );
|
|
|
+ if ( archiveProcInst != null && StrUtil.isNotBlank ( (String) archiveProcInst.get ( "START_USER_ID_" ) ) ) {
|
|
|
+ UserDTO user = userApi.getById ( (String) archiveProcInst.get ( "START_USER_ID_" ) );
|
|
|
+ if ( user != null ) {
|
|
|
+ e.setAssignee ( histIns.getAssignee ( ) );
|
|
|
+ e.setAssigneeName ( user.getName ( ) );
|
|
|
+ e.setAssigneeId ( user.getId ( ) );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if ( il.size ( ) > 0 && StrUtil.isNotBlank ( il.get ( 0 ).getStartUserId ( ) ) ) {
|
|
|
+ UserDTO user = userApi.getById ( il.get ( 0 ).getStartUserId ( ) );
|
|
|
+ if ( user != null ) {
|
|
|
+ e.setAssignee ( histIns.getAssignee ( ) );
|
|
|
+ e.setAssigneeName ( user.getName ( ) );
|
|
|
+ e.setAssigneeId ( user.getId ( ) );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ TaskComment taskComment = new TaskComment ( );
|
|
|
+ taskComment.setStatus ( FlowableConstant.START_EVENT_LABEL );
|
|
|
+ taskComment.setMessage ( FlowableConstant.START_EVENT_COMMENT );
|
|
|
+ e.setComment ( taskComment );
|
|
|
+ return e;
|
|
|
+ }
|
|
|
+ if ( BpmnXMLConstants.ELEMENT_EVENT_END.equals ( histIns.getActivityType ( ) ) ) {
|
|
|
+ TaskComment taskComment = new TaskComment ( );
|
|
|
+ taskComment.setStatus ( FlowableConstant.END_EVENT_LABEL );
|
|
|
+ taskComment.setMessage ( FlowableConstant.END_EVENT_COMMENT );
|
|
|
+ e.setAssigneeName ( FlowableConstant.SYSTEM_EVENT_COMMENT );
|
|
|
+ e.setComment ( taskComment );
|
|
|
+ return e;
|
|
|
+ }
|
|
|
+ // 获取任务执行人名称
|
|
|
+ if ( StrUtil.isNotEmpty ( histIns.getAssignee ( ) ) ) {
|
|
|
+ UserDTO user = userApi.getFlowAbleById ( histIns.getAssignee ( ) );
|
|
|
+ if ( user != null ) {
|
|
|
+ e.setAssignee ( histIns.getAssignee ( ) );
|
|
|
+ e.setAssigneeName ( user.getName ( ) );
|
|
|
+ e.setAssigneeId ( user.getId ( ) );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 从归档表获取意见评论内容(先查归档表,归档表无数据再查热表兜底)
|
|
|
+ if ( StrUtil.isNotBlank ( histIns.getTaskId ( ) ) ) {
|
|
|
+ List<Map<String, Object>> archiveComments = flowArchiveService.findTaskComments ( histIns.getTaskId ( ) );
|
|
|
+ if ( archiveComments.isEmpty ( ) ) {
|
|
|
+ // 归档表无评论,回退到热表查询
|
|
|
+ List <TaskComment> commentList = this.getTaskComments ( histIns.getTaskId ( ) );
|
|
|
+ if ( commentList.size ( ) > 0 ) {
|
|
|
+ e.setComment ( commentList.get ( commentList.size ( ) - 1 ) );
|
|
|
+ } else {
|
|
|
+ e.setComment ( new TaskComment ( ) );
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 从归档评论中构建TaskComment
|
|
|
+ Map<String, Object> lastComment = archiveComments.get ( 0 );
|
|
|
+ TaskComment tc = new TaskComment ( );
|
|
|
+ tc.setCommentType ( (String) lastComment.get ( "TYPE_" ) );
|
|
|
+ Object fullMsg = lastComment.get ( "FULL_MSG_" );
|
|
|
+ if ( fullMsg instanceof byte[] ) {
|
|
|
+ tc.setFullMessage ( new String ( (byte[]) fullMsg ) );
|
|
|
+ }
|
|
|
+ e.setComment ( tc );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 归档数据中不会有等待执行的任务
|
|
|
+ if ( histIns.getEndTime ( ) == null ) {
|
|
|
+ TaskComment taskComment = new TaskComment ( );
|
|
|
+ taskComment.setStatus ( ActionType.WAITING.getStatus ( ) );
|
|
|
+ e.setComment ( taskComment );
|
|
|
+ }
|
|
|
+ return e;
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
public List <TaskComment> getTaskComments(String taskId) {
|
|
|
- return jdbcTemplate.query ( "select * from ACT_HI_COMMENT where TYPE_ like '" + TaskComment.prefix + "%' and TASK_ID_ = '" + taskId + "' order by TIME_ desc", new RowMapper <TaskComment> ( ) {
|
|
|
+ return jdbcTemplate.query ( "select * from ACT_HI_COMMENT where TYPE_ like ? and TASK_ID_ = ? order by TIME_ desc",
|
|
|
+ new Object[] { TaskComment.prefix + "%", taskId },
|
|
|
+ new RowMapper <TaskComment> ( ) {
|
|
|
@Override
|
|
|
public TaskComment mapRow(ResultSet rs, int rowNum) throws SQLException {
|
|
|
TaskComment taskComment = new TaskComment ( );
|
|
|
@@ -1087,6 +1262,15 @@ public class FlowTaskService {
|
|
|
}
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
+ * 获取流程图数据(用于前端流程图展示)
|
|
|
+ *
|
|
|
+ * 支持冷表回查:
|
|
|
+ * 1. 先查运行时表获取流程定义ID
|
|
|
+ * 2. 运行时表无数据查历史热表
|
|
|
+ * 3. 热表无数据查归档表获取流程定义ID
|
|
|
+ * 4. 归档数据跳过热表任务检查(因为归档流程的任务实例已不在热表中)
|
|
|
+ */
|
|
|
public Map getDiagram(String processId) {
|
|
|
Map m = new HashMap ( );
|
|
|
try {
|
|
|
@@ -1094,7 +1278,19 @@ public class FlowTaskService {
|
|
|
ProcessInstance pi = runtimeService.createProcessInstanceQuery ( ).processInstanceId ( processId ).singleResult ( );
|
|
|
//流程走完的不显示图
|
|
|
if ( pi == null ) {
|
|
|
- processDefId = historyService.createHistoricProcessInstanceQuery ( ).processInstanceId ( processId ).singleResult ( ).getProcessDefinitionId ( );
|
|
|
+ HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery ( ).processInstanceId ( processId ).singleResult ( );
|
|
|
+ if ( hpi == null ) {
|
|
|
+ // 冷表回查:热表无数据时从归档表获取流程定义ID
|
|
|
+ Map<String, Object> archiveProcInst = flowArchiveService.findHistoricProcessInstance ( processId );
|
|
|
+ if ( archiveProcInst != null ) {
|
|
|
+ processDefId = (String) archiveProcInst.get ( "PROC_DEF_ID_" );
|
|
|
+ log.info ( "流程图[{}]从归档表查询流程定义ID", processId );
|
|
|
+ } else {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ processDefId = hpi.getProcessDefinitionId ( );
|
|
|
+ }
|
|
|
} else {
|
|
|
processDefId = pi.getProcessDefinitionId ( );
|
|
|
}
|
|
|
@@ -1102,10 +1298,20 @@ public class FlowTaskService {
|
|
|
List <HistoricActivityInstance> historyProcess = getHistoryProcess ( processId );
|
|
|
Set <String> activityIds = new LinkedHashSet <> ( );
|
|
|
List <String> flows = new ArrayList <> ( );
|
|
|
+ // 判断是否为归档数据(归档表有数据但热表无数据)
|
|
|
+ boolean isArchive = !historyProcess.isEmpty ( ) && historyService.createHistoricActivityInstanceQuery ( ).processInstanceId ( processId ).count ( ) == 0;
|
|
|
for (HistoricActivityInstance hi : historyProcess) {
|
|
|
String activityType = hi.getActivityType ( );
|
|
|
if ( activityType.equals ( BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW ) || activityType.equals ( BpmnXMLConstants.ELEMENT_GATEWAY_EXCLUSIVE ) ) {
|
|
|
flows.add ( hi.getActivityId ( ) );
|
|
|
+ } else if ( isArchive ) {
|
|
|
+ // 归档数据:跳过热表任务实例检查(归档流程的任务已不在 act_hi_taskinst 中)
|
|
|
+ if ( StrUtil.isNotBlank ( hi.getAssignee ( ) )
|
|
|
+ || BpmnXMLConstants.ELEMENT_TASK_USER.equals ( hi.getActivityType ( ) ) && hi.getEndTime ( ) == null
|
|
|
+ || BpmnXMLConstants.ELEMENT_EVENT_START.equals ( hi.getActivityType ( ) )
|
|
|
+ || BpmnXMLConstants.ELEMENT_EVENT_END.equals ( hi.getActivityType ( ) ) ) {
|
|
|
+ activityIds.add ( hi.getActivityId ( ) );
|
|
|
+ }
|
|
|
} else if ( StrUtil.isNotBlank ( hi.getAssignee ( ) )
|
|
|
&& historyService.createHistoricTaskInstanceQuery ( ).taskId ( hi.getTaskId ( ) ).count ( ) != 0
|
|
|
|| BpmnXMLConstants.ELEMENT_TASK_USER.equals ( hi.getActivityType ( ) ) && hi.getEndTime ( ) == null
|
|
|
@@ -1132,7 +1338,9 @@ public class FlowTaskService {
|
|
|
|
|
|
|
|
|
/**
|
|
|
- * 任务历史
|
|
|
+ * 任务历史(获取已结束的活动实例列表)
|
|
|
+ *
|
|
|
+ * 支持冷表回查:热表无数据时从归档表查询
|
|
|
*
|
|
|
* @param processId 部署id
|
|
|
*/
|
|
|
@@ -1142,6 +1350,13 @@ public class FlowTaskService {
|
|
|
.processInstanceId ( processId ) // 执行流程实例id
|
|
|
.finished ( ).orderByHistoricActivityInstanceEndTime ( ).asc ( )
|
|
|
.list ( );
|
|
|
+ // 冷表回查:热表无数据时从归档表查询已结束的活动实例
|
|
|
+ if ( list.isEmpty ( ) ) {
|
|
|
+ list = flowArchiveService.findFinishedActivityInstances ( processId );
|
|
|
+ if ( !list.isEmpty ( ) ) {
|
|
|
+ log.info ( "流程[{}]历史活动从归档表查询", processId );
|
|
|
+ }
|
|
|
+ }
|
|
|
return list;
|
|
|
}
|
|
|
|