cc12458 6 месяцев назад
Родитель
Сommit
31691f991f

+ 5 - 0
package.json

@@ -14,6 +14,10 @@
   },
   "dependencies": {
     "@ant-design/icons-vue": "^7.0.1",
+    "@logicflow/core": "^2.1.2",
+    "@logicflow/extension": "^2.1.4",
+    "@logicflow/layout": "^2.0.2",
+    "@logicflow/vue-node-registry": "^1.1.3",
     "@unocss/reset": "^0.61.0",
     "@vueuse/components": "^10.11.0",
     "@vueuse/core": "^10.11.0",
@@ -27,6 +31,7 @@
     "pinia-plugin-persistedstate": "^3.2.1",
     "swiper": "^8.4.7",
     "v-selectpage": "^3.0.1",
+    "vite-svg-loader": "^5.1.0",
     "vue": "^3.4.29",
     "vue-echarts": "^7.0.2",
     "vue-range-component": "^1.0.3",

+ 292 - 0
pnpm-lock.yaml

@@ -11,6 +11,18 @@ importers:
       '@ant-design/icons-vue':
         specifier: ^7.0.1
         version: 7.0.1(vue@3.5.13(typescript@5.4.5))
+      '@logicflow/core':
+        specifier: ^2.1.2
+        version: 2.1.2
+      '@logicflow/extension':
+        specifier: ^2.1.4
+        version: 2.1.4(@logicflow/core@2.1.2)(@logicflow/vue-node-registry@1.1.3(@logicflow/core@2.1.2)(vue@3.5.13(typescript@5.4.5)))
+      '@logicflow/layout':
+        specifier: ^2.0.2
+        version: 2.0.2
+      '@logicflow/vue-node-registry':
+        specifier: ^1.1.3
+        version: 1.1.3(@logicflow/core@2.1.2)(vue@3.5.13(typescript@5.4.5))
       '@unocss/reset':
         specifier: ^0.61.0
         version: 0.61.9
@@ -50,6 +62,9 @@ importers:
       v-selectpage:
         specifier: ^3.0.1
         version: 3.0.1(vue@3.5.13(typescript@5.4.5))
+      vite-svg-loader:
+        specifier: ^5.1.0
+        version: 5.1.0(vue@3.5.13(typescript@5.4.5))
       vue:
         specifier: ^3.4.29
         version: 3.5.13(typescript@5.4.5)
@@ -68,6 +83,9 @@ importers:
       vue3-slider:
         specifier: ^1.10.1
         version: 1.10.1(vue@3.5.13(typescript@5.4.5))
+      vuedraggable:
+        specifier: ^4.1.0
+        version: 4.1.0(vue@3.5.13(typescript@5.4.5))
       vxe-pc-ui:
         specifier: ^4.6.42
         version: 4.6.42(vue@3.5.13(typescript@5.4.5))
@@ -194,6 +212,9 @@ packages:
   '@antfu/utils@8.1.1':
     resolution: {integrity: sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==}
 
+  '@antv/hierarchy@0.6.14':
+    resolution: {integrity: sha512-V3uknf7bhynOqQDw2sg+9r9DwZ9pc6k/EcqyTFdfXB1+ydr7urisP0MipIuimucvQKN+Qkd+d6w601r1UIroqQ==}
+
   '@babel/code-frame@7.26.2':
     resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==}
     engines: {node: '>=6.9.0'}
@@ -860,6 +881,28 @@ packages:
   '@jridgewell/trace-mapping@0.3.25':
     resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
 
+  '@logicflow/core@2.1.2':
+    resolution: {integrity: sha512-2LW4ZMt0krcEgybkbnn1L0SzSXv02eEMAbTMKwQzBd4Bi2Si56j/OxMMLmx+dhfLNzw2g8JW/98Aj0tP8gDxcw==}
+
+  '@logicflow/extension@2.1.4':
+    resolution: {integrity: sha512-vMYwWYaNQNYruqdKnm7vcP4PiP+sIadulZfycmC+Acdn/3JYCEtAZzJOGt5gorG8F1H5vKXIXOFzwVLuuetoLQ==}
+    peerDependencies:
+      '@logicflow/core': 2.1.2
+      '@logicflow/vue-node-registry': 1.1.3
+
+  '@logicflow/layout@2.0.2':
+    resolution: {integrity: sha512-Ux47QLaxQ0nT91oA+XZ7mDZs8tbCbJuFihoT/zQQv6XsqSy6x9cPP+OxwswxqQb5HGrOIGXLM0MrEEPKQxf2VQ==}
+
+  '@logicflow/vue-node-registry@1.1.3':
+    resolution: {integrity: sha512-8xgAd8MQ1PD2ZjM8TCzHtE+nS2uRm+nkRV74wxKPk7ZL3TRj3dJFH0VdLctMxAN+ouq1QPXMsjhWBmHWYSKZKQ==}
+    peerDependencies:
+      '@logicflow/core': 2.1.2
+      '@vue/composition-api': ^1.0.0-rc.10
+      vue: ^2.0.0 || >=3.0.0
+    peerDependenciesMeta:
+      '@vue/composition-api':
+        optional: true
+
   '@nodelib/fs.scandir@2.1.5':
     resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
     engines: {node: '>= 8'}
