Activiti工作流查看流程視圖
思路
首先我們要知道Activiti工作流查看流程針對的是運行的實例, 可以看到流程流轉到那個節點。
但是大多數情況實例對業務來說是沒有意義的,那麼我就需要業務key,每個業務key對應工作流唯一的task任務。
有了這些想法我們就能構思查看流程視圖的接口了,入參肯定是業務能夠提供的,出參沒有疑問那就是圖片了,爲了方便我們直接返回圖片流InputStream
業務key轉換流程實例
通過businessKey 查詢業務key對應的task任務
List<Task> tasks = taskService.createTaskQuery().processInstanceBusinessKey(businessKey).list();
理論上來說業務businessKey也是唯一的,但是對Activiti來說只是某一列返回List,沒事我們直接加判斷,不唯一就異常出去。
if(tasks != null && tasks.size() == 1){
String taskId = tasks.get(0).getId();
Task nowTask = taskService.createTaskQuery().taskId(taskId).singleResult();
processInstanceId = nowTask.getProcessInstanceId();
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
processDefinitionId = processInstance.getProcessDefinitionId();
}else if (tasks != null && tasks.size() == 0){
List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().finished().processInstanceBusinessKey(businessKey).list();
if(list != null && list.size() == 1){
processDefinitionId = list.get(0).getProcessDefinitionId();
processInstanceId = list.get(0).getId();
}
}
有了思路不多說直接上代碼
public InputStream _$look_png(String businessKey) {
logger.info("_$look_png---參數businessKey="+businessKey);
InputStream inputStream= null;
String processInstanceId = null;
String processDefinitionId = null;
try {
List<Task> tasks = taskService.createTaskQuery().processInstanceBusinessKey(businessKey).list();
logger.info("_$look_png---任務tasks="+ tasks);
if(tasks != null && tasks.size() == 1){
String taskId = tasks.get(0).getId();
Task nowTask = taskService.createTaskQuery().taskId(taskId).singleResult();
processInstanceId = nowTask.getProcessInstanceId();
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
processDefinitionId = processInstance.getProcessDefinitionId();
}else if (tasks != null && tasks.size() == 0){
List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().finished().processInstanceBusinessKey(businessKey).list();
if(list != null && list.size() == 1){
processDefinitionId = list.get(0).getProcessDefinitionId();
processInstanceId = list.get(0).getId();
}
}
if(StringUtils.isBlank(processInstanceId) || StringUtils.isBlank(processDefinitionId)){
logger.info("_$look_png---異常,未找到或發現多個流程!businessKey="+businessKey);
String result = "未找到或發現多個流程!businessKey="+businessKey;
inputStream = new ByteArrayInputStream(result.getBytes());
return inputStream;
}
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
List<HistoricActivityInstance> activityInstances = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list();
List<String> activityIds = new ArrayList<String>();
List<String> flowIds = new ArrayList<String>();
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(processDefinitionId);
//獲取流程走過的線
flowIds = getHighLightedFlows(processDefinition, activityInstances);
for (HistoricActivityInstance hai : activityInstances) {
//獲取流程走過的節點
activityIds.add(hai.getActivityId());
}
ImageIO.setCacheDirectory(new File(_PNG_PATH));
inputStream = processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator().generateDiagram(bpmnModel, "png", activityIds, flowIds,"宋體", "宋體", "宋體", null, 1.0);
}catch (Exception e){
e.printStackTrace();
logger.error("_$look_png---異常:", e);
}
return inputStream;
}
這裏有個注意的地方, linux注意安裝字體
linux 安裝字體
yum install -y fontconfig mkfontscale
將 宋體 丟入/usr/share/fonts/
建立字體索引信息,更新字體緩存,使用如下命令:
mkfontscale
mkfontdir
fc-cache
查看安裝字體fc-list,重啓服務
//獲取流程走過的線
public static List<String> getHighLightedFlows(ProcessDefinitionEntity processDefinitionEntity,List<HistoricActivityInstance> haiList) throws Exception{
//用來保存高亮的線 flowId
List<String> highFlows = new ArrayList<String>();
for (int i = 0; i < haiList.size() - 1; i++) {
//對歷史流程節點進行遍歷
//得到節點定義的詳細信息
ActivityImpl activityImpl = processDefinitionEntity.findActivity(haiList.get(i).getActivityId());
//用以保存後需要開始時間相同的節點
List<ActivityImpl> sameStartTimeNodes = new ArrayList<ActivityImpl>();
ActivityImpl sameActivityImpl1 = processDefinitionEntity.findActivity(haiList.get(i + 1).getActivityId());
//講後面第一個節點放在時間相同節點的集合裏
sameStartTimeNodes.add(sameActivityImpl1);
for (int j = i + 1; j < haiList.size() - 1; j++) {
HistoricActivityInstance activityImpl1 = haiList.get(j);//後續第一個節點
HistoricActivityInstance activityImpl2 = haiList.get(j + 1);//後續第而個節點
if(activityImpl1.getStartTime().equals(activityImpl2.getStartTime())){
//如果第一個節點和第二個節點開始時間相同保存
ActivityImpl sameActivityImpl2 = processDefinitionEntity.findActivity(activityImpl2.getActivityId());
sameStartTimeNodes.add(sameActivityImpl2);
}else{
//不同就調查循環
break;
}
}
//取出節點的所有出去的線
List<PvmTransition> pvmTransitions = activityImpl.getOutgoingTransitions();
for(PvmTransition pvmTransition : pvmTransitions){
//對所有的線進行遍歷
ActivityImpl pvmActivityImpl = (ActivityImpl) pvmTransition.getDestination();
//如果取出的線的目標節點存在時間相同的節點裏,保存該線的id,進行高亮顯示
if(sameStartTimeNodes.contains(pvmActivityImpl)){
highFlows.add(pvmTransition.getId());
}
}
}
return highFlows;
}