基于Activiti的简单流程历史图形展示

以前采用jbpm编写流程,后来决定采用activiti在新系统中进行流程实现,所以重新编写了流程历史图形展示


[list=1]
[*]首先需要获取流程定义图

ByteArrayOutputStream os = new ByteArrayOutputStream();
InputStream is = getProcessEngine().getRepositoryService().getProcessDiagram(processDefinitionId);

try {
new BASE64Encoder().encode(is, os);
is.close();
} catch (Exception e) {
;
}

String image = os.toString();

将image缓存起来备用


[*]读取流程定义信息,获取流程节点信息
基于BPMN2.0的Activiti流程图定义是以xml形式记录的,内容中不仅保存了流程信息,还保存了流程图示信息,我们可以解析流程图示信息,用于之后流程节点的展示
我们定义如下的流程图
[img]http://dl2.iteye.com/upload/attachment/0086/0460/50583d57-b73b-3646-98a4-10f92b322aa6.png[/img]
它的xml定义为

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema"
expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
<process id="process1" name="process1">
<startEvent id="startevent1" name="Start"></startEvent>
<endEvent id="endevent1" name="End"></endEvent>
<userTask id="usertask1" name="User Task1"></userTask>
<sequenceFlow id="flow1" name="" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
<sequenceFlow id="flow2" name="" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
<userTask id="usertask2" name="User Task2"></userTask>
<sequenceFlow id="flow3" name="" sourceRef="usertask2" targetRef="endevent1"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_process1">
<bpmndi:BPMNPlane bpmnElement="process1" id="BPMNPlane_process1">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="35" width="35" x="70" y="20"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
<omgdc:Bounds height="35" width="35" x="70" y="260"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
<omgdc:Bounds height="55" width="105" x="35" y="90"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
<omgdc:Bounds height="55" width="105" x="35" y="170"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="87" y="55"></omgdi:waypoint>
<omgdi:waypoint x="87" y="90"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="87" y="145"></omgdi:waypoint>
<omgdi:waypoint x="87" y="170"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="87" y="225"></omgdi:waypoint>
<omgdi:waypoint x="87" y="260"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>

其中bpmndi:BPMNDiagram记录了流程图示信息,bpmndi:BPMNShape记录节点,omgdc:Bounds记录节点的位置和大小信息,我们只需要通过sax解析该xml文件,即可获得节点图示信息


InputStream is = getProcessEngine().getRepositoryService().getProcessModel(processDefinitionId);
try {
SAXParserFactory.newInstance().newSAXParser().parse(is, new DefaultHandler() {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
switch (qName) {
case SHAPE:
n = attributes.getValue(SHAPE_NAME);
ds = new Double[4];
break;
case BOUND:
if (ds != null) {
ds[0] = Double.parseDouble(attributes.getValue("x"));
ds[1] = Double.parseDouble(attributes.getValue("y"));
ds[2] = Double.parseDouble(attributes.getValue("width"));
ds[3] = Double.parseDouble(attributes.getValue("height"));
}
break;
default:
}
}

@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qName.equals(SHAPE)) {
// TODO 存储节点图示信息
// k = processDefinitionId + n
// v = ds
n = null;
ds = null;
}
}

private static final String SHAPE = "bpmndi:BPMNShape";
private static final String SHAPE_NAME = "bpmnElement";
private static final String BOUND = "omgdc:Bounds";
private String n;
private Double[] ds;
});
} catch (Exception e) {
e.printStackTrace();
}

在代码的TODO部分,将节点图示信息缓存起来备用


[*]展示流程运行情况
通过activiti api获取历史审核情况

HistoricTaskInstanceQuery taskQuery = getProcessEngine().getHistoryService().createHistoricTaskInstanceQuery();
taskQuery.processInstanceId(processInstanceId);
List<HistoricTaskInstance> list = taskQuery.list();
for (HistoricTaskInstance taskInstance : list) {
Double[] shape = getShape(processDefinitionId, taskInstance.getTaskDefinitionKey()); // TODO 从缓存获取节点图示信息
taskInstance.getAssignee();
taskInstance.getStartTime();
taskInstance.getEndTime();
}

在代码的TODO部分,从缓存获取节点图示信息;
并且可以从taskInstance获取节点审核相关信息,这些信息就可以用于在页面上通过html进行展示

页面上,由于流程定义图已经以base64编码,所以可以直接用[img]data:image/png;base64,[/img]展示,而审核历史节点,则采用<div style="left:px,top:px,width:px,height:px"></div>以position:absolute;展示在流程定义图上
由于流程图上的节点可能有圆角,所以css上还需要加上radius来展示

实际使用效果如图
[img]http://dl2.iteye.com/upload/attachment/0086/0486/ae8e67f4-744c-3acf-80d6-f82c286aa1d2.png[/img]


[*]我们还可以
除了审核历史节点,还可以通过taskquery查询等待审核的节点,以不同的效果展现
我们还可以在鼠标放到节点上的时候,展示节点的审核信息,如审核人、审核时间、审核意见和办结花费时间等
由于流程审核过程可能比较复杂,所以还可以作一个过程展示,按审核顺序依次加亮审核节点,用于过程展示

[img]http://dl2.iteye.com/upload/attachment/0086/0492/f481bbda-11ad-33f1-a4e3-422d3f1b4236.png[/img]

[/list]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值