@@ -1083,9 +1126,16 @@ packages:
     resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
     engines: {node: '>=18'}
 
+  '@sphinxxxx/color-conversion@2.2.2':
+    resolution: {integrity: sha512-XExJS3cLqgrmNBIP3bBw6+1oQ1ksGjFh0+oClDKFYpCCqx/hlqwWO5KO/S63fzUo67SxI9dMrF0y5T/Ey7h8Zw==}
+
   '@sxzz/popperjs-es@2.11.7':
     resolution: {integrity: sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==}
 
+  '@trysound/sax@0.2.0':
+    resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
+    engines: {node: '>=10.13.0'}
+
   '@tsconfig/node20@20.1.5':
     resolution: {integrity: sha512-Vm8e3WxDTqMGPU4GATF9keQAIy1Drd7bPwlgzKJnZtoOsTm1tduUTbDjg0W5qERvGuxPI2h9RbMufH0YdfBylA==}
 
@@ -1534,6 +1584,9 @@ packages:
     resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
     engines: {node: '>= 14.16.0'}
 
+  classnames@2.5.1:
+    resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==}
+
   color-convert@2.0.1:
     resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
     engines: {node: '>=7.0.0'}
@@ -1548,6 +1601,10 @@ packages:
     resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==}
     engines: {node: '>=18'}
 
+  commander@7.2.0:
+    resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
+    engines: {node: '>= 10'}
+
   compute-scroll-into-view@1.0.20:
     resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==}
 
@@ -1578,18 +1635,36 @@ packages:
     resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
     engines: {node: '>= 8'}
 
+  css-select@5.2.2:
+    resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==}
+
+  css-tree@2.2.1:
+    resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==}
+    engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
+
   css-tree@2.3.1:
     resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==}
     engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
 
+  css-what@6.2.2:
+    resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==}
+    engines: {node: '>= 6'}
+
   cssesc@3.0.0:
     resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
     engines: {node: '>=4'}
     hasBin: true
 
+  csso@5.0.5:
+    resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==}
+    engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
+
   csstype@3.1.3:
     resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
 
+  dagre@0.8.5:
+    resolution: {integrity: sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==}
+
   dayjs@1.11.13:
     resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==}
 
@@ -1645,12 +1720,25 @@ packages:
   dom-scroll-into-view@2.0.1:
     resolution: {integrity: sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==}
 
+  dom-serializer@2.0.0:
+    resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
+
   dom-zindex@1.0.6:
     resolution: {integrity: sha512-FKWIhiU96bi3xpP9ewRMgANsoVmMUBnMnmpCT6dPMZOunVYJQmJhSRruoI0XSPoHeIif3kyEuiHbFrOJwEJaEA==}
 
   dom7@4.0.6:
     resolution: {integrity: sha512-emjdpPLhpNubapLFdjNL9tP06Sr+GZkrIHEXLWvOGsytACUrkbeIdjO5g77m00BrHTznnlcNqgmn7pCN192TBA==}
 
+  domelementtype@2.3.0:
+    resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
+
+  domhandler@5.0.3:
+    resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
+    engines: {node: '>= 4'}
+
+  domutils@3.2.2:
+    resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==}
+
   duplexer@0.1.2:
     resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
 
@@ -1877,6 +1965,9 @@ packages:
   graphemer@1.4.0:
     resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
 
+  graphlib@2.1.8:
+    resolution: {integrity: sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==}
+
   gzip-size@6.0.0:
     resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==}
     engines: {node: '>=10'}
@@ -1889,6 +1980,9 @@ packages:
     resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
     hasBin: true
 
+  hoist-non-react-statics@2.5.5:
+    resolution: {integrity: sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==}
+
   hookable@5.5.3:
     resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
 
@@ -2078,9 +2172,15 @@ packages:
   magic-string@0.30.17:
     resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
 
+  mdn-data@2.0.28:
+    resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==}
+
   mdn-data@2.0.30:
     resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==}
 
