2022-01-03 02:41:24 +08:00
|
|
|
<template>
|
|
|
|
<div class="my-process-designer">
|
|
|
|
<div class="my-process-designer__container">
|
2022-01-18 08:15:43 +08:00
|
|
|
<div class="my-process-designer__canvas" ref="bpmn-canvas"></div>
|
2022-01-03 02:41:24 +08:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
import BpmnViewer from "bpmn-js/lib/Viewer";
|
|
|
|
import DefaultEmptyXML from "./plugins/defaultEmpty";
|
|
|
|
|
|
|
|
export default {
|
|
|
|
name: "MyProcessViewer",
|
|
|
|
componentName: "MyProcessViewer",
|
|
|
|
props: {
|
|
|
|
value: String, // xml 字符串
|
|
|
|
prefix: {
|
|
|
|
type: String,
|
|
|
|
default: "camunda"
|
2022-01-18 01:41:22 +08:00
|
|
|
},
|
|
|
|
taskData: {
|
|
|
|
type: Array,
|
|
|
|
default: () => []
|
2022-01-03 02:41:24 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
data() {
|
2022-01-18 01:41:22 +08:00
|
|
|
return {
|
|
|
|
xml: '',
|
|
|
|
tasks: [],
|
|
|
|
};
|
2022-01-03 02:41:24 +08:00
|
|
|
},
|
|
|
|
mounted() {
|
2022-01-18 01:41:22 +08:00
|
|
|
this.xml = this.value;
|
|
|
|
this.tasks = this.taskData;
|
|
|
|
// 初始化
|
2022-01-03 02:41:24 +08:00
|
|
|
this.initBpmnModeler();
|
2022-01-18 01:41:22 +08:00
|
|
|
this.createNewDiagram(this.xml);
|
2022-01-03 02:41:24 +08:00
|
|
|
this.$once("hook:beforeDestroy", () => {
|
|
|
|
if (this.bpmnModeler) this.bpmnModeler.destroy();
|
|
|
|
this.$emit("destroy", this.bpmnModeler);
|
|
|
|
this.bpmnModeler = null;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
watch: {
|
|
|
|
value: function (newValue) { // 在 xmlString 发生变化时,重新创建,从而绘制流程图
|
2022-01-18 01:41:22 +08:00
|
|
|
this.xml = newValue;
|
|
|
|
this.createNewDiagram(this.xml);
|
|
|
|
},
|
|
|
|
taskData: function (newTaskData) {
|
|
|
|
this.tasks = newTaskData;
|
|
|
|
this.createNewDiagram(this.xml);
|
2022-01-03 02:41:24 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
initBpmnModeler() {
|
|
|
|
if (this.bpmnModeler) return;
|
|
|
|
this.bpmnModeler = new BpmnViewer({
|
2022-01-18 08:15:43 +08:00
|
|
|
container: this.$refs["bpmn-canvas"],
|
2022-01-18 01:41:22 +08:00
|
|
|
bpmnRenderer: {
|
|
|
|
}
|
2022-01-03 02:41:24 +08:00
|
|
|
})
|
|
|
|
},
|
|
|
|
/* 创建新的流程图 */
|
|
|
|
async createNewDiagram(xml) {
|
|
|
|
// 将字符串转换成图显示出来
|
|
|
|
let newId = `Process_${new Date().getTime()}`;
|
|
|
|
let newName = `业务流程_${new Date().getTime()}`;
|
|
|
|
let xmlString = xml || DefaultEmptyXML(newId, newName, this.prefix);
|
|
|
|
try {
|
2022-01-18 01:41:22 +08:00
|
|
|
// console.log(this.bpmnModeler.importXML);
|
2022-01-03 02:41:24 +08:00
|
|
|
let { warnings } = await this.bpmnModeler.importXML(xmlString);
|
|
|
|
if (warnings && warnings.length) {
|
|
|
|
warnings.forEach(warn => console.warn(warn));
|
|
|
|
}
|
2022-01-18 01:41:22 +08:00
|
|
|
// 高亮流程图
|
|
|
|
await this.highlightDiagram();
|
2022-01-03 02:41:24 +08:00
|
|
|
} catch (e) {
|
2022-01-18 01:41:22 +08:00
|
|
|
console.error(e);
|
|
|
|
// console.error(`[Process Designer Warn]: ${e?.message || e}`);
|
2022-01-03 02:41:24 +08:00
|
|
|
}
|
2022-01-18 01:41:22 +08:00
|
|
|
},
|
|
|
|
/* 高亮流程图 */
|
|
|
|
async highlightDiagram() {
|
|
|
|
if (this.tasks.length === 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!this.bpmnModeler.getDefinitions().rootElements[0].flowElements) {
|
|
|
|
return;
|
|
|
|
}
|
2022-01-18 08:15:43 +08:00
|
|
|
// 参考自 https://gitee.com/tony2y/RuoYi-flowable/blob/master/ruoyi-ui/src/components/Process/index.vue#L222 实现
|
2022-01-18 01:41:22 +08:00
|
|
|
let canvas = this.bpmnModeler.get('canvas');
|
2022-01-18 08:15:43 +08:00
|
|
|
this.bpmnModeler.getDefinitions().rootElements[0].flowElements?.forEach(n => {
|
|
|
|
let completeTask = this.tasks.find(m => m.definitionKey === n.id)
|
|
|
|
let todoTask = this.tasks.find(m => !m.endTime)
|
|
|
|
let endTask = this.tasks[this.tasks.length - 1]
|
2022-01-18 01:41:22 +08:00
|
|
|
if (n.$type === 'bpmn:UserTask') {
|
|
|
|
if (completeTask) {
|
|
|
|
canvas.addMarker(n.id, completeTask.endTime ? 'highlight' : 'highlight-todo');
|
2022-01-18 08:15:43 +08:00
|
|
|
// console.log(n.id + ' : ' + (completeTask.endTime ? 'highlight' : 'highlight-todo'));
|
|
|
|
n.outgoing?.forEach(nn => {
|
|
|
|
let targetTask = this.tasks.find(m => m.definitionKey === nn.targetRef.id)
|
|
|
|
if (targetTask) {
|
|
|
|
canvas.addMarker(nn.id, targetTask.endTime ? 'highlight' : 'highlight-todo');
|
|
|
|
} else if (nn.targetRef.$type === 'bpmn:ExclusiveGateway') {
|
|
|
|
// canvas.addMarker(nn.id, 'highlight');
|
|
|
|
canvas.addMarker(nn.id, completeTask.endTime ? 'highlight' : 'highlight-todo');
|
|
|
|
canvas.addMarker(nn.targetRef.id, completeTask.endTime ? 'highlight' : 'highlight-todo');
|
|
|
|
} else if (nn.targetRef.$type === 'bpmn:EndEvent') {
|
|
|
|
if (!todoTask && endTask.definitionKey === n.id) {
|
|
|
|
canvas.addMarker(nn.id, 'highlight');
|
|
|
|
canvas.addMarker(nn.targetRef.id, 'highlight');
|
|
|
|
}
|
|
|
|
if (!completeTask.endTime) {
|
|
|
|
canvas.addMarker(nn.id, 'highlight-todo');
|
|
|
|
canvas.addMarker(nn.targetRef.id, 'highlight-todo');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2022-01-18 01:41:22 +08:00
|
|
|
}
|
|
|
|
} else if (n.$type === 'bpmn:ExclusiveGateway') {
|
2022-01-18 08:15:43 +08:00
|
|
|
n.outgoing?.forEach(nn => {
|
|
|
|
let targetTask = this.tasks.find(m => m.definitionKey === nn.targetRef.id)
|
|
|
|
if (targetTask) {
|
|
|
|
canvas.addMarker(nn.id, targetTask.endTime ? 'highlight' : 'highlight-todo');
|
|
|
|
}
|
|
|
|
})
|
|
|
|
} else if (n.$type === 'bpmn:ParallelGateway') {
|
|
|
|
if (completeTask) {
|
|
|
|
canvas.addMarker(n.id, completeTask.endTime ? 'highlight' : 'highlight-todo')
|
|
|
|
n.outgoing?.forEach(nn => {
|
|
|
|
const targetTask = this.taskList.find(m => m.definitionKey === nn.targetRef.id)
|
|
|
|
if (targetTask) {
|
|
|
|
canvas.addMarker(nn.id, targetTask.endTime ? 'highlight' : 'highlight-todo')
|
|
|
|
canvas.addMarker(nn.targetRef.id, targetTask.endTime ? 'highlight' : 'highlight-todo')
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
} else if (n.$type === 'bpmn:StartEvent') {
|
|
|
|
n.outgoing?.forEach(nn => {
|
|
|
|
let completeTask = this.tasks.find(m => m.definitionKey === nn.targetRef.id)
|
|
|
|
if (completeTask) {
|
|
|
|
canvas.addMarker(nn.id, 'highlight');
|
|
|
|
canvas.addMarker(n.id, 'highlight');
|
|
|
|
return
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else if (n.$type === 'bpmn:EndEvent') {
|
|
|
|
if (endTask.definitionKey === n.id && endTask.endTime) {
|
|
|
|
canvas.addMarker(n.id, 'highlight')
|
|
|
|
return
|
|
|
|
}
|
2022-01-18 01:41:22 +08:00
|
|
|
}
|
|
|
|
})
|
2022-01-03 02:41:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
</script>
|
2022-01-18 01:41:22 +08:00
|
|
|
|
|
|
|
<style>
|
2022-01-18 08:15:43 +08:00
|
|
|
|
|
|
|
.highlight.djs-shape .djs-visual > :nth-child(1) {
|
|
|
|
fill: green !important;
|
|
|
|
stroke: green !important;
|
|
|
|
fill-opacity: 0.2 !important;
|
2022-01-18 01:41:22 +08:00
|
|
|
}
|
2022-01-18 08:15:43 +08:00
|
|
|
.highlight.djs-shape .djs-visual > :nth-child(2) {
|
|
|
|
fill: green !important;
|
|
|
|
}
|
|
|
|
.highlight.djs-shape .djs-visual > path {
|
|
|
|
fill: green !important;
|
|
|
|
fill-opacity: 0.2 !important;
|
|
|
|
stroke: green !important;
|
|
|
|
}
|
|
|
|
.highlight.djs-connection > .djs-visual > path {
|
|
|
|
stroke: green !important;
|
|
|
|
}
|
|
|
|
|
|
|
|
.highlight-todo.djs-connection > .djs-visual > path {
|
|
|
|
stroke: orange !important;
|
|
|
|
stroke-dasharray: 4px !important;
|
|
|
|
fill-opacity: 0.2 !important;
|
|
|
|
}
|
|
|
|
.highlight-todo.djs-shape .djs-visual > :nth-child(1) {
|
|
|
|
fill: orange !important;
|
|
|
|
stroke: orange !important;
|
|
|
|
stroke-dasharray: 4px !important;
|
|
|
|
fill-opacity: 0.2 !important;
|
2022-01-18 01:41:22 +08:00
|
|
|
}
|
|
|
|
|
2022-01-18 08:15:43 +08:00
|
|
|
.highlight:not(.djs-connection) .djs-visual > :nth-child(1) {
|
|
|
|
fill: green !important; /* color elements as green */
|
|
|
|
}
|
2022-01-18 01:41:22 +08:00
|
|
|
|
|
|
|
/deep/.highlight.djs-shape .djs-visual > :nth-child(1) {
|
|
|
|
fill: green !important;
|
|
|
|
stroke: green !important;
|
|
|
|
fill-opacity: 0.2 !important;
|
|
|
|
}
|
|
|
|
/deep/.highlight.djs-shape .djs-visual > :nth-child(2) {
|
|
|
|
fill: green !important;
|
|
|
|
}
|
|
|
|
/deep/.highlight.djs-shape .djs-visual > path {
|
|
|
|
fill: green !important;
|
|
|
|
fill-opacity: 0.2 !important;
|
|
|
|
stroke: green !important;
|
|
|
|
}
|
|
|
|
/deep/.highlight.djs-connection > .djs-visual > path {
|
|
|
|
stroke: green !important;
|
|
|
|
}
|
|
|
|
/deep/.highlight-todo.djs-connection > .djs-visual > path {
|
|
|
|
stroke: orange !important;
|
|
|
|
stroke-dasharray: 4px !important;
|
|
|
|
fill-opacity: 0.2 !important;
|
|
|
|
marker-end: url(#sequenceflow-end-_E7DFDF-_E7DFDF-803g1kf6zwzmcig1y2ulm5egr);
|
|
|
|
}
|
|
|
|
/deep/.highlight-todo.djs-shape .djs-visual > :nth-child(1) {
|
|
|
|
fill: orange !important;
|
|
|
|
stroke: orange !important;
|
|
|
|
stroke-dasharray: 4px !important;
|
|
|
|
fill-opacity: 0.2 !important;
|
|
|
|
}
|
2022-01-18 08:15:43 +08:00
|
|
|
|
2022-01-18 01:41:22 +08:00
|
|
|
</style>
|