diff --git a/package-lock.json b/package-lock.json index e4c6c0c..e68d7f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,6 @@ "@wangeditor/editor-for-vue": "^5.1.12", "alova": "^3.4.0", "axios": "^0.24.0", - "bpmn-js": "^17.11.1", "lodash": "^4.17.21", "mitt": "^3.0.1", "mockjs": "^1.1.0", @@ -296,16 +295,6 @@ "node": ">=6.9.0" } }, - "node_modules/@bpmn-io/diagram-js-ui": { - "version": "0.2.4", - "resolved": "https://registry.npmmirror.com/@bpmn-io/diagram-js-ui/-/diagram-js-ui-0.2.4.tgz", - "integrity": "sha512-I678ZGtoH7z7FgzFhzzppM9ThsJ3Lh83kW3GjhjG3xyYciIPYHMaHK1MABP8F69H9pFZpViM6t4qUo8dwrVz0w==", - "license": "MIT", - "dependencies": { - "htm": "^3.1.1", - "preact": "^10.29.2" - } - }, "node_modules/@braintree/sanitize-url": { "version": "7.1.2", "resolved": "https://registry.npmmirror.com/@braintree/sanitize-url/-/sanitize-url-7.1.2.tgz", @@ -2974,36 +2963,6 @@ "dev": true, "license": "ISC" }, - "node_modules/bpmn-js": { - "version": "17.11.1", - "resolved": "https://registry.npmmirror.com/bpmn-js/-/bpmn-js-17.11.1.tgz", - "integrity": "sha512-ywCeTg5kvN8lYkU+fHE+YXTGlfKc55lRBn7zW3k1//toeMNPy/PS/uQiujRWdFhMrH5dbtDvlwWukNw2pjWw8Q==", - "license": "SEE LICENSE IN LICENSE", - "dependencies": { - "bpmn-moddle": "^8.1.0", - "diagram-js": "^14.10.0", - "diagram-js-direct-editing": "^3.0.1", - "ids": "^1.0.5", - "inherits-browser": "^0.1.0", - "min-dash": "^4.1.1", - "min-dom": "^4.2.1", - "tiny-svg": "^3.1.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/bpmn-moddle": { - "version": "8.1.0", - "resolved": "https://registry.npmmirror.com/bpmn-moddle/-/bpmn-moddle-8.1.0.tgz", - "integrity": "sha512-yI5OAFfYVJwViKTsTsonVfCBPtB3MlefADUORwNIxxBOMp21vnoxuxsdgUWlPH/dvAEZh/+mr8UtqOBNu8NC5Q==", - "license": "MIT", - "dependencies": { - "min-dash": "^4.0.0", - "moddle": "^6.2.3", - "moddle-xml": "^10.1.0" - } - }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz", @@ -3306,15 +3265,6 @@ "node": ">=0.8" } }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/collection-visit/-/collection-visit-1.0.0.tgz", @@ -3373,12 +3323,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/component-event": { - "version": "0.2.1", - "resolved": "https://registry.npmmirror.com/component-event/-/component-event-0.2.1.tgz", - "integrity": "sha512-wGA++isMqiDq1jPYeyv2as/Bt/u+3iLW0rEa+8NQ82jAv3TgqMiCM+B2SaBdn2DfLilLjjq736YcezihRYhfxw==", - "license": "MIT" - }, "node_modules/compute-scroll-into-view": { "version": "1.0.20", "resolved": "https://registry.npmmirror.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz", @@ -4325,79 +4269,6 @@ "node": ">=8" } }, - "node_modules/diagram-js": { - "version": "14.11.3", - "resolved": "https://registry.npmmirror.com/diagram-js/-/diagram-js-14.11.3.tgz", - "integrity": "sha512-Seq9BHAXfzKS60L4v4Gvgvv72wOtvrfJQAyyPm9pntSZDMzjoodPSXnEUPud1G2zVCMGEUUW++s0reEdaWgkXA==", - "license": "MIT", - "dependencies": { - "@bpmn-io/diagram-js-ui": "^0.2.3", - "clsx": "^2.1.0", - "didi": "^10.2.2", - "inherits-browser": "^0.1.0", - "min-dash": "^4.1.0", - "min-dom": "^4.2.1", - "object-refs": "^0.4.0", - "path-intersection": "^3.0.0", - "tiny-svg": "^3.1.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/diagram-js-direct-editing": { - "version": "3.5.1", - "resolved": "https://registry.npmmirror.com/diagram-js-direct-editing/-/diagram-js-direct-editing-3.5.1.tgz", - "integrity": "sha512-fEQCQ/x5oKVV0m7Nmgv7i85Vhw+kJkKNXF8zcV5Vm0KwF8x/8e3Ax0aJgdXt8/fDPymEkY8HmZweXIipCeeh+g==", - "license": "MIT", - "dependencies": { - "min-dash": "^5.0.0", - "min-dom": "^5.3.0" - }, - "engines": { - "node": "*" - }, - "peerDependencies": { - "diagram-js": "*" - } - }, - "node_modules/diagram-js-direct-editing/node_modules/domify": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/domify/-/domify-3.0.0.tgz", - "integrity": "sha512-bs2yO68JDFOm6rKv8f0EnrM2cENduhRkpqOtt/s5l5JBA/eqGBZCzLPmdYoHtJ6utgLGgcBajFsEQbl12pT0lQ==", - "license": "MIT", - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/diagram-js-direct-editing/node_modules/min-dash": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/min-dash/-/min-dash-5.1.0.tgz", - "integrity": "sha512-HAvN6XzmCQj+js43G9sJRRw8kj/7DvoxN7qhoIN9Xo5ZN1NMljtpyKs/NunXmw0QSWwlgZzNv6tLeEa4xaZ0tg==", - "license": "MIT" - }, - "node_modules/diagram-js-direct-editing/node_modules/min-dom": { - "version": "5.3.0", - "resolved": "https://registry.npmmirror.com/min-dom/-/min-dom-5.3.0.tgz", - "integrity": "sha512-0w5FEBgPAyHhmFojW3zxd7we3D+m5XYS3E/06OyvxmbHJoiQVa4Nagj6RWvoAKYRw5xth6cP5TMePc5cR1M9hA==", - "license": "MIT", - "dependencies": { - "domify": "^3.0.0", - "min-dash": "^5.0.0" - } - }, - "node_modules/didi": { - "version": "10.2.2", - "resolved": "https://registry.npmmirror.com/didi/-/didi-10.2.2.tgz", - "integrity": "sha512-l8NYkYFXV1izHI65EyT8EXOjUZtKmQkHLTT89cSP7HU5J/G7AOj0dXKtLc04EXYlga99PBY18IPjOeZ+c3DI4w==", - "license": "MIT", - "engines": { - "node": ">= 16" - } - }, "node_modules/dingbat-to-unicode": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/dingbat-to-unicode/-/dingbat-to-unicode-1.0.1.tgz", @@ -4466,15 +4337,6 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/domify": { - "version": "1.4.2", - "resolved": "https://registry.npmmirror.com/domify/-/domify-1.4.2.tgz", - "integrity": "sha512-m4yreHcUWHBncGVV7U+yQzc12vIlq0jMrtHZ5mW6dQMiL/7skSYNVX9wqKwOtyO9SGCgevrAFEgOCAHmamHTUA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/dompurify": { "version": "3.4.15", "resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-3.4.15.tgz", @@ -5660,12 +5522,6 @@ "integrity": "sha512-CW/pPvSOFIRsosbwxrYaE9ERmpTo5fbTqL7wCvuCFlqW1Bmb1K5fXsY7yiH95rmlr4rVuA7UXHbM/cIXQ6AXwg==", "license": "Apache-2.0" }, - "node_modules/htm": { - "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/htm/-/htm-3.1.1.tgz", - "integrity": "sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==", - "license": "Apache-2.0" - }, "node_modules/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmmirror.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -5851,12 +5707,6 @@ "node": ">=0.10.0" } }, - "node_modules/ids": { - "version": "1.0.5", - "resolved": "https://registry.npmmirror.com/ids/-/ids-1.0.5.tgz", - "integrity": "sha512-XQ0yom/4KWTL29sLG+tyuycy7UmeaM/79GRtSJq6IG9cJGIPeBz5kwDCguie3TwxaMNIc3WtPi0cTa1XYHicpw==", - "license": "MIT" - }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz", @@ -5946,12 +5796,6 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, - "node_modules/inherits-browser": { - "version": "0.1.0", - "resolved": "https://registry.npmmirror.com/inherits-browser/-/inherits-browser-0.1.0.tgz", - "integrity": "sha512-CJHHvW3jQ6q7lzsXPpapLdMx5hDpSF3FSh45pwsj6bKxJJ8Nl8v43i5yXnr3BdfOimGHKyniewQtnAIp3vyJJw==", - "license": "ISC" - }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/internal-slot/-/internal-slot-1.1.0.tgz", @@ -7153,23 +6997,6 @@ "node": ">=6" } }, - "node_modules/min-dash": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/min-dash/-/min-dash-4.2.3.tgz", - "integrity": "sha512-VLMYQI5+FcD9Ad24VcB08uA83B07OhueAlZ88jBK6PyupTvEJwllTMUqMy0wPGYs7pZUEtEEMWdHB63m3LtEcg==", - "license": "MIT" - }, - "node_modules/min-dom": { - "version": "4.2.1", - "resolved": "https://registry.npmmirror.com/min-dom/-/min-dom-4.2.1.tgz", - "integrity": "sha512-TMoL8SEEIhUWYgkj7XMSgxmwSyGI+4fP2KFFGnN3FbHfbGHVdsLYSz8LoIsgPhz4dWRmLvxWWSMgzZMJW5sZuA==", - "license": "MIT", - "dependencies": { - "component-event": "^0.2.1", - "domify": "^1.4.1", - "min-dash": "^4.2.1" - } - }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz", @@ -7236,26 +7063,6 @@ "random": "bin/random" } }, - "node_modules/moddle": { - "version": "6.2.3", - "resolved": "https://registry.npmmirror.com/moddle/-/moddle-6.2.3.tgz", - "integrity": "sha512-bLVN+ZHL3aKnhxc19XtjUfvdJsS3EsiEJC7bT6YPD11qYmTzvsxrGgyYz1Ouof7TZuGw0lDJ1OLmEnxcpQWk3Q==", - "license": "MIT", - "dependencies": { - "min-dash": "^4.0.0" - } - }, - "node_modules/moddle-xml": { - "version": "10.1.0", - "resolved": "https://registry.npmmirror.com/moddle-xml/-/moddle-xml-10.1.0.tgz", - "integrity": "sha512-erWckwLt+dYskewKXJso9u+aAZ5172lOiYxSOqKCPTy7L/xmqH1PoeoA7eVC7oJTt3PqF5TkZzUmbjGH6soQBg==", - "license": "MIT", - "dependencies": { - "min-dash": "^4.0.0", - "moddle": "^6.0.0", - "saxen": "^8.1.2" - } - }, "node_modules/mrmime": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/mrmime/-/mrmime-2.0.1.tgz", @@ -7624,15 +7431,6 @@ "node": ">= 0.4" } }, - "node_modules/object-refs": { - "version": "0.4.0", - "resolved": "https://registry.npmmirror.com/object-refs/-/object-refs-0.4.0.tgz", - "integrity": "sha512-6kJqKWryKZmtte6QYvouas0/EIJKPI1/MMIuRsiBlNuhIMfqYTggzX2F1AJ2+cDs288xyi9GL7FyasHINR98BQ==", - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/object-visit": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/object-visit/-/object-visit-1.0.1.tgz", @@ -7929,15 +7727,6 @@ "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==", "license": "MIT" }, - "node_modules/path-intersection": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/path-intersection/-/path-intersection-3.1.0.tgz", - "integrity": "sha512-3xS3lvv/vuwm5aH2BVvNRvnvwR2Drde7jQClKpCXTYXIMMjcw/EnMhzCgeHwqbCpzi760PEfAkU53vSIlrNr9A==", - "license": "MIT", - "engines": { - "node": ">= 14.20" - } - }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -8860,12 +8649,6 @@ "node": ">=11.0.0" } }, - "node_modules/saxen": { - "version": "8.1.2", - "resolved": "https://registry.npmmirror.com/saxen/-/saxen-8.1.2.tgz", - "integrity": "sha512-xUOiiFbc3Ow7p8KMxwsGICPx46ZQvy3+qfNVhrkwfz3Vvq45eGt98Ft5IQaA1R/7Tb5B5MKh9fUR9x3c3nDTxw==", - "license": "MIT" - }, "node_modules/scroll-into-view-if-needed": { "version": "2.2.31", "resolved": "https://registry.npmmirror.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz", @@ -9875,12 +9658,6 @@ "integrity": "sha512-wtTRjG92pM5eUg/KuUnHsqSAlPM296brTOcLgMRqEeylYTh/CdtvKUvCyyCQTzFuStieWxvZb8mVTMvdPyUpxg==", "license": "MIT" }, - "node_modules/tiny-svg": { - "version": "3.1.3", - "resolved": "https://registry.npmmirror.com/tiny-svg/-/tiny-svg-3.1.3.tgz", - "integrity": "sha512-9mwnPqXInRsBmH/DO6NMxBE++9LsqpVXQSSTZGc5bomoKKvL5OX/Hlotw7XVXP6XLRcHWIzZpxfovGqWKgCypQ==", - "license": "MIT" - }, "node_modules/tiny-warning": { "version": "1.0.3", "resolved": "https://registry.npmmirror.com/tiny-warning/-/tiny-warning-1.0.3.tgz", diff --git a/package.json b/package.json index 8b09ce1..82e6521 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ "@wangeditor/editor-for-vue": "^5.1.12", "alova": "^3.4.0", "axios": "^0.24.0", - "bpmn-js": "^17.11.1", "lodash": "^4.17.21", "mitt": "^3.0.1", "mockjs": "^1.1.0", diff --git a/src/views/flow/admin/def-editor/bpmn/custom.ts b/src/views/flow/admin/def-editor/bpmn/custom.ts deleted file mode 100644 index 747ba81..0000000 --- a/src/views/flow/admin/def-editor/bpmn/custom.ts +++ /dev/null @@ -1,110 +0,0 @@ -/** - * bpmn-js 定制模块:调色板/上下文垫收敛为 4 类业务节点 + 汉化。 - * 拖拽/多选/撤销重做/缩放平移均为 bpmn-js 内建能力,此处无需实现。 - * 调色板与上下文垫只暴露业务语义的 5 类元素(开始/结束/审批/并行分发/并行合并用同一 ParallelGateway, - * split/join 由 serialize.ts 以扩展属性 flowNodeType 显式标记),其余 BPMN 形状对管理员隐藏。 - * bpmn.io 水印为协议要求,不做隐藏。 - */ -import Modeler from "bpmn-js/lib/Modeler"; -import PaletteProvider from "bpmn-js/lib/features/palette/PaletteProvider"; -// 必需:diagram-js 画布/连线/调色板样式 + bpmn 字体图标;漏引会导致连线变黑条、黑锚点外露、左侧工具栏不可见 -import "diagram-js/assets/diagram-js.css"; -import "bpmn-js/dist/assets/bpmn-js.css"; -import "bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css"; - -/** 汉化词表(palette/contextPad/常用按钮;未命中键原样透回) */ -const TRANSLATIONS: Record = { - "Create StartEvent": "创建开始", - "Create EndEvent": "创建结束", - "Create Task": "创建审批节点", - "Create User Task": "创建审批节点", - "Create Service Task": "创建抄送节点", - "Create Gateway": "创建并行分支", - "Create Gateways": "创建并行分支", - "Create ParallelGateway": "创建并行分支", - "Create expanded ParallelGateway": "创建并行分支", - "Create ExclusiveGateway": "创建条件分支", - "Create expanded ExclusiveGateway": "创建条件分支", - "Append anything": "追加", - "Change type": "变更类型", - "Remove element": "删除", - Connect: "连线", - "Connect to other element": "连线到其他元素", - "Connect using Association/Sequence/DataAssociation": "连线", - "Activate the global connect tool": "激活全局连线工具", - "Activate the create/remove space tool": "激活空间调整工具", - "Activate the lasso tool": "激活套索选择", - "Activate the hand tool": "激活平移", - "Activate the direct editing tool": "激活文本编辑", - undo: "撤销", - redo: "重做", -}; - -function createTranslateModule() { - return { - translate: [ - "value", - (template: string, replacements?: Record) => { - let t = TRANSLATIONS[template] || template; - if (replacements) { - for (const [k, v] of Object.entries(replacements)) { - t = t.replace(`{${k}}`, v); - } - } - return t; - }, - ], - }; -} - -/** 调色板收敛:仅连线工具 + 4 类节点 */ -function createPaletteModule() { - function CustomPaletteProvider(this: unknown, palette: unknown, create: unknown, elementFactory: unknown, - globalConnect: unknown, translate: unknown) { - // @ts-expect-error 继承自 bpmn-js 内部父类(js 库,无类型面板) - PaletteProvider.call(this, palette, create, elementFactory, globalConnect, translate); - this.create = create; - this.elementFactory = elementFactory; - this.globalConnect = globalConnect; - this.translate = translate; - } - CustomPaletteProvider.$inject = ["palette", "create", "elementFactory", "globalConnect", "translate"]; - CustomPaletteProvider.prototype = Object.create(PaletteProvider.prototype); - CustomPaletteProvider.prototype.getPaletteEntries = function (this: { elementFactory: unknown } & Record) { - const { create, elementFactory, translate, globalConnect } = this as Record; - const action = (type: string, label: string, className: string) => ({ - group: "flow", - className, - title: translate(label), - action: { - dragstart: (evt: unknown) => create.start(evt, elementFactory.createShape({ type })), - click: (evt: unknown) => create.start(evt, elementFactory.createShape({ type })), - }, - }); - return { - "lc-connect": { - group: "tools", - className: "bpmn-icon-connection-multi", - title: translate("连线"), - action: { click: (evt: unknown) => globalConnect.toggle(evt) }, - }, - "lc-sep": { group: "tools", separator: true }, - "lc-start": action("bpmn:StartEvent", "创建开始", "bpmn-icon-start-event-none"), - "lc-end": action("bpmn:EndEvent", "创建结束", "bpmn-icon-end-event-none"), - "lc-task": action("bpmn:UserTask", "创建审批节点", "bpmn-icon-user-task"), - "lc-notify": action("bpmn:ServiceTask", "创建抄送节点", "bpmn-icon-send-task"), - "lc-gateway": action("bpmn:ParallelGateway", "创建并行分支", "bpmn-icon-gateway-parallel"), - "lc-condition": action("bpmn:ExclusiveGateway", "创建条件分支", "bpmn-icon-gateway-xor"), - }; - }; - return { __init__: ["paletteProvider"], paletteProvider: ["type", CustomPaletteProvider] }; -} - -/** 创建设计器实例(调色板收敛 + 汉化;快捷键绑定 window:Ctrl+Z 撤销等) */ -export function createDesigner(container: HTMLElement): Modeler { - return new Modeler({ - container, - keyboard: { bindTo: window }, - additionalModules: [createPaletteModule(), createTranslateModule()], - }); -} diff --git a/src/views/flow/admin/def-editor/bpmn/serialize.ts b/src/views/flow/admin/def-editor/bpmn/serialize.ts deleted file mode 100644 index e8a530c..0000000 --- a/src/views/flow/admin/def-editor/bpmn/serialize.ts +++ /dev/null @@ -1,277 +0,0 @@ -/** - * contentJson(+layout) ⇄ bpmn-js 内存图 双向转换(画布模式数据通道)。 - * - * 设计决策(方案 §二):BPMN XML 不作为持久化格式——contentJson 仍是唯一运行时格式, - * bpmn-js 仅作内存画布。节点映射:START→StartEvent / END→EndEvent / APPROVAL→UserTask / - * PARALLEL_SPLIT|JOIN→ParallelGateway,用扩展属性 flowNodeType 显式区分 split/join - * (不靠出入度推断,用户编辑连线后语义不漂移);出边 name 即多出口按钮文案。 - * 坐标缺失(旧定义无 layout)时用共享 flowLayout 算初始坐标。 - */ -import { layout as autoLayout } from "@/utils/flowLayout"; - -/** bpmn 画布尺寸(与 flowLayout 的槽位框不同——bpmn 内建元素有自己尺寸,就不指定 shape 尺寸) */ -const CANVAS_GAP_X = 96; -const CANVAS_ROW_H = 96; -const CANVAS_START = { x: 160, y: 160 }; - -/** 画布模式读写接口(与后端 contentJson 同构,另含可选 layout 坐标) */ -export interface CanvasJson { - code: string; - name: string; - start: string; - nodes: Array>; - edges: Array>; - settings: Record; - layout?: Record; -} - -const BPMN_TYPE: Record = { - START: "bpmn:StartEvent", - END: "bpmn:EndEvent", - APPROVAL: "bpmn:UserTask", - NOTIFY: "bpmn:ServiceTask", - PARALLEL_SPLIT: "bpmn:ParallelGateway", - PARALLEL_JOIN: "bpmn:ParallelGateway", - CONDITION: "bpmn:ExclusiveGateway", -}; - -/** 把 contentJson 画到画布上(缺 layout 时自动布局) */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function toBpmn(modeler: any, def: CanvasJson): void { - const nodes = def.nodes || []; - const edges = def.edges || []; - // 自动布局:有保存坐标用保存坐标,否则 Kahn 分层换算为 bpmn 网格 - let pos: Record = def.layout || (undefined as never); - if (!pos || !Object.keys(pos).length) { - const auto = autoLayout({ nodes, edges }); - pos = {}; - Object.entries(auto).forEach(([id, p]) => { - pos![id] = { x: CANVAS_START.x + p.x + p.w / 2, y: CANVAS_START.y + p.y + p.h / 2 }; - }); - } - const modeling = modeler.get("modeling"); - const canvas = modeler.get("canvas"); - const root = canvas.getRootElement(); - const byId: Record = {}; - nodes.forEach((n) => { - const type = BPMN_TYPE[String(n.type)]; - if (!type) return; // 未知类型不渲染(local validate 会提示) - const p = pos[String(n.id)] || CANVAS_START; - const shape = modeling.createShape({ type }, { x: p.x, y: p.y }, root); - // id 必须显式落 businessObject:配置回填与跨会话稳定绑定都按 contentJson 的节点 id 走 - // (若不设,bpmn-js 生成 Task_xxx 随机 id,二次载入时审批人/会签等配置将失配丢失) - // 节点名(直编可改);split/join 语义由「载入显式类型 / 读出按出入度」两段规则维持,存储在 contentJson - modeling.updateProperties(shape, { id: String(n.id), name: String(n.name || "") }); - byId[String(n.id)] = shape; - }); - edges.forEach((e) => { - const src = byId[String(e.from)]; - const tgt = byId[String(e.to)]; - if (!src || !tgt) return; - // connect(source, target) 按规则自动建 SequenceFlow - const conn = modeling.connect(src, tgt); - if (e.name) { - modeling.updateProperties(conn, { name: String(e.name) }); - } - }); -} - -/** bpmn 内存图 → {nodes,edges,layout}:遍历 elementRegistry 序列化回 contentJson 主体 */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function fromBpmn(modeler: any, base: CanvasJson, code: string, name: string): CanvasJson { - const registry = modeler.get("elementRegistry"); - const all = registry.getAll(); - const nodes: Array> = []; - const edges: Array> = []; - const layoutOut: Record = {}; - let startId = ""; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const nodeTypeOf = (n: any): string | null => { - switch (n.type) { - case "bpmn:StartEvent": { - return "START"; - } - case "bpmn:EndEvent": { - return "END"; - } - case "bpmn:UserTask": { - return "APPROVAL"; - } - case "bpmn:ServiceTask": { - return "NOTIFY"; - } - case "bpmn:ParallelGateway": { - // 读出推断:>1 入 = 汇聚;否则分发(存储在 contentJson,故多数载入已在 JSON 有显式类型) - return (n.incoming || []).length > 1 ? "PARALLEL_JOIN" : "PARALLEL_SPLIT"; - } - case "bpmn:ExclusiveGateway": { - // CONDITION 无 join 对应物(排他网关不用于汇聚):多入口也按条件分支读出 - return "CONDITION"; - } - default: - return null; - } - }; - // 节点业务配置(审批人等)以 base 内容继承,这里只做几何/连线 - all.forEach((n: any) => { - const type = nodeTypeOf(n); - if (!type) return; - const biz = n.businessObject || {}; - const node: Record = { - id: String(biz.id || n.id), - type, - }; - if (biz.name) node.name = biz.name; - if (type === "APPROVAL" || type === "NOTIFY" || type === "CONDITION") { - // 审批人/抄送对象/判断服务等业务属性:从 base 中同 id 继承(编辑连线不影响已有配置) - const prev = base.nodes.find((x) => String(x.id) === String(node.id)); - if (prev) { - const keys = type === "APPROVAL" - ? ["assignee", "countersign", "deadlineHours"] - : type === "NOTIFY" ? ["receivers"] : ["routerKey"]; - keys.forEach((k) => { - if (prev[k] !== undefined) node[k] = prev[k]; - }); - if (!node.name && prev.name) node.name = prev.name; - } - } - nodes.push(node); - layoutOut[String(node.id)] = { x: Math.round(n.x), y: Math.round(n.y) }; - if (type === "START") startId = String(node.id); - }); - all.forEach((n: any) => { - (n.outgoing || []).forEach((c: any) => { - if (c.type !== "bpmn:SequenceFlow") return; - const target = c.target; - if (!target) return; - const edge: Record = { - from: String(n.businessObject.id || n.id), - to: String(target.businessObject.id || target.id), - }; - if (c.businessObject?.name) edge.name = c.businessObject.name; - edges.push(edge); - }); - }); - if (!startId && nodes.length) { - throw new Error("画布缺少开始节点"); - } - // 已有定义继承 settings/审批配置由 base 传入 - return { - code, - name, - start: startId, - nodes, - edges, - settings: base?.settings || { rejectPolicy: "END_REJECTED" }, - layout: layoutOut, - }; -} - -/** contentJson → CanvasJson(对既有 struct 直接加 layout) */ -export function toCanvasJson(contentJson: string | CanvasJson): CanvasJson { - if (typeof contentJson === "string") { - return JSON.parse(contentJson) as CanvasJson; - } - return contentJson; -} - -/** 查看器 BPMN DI 形状尺寸(事件 36、网关 50、任务两行文本 150x76) */ -const DI_SIZE: Record = { - START: { w: 36, h: 36 }, - END: { w: 36, h: 36 }, - APPROVAL: { w: 150, h: 76 }, - NOTIFY: { w: 150, h: 76 }, - PARALLEL_SPLIT: { w: 50, h: 50 }, - PARALLEL_JOIN: { w: 50, h: 50 }, - CONDITION: { w: 50, h: 50 }, -}; - -/** - * contentJson(+layout) → 可导入只读 Viewer 的 BPMN XML(含 DI 布局)。 - * 画布视图专用:bpmn-js Viewer 没有 modeling 模块,不能走 toBpmn 的程序化布点, - * 直接生成带 BPMNShape/BPMNEdge 的 XML 一次导入;连线给正交 waypoints(右中→中线→左中)。 - */ -export function toBpmnXml(def: CanvasJson): string { - const nodes: any[] = def.nodes || []; - const edges: any[] = def.edges || []; - // 元素中心点:layout 覆盖全部节点用 layout(编辑器保存的是中心坐标),否则回退自动布局 - const saved = def.layout || {}; - const useSaved = nodes.length > 0 && nodes.every((n) => saved[String(n.id)]); - const centers: Record = {}; - if (useSaved) { - nodes.forEach((n) => { centers[String(n.id)] = saved[String(n.id)]; }); - } else { - const auto = autoLayout({ nodes, edges }); - nodes.forEach((n) => { - const p = auto[String(n.id)]; - if (p) centers[String(n.id)] = { x: p.x + p.w / 2, y: p.y + p.h / 2 }; - }); - } - const esc = (s: unknown): string => - String(s ?? "").replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); - const body = nodes.filter((n) => BPMN_TYPE[String(n.type)] && centers[String(n.id)]); - const flows = edges.filter((e) => centers[String(e.from)] && centers[String(e.to)]); - - const elems = body - .map((n) => { - const tag = BPMN_TYPE[String(n.type)].replace("bpmn:", ""); - const name = n.name ? ` name="${esc(n.name)}"` : ""; - return ` `; - }) - .join("\n"); - const flowElems = flows - .map((e, i) => { - const name = e.name ? ` name="${esc(e.name)}"` : ""; - return ` `; - }) - .join("\n"); - - const bounds = (id: string): { x: number; y: number; w: number; h: number } => { - const c = centers[id]; - const type = String(nodes.find((n) => String(n.id) === id)?.type || "APPROVAL"); - const s = DI_SIZE[type] || DI_SIZE.APPROVAL; - return { x: Math.round(c.x - s.w / 2), y: Math.round(c.y - s.h / 2), w: s.w, h: s.h }; - }; - const shapes = body - .map((n) => { - const b = bounds(String(n.id)); - return ` - - `; - }) - .join("\n"); - const edgeDi = flows - .map((e, i) => { - const fb = bounds(String(e.from)); - const tb = bounds(String(e.to)); - const x1 = fb.x + fb.w; - const y1 = fb.y + fb.h / 2; - const x2 = tb.x; - const y2 = tb.y + tb.h / 2; - const mid = Math.round((x1 + x2) / 2); - const pts = Math.abs(y1 - y2) < 2 - ? [[x1, y1], [x2, y2]] - : [[x1, y1], [mid, y1], [mid, y2], [x2, y2]]; - const wp = pts.map(([x, y]) => ` `).join("\n"); - return ` \n${wp}\n `; - }) - .join("\n"); - - return ` - - -${elems} -${flowElems} - - - -${shapes} -${edgeDi} - - -`; -} diff --git a/src/views/flow/admin/def-editor/components/BpmnCanvas.vue b/src/views/flow/admin/def-editor/components/BpmnCanvas.vue deleted file mode 100644 index 3eb50f2..0000000 --- a/src/views/flow/admin/def-editor/components/BpmnCanvas.vue +++ /dev/null @@ -1,226 +0,0 @@ - - - - -