+  medium-editor@5.23.3:
+    resolution: {integrity: sha512-he9/TdjX8f8MGdXGfCs8AllrYnqXJJvjNkDKmPg3aPW/uoIrlRqtkFthrwvmd+u4QyzEiadhCCM0EwTiRdUCJw==}
+
   memoize-one@6.0.0:
     resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==}
 
@@ -2112,10 +2212,27 @@ packages:
   mlly@1.7.4:
     resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==}
 
+  mobx-preact@3.0.0:
+    resolution: {integrity: sha512-ijan/cBs3WmRye87E5+3JmoFBB00KDAwNA3pm7bMwYLPHBAXlN86aC3gdrXw8aKzM5RI8V3a993PphzPv6P4FA==}
+    peerDependencies:
+      mobx: 5.x
+      preact: '>=8'
+
+  mobx-utils@5.6.2:
+    resolution: {integrity: sha512-a/WlXyGkp6F12b01sTarENpxbmlRgPHFyR1Xv2bsSjQBm5dcOtd16ONb40/vOqck8L99NHpI+C9MXQ+SZ8f+yw==}
+    peerDependencies:
+      mobx: ^4.13.1 || ^5.13.1
+
+  mobx@5.15.7:
+    resolution: {integrity: sha512-wyM3FghTkhmC+hQjyPGGFdpehrcX1KOXsDuERhfK2YbJemkUhEB+6wzEN639T21onxlfYBmriA1PFnvxTUhcKw==}
+
   mockjs@1.1.0:
     resolution: {integrity: sha512-eQsKcWzIaZzEZ07NuEyO4Nw65g0hdWAyurVol1IPl1gahRwY+svqzfgfey8U8dahLwG44d6/RwEzuK52rSa/JQ==}
     hasBin: true
 
+  mousetrap@1.6.5:
+    resolution: {integrity: sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==}
+
   mrmime@2.0.1:
     resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
     engines: {node: '>=10'}
@@ -2283,6 +2400,9 @@ packages:
     resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==}
     engines: {node: ^10 || ^12 || >=14}
 
+  preact@10.27.2:
+    resolution: {integrity: sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==}
+
   prelude-ls@1.2.1:
     resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
     engines: {node: '>= 0.8.0'}
@@ -2310,6 +2430,9 @@ packages:
   queue-microtask@1.2.3:
     resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
 
+  rangy@1.3.2:
+    resolution: {integrity: sha512-fS1C4MOyk8T+ZJZdLcgrukPWxkyDXa+Hd2Kj+Zg4wIK71yrWgmjzHubzPMY1G+WD9EgGxMp3fIL0zQ1ickmSWA==}
+
   rate-limiter-flexible@5.0.5:
     resolution: {integrity: sha512-+/dSQfo+3FYwYygUs/V2BBdwGa9nFtakDwKt4l0bnvNB53TNT++QSFewwHX9qXrZJuMe9j+TUaU21lm5ARgqdQ==}
 
@@ -2413,6 +2536,9 @@ packages:
     resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
     engines: {node: '>=8'}
 
+  sortablejs@1.14.0:
+    resolution: {integrity: sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==}
+
   source-map-js@1.2.1:
     resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
     engines: {node: '>=0.10.0'}
@@ -2450,6 +2576,11 @@ packages:
     resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
     engines: {node: '>=8'}
 
+  svgo@3.3.2:
+    resolution: {integrity: sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==}
+    engines: {node: '>=14.0.0'}
+    hasBin: true
+
   swiper@8.4.7:
     resolution: {integrity: sha512-VwO/KU3i9IV2Sf+W2NqyzwWob4yX9Qdedq6vBtS0rFqJ6Fa5iLUJwxQkuD4I38w0WDJwmFl8ojkdcRFPHWD+2g==}
     engines: {node: '>= 4.7.0'}
@@ -2591,6 +2722,10 @@ packages:
   util-deprecate@1.0.2:
     resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
 
+  uuid@9.0.1:
+    resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
+    hasBin: true
+
   v-dropdown@3.0.0:
     resolution: {integrity: sha512-sDBiHhTjm0/eLmC83vUbOIHXNTlQD30w+usrh779OG+aNc/5vqyFQbSBPGekvD7pQPbWSPc5esVT8jcqfLRnrg==}
     peerDependencies:
@@ -2601,6 +2736,9 @@ packages:
     peerDependencies:
       vue: ^3.2.0
 
