first commit
This commit is contained in:
@@ -0,0 +1,292 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="jee-bpm-graphic-containers">
|
||||
<div class="jee-bpm-graphic-canvas" :id="containerId"></div>
|
||||
</div>
|
||||
<bpm-node-info-modal @register="registerModal" @notify="handleModalVisible"></bpm-node-info-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { watch, ref, onMounted } from 'vue';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import BpmNodeInfoModal from './BpmNodeInfoModal.vue';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import inherits from 'inherits';
|
||||
import Viewer from 'bpmn-js/lib/Viewer';
|
||||
import ZoomScrollModule from 'diagram-js/lib/navigation/zoomscroll';
|
||||
import MoveCanvasModule from 'diagram-js/lib/navigation/movecanvas';
|
||||
import { append as svgAppend, attr as svgAttr, create as svgCreate } from 'tiny-svg';
|
||||
import { query as domQuery } from 'min-dom';
|
||||
function CustomViewer(options) {
|
||||
Viewer.call(this, options);
|
||||
}
|
||||
inherits(CustomViewer, Viewer);
|
||||
CustomViewer.prototype._modules = [].concat(Viewer.prototype._modules, [ZoomScrollModule, MoveCanvasModule]);
|
||||
|
||||
export default {
|
||||
name: 'BpmGraphic',
|
||||
props: {
|
||||
// 流程实例ID
|
||||
instanceId: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
center:{
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
BpmNodeInfoModal,
|
||||
},
|
||||
emits: ['task'],
|
||||
setup(props, { emit }) {
|
||||
const url = {
|
||||
getProcessInfo: '/act/designer/api/getProcessXmlByInstanceId',
|
||||
getInstanceInfo: '/act/task/getFlowMsgByProcInstId',
|
||||
getNodePositionInfo: '/act/task/getNodePositionInfo',
|
||||
};
|
||||
const [registerModal, { openModal, closeModal }] = useModal();
|
||||
const containerId = 'jee-bpm-graphic-canvas';
|
||||
let bpmViewer = null;
|
||||
onMounted(() => {
|
||||
newViewer();
|
||||
});
|
||||
|
||||
let taskList = [];
|
||||
let currentTaskId = '';
|
||||
let currentNodeList = [];
|
||||
let historyNodeList = [];
|
||||
let historyLineList = [];
|
||||
let delayHandler = '';
|
||||
|
||||
watch(
|
||||
() => props.instanceId,
|
||||
(val) => {
|
||||
if (val) {
|
||||
init();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
async function init() {
|
||||
let params = { processInstanceId: props.instanceId };
|
||||
// 1.加载流程设计xml
|
||||
let xml = await defHttp.get({ url: url.getProcessInfo, params }, { isTransformResponse: false });
|
||||
//console.log('xml', xml);
|
||||
// 2.加载流程实例信息
|
||||
let instanceInfo = await defHttp.get({ url: url.getInstanceInfo, params }, { isTransformResponse: false });
|
||||
//console.log('instanceInfo', instanceInfo);
|
||||
// 2.加载节点信息 NY5LzSY2VW1BSthYSnJArCFqbgwtZqSuyPQ/OD1n1twWJGU2RN/wkzf+kBVO5DztN85Ca9keeuaRAiwcatr8N0M15+Wv2SmRw82lMwawE2naX5tpJMpkxrUhUUcjnC+BSBL4+PV2JUXBFW8/oOG8HLqYvmPxoP7MMBhMi9D7lRY=
|
||||
let nodeInfo = await defHttp.get({ url: url.getNodePositionInfo, params }, { isTransformResponse: false });
|
||||
//console.log('nodeInfo', nodeInfo);
|
||||
if (nodeInfo.success) {
|
||||
taskList = nodeInfo.result.hisTasks;
|
||||
emit('task', taskList);
|
||||
}
|
||||
// console.log('taskList', nodeInfo.result)
|
||||
try {
|
||||
// 3.解析流程实例信息
|
||||
if (instanceInfo.success) {
|
||||
historyNodeList = instanceInfo.result.highLightedActivitiIdList;
|
||||
currentNodeList = instanceInfo.result.runningActivitiIdList;
|
||||
historyLineList = instanceInfo.result.highLightedFlowIds;
|
||||
}
|
||||
// 4.绘制流程
|
||||
newViewer();
|
||||
const result = await bpmViewer.importXML(xml);
|
||||
const { warnings } = result;
|
||||
console.log('bpm graphic warnings', warnings);
|
||||
// 5.调整图片位置
|
||||
const canvas = bpmViewer.get('canvas');
|
||||
if(props.center == true){
|
||||
canvas.zoom('fit-viewport', true);
|
||||
}
|
||||
// 6.创建箭头标记
|
||||
createArrow();
|
||||
// 7.设置节点、线的颜色
|
||||
setColor();
|
||||
// 8.节点事件
|
||||
addEvent();
|
||||
} catch (err) {
|
||||
console.log(err.message, err.warnings);
|
||||
}
|
||||
}
|
||||
|
||||
function setColor() {
|
||||
// access viewer components
|
||||
const canvas = bpmViewer.get('canvas');
|
||||
// 获取到全部节点
|
||||
const allShapes = bpmViewer.get('elementRegistry').getAll();
|
||||
//循环节点添加class
|
||||
allShapes.forEach((element) => {
|
||||
const shapeId = element.businessObject.id;
|
||||
// const shapeAttrs = element.businessObject.$attrs
|
||||
//console.info('123element', element)
|
||||
let type = element.type;
|
||||
if (type == 'bpmn:ExclusiveGateway' || type == 'bpmn:InclusiveGateway' || type == 'bpmn:ParallelGateway') {
|
||||
canvas.addMarker(shapeId, 'jee-bpm-gateway');
|
||||
}
|
||||
// add marker
|
||||
if (element.businessObject.$type != 'bpmn:Group') {
|
||||
if (element.businessObject.$type == 'bpmn:SequenceFlow') {
|
||||
if (historyLineList.includes(shapeId)) {
|
||||
canvas.addMarker(shapeId, 'jee-bpm-history-line');
|
||||
}
|
||||
} else {
|
||||
if (historyNodeList.includes(shapeId) && !currentNodeList.includes(shapeId)) {
|
||||
canvas.addMarker(shapeId, 'jee-bpm-history-node');
|
||||
}
|
||||
if (currentNodeList.includes(shapeId)) {
|
||||
canvas.addMarker(shapeId, 'jee-bpm-current-node');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 自定义箭头标记-默认箭头是黑色的
|
||||
function createArrow() {
|
||||
const marker = svgCreate('marker');
|
||||
svgAttr(marker, {
|
||||
id: 'active-arrow',
|
||||
viewBox: '0 0 20 20',
|
||||
refX: '11',
|
||||
refY: '10',
|
||||
markerWidth: '10',
|
||||
markerHeight: '10',
|
||||
orient: 'auto',
|
||||
fill: '#408af1',
|
||||
});
|
||||
const path = svgCreate('path');
|
||||
svgAttr(path, {
|
||||
d: 'M 1 5 L 11 10 L 1 15 Z',
|
||||
style: 'stroke-width: 1px; stroke-linecap: round; stroke-dasharray: 10000, 1;',
|
||||
});
|
||||
const defs = domQuery('defs');
|
||||
svgAppend(marker, path);
|
||||
svgAppend(defs, marker);
|
||||
}
|
||||
|
||||
//添加节点事件
|
||||
function addEvent() {
|
||||
const eventBus = bpmViewer.get('eventBus');
|
||||
eventBus.on('element.hover', (e) => {
|
||||
const { element } = e;
|
||||
if (!element.parent) {
|
||||
// 这里关闭modal
|
||||
delayClose();
|
||||
currentTaskId = '';
|
||||
//console.log('鼠标移至空白处', element);
|
||||
return;
|
||||
}
|
||||
if (!e || element.type === 'bpmn:Process') {
|
||||
return false;
|
||||
} else {
|
||||
let temp = element.id;
|
||||
let type = element.type;
|
||||
if (currentTaskId != temp && 'bpmn:UserTask' == type && historyNodeList.indexOf(temp) >= 0) {
|
||||
/**
|
||||
* 满足3个条件才弹框显示节点信息
|
||||
* 1.当前节点不是鼠标选中的节点,防止多次调用
|
||||
* 2.必须是任务节点
|
||||
* 3.必须是处理过的节点
|
||||
*/
|
||||
currentTaskId = temp;
|
||||
//console.log('准备开启modal', e);
|
||||
showNodeInfo();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function showNodeInfo() {
|
||||
closeModal();
|
||||
openModal(true, {
|
||||
dataList: taskList,
|
||||
taskId: currentTaskId,
|
||||
});
|
||||
}
|
||||
|
||||
function handleModalVisible(flag) {
|
||||
//console.log('handleModalVisible', flag)
|
||||
if (flag == true) {
|
||||
clearTimeout(delayHandler);
|
||||
}
|
||||
}
|
||||
|
||||
function delayClose() {
|
||||
//console.log('delayClose')
|
||||
delayHandler = setTimeout(() => {
|
||||
//console.log('准备关闭modal');
|
||||
if (currentTaskId) {
|
||||
showNodeInfo();
|
||||
} else {
|
||||
closeModal();
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function newViewer() {
|
||||
if (bpmViewer == null) {
|
||||
let dom = document.getElementById(containerId);
|
||||
bpmViewer = new CustomViewer({
|
||||
container: dom,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
registerModal,
|
||||
containerId,
|
||||
handleModalVisible,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.jee-bpm-graphic-containers {
|
||||
width: 100%;
|
||||
height: calc(100vh - 250px);
|
||||
}
|
||||
|
||||
.jee-bpm-graphic-canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.jee-bpm-graphic-canvas .bjs-powered-by {
|
||||
display: none;
|
||||
}
|
||||
/**网关样式*/
|
||||
.jee-bpm-gateway .djs-visual path {
|
||||
stroke: none !important;
|
||||
}
|
||||
|
||||
/**走过的分支线样式 */
|
||||
.jee-bpm-history-line .djs-visual > :nth-child(1) {
|
||||
stroke: #408af1 !important;
|
||||
}
|
||||
.jee-bpm-history-line path {
|
||||
marker-end: url(#active-arrow) !important;
|
||||
stroke-width: 2px!important;
|
||||
}
|
||||
|
||||
/**走过的节点样式 */
|
||||
.jee-bpm-history-node .djs-visual > :nth-child(1) {
|
||||
fill: #51a2f13b !important;
|
||||
stroke: #408af1 !important;
|
||||
}
|
||||
|
||||
/**当前节点样式 */
|
||||
.jee-bpm-current-node .djs-visual > :nth-child(1) {
|
||||
fill: #f9ca6d !important;
|
||||
stroke: #cd9423 !important;
|
||||
}
|
||||
/* .jee-bpm-current-node .djs-visual > text {
|
||||
fill: #fff !important;
|
||||
}*/
|
||||
</style>
|
||||
Reference in New Issue
Block a user