在前端开发中,cmmnjs模型和bpmnjs模型有许多类似可参照的地方,本文聚焦于cmmnjs的使用,与bpmn中类似的点将不做赘述。主要说明cmmn和bpmn的不同之处和节点的相关操作。
示例:项目地址 ,基于vue实现,但cmmnjs相关逻辑与框架无关,可直接迁移至其它框架。
代码中涉及到功能模块的部分,将直接以对应模块名称代替,实际开发时需要通过cmmnModeler.get('模块名')获取。
一、辅助元素
辅助元素是指在不会出现在画布上,对节点补充描述或定义执行规则的元素。 在cmmn中,对节点更新属性使用modeling.updateProperties方法,更新辅助元素使用modeling.updateControls方法。 以下说明一些常见的辅助元素。
二、documentation文档节点
文档节点是节点的附加信息,对流程执行无影响。可通过以下方式添加
// 通过text指定内容
const exp = cmmnFactory.create('cmmn:Documentation', {
text: '111'
});
let documentation = shape.businessObject.definitionRef.documentation || [];
documentation.push(exp);
modeling.updateControls(shape, {
documentation,
});
对应的xml文件表现为
<cmmn:planItem id="PlanItem_1eavv6s" definitionRef="HumanTask_1b7x2ml" />
<cmmn:humanTask id="HumanTask_1b7x2ml">
<cmmn:documentation id="Documentation_0gsnhox">111</cmmn:documentation>
</cmmn:humanTask>
如上,文档节点会出现在节点定义中。一个节点定义可以包含多个文档节点,通过 shape.businessObject.definitionRef.documentation 获取
三、控制节点
控制节点一般用于定义节点执行时的规则或逻辑,在使用不同执行规则时需要添加不同的控制节点,一般通过cmmnFactory.create方法创建。常见的比如规定某节点需要手动激活时,需要添加ManualActivationRule节点。
const exp = cmmnFactory.create("cmmn:ManualActivationRule");
modeling.updateControls(shape, {
manualActivationRule: exp,
});
或是指定一些特殊节点中的表达式。
// 指定子案例节点中的子案例id
const target = elementRegistry.get("CasePlanModel_1");
const ele = elementFactory.createPlanItemShape("cmmn:CaseTask");
modeling.createShape(ele, { x: 650, y: 300 }, target);
// 通过body指定表达式内容
const exp = cmmnFactory.create("cmmn:Expression", {
body: `<![CDATA[子案例id]]>`,
});
modeling.updateControls(ele, {
caseRefExpression: exp,
});
// 指定时间监听器中的时间表达式
const target = elementRegistry.get("CasePlanModel_1");
const ele = elementFactory.createPlanItemShape("cmmn:TimerEventListener");
modeling.createShape(ele, { x: 650, y: 300 }, target);
const exp = cmmnFactory.create("cmmn:Expression", {
body: `<![CDATA[${new Date().toISOString()}]]>`,
});
modeling.updateControls(ele, {
timerExpression: exp,
});
表达式中的CDATA是xml中的一种特殊语法,会将其中的内容视为纯文本,避免内容被解析或转义。 不同规则会使用不同的控制节点不同,但创建方式类似,具体添加进哪个属性中需按规则确定。
四、自定义扩展元素
配合特定执行引擎(比如camunda、flowable)时,可以在cmmn中使用扩展元素增加功能。 要添加自定义扩展元素,需要先写对应的描述文件,在初始化时添加进moddleExtensions中。描述文件的结构与bpmn基本相同,可参照bpmn的相关文章,如 bpmn描述文件说明。
写好描述文件后,在初始化时指定。
cmmnModeler = new CmmnModeler({
container: container.value,
moddleExtensions: {
flowable: flowableModdleDescriptor,
},
});
就可以通过moddle.create方法创建扩展元素,并添加进对应节点的extensionElements中。
// 获取原有的扩展元素
let extensionElements = shape.businessObject?.definitionRef?.extensionElements;
// 创建扩展元素并配置描述文件中定义好的属性
const exp = moddle.create("flowable:TaskListener", {
event: "create",
delegateExpression: "${nodeService}",
});
// 原有的扩展元素存在则添加 不存在则创建
if (extensionElements) {
extensionElements.get("values").push(exp);
} else {
extensionElements = moddle.create("cmmn:ExtensionElements", { values: [] });
// 通过values属性添加扩展元素
extensionElements.values.push(exp);
}
// 更新
modeling.updateControls(shape, {
extensionElements: extensionElements,
});