+  vanilla-picker@2.12.3:
+    resolution: {integrity: sha512-qVkT1E7yMbUsB2mmJNFmaXMWE2hF8ffqzMMwe9zdAikd8u2VfnsVY2HQcOUi2F38bgbxzlJBEdS1UUhOXdF9GQ==}
+
   vite-hot-client@0.2.4:
     resolution: {integrity: sha512-a1nzURqO7DDmnXqabFOliz908FRmIppkBKsJthS8rbe8hBEXwEwe4C3Pp33Z1JoFCYfVL4kTOMLKk0ZZxREIeA==}
     peerDependencies:
@@ -2630,6 +2768,11 @@ packages:
     peerDependencies:
       vite: ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0
 
+  vite-svg-loader@5.1.0:
+    resolution: {integrity: sha512-M/wqwtOEjgb956/+m5ZrYT/Iq6Hax0OakWbokj8+9PXOnB7b/4AxESHieEtnNEy7ZpjsjYW1/5nK8fATQMmRxw==}
+    peerDependencies:
+      vue: '>=3.2.13'
+
   vite@5.4.16:
     resolution: {integrity: sha512-Y5gnfp4NemVfgOTDQAunSD4346fal44L9mszGGY/e+qxsRT5y1sMlS/8tiQ8AFAp+MFgYNSINdfEchJiPm41vQ==}
     engines: {node: ^18.0.0 || >=20.0.0}
@@ -2751,6 +2894,11 @@ packages:
       typescript:
         optional: true
 
+  vuedraggable@4.1.0:
+    resolution: {integrity: sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==}
+    peerDependencies:
+      vue: ^3.0.1
+
   vxe-pc-ui@4.6.42:
     resolution: {integrity: sha512-grBaVbagoc5rbTq2jj1P/cWYP+sBo+VSXFRpNGYOe9Ka4EG9JP+LIa7h0lKfojDE5fGlPUYTkkYNe0fsQVDQ0g==}
 
@@ -2844,6 +2992,8 @@ snapshots:
 
   '@antfu/utils@8.1.1': {}
 
+  '@antv/hierarchy@0.6.14': {}
+
   '@babel/code-frame@7.26.2':
     dependencies:
       '@babel/helper-validator-identifier': 7.25.9
@@ -3365,6 +3515,42 @@ snapshots:
       '@jridgewell/resolve-uri': 3.1.2
       '@jridgewell/sourcemap-codec': 1.5.0
 
+  '@logicflow/core@2.1.2':
+    dependencies:
+      classnames: 2.5.1
+      lodash-es: 4.17.21
+      mobx: 5.15.7
+      mobx-preact: 3.0.0(mobx@5.15.7)(preact@10.27.2)
+      mobx-utils: 5.6.2(mobx@5.15.7)
+      mousetrap: 1.6.5
+      preact: 10.27.2
+      uuid: 9.0.1
+
+  '@logicflow/extension@2.1.4(@logicflow/core@2.1.2)(@logicflow/vue-node-registry@1.1.3(@logicflow/core@2.1.2)(vue@3.5.13(typescript@5.4.5)))':
+    dependencies:
+      '@antv/hierarchy': 0.6.14
+      '@logicflow/core': 2.1.2
+      '@logicflow/vue-node-registry': 1.1.3(@logicflow/core@2.1.2)(vue@3.5.13(typescript@5.4.5))
+      classnames: 2.5.1
+      lodash-es: 4.17.21
+      medium-editor: 5.23.3
+      mobx: 5.15.7
+      preact: 10.27.2
+      rangy: 1.3.2
+      vanilla-picker: 2.12.3
+
+  '@logicflow/layout@2.0.2':
+    dependencies:
+      '@logicflow/core': 2.1.2
+      dagre: 0.8.5
+
+  '@logicflow/vue-node-registry@1.1.3(@logicflow/core@2.1.2)(vue@3.5.13(typescript@5.4.5))':
+    dependencies:
+      '@logicflow/core': 2.1.2
+      lodash-es: 4.17.21
+      vue: 3.5.13(typescript@5.4.5)
+      vue-demi: 0.14.10(vue@3.5.13(typescript@5.4.5))
+
   '@nodelib/fs.scandir@2.1.5':
     dependencies:
       '@nodelib/fs.stat': 2.0.5
@@ -3521,8 +3707,12 @@ snapshots:
 
   '@sindresorhus/merge-streams@4.0.0': {}
 
+  '@sphinxxxx/color-conversion@2.2.2': {}
+
   '@sxzz/popperjs-es@2.11.7': {}
 
+  '@trysound/sax@0.2.0': {}
+
   '@tsconfig/node20@20.1.5': {}
 
   '@types/estree@1.0.7': {}
@@ -4179,6 +4369,8 @@ snapshots:
     dependencies:
       readdirp: 4.1.2
 
+  classnames@2.5.1: {}
+
   color-convert@2.0.1:
     dependencies:
       color-name: 1.1.4
