index.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. var __read = (this && this.__read) || function (o, n) {
  2. var m = typeof Symbol === "function" && o[Symbol.iterator];
  3. if (!m) return o;
  4. var i = m.call(o), r, ar = [], e;
  5. try {
  6. while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
  7. }
  8. catch (error) { e = { error: error }; }
  9. finally {
  10. try {
  11. if (r && !r.done && (m = i["return"])) m.call(i);
  12. }
  13. finally { if (e) throw e.error; }
  14. }
  15. return ar;
  16. };
  17. import { getBpmnId } from './bpmnIds';
  18. import { lfJson2Xml } from './json2xml';
  19. import { lfXml2Json } from './xml2json';
  20. import { ExclusiveGatewayConfig, StartEventConfig, EndEventConfig, ServiceTaskConfig, UserTaskConfig, } from '../bpmn/constant';
  21. var BpmnElements;
  22. (function (BpmnElements) {
  23. BpmnElements["START"] = "bpmn:startEvent";
  24. BpmnElements["END"] = "bpmn:endEvent";
  25. BpmnElements["GATEWAY"] = "bpmn:exclusiveGateway";
  26. BpmnElements["USER"] = "bpmn:userTask";
  27. BpmnElements["SYSTEM"] = "bpmn:serviceTask";
  28. BpmnElements["FLOW"] = "bpmn:sequenceFlow";
  29. })(BpmnElements || (BpmnElements = {}));
  30. var defaultAttrs = ['-name', '-id', 'bpmn:incoming', 'bpmn:outgoing', '-sourceRef', '-targetRef'];
  31. /**
  32. * 将普通json转换为xmlJson
  33. * xmlJson中property会以“-”开头
  34. * 如果没有“-”表示为子节点
  35. */
  36. function toXmlJson(json) {
  37. var xmlJson = {};
  38. Object.entries(json).forEach(function (_a) {
  39. var _b = __read(_a, 2), key = _b[0], value = _b[1];
  40. if (typeof value !== 'object') {
  41. if (key.indexOf('-') === 0) { // 如果本来就是“-”开头的了,那就不处理了。
  42. xmlJson[key] = value;
  43. }
  44. else {
  45. xmlJson["-" + key] = value;
  46. }
  47. }
  48. else {
  49. xmlJson[key] = toXmlJson(value);
  50. }
  51. });
  52. return xmlJson;
  53. }
  54. /**
  55. * 将xmlJson转换为普通的json,在内部使用。
  56. */
  57. function toNormalJson(xmlJson) {
  58. var json = {};
  59. Object.entries(xmlJson).forEach(function (_a) {
  60. var _b = __read(_a, 2), key = _b[0], value = _b[1];
  61. if (typeof value === 'string') {
  62. if (key.indexOf('-') === 0) { // 如果本来就是“-”开头的了,那就不处理了。
  63. json[key.substr(1)] = value;
  64. }
  65. else {
  66. json[key] = value;
  67. }
  68. }
  69. else if (typeof value === 'object') {
  70. json[key] = toNormalJson(value);
  71. }
  72. else {
  73. json[key] = value;
  74. }
  75. });
  76. return json;
  77. }
  78. /**
  79. * 设置bpmn process信息
  80. * 目标格式请参考examples/bpmn.json
  81. * bpmn因为是默认基于xml格式的,其特点与json存在差异。
  82. * 1) 如果是xml的属性,json中属性用'-'开头
  83. * 2)如果只有一个子元素,json中表示为正常属性
  84. * 3)如果是多个子元素,json中使用数组存储
  85. */
  86. function convertLf2ProcessData(bpmnProcessData, data) {
  87. var nodeMap = new Map();
  88. data.nodes.forEach(function (node) {
  89. var _a;
  90. var processNode = {
  91. '-id': node.id,
  92. };
  93. if ((_a = node.text) === null || _a === void 0 ? void 0 : _a.value) {
  94. processNode['-name'] = node.text.value;
  95. }
  96. if (node.properties) {
  97. var properties = toXmlJson(node.properties);
  98. Object.assign(processNode, properties);
  99. }
  100. nodeMap.set(node.id, processNode);
  101. if (!bpmnProcessData[node.type]) {
  102. bpmnProcessData[node.type] = processNode; // 如果只有一个子元素,json中表示为正常属性
  103. }
  104. else if (Array.isArray(bpmnProcessData[node.type])) { // 如果是多个子元素,json中使用数组存储
  105. bpmnProcessData[node.type].push(processNode);
  106. }
  107. else { // 如果是多个子元素,json中使用数组存储
  108. bpmnProcessData[node.type] = [
  109. bpmnProcessData[node.type],
  110. processNode,
  111. ];
  112. }
  113. });
  114. var sequenceFlow = data.edges.map(function (edge) {
  115. var _a, _b;
  116. var targetNode = nodeMap.get(edge.targetNodeId);
  117. // @see https://github.com/didi/LogicFlow/issues/325
  118. // 需要保证incomming在outgoing之前
  119. if (!targetNode['bpmn:incoming']) {
  120. targetNode['bpmn:incoming'] = edge.id;
  121. }
  122. else if (Array.isArray(targetNode['bpmn:incoming'])) {
  123. targetNode['bpmn:incoming'].push(edge.id);
  124. }
  125. else {
  126. targetNode['bpmn:incoming'] = [
  127. targetNode['bpmn:incoming'],
  128. edge.id,
  129. ];
  130. }
  131. var sourceNode = nodeMap.get(edge.sourceNodeId);
  132. if (!sourceNode['bpmn:outgoing']) {
  133. sourceNode['bpmn:outgoing'] = edge.id;
  134. }
  135. else if (Array.isArray(sourceNode['bpmn:outgoing'])) {
  136. sourceNode['bpmn:outgoing'].push(edge.id);
  137. }
  138. else { // 字符串转数组
  139. sourceNode['bpmn:outgoing'] = [
  140. sourceNode['bpmn:outgoing'],
  141. edge.id,
  142. ];
  143. }
  144. var edgeConfig = {
  145. '-id': edge.id,
  146. '-sourceRef': edge.sourceNodeId,
  147. '-targetRef': edge.targetNodeId,
  148. };
  149. if ((_a = edge.text) === null || _a === void 0 ? void 0 : _a.value) {
  150. edgeConfig['-name'] = (_b = edge.text) === null || _b === void 0 ? void 0 : _b.value;
  151. }
  152. if (edge.properties) {
  153. var properties = toXmlJson(edge.properties);
  154. Object.assign(edgeConfig, properties);
  155. }
  156. return edgeConfig;
  157. });
  158. bpmnProcessData[BpmnElements.FLOW] = sequenceFlow;
  159. }
  160. /**
  161. * adapterOut 设置bpmn diagram信息
  162. */
  163. function convertLf2DiagramData(bpmnDiagramData, data) {
  164. bpmnDiagramData['bpmndi:BPMNEdge'] = data.edges.map(function (edge) {
  165. var _a;
  166. var edgeId = edge.id;
  167. var pointsList = edge.pointsList.map(function (_a) {
  168. var x = _a.x, y = _a.y;
  169. return ({ '-x': x, '-y': y });
  170. });
  171. var diagramData = {
  172. '-id': edgeId + "_di",
  173. '-bpmnElement': edgeId,
  174. 'di:waypoint': pointsList,
  175. };
  176. if ((_a = edge.text) === null || _a === void 0 ? void 0 : _a.value) {
  177. diagramData['bpmndi:BPMNLabel'] = {
  178. 'dc:Bounds': {
  179. '-x': edge.text.x - (edge.text.value.length * 10) / 2,
  180. '-y': edge.text.y - 7,
  181. '-width': edge.text.value.length * 10,
  182. '-height': 14,
  183. },
  184. };
  185. }
  186. return diagramData;
  187. });
  188. bpmnDiagramData['bpmndi:BPMNShape'] = data.nodes.map(function (node) {
  189. var _a;
  190. var nodeId = node.id;
  191. var width = 100;
  192. var height = 80;
  193. var x = node.x, y = node.y;
  194. // bpmn坐标是基于左上角,LogicFlow基于中心点,此处处理一下。
  195. var shapeConfig = BpmnAdapter.shapeConfigMap.get(node.type);
  196. if (shapeConfig) {
  197. width = shapeConfig.width;
  198. height = shapeConfig.height;
  199. }
  200. x -= width / 2;
  201. y -= height / 2;
  202. var diagramData = {
  203. '-id': nodeId + "_di",
  204. '-bpmnElement': nodeId,
  205. 'dc:Bounds': {
  206. '-x': x,
  207. '-y': y,
  208. '-width': width,
  209. '-height': height,
  210. },
  211. };
  212. if ((_a = node.text) === null || _a === void 0 ? void 0 : _a.value) {
  213. diagramData['bpmndi:BPMNLabel'] = {
  214. 'dc:Bounds': {
  215. '-x': node.text.x - (node.text.value.length * 10) / 2,
  216. '-y': node.text.y - 7,
  217. '-width': node.text.value.length * 10,
  218. '-height': 14,
  219. },
  220. };
  221. }
  222. return diagramData;
  223. });
  224. }
  225. /**
  226. * 将bpmn数据转换为LogicFlow内部能识别数据
  227. */
  228. function convertBpmn2LfData(bpmnData) {
  229. var nodes = [];
  230. var edges = [];
  231. var definitions = bpmnData['bpmn:definitions'];
  232. if (definitions) {
  233. var process_1 = definitions['bpmn:process'];
  234. Object.keys(process_1).forEach(function (key) {
  235. if (key.indexOf('bpmn:') === 0) {
  236. var value = process_1[key];
  237. if (key === BpmnElements.FLOW) {
  238. var bpmnEdges = definitions['bpmndi:BPMNDiagram']['bpmndi:BPMNPlane']['bpmndi:BPMNEdge'];
  239. edges = getLfEdges(value, bpmnEdges);
  240. }
  241. else {
  242. var shapes = definitions['bpmndi:BPMNDiagram']['bpmndi:BPMNPlane']['bpmndi:BPMNShape'];
  243. nodes = nodes.concat(getLfNodes(value, shapes, key));
  244. }
  245. }
  246. });
  247. }
  248. return {
  249. nodes: nodes,
  250. edges: edges,
  251. };
  252. }
  253. function getLfNodes(value, shapes, key) {
  254. var nodes = [];
  255. if (Array.isArray(value)) { // 数组
  256. value.forEach(function (val) {
  257. var shapeValue;
  258. if (Array.isArray(shapes)) {
  259. shapeValue = shapes.find(function (shape) { return shape['-bpmnElement'] === val['-id']; });
  260. }
  261. else {
  262. shapeValue = shapes;
  263. }
  264. var node = getNodeConfig(shapeValue, key, val);
  265. nodes.push(node);
  266. });
  267. }
  268. else {
  269. var shapeValue = void 0;
  270. if (Array.isArray(shapes)) {
  271. shapeValue = shapes.find(function (shape) { return shape['-bpmnElement'] === value['-id']; });
  272. }
  273. else {
  274. shapeValue = shapes;
  275. }
  276. var node = getNodeConfig(shapeValue, key, value);
  277. nodes.push(node);
  278. }
  279. return nodes;
  280. }
  281. function getNodeConfig(shapeValue, type, processValue) {
  282. var x = Number(shapeValue['dc:Bounds']['-x']);
  283. var y = Number(shapeValue['dc:Bounds']['-y']);
  284. var name = processValue['-name'];
  285. var shapeConfig = BpmnAdapter.shapeConfigMap.get(type);
  286. if (shapeConfig) {
  287. x += shapeConfig.width / 2;
  288. y += shapeConfig.height / 2;
  289. }
  290. var properties;
  291. // 判断是否存在额外的属性,将额外的属性放到properties中
  292. Object.entries(processValue).forEach(function (_a) {
  293. var _b = __read(_a, 2), key = _b[0], value = _b[1];
  294. if (defaultAttrs.indexOf(key) === -1) {
  295. if (!properties)
  296. properties = {};
  297. properties[key] = value;
  298. }
  299. });
  300. if (properties) {
  301. properties = toNormalJson(properties);
  302. }
  303. var text;
  304. if (name) {
  305. text = {
  306. x: x,
  307. y: y,
  308. value: name,
  309. };
  310. // 自定义文本位置
  311. if (shapeValue['bpmndi:BPMNLabel'] && shapeValue['bpmndi:BPMNLabel']['dc:Bounds']) {
  312. var textBounds = shapeValue['bpmndi:BPMNLabel']['dc:Bounds'];
  313. text.x = Number(textBounds['-x']) + Number(textBounds['-width']) / 2;
  314. text.y = Number(textBounds['-y']) + Number(textBounds['-height']) / 2;
  315. }
  316. }
  317. var nodeConfig = {
  318. id: shapeValue['-bpmnElement'],
  319. type: type,
  320. x: x,
  321. y: y,
  322. properties: properties,
  323. };
  324. if (text) {
  325. nodeConfig.text = text;
  326. }
  327. return nodeConfig;
  328. }
  329. function getLfEdges(value, bpmnEdges) {
  330. var edges = [];
  331. if (Array.isArray(value)) {
  332. value.forEach(function (val) {
  333. var edgeValue;
  334. if (Array.isArray(bpmnEdges)) {
  335. edgeValue = bpmnEdges.find(function (edge) { return edge['-bpmnElement'] === val['-id']; });
  336. }
  337. else {
  338. edgeValue = bpmnEdges;
  339. }
  340. edges.push(getEdgeConfig(edgeValue, val));
  341. });
  342. }
  343. else {
  344. var edgeValue = void 0;
  345. if (Array.isArray(bpmnEdges)) {
  346. edgeValue = bpmnEdges.find(function (edge) { return edge['-bpmnElement'] === value['-id']; });
  347. }
  348. else {
  349. edgeValue = bpmnEdges;
  350. }
  351. edges.push(getEdgeConfig(edgeValue, value));
  352. }
  353. return edges;
  354. }
  355. function getEdgeConfig(edgeValue, processValue) {
  356. var text;
  357. var textVal = processValue['-name'];
  358. if (textVal) {
  359. var textBounds = edgeValue['bpmndi:BPMNLabel']['dc:Bounds'];
  360. // 如果边文本换行,则其偏移量应该是最长一行的位置
  361. var textLength_1 = 0;
  362. textVal.split('\n').forEach(function (textSpan) {
  363. if (textLength_1 < textSpan.length) {
  364. textLength_1 = textSpan.length;
  365. }
  366. });
  367. text = {
  368. value: textVal,
  369. x: Number(textBounds['-x']) + (textLength_1 * 10) / 2,
  370. y: Number(textBounds['-y']) + 7,
  371. };
  372. }
  373. var properties;
  374. // 判断是否存在额外的属性,将额外的属性放到properties中
  375. Object.entries(processValue).forEach(function (_a) {
  376. var _b = __read(_a, 2), key = _b[0], value = _b[1];
  377. if (defaultAttrs.indexOf(key) === -1) {
  378. if (!properties)
  379. properties = {};
  380. properties[key] = value;
  381. }
  382. });
  383. if (properties) {
  384. properties = toNormalJson(properties);
  385. }
  386. var edge = {
  387. id: processValue['-id'],
  388. type: BpmnElements.FLOW,
  389. pointsList: edgeValue['di:waypoint'].map(function (point) { return ({
  390. x: Number(point['-x']),
  391. y: Number(point['-y']),
  392. }); }),
  393. sourceNodeId: processValue['-sourceRef'],
  394. targetNodeId: processValue['-targetRef'],
  395. properties: properties,
  396. };
  397. if (text) {
  398. edge.text = text;
  399. }
  400. return edge;
  401. }
  402. var BpmnAdapter = {
  403. pluginName: 'bpmn-adapter',
  404. install: function (lf) {
  405. lf.adapterIn = this.adapterIn;
  406. lf.adapterOut = this.adapterOut;
  407. },
  408. shapeConfigMap: new Map(),
  409. setCustomShape: function (key, val) {
  410. this.shapeConfigMap.set(key, val);
  411. },
  412. adapterOut: function (data) {
  413. var bpmnProcessData = {
  414. '-id': "Process_" + getBpmnId(),
  415. '-isExecutable': 'false',
  416. };
  417. convertLf2ProcessData(bpmnProcessData, data);
  418. var bpmnDiagramData = {
  419. '-id': 'BPMNPlane_1',
  420. '-bpmnElement': bpmnProcessData['-id'],
  421. };
  422. convertLf2DiagramData(bpmnDiagramData, data);
  423. var bpmnData = {
  424. 'bpmn:definitions': {
  425. '-id': "Definitions_" + getBpmnId(),
  426. '-xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
  427. '-xmlns:bpmn': 'http://www.omg.org/spec/BPMN/20100524/MODEL',
  428. '-xmlns:bpmndi': 'http://www.omg.org/spec/BPMN/20100524/DI',
  429. '-xmlns:dc': 'http://www.omg.org/spec/DD/20100524/DC',
  430. '-xmlns:di': 'http://www.omg.org/spec/DD/20100524/DI',
  431. '-targetNamespace': 'http://bpmn.io/schema/bpmn',
  432. '-exporter': 'bpmn-js (https://demo.bpmn.io)',
  433. '-exporterVersion': '7.3.0',
  434. 'bpmn:process': bpmnProcessData,
  435. 'bpmndi:BPMNDiagram': {
  436. '-id': 'BPMNDiagram_1',
  437. 'bpmndi:BPMNPlane': bpmnDiagramData,
  438. },
  439. },
  440. };
  441. return bpmnData;
  442. },
  443. adapterIn: function (bpmnData) {
  444. if (bpmnData) {
  445. return convertBpmn2LfData(bpmnData);
  446. }
  447. },
  448. };
  449. BpmnAdapter.shapeConfigMap.set(BpmnElements.START, {
  450. width: StartEventConfig.width,
  451. height: StartEventConfig.height,
  452. });
  453. BpmnAdapter.shapeConfigMap.set(BpmnElements.END, {
  454. width: EndEventConfig.width,
  455. height: EndEventConfig.height,
  456. });
  457. BpmnAdapter.shapeConfigMap.set(BpmnElements.GATEWAY, {
  458. width: ExclusiveGatewayConfig.width,
  459. height: ExclusiveGatewayConfig.height,
  460. });
  461. BpmnAdapter.shapeConfigMap.set(BpmnElements.SYSTEM, {
  462. width: ServiceTaskConfig.width,
  463. height: ServiceTaskConfig.height,
  464. });
  465. BpmnAdapter.shapeConfigMap.set(BpmnElements.USER, {
  466. width: UserTaskConfig.width,
  467. height: UserTaskConfig.height,
  468. });
  469. var BpmnXmlAdapter = {
  470. pluginName: 'bpmnXmlAdapter',
  471. install: function (lf) {
  472. lf.adapterIn = this.adapterXmlIn;
  473. lf.adapterOut = this.adapterXmlOut;
  474. },
  475. adapterXmlIn: function (bpmnData) {
  476. var json = lfXml2Json(bpmnData);
  477. return BpmnAdapter.adapterIn(json);
  478. },
  479. adapterXmlOut: function (data) {
  480. var outData = BpmnAdapter.adapterOut(data);
  481. return lfJson2Xml(outData);
  482. },
  483. };
  484. export { BpmnAdapter, BpmnXmlAdapter, };
  485. export default BpmnAdapter;