Files
pet-ai/web/src/components/gva-wfd/util/bpmn.js
T

226 lines
10 KiB
JavaScript

/* eslint-disable */
function tab(len){
return [...Array(len)].map(a => " ").join('')
}
export function exportXML(json,canvas,createFile = true) {
const id = canvas.id || "flow";
const name = canvas.name || "flow";
let dataObjs = "";
canvas.dataObjs.forEach(s => {
dataObjs += `${tab(4)}<dataObject id="${s.id}" name="${s.name}" itemSubjectRef="xsd:${s.type}"></dataObject>\n`;
});
let signals = "";
canvas.signalDefs.forEach(s => {
signals += `${tab(2)}<signal id="${s.id}" name="${s.name}" flowable:scope="${s.scope}"></signal>\n`;
});
let messages = "";
canvas.messageDefs.forEach(s => {
messages += `${tab(2)}<message id="${s.id}" name="${s.name}"></message>\n`;
});
let BPMNShape = ``;
let BPMNEdge = ``;
let processXML = `${tab(2)}<process id="${id}" name="${name}">\n`;
processXML += dataObjs;
json.nodes.forEach(node => {
BPMNShape += `${tab(6)}<bpmndi:BPMNShape bpmnElement="${node.id}" id="BPMNShape_${node.id}">\n`+
`${tab(8)}<omgdc:Bounds width="${node.size[0]}" height="${node.size[1]}" x="${node.x}" y="${node.y}"></omgdc:Bounds>\n`+
`${tab(6)}</bpmndi:BPMNShape>\n`;
switch (node.clazz) {
case 'start':
processXML += `${tab(4)}<startEvent id="${node.id}"></startEvent>\n`;
break;
case 'end':
processXML += `${tab(4)}<endEvent id="${node.id}"></endEvent>\n`;
break;
case 'userTask': {
let assignments = "";
if(node.assignValue && node.assignValue.length > 0){
if(node.assignType === 'person'){
assignments += `flowable:candidateUsers="${node.assignValue.join(',')}"`;
}else if(node.assignType === 'assignee'){
assignments += `flowable:assignee="${node.assignValue[0]}"`;
}else if(node.assignType === 'persongroup'){
assignments += `flowable:candidateGroups="${node.assignValue.join(',')}"`;
}
}
processXML += `${tab(4)}<userTask id="${node.id}" name="${node.label}" ${assignments}></userTask>\n`;
break;
}
case 'javaTask': {
let javaClass = "";
if(node.javaClass){
javaClass = `flowable:class="${node.javaClass}"`;
}
processXML += `${tab(4)}<serviceTask id="${node.id}" name="${node.label}" ${javaClass}></serviceTask>\n`;
break;
}
case 'scriptTask': {
let script = "";
if(node.script) {
script = `${tab(6)}<script><![CDATA[${node.script}]]></script>\n`;
}
processXML += `${tab(4)}<scriptTask id="${node.id}" name="${node.label}">\n${script}${tab(4)}</scriptTask>\n`;
break;
}
case 'receiveTask':
processXML += `${tab(4)}<receiveTask id="${node.id}" name="${node.label}"></receiveTask>\n`;
break;
case 'mailTask': {
let to = `${tab(8)}<flowable:field name="to">\n`;
to += `${tab(10)}<flowable:string><![CDATA[${node.to}]]></flowable:string>\n`;
to += `${tab(8)}</flowable:field>\n`;
let subject = `${tab(8)}<flowable:field name="subject">\n`;
subject += `${tab(10)}<flowable:string><![CDATA[${node.subject}]]></flowable:string>\n`;
subject += `${tab(8)}</flowable:field>\n`;
let text = `${tab(8)}<flowable:field name="text">\n`;
text += `${tab(10)}<flowable:string><![CDATA[${node.content}]]></flowable:string>\n`;
text += `${tab(8)}</flowable:field>\n`;
let extension = `${tab(6)}<extensionElements>\n${to}${subject}${text}${tab(6)}</extensionElements>\n`;
processXML += `${tab(4)}<serviceTask id="${node.id}" name="${node.label}" flowable:type="mail">\n${extension}${tab(4)}</serviceTask>\n`;
break;
}
case 'timerStart': {
const timer = `${tab(6)}<timerEventDefinition>\n${tab(8)}<timeCycle>${node.cycle}</timeCycle>\n${tab(6)}</timerEventDefinition>\n`;
processXML += `${tab(4)}<startEvent id="${node.id}" isInterrupting="false">\n${timer}${tab(4)}</startEvent>\n`;
break;
}
case 'timerCatch': {
const timer = `${tab(6)}<timerEventDefinition>\n${tab(8)}<timeCycle>${node.cycle}</timeCycle>\n${tab(6)}</timerEventDefinition>\n`;
processXML += `${tab(4)}<intermediateCatchEvent id="${node.id}">\n${timer}${tab(4)}</intermediateCatchEvent>\n`;
break;
}
case 'signalStart': {
const signal = `${tab(6)}<signalEventDefinition signalRef="${node.signal}"></signalEventDefinition>\n`;
processXML += `${tab(4)}<startEvent id="${node.id}" isInterrupting="true">\n${signal}${tab(4)}</startEvent>\n`;
break;
}
case 'signalCatch': {
const signal = `${tab(6)}<signalEventDefinition signalRef="${node.signal}"></signalEventDefinition>\n`;
processXML += `${tab(4)}<intermediateCatchEvent id="${node.id}">\n${signal}${tab(4)}</intermediateCatchEvent>\n`;
break;
}
case 'messageStart': {
const message = `${tab(6)}<messageEventDefinition messageRef="${node.message}"></messageEventDefinition>\n`;
processXML += `${tab(4)}<startEvent id="${node.id}" isInterrupting="true">\n${message}${tab(4)}</startEvent>\n`;
break;
}
case 'messageCatch': {
const message = `${tab(6)}<messageEventDefinition messageRef="${node.message}"></messageEventDefinition>\n`;
processXML += `${tab(4)}<intermediateCatchEvent id="${node.id}">\n${message}${tab(4)}</intermediateCatchEvent>\n`;
break;
}
case 'gateway':
processXML += `${tab(4)}<exclusiveGateway id="${node.id}" name="${node.label}"></exclusiveGateway>\n`;
break;
case 'exclusiveGateway':
processXML += `${tab(4)}<exclusiveGateway id="${node.id}" name="${node.label}"></exclusiveGateway>\n`;
break;
case 'parallelGateway':
processXML += `${tab(4)}<parallelGateway id="${node.id}" name="${node.label}"></parallelGateway>\n`;
break;
case 'inclusiveGateway':
processXML += `${tab(4)}<inclusiveGateway id="${node.id}" name="${node.label}"></inclusiveGateway>\n`;
break;
default:
break;
}
});
json.edges.forEach(edge => {
BPMNEdge += `${tab(6)}<bpmndi:BPMNEdge bpmnElement="${edge.source}_${edge.sourceAnchor}-${edge.target}_${edge.targetAnchor}" `+
`id="BPMNEdge_${edge.source}_${edge.sourceAnchor}-${edge.target}_${edge.targetAnchor}">\n`+
`${tab(8)}<omgdi:waypoint x="${edge.startPoint.x}" y="${edge.startPoint.y}"></omgdi:waypoint>\n`+
`${tab(8)}<omgdi:waypoint x="${edge.endPoint.x}" y="${edge.endPoint.y}"></omgdi:waypoint>\n`+
`${tab(6)}</bpmndi:BPMNEdge>\n`;
let condition = "";
if(edge.conditionExpression){
condition = `${tab(6)}<conditionExpression xsi:type="tFormalExpression"><![CDATA[${edge.conditionExpression}]]></conditionExpression>\n`;
}
processXML += `${tab(4)}<sequenceFlow id="${edge.source}_${edge.sourceAnchor}-${edge.target}_${edge.targetAnchor}" sourceRef="${edge.source}" targetRef="${edge.target}">${condition}</sequenceFlow>\n`;
});
processXML += `${tab(2)}</process>\n`;
let BPMNDiagram = `${tab(2)}<bpmndi:BPMNDiagram id="BPMNDiagram_${id}">\n`+
`${tab(4)}<bpmndi:BPMNPlane bpmnElement="${id}" id="BPMNPlane_${id}">\n${BPMNShape}${BPMNEdge}${tab(4)}</bpmndi:BPMNPlane>\n`+
`${tab(2)}</bpmndi:BPMNDiagram>\n`;
let xml = `<?xml version="1.0" encoding="UTF-8"?>\n`;
xml += `<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" `+
`xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" `+
`xmlns:xsd="http://www.w3.org/2001/XMLSchema" `+
`xmlns:flowable="http://flowable.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.flowable.org/processdef">\n`;
xml += signals;
xml += messages;
xml += processXML;
xml += BPMNDiagram;
xml += `</definitions>`;
if(createFile) {
downloadFile(xml, 'application/xml;charset=utf-8;', `${name}.bpmn20.xml`)
}
return xml;
}
export function exportImg(canvasPanel,filename,createFile = true) {
filename = filename || 'flow'
let canvas = canvasPanel.querySelector('canvas')
let context = canvas.getContext('2d')
let imgData = context.getImageData(0, 0, canvas.width, canvas.height).data
let left = canvas.width;
let right = 0;
let top = canvas.height;
let bottom = 0
for (let i = 0; i < canvas.width; i++) {
for (let j = 0; j < canvas.height; j++) {
let pos = (i + canvas.width * j) * 4
if (imgData[pos] > 0 || imgData[pos + 1] > 0 || imgData[pos + 2] || imgData[pos + 3] > 0) {
bottom = Math.max(j, bottom) // 找到有色彩的最下端
right = Math.max(i, right) // 找到有色彩的最右端
top = Math.min(j, top) // 找到有色彩的最上端
left = Math.min(i, left) // 找到有色彩的最左端
}
}
}
let c = document.createElement('canvas')
// 四周空白余量
let blankWidth = 60
c.width = right - left + blankWidth*2
c.height = bottom - top + blankWidth*2
let ctx = c.getContext('2d')
// 设置白底
ctx.fillStyle = '#fff';
ctx.fillRect(0, 0, c.width, c.height);
ctx.drawImage(canvas, left-blankWidth, top-blankWidth, c.width, c.height, 0, 0, c.width, c.height)
let data = c.toDataURL("image/jpeg")
if(createFile) {
let parts = data.split(';base64,');
let contentType = parts[0].split(':')[1];
let raw = window.atob(parts[1]);
let uInt8Array = new Uint8Array(raw.length);
for (let i = 0; i < raw.length; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
downloadFile(uInt8Array, contentType, `${filename}.jpg`)
}
return data
}
function downloadFile(data, type, filename) {
const blob = new Blob([data], { type });
let link = document.createElement('a');
if (link.download !== undefined) {
let url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}