@@ -4189,6 +4381,8 @@ snapshots:
 
   commander@13.1.0: {}
 
+  commander@7.2.0: {}
+
   compute-scroll-into-view@1.0.20: {}
 
   concat-map@0.0.1: {}
@@ -4213,15 +4407,39 @@ snapshots:
       shebang-command: 2.0.0
       which: 2.0.2
 
+  css-select@5.2.2:
+    dependencies:
+      boolbase: 1.0.0
+      css-what: 6.2.2
+      domhandler: 5.0.3
+      domutils: 3.2.2
+      nth-check: 2.1.1
+
+  css-tree@2.2.1:
+    dependencies:
+      mdn-data: 2.0.28
+      source-map-js: 1.2.1
+
   css-tree@2.3.1:
     dependencies:
       mdn-data: 2.0.30
       source-map-js: 1.2.1
 
+  css-what@6.2.2: {}
+
   cssesc@3.0.0: {}
 
+  csso@5.0.5:
+    dependencies:
+      css-tree: 2.2.1
+
   csstype@3.1.3: {}
 
+  dagre@0.8.5:
+    dependencies:
+      graphlib: 2.1.8
+      lodash: 4.17.21
+
   dayjs@1.11.13: {}
 
   de-indent@1.0.2: {}
@@ -4260,12 +4478,30 @@ snapshots:
 
   dom-scroll-into-view@2.0.1: {}
 
+  dom-serializer@2.0.0:
+    dependencies:
+      domelementtype: 2.3.0
+      domhandler: 5.0.3
+      entities: 4.5.0
+
   dom-zindex@1.0.6: {}
 
   dom7@4.0.6:
     dependencies:
       ssr-window: 4.0.2
 
+  domelementtype@2.3.0: {}
+
+  domhandler@5.0.3:
+    dependencies:
+      domelementtype: 2.3.0
+
+  domutils@3.2.2:
+    dependencies:
+      dom-serializer: 2.0.0
+      domelementtype: 2.3.0
+      domhandler: 5.0.3
+
   duplexer@0.1.2: {}
 
   echarts@5.6.0:
@@ -4614,6 +4850,10 @@ snapshots:
 
   graphemer@1.4.0: {}
 
+  graphlib@2.1.8:
+    dependencies:
+      lodash: 4.17.21
+
   gzip-size@6.0.0:
     dependencies:
       duplexer: 0.1.2
@@ -4622,6 +4862,8 @@ snapshots:
 
   he@1.2.0: {}
 
+  hoist-non-react-statics@2.5.5: {}
+
   hookable@5.5.3: {}
 
   human-signals@8.0.1: {}
@@ -4778,8 +5020,12 @@ snapshots:
     dependencies:
       '@jridgewell/sourcemap-codec': 1.5.0
 
+  mdn-data@2.0.28: {}
+
   mdn-data@2.0.30: {}
 
+  medium-editor@5.23.3: {}
+
   memoize-one@6.0.0: {}
 
   memorystream@0.3.1: {}
@@ -4810,10 +5056,24 @@ snapshots:
       pkg-types: 1.3.1
       ufo: 1.5.4
 
+  mobx-preact@3.0.0(mobx@5.15.7)(preact@10.27.2):
+    dependencies:
+      hoist-non-react-statics: 2.5.5
+      mobx: 5.15.7
+      preact: 10.27.2
+
+  mobx-utils@5.6.2(mobx@5.15.7):
+    dependencies:
+      mobx: 5.15.7
+
+  mobx@5.15.7: {}
+
   mockjs@1.1.0:
     dependencies:
       commander: 13.1.0
 
+  mousetrap@1.6.5: {}
+
   mrmime@2.0.1: {}
 
   ms@2.1.3: {}
@@ -4968,6 +5228,8 @@ snapshots:
       picocolors: 1.1.1
       source-map-js: 1.2.1
 
+  preact@10.27.2: {}
+
   prelude-ls@1.2.1: {}
 
   prettier-linter-helpers@1.0.0:
@@ -4986,6 +5248,8 @@ snapshots:
 
   queue-microtask@1.2.3: {}
 
+  rangy@1.3.2: {}
+
   rate-limiter-flexible@5.0.5: {}
 
   read-package-json-fast@3.0.2:
@@ -5091,6 +5355,8 @@ snapshots:
 
   slash@3.0.0: {}
 
+  sortablejs@1.14.0: {}
+
   source-map-js@1.2.1: {}
 
   speakingurl@14.0.1: {}
@@ -5119,6 +5385,16 @@ snapshots:
     dependencies:
       has-flag: 4.0.0
 
+  svgo@3.3.2:
+    dependencies:
+      '@trysound/sax': 0.2.0
+      commander: 7.2.0
+      css-select: 5.2.2
+      css-tree: 2.3.1
+      css-what: 6.2.2
+      csso: 5.0.5
+      picocolors: 1.1.1
+
   swiper@8.4.7:
     dependencies:
       dom7: 4.0.6
@@ -5306,6 +5582,8 @@ snapshots:
 
   util-deprecate@1.0.2: {}
 
+  uuid@9.0.1: {}
+
   v-dropdown@3.0.0(vue@3.5.13(typescript@5.4.5)):
     dependencies:
       vue: 3.5.13(typescript@5.4.5)
@@ -5315,6 +5593,10 @@ snapshots:
       v-dropdown: 3.0.0(vue@3.5.13(typescript@5.4.5))
       vue: 3.5.13(typescript@5.4.5)
 
+  vanilla-picker@2.12.3:
+    dependencies:
+      '@sphinxxxx/color-conversion': 2.2.2
+
   vite-hot-client@0.2.4(vite@5.4.16(@types/node@20.17.29)(sass@1.86.1)):
     dependencies:
       vite: 5.4.16(@types/node@20.17.29)(sass@1.86.1)
@@ -5373,6 +5655,11 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
+  vite-svg-loader@5.1.0(vue@3.5.13(typescript@5.4.5)):
+    dependencies:
+      svgo: 3.3.2
+      vue: 3.5.13(typescript@5.4.5)
+
   vite@5.4.16(@types/node@20.17.29)(sass@1.86.1):
     dependencies:
       esbuild: 0.21.5
@@ -5463,6 +5750,11 @@ snapshots:
     optionalDependencies:
       typescript: 5.4.5
 
+  vuedraggable@4.1.0(vue@3.5.13(typescript@5.4.5)):
+    dependencies:
+      sortablejs: 1.14.0
+      vue: 3.5.13(typescript@5.4.5)
+
   vxe-pc-ui@4.6.42(vue@3.5.13(typescript@5.4.5)):
     dependencies:
       '@vxe-ui/core': 4.1.5(vue@3.5.13(typescript@5.4.5))

+ 57 - 0
src/libs/logic-flow/VLogicFlow.vue

@@ -0,0 +1,57 @@
+<script setup lang="ts">
+import { tryOnMounted } from '@vueuse/core';
+import { LogicFlow } from '@logicflow/core';
+
+import { provideLogicFlow, tryLogicFlow } from './use';
+import { EndNode, StartNode } from './nodes';
+import { PolylineEdge } from './edges';
+
+import type { LogicFlowInstance, LogicFlowOptions } from './types';
+
+defineOptions({
+  name: 'VLogicFlow',
+});
+const props = defineProps<{ options?: LogicFlowOptions }>();
+const emits = defineEmits<{ loaded: [LogicFlowInstance] }>();
+const containerRef = useTemplateRef('container');
+tryOnMounted(() => {
+  const options = {
+    ...props.options,
+    parentTransform: tryLogicFlow()?.graphModel.transformModel,
+    container: containerRef.value!,
+  };
+  const lf = new LogicFlow(options);
+  lf.register(PolylineEdge);
+  lf.register(StartNode);
+  lf.register(EndNode);
+  lf.setDefaultEdgeType('custom-polyline-edge');
+  provideLogicFlow(lf);
+  emits('loaded', lf);
+});
+</script>
+
+<template>
+  <div class="v-logic-flow" v-bind="$attrs">
+    <main ref="container"></main>
+    <slot name="top"></slot>
+    <slot name="panel"></slot>
+    <slot name="float"></slot>
+  </div>
+</template>
+
+<style scoped lang="scss">
+.v-logic-flow {
+  width: 100%;
+  height: 100%;
+  position: relative;
+  > main {
+    width: 100%;
+    height: 100%;
+  }
+}
+.panel-wrapper {
+  position: absolute;
+  top: 0;
+  left: 0;
+}
+</style>

+ 2 - 0
src/libs/logic-flow/constant.ts

@@ -0,0 +1,2 @@
+export const START_ID = `start`;
+export const END_ID = `end`;

+ 5 - 0
src/libs/logic-flow/edges/index.ts

@@ -0,0 +1,5 @@
+import __polyline from './polyline';
+
+export {
+  __polyline as PolylineEdge,
+}

+ 22 - 0
src/libs/logic-flow/edges/polyline.ts

@@ -0,0 +1,22 @@
+import { PolylineEdge as __PolylineEdge, PolylineEdgeModel as __PolylineEdgeModel } from '@logicflow/core';
+
+class PolylineEdgeModel extends __PolylineEdgeModel {
+  getEdgeAnimationStyle() {
+    const style = super.getEdgeAnimationStyle();
+    style.strokeDasharray = '5 5';
+    style.strokeDashoffset = '100%';
+    style.animationDuration = '10s';
+    return style;
+  }
+  setProperties(properties: Record<string, any>) {
+    super.setProperties(properties);
+    if ('id' in properties) this.id = properties.id;
+    if ('isAnimation' in properties) this.isAnimation = properties.isAnimation;
+  }
+}
+
+export default {
+  type: 'custom-polyline-edge',
+  model: PolylineEdgeModel,
+  view: __PolylineEdge,
+};

+ 64 - 0
src/libs/logic-flow/index.ts

@@ -0,0 +1,64 @@
+import { type CallbackArgs, type EventArgs, type EventCallback, LogicFlow } from '@logicflow/core';
+import { register as __register } from '@logicflow/vue-node-registry';
+import type { Dagre } from '@logicflow/layout';
+
+import '@logicflow/core/lib/style/index.css';
+import '@logicflow/extension/es/index.css';
+import '@logicflow/extension/lib/style/index.css';
+
+import VLogicFlow from './VLogicFlow.vue';
+import { useEventListener } from './use';
+import type { LogicFlowInstance } from './types';
+
+export type * from './types';
+export { VLogicFlow };
+
+export type GraphData = LogicFlow.GraphConfigData;
+
+export default function init(
+  lf: LogicFlowInstance,
+  config?: {
+    register: { category: 'node' | 'edge'; type: string; view: any; model: any }[];
+    graph?: GraphData;
+  }
+) {
+  const register = (type: string, component: Component, model?: any) => __register({ type, component, model }, lf);
+  const listener = <T extends keyof EventArgs>(event: T, callback: EventCallback<T>, predicate?: (event: CallbackArgs<T>) => boolean, once?: boolean) =>
+    useEventListener(lf.graphModel.eventCenter, event, callback, predicate, once);
+  const getDagre = () => lf.extension.dagre as Dagre;
+
+  for (const { category, type, view, model } of config?.register ?? []) {
+    if (category === 'node') register(type, view, model);
+  }
+  lf.renderRawData(config?.graph ?? {});
+
+  let delayClick: ReturnType<typeof setTimeout>;
+  listener('edge:dbclick', (event) => {
+    lf.deleteEdge(event.data.id);
+  });
+  listener('node:dbclick', (event) => {
+    clearTimeout(delayClick);
+    lf.deleteNode(event.data.id);
+  });
+  listener('node:click', (event) => {
+    delayClick = setTimeout(() => {
+      lf.graphModel.eventCenter.emit('node:click:300', event);
+    }, 300);
+  });
+
+  /**
+   * 增强功能
+   * @description 渐进连线成功触发 [edge:proximity-connect] 事件
+   */
+  let dropAddEdgeTime = 0;
+  listener('node:drop', () => {
+    if (Date.now() - dropAddEdgeTime < 100) lf.graphModel.eventCenter.emit('edge:proximity-connect', {});
+  });
+  listener('edge:add', () => {
+    dropAddEdgeTime = Date.now();
+  });
+
+  return { lf, register, getDagre, listener };
+}
+
+export type VLogicFlowInstance = ReturnType<typeof init>;

+ 48 - 0
src/libs/logic-flow/nodes/end.ts

@@ -0,0 +1,48 @@
+import { RectNode, RectNodeModel } from '@logicflow/core';
+import { START_ID } from '../constant';
+
+class EndNodeModel extends RectNodeModel {
+  getDefaultAnchor() {
+    return super.getDefaultAnchor().map((anchor) => Object.assign(anchor, { type: 'incoming' }));
+  }
+
+  getConnectedSourceRules() {
+    const rules = super.getConnectedSourceRules();
+    rules.push({
+      message: '结束节点不允许输出',
+      validate: () => false,
+    });
+    return rules;
+  }
+
+  getConnectedTargetRules() {
+    const rules = super.getConnectedTargetRules();
+    rules.push({
+      message: `当前节点不是输出锚点`,
+      validate: (source, target, sourceAnchor, targetAnchor) => {
+        return !sourceAnchor?.type || sourceAnchor?.type === 'outgoing';
+      }
+    })
+
+    rules.push({
+      message: '禁止直接连接开始节点',
+      validate: (source, target, sourceAnchor, targetAnchor) => {
+        return !source || source.id !== START_ID;
+      },
+    });
+
+    rules.push({
+      message: `当前节点和目标节点已存在连接`,
+      validate: (source, target) => {
+        return !target?.graphModel.getNodeIncomingNode(target?.id).find(node => node.id === source?.id)
+      }
+    })
+    return rules;
+  }
+}
+
+export default {
+  type: 'EndNode',
+  model: EndNodeModel,
+  view: RectNode,
+};

+ 8 - 0
src/libs/logic-flow/nodes/index.ts

@@ -0,0 +1,8 @@
+import __start from './start';
+import __end from './end';
+
+
+export {
+  __start as StartNode,
+  __end as EndNode,
+}

+ 34 - 0
src/libs/logic-flow/nodes/start.ts

@@ -0,0 +1,34 @@
+import { RectNode, RectNodeModel } from '@logicflow/core';
+
+class StartNodeModel extends RectNodeModel {
+  getDefaultAnchor() {
+    return super.getDefaultAnchor().map((anchor) => Object.assign(anchor, { type: 'outgoing' }));
+  }
+
+  getConnectedSourceRules() {
+    const rules = super.getConnectedSourceRules();
+    rules.push({
+      message: '开始节点仅允许1个输出',
+      validate: (source) => {
+        const edge = this.graphModel.getNodeOutgoingEdge(source!.id);
+        return !edge.length;
+      },
+    });
+    return rules;
+  }
+
+  getConnectedTargetRules() {
+    const rules = super.getConnectedTargetRules();
+    rules.push({
+      message: '开始节点不允许输入',
+      validate: () => false,
+    });
+    return rules;
+  }
+}
+
+export default {
+  type: 'StartNode',
+  model: StartNodeModel,
+  view: RectNode,
+};

+ 9 - 0
src/libs/logic-flow/types.ts

@@ -0,0 +1,9 @@
+import type { LogicFlow, Options } from '@logicflow/core';
+import { LogicFlow as LogicFlowClass } from '@logicflow/core';
+
+export type LogicFlowInstance = InstanceType<typeof LogicFlowClass>;
+export type LogicFlowOptions = Partial<Options.Common>;
+
+export type LogicFlowNodeProperties = LogicFlow.PropertiesType;
+export type LogicFlowNode<P extends LogicFlowNodeProperties = LogicFlowNodeProperties> = LogicFlow.NodeConfig<P>;
+export type LogicFlowGraphData = LogicFlow.GraphConfigData;

+ 45 - 0
src/libs/logic-flow/use.ts

@@ -0,0 +1,45 @@
+import type { LogicFlowInstance } from './types';
+import type { CallbackArgs, EventArgs, EventCallback, EventEmitter } from '@logicflow/core';
+import { tryOnScopeDispose } from '@vueuse/core';
+
+const symbol = Symbol('logicFlow') as InjectionKey<LogicFlowInstance>;
+
+export function provideLogicFlow(lf: LogicFlowInstance) {
+  provide(symbol, lf);
+}
+
+export function useLogicFlow(): LogicFlowInstance {
+  const lf = inject(symbol, null);
+  if (!lf) throw new Error('LogicFlow instance is not provided. Please ensure you have called provideLogicFlow before using useLogicFlow.');
+  return lf;
+}
+
+export function tryLogicFlow(): LogicFlowInstance | null {
+  try {
+    return useLogicFlow();
+  } catch (error) {
+    return null;
+  }
+}
+
+export function useEventListener<T extends keyof EventArgs>(
+  emitter: EventEmitter,
+  event: T,
+  callback: EventCallback<T>,
+  predicate?: (event: CallbackArgs<T>) => boolean,
+  once?: boolean
+): () => void {
+  const cleanups: Function[] = [];
+  const cleanup = () => {
+    cleanups.forEach((fn) => fn());
+    cleanups.length = 0;
+  };
+
+  const cb: EventCallback<T> = typeof predicate === 'function' ? (event) => (predicate(event) ?? true) && callback(event) : callback;
+
+  emitter.on(event, cb, once);
+  cleanups.push(() => emitter.off(event, cb));
+
+  tryOnScopeDispose(cleanup);
+  return () => cleanup();
+}

+ 2 - 0
vite.config.ts

@@ -4,6 +4,7 @@ import vueJsx from '@vitejs/plugin-vue-jsx';
 import { fileURLToPath, URL } from 'node:url';
 
 import UnoCSS from 'unocss/vite';
+import SVGLoader from 'vite-svg-loader';
 
 import AutoImport               from 'unplugin-auto-import/vite';
 import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers';
@@ -41,6 +42,7 @@ export default defineConfig((configEnv) => {
       vueJsx(),
       vueDevTools(),
       UnoCSS(),
+      SVGLoader(),
       AutoImport({
         imports: [
           'vue',