Просмотр исходного кода

Merge remote-tracking branch 'origin/mergeBranch' into mergeBranch

qymljy 3 лет назад
Родитель
Сommit
ef55ed384c

+ 690 - 4
package-lock.json

@@ -10,6 +10,7 @@
       "dependencies": {
         "@antv/g2": "^4.1.46",
         "@antv/g2plot": "^2.4.8",
+        "@antv/g6": "^4.8.17",
         "@riophae/vue-treeselect": "^0.4.0",
         "@sv-print/vue": "^0.1.4",
         "@wangeditor/editor": "^5.1.1",
@@ -59,6 +60,14 @@
         "node": ">=6.0.0"
       }
     },
+    "node_modules/@ant-design/colors": {
+      "version": "4.0.5",
+      "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-4.0.5.tgz",
+      "integrity": "sha512-3mnuX2prnWOWvpFTS2WH2LoouWlOgtnIpc6IarWN6GOzzLF8dW/U8UctuvIPhoboETehZfJ61XP+CGakBEPJ3Q==",
+      "dependencies": {
+        "tinycolor2": "^1.4.1"
+      }
+    },
     "node_modules/@antv/adjust": {
       "version": "0.2.5",
       "resolved": "https://registry.npmjs.org/@antv/adjust/-/adjust-0.2.5.tgz",
@@ -73,6 +82,15 @@
       "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
       "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
     },
+    "node_modules/@antv/algorithm": {
+      "version": "0.1.25",
+      "resolved": "https://registry.npmjs.org/@antv/algorithm/-/algorithm-0.1.25.tgz",
+      "integrity": "sha512-TGwPyFoAu4+iEJd0y1l0gHdBXCbUj8a4gR7P3GzZRfEfRnWfk+gswApzOSTd7c6HP402JOEF64PAJQKxQgSPSQ==",
+      "dependencies": {
+        "@antv/util": "^2.0.13",
+        "tslib": "^2.0.0"
+      }
+    },
     "node_modules/@antv/attr": {
       "version": "0.3.3",
       "resolved": "https://registry.npmjs.org/@antv/attr/-/attr-0.3.3.tgz",
@@ -189,6 +207,40 @@
         "tslib": "^2.0.3"
       }
     },
+    "node_modules/@antv/g-webgpu": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/@antv/g-webgpu/-/g-webgpu-0.7.2.tgz",
+      "integrity": "sha512-kw+oYGsdvj5qeUfy5DPb/jztZBV+2fmqBd3Vv8NlKatfBmv8AirYX/CCW74AUSdWm99rEiLyxFB1VdRZ6b/wnQ==",
+      "dependencies": {
+        "@antv/g-webgpu-core": "^0.7.2",
+        "@antv/g-webgpu-engine": "^0.7.2",
+        "gl-matrix": "^3.1.0",
+        "gl-vec2": "^1.3.0",
+        "lodash": "^4.17.15"
+      }
+    },
+    "node_modules/@antv/g-webgpu-core": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/@antv/g-webgpu-core/-/g-webgpu-core-0.7.2.tgz",
+      "integrity": "sha512-xUMmop7f3Rs34zFYKXLqHhDR1CQTeDl/7vI7Sn3X/73BqJc3X3HIIRvm83Fg2CjVACaOzw4WeLRXNaOCp9fz9w==",
+      "dependencies": {
+        "eventemitter3": "^4.0.0",
+        "gl-matrix": "^3.1.0",
+        "lodash": "^4.17.15",
+        "probe.gl": "^3.1.1"
+      }
+    },
+    "node_modules/@antv/g-webgpu-engine": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/@antv/g-webgpu-engine/-/g-webgpu-engine-0.7.2.tgz",
+      "integrity": "sha512-lx8Y93IW2cnJvdoDRKyMmTdYqSC1pOmF0nyG3PGGyA0NI9vBYVgO0KTF6hkyWjdTWVq7XDZyf/h8CJridLh3lg==",
+      "dependencies": {
+        "@antv/g-webgpu-core": "^0.7.2",
+        "gl-matrix": "^3.1.0",
+        "lodash": "^4.17.15",
+        "regl": "^1.3.11"
+      }
+    },
     "node_modules/@antv/g2": {
       "version": "4.2.2",
       "resolved": "https://registry.npmjs.org/@antv/g2/-/g2-4.2.2.tgz",
@@ -227,6 +279,124 @@
         "tslib": "^2.0.3"
       }
     },
+    "node_modules/@antv/g6": {
+      "version": "4.8.17",
+      "resolved": "https://registry.npmjs.org/@antv/g6/-/g6-4.8.17.tgz",
+      "integrity": "sha512-THpCDHjTyQWrFhM0xwahkpYUe+nHFtq33Ayrq0XA3nbnJw1AmJXnpPJE21rpkoluZhHKhFlXazl739Hb22e+5Q==",
+      "dependencies": {
+        "@antv/g6-pc": "0.8.18"
+      }
+    },
+    "node_modules/@antv/g6-core": {
+      "version": "0.8.17",
+      "resolved": "https://registry.npmjs.org/@antv/g6-core/-/g6-core-0.8.17.tgz",
+      "integrity": "sha512-XKwZO1mQQTSQxM/1mV5t50ai0AqN4f7ofKubE454tE3lm2br6zDeZ3objq3w7gZWF4uVccsRJE2wiMW/UA1n0g==",
+      "dependencies": {
+        "@antv/algorithm": "^0.1.8",
+        "@antv/dom-util": "^2.0.1",
+        "@antv/event-emitter": "~0.1.0",
+        "@antv/g-base": "^0.5.1",
+        "@antv/g-math": "^0.1.1",
+        "@antv/matrix-util": "^3.1.0-beta.3",
+        "@antv/path-util": "^2.0.3",
+        "@antv/util": "~2.0.5",
+        "ml-matrix": "^6.5.0",
+        "tslib": "^2.1.0"
+      }
+    },
+    "node_modules/@antv/g6-element": {
+      "version": "0.8.17",
+      "resolved": "https://registry.npmjs.org/@antv/g6-element/-/g6-element-0.8.17.tgz",
+      "integrity": "sha512-b9jmrr+xf+dSDOwNyvSA5i+nHvJZR7JLLJgWreZOSyHKICRR5yXt+GKYl5+k9qBaImBusbqML4W+Zr82OXCy5Q==",
+      "dependencies": {
+        "@antv/g-base": "^0.5.1",
+        "@antv/g6-core": "0.8.17",
+        "@antv/util": "~2.0.5"
+      }
+    },
+    "node_modules/@antv/g6-pc": {
+      "version": "0.8.18",
+      "resolved": "https://registry.npmjs.org/@antv/g6-pc/-/g6-pc-0.8.18.tgz",
+      "integrity": "sha512-dUxjplQm1XgziaQ5GQLU+SLW+jArHF2rCVWHS1ewt1sKtJoIOzP0xPk1gMLE7DmRR+LpnWV2Ne4aQkQqPEDoMQ==",
+      "dependencies": {
+        "@ant-design/colors": "^4.0.5",
+        "@antv/algorithm": "^0.1.8",
+        "@antv/dom-util": "^2.0.1",
+        "@antv/event-emitter": "~0.1.0",
+        "@antv/g-base": "^0.5.1",
+        "@antv/g-canvas": "^0.5.2",
+        "@antv/g-math": "^0.1.1",
+        "@antv/g-svg": "^0.5.1",
+        "@antv/g6-core": "0.8.17",
+        "@antv/g6-element": "0.8.17",
+        "@antv/g6-plugin": "0.8.17",
+        "@antv/hierarchy": "^0.6.10",
+        "@antv/layout": "^0.3.0",
+        "@antv/matrix-util": "^3.1.0-beta.3",
+        "@antv/path-util": "^2.0.3",
+        "@antv/util": "~2.0.5",
+        "color": "^3.1.3",
+        "d3-force": "^2.0.1",
+        "dagre": "^0.8.5",
+        "insert-css": "^2.0.0",
+        "ml-matrix": "^6.5.0"
+      }
+    },
+    "node_modules/@antv/g6-plugin": {
+      "version": "0.8.17",
+      "resolved": "https://registry.npmjs.org/@antv/g6-plugin/-/g6-plugin-0.8.17.tgz",
+      "integrity": "sha512-nAqUTG08ss+Y17AgP0R6FzF7P9Y3xhX8dYv12UyyAop0bxch5jX0l6YvC5jCDf9WDjQaXMf/YdCUqFpB8rh9Pg==",
+      "dependencies": {
+        "@antv/dom-util": "^2.0.2",
+        "@antv/g-base": "^0.5.1",
+        "@antv/g-canvas": "^0.5.2",
+        "@antv/g-svg": "^0.5.2",
+        "@antv/g6-core": "0.8.17",
+        "@antv/g6-element": "0.8.17",
+        "@antv/matrix-util": "^3.1.0-beta.3",
+        "@antv/path-util": "^2.0.3",
+        "@antv/scale": "^0.3.4",
+        "@antv/util": "^2.0.9",
+        "insert-css": "^2.0.0"
+      }
+    },
+    "node_modules/@antv/graphlib": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@antv/graphlib/-/graphlib-1.2.0.tgz",
+      "integrity": "sha512-hhJOMThec51nU4Fe5p/viLlNIL71uDEgYFzKPajWjr2715SFG1HAgiP6AVylIeqBcAZ04u3Lw7usjl/TuI5RuQ=="
+    },
+    "node_modules/@antv/hierarchy": {
+      "version": "0.6.11",
+      "resolved": "https://registry.npmjs.org/@antv/hierarchy/-/hierarchy-0.6.11.tgz",
+      "integrity": "sha512-RJVhEMCuu4vj+Dt25lXIiNdd7jaqm/fqWGYikiELha4S5tnzdJoTUaUvvpfWlxLx4B0RsS9XRwBs1bOKN71TKg==",
+      "dependencies": {
+        "@antv/util": "^2.0.7"
+      }
+    },
+    "node_modules/@antv/layout": {
+      "version": "0.3.23",
+      "resolved": "https://registry.npmjs.org/@antv/layout/-/layout-0.3.23.tgz",
+      "integrity": "sha512-F/CyfQuc1WSgCVemX0jA3pE3XuDRbDJmMueY1cL8WgL6nhdzm3/jg5UPamwbBVnhLk+rzNUDYdEIyX+RJbpcMA==",
+      "dependencies": {
+        "@antv/g-webgpu": "0.7.2",
+        "@antv/graphlib": "^1.0.0",
+        "@antv/util": "^3.3.2",
+        "d3-force": "^2.1.1",
+        "d3-quadtree": "^2.0.0",
+        "dagre-compound": "^0.0.11",
+        "ml-matrix": "^6.5.0"
+      }
+    },
+    "node_modules/@antv/layout/node_modules/@antv/util": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/@antv/util/-/util-3.3.2.tgz",
+      "integrity": "sha512-uvyQxEOugdJs/FVlpz/+8pKxn70z8jEVydPqv+LI62cpIF7YDjVnMfNIsoMqwEoTzPUJ9TJalyLqZhT5rYez0w==",
+      "dependencies": {
+        "fast-deep-equal": "^3.1.3",
+        "gl-matrix": "^3.3.0",
+        "tslib": "^2.3.1"
+      }
+    },
     "node_modules/@antv/matrix-util": {
       "version": "3.1.0-beta.3",
       "resolved": "https://registry.npmjs.org/@antv/matrix-util/-/matrix-util-3.1.0-beta.3.tgz",
@@ -2442,6 +2612,31 @@
       "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==",
       "dev": true
     },
+    "node_modules/@probe.gl/env": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/@probe.gl/env/-/env-3.6.0.tgz",
+      "integrity": "sha512-4tTZYUg/8BICC3Yyb9rOeoKeijKbZHRXBEKObrfPmX4sQmYB15ZOUpoVBhAyJkOYVAM8EkPci6Uw5dLCwx2BEQ==",
+      "dependencies": {
+        "@babel/runtime": "^7.0.0"
+      }
+    },
+    "node_modules/@probe.gl/log": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/@probe.gl/log/-/log-3.6.0.tgz",
+      "integrity": "sha512-hjpyenpEvOdowgZ1qMeCJxfRD4JkKdlXz0RC14m42Un62NtOT+GpWyKA4LssT0+xyLULCByRAtG2fzZorpIAcA==",
+      "dependencies": {
+        "@babel/runtime": "^7.0.0",
+        "@probe.gl/env": "3.6.0"
+      }
+    },
+    "node_modules/@probe.gl/stats": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/@probe.gl/stats/-/stats-3.6.0.tgz",
+      "integrity": "sha512-JdALQXB44OP4kUBN/UrQgzbJe4qokbVF4Y8lkIA8iVCFnjVowWIgkD/z/0QO65yELT54tTrtepw1jScjKB+rhQ==",
+      "dependencies": {
+        "@babel/runtime": "^7.0.0"
+      }
+    },
     "node_modules/@riophae/vue-treeselect": {
       "version": "0.4.0",
       "resolved": "https://registry.npmmirror.com/@riophae/vue-treeselect/-/vue-treeselect-0.4.0.tgz",
@@ -5563,6 +5758,15 @@
         "node": ">=0.8"
       }
     },
+    "node_modules/color": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
+      "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
+      "dependencies": {
+        "color-convert": "^1.9.3",
+        "color-string": "^1.6.0"
+      }
+    },
     "node_modules/color-convert": {
       "version": "1.9.3",
       "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz",
@@ -5576,6 +5780,15 @@
       "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz",
       "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
     },
+    "node_modules/color-string": {
+      "version": "1.9.1",
+      "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
+      "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+      "dependencies": {
+        "color-name": "^1.0.0",
+        "simple-swizzle": "^0.2.2"
+      }
+    },
     "node_modules/colord": {
       "version": "2.9.2",
       "resolved": "https://registry.npmmirror.com/colord/-/colord-2.9.2.tgz",
@@ -6190,11 +6403,26 @@
       "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz",
       "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q=="
     },
+    "node_modules/d3-dispatch": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-2.0.0.tgz",
+      "integrity": "sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA=="
+    },
     "node_modules/d3-ease": {
       "version": "1.0.7",
       "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz",
       "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ=="
     },
+    "node_modules/d3-force": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-2.1.1.tgz",
+      "integrity": "sha512-nAuHEzBqMvpFVMf9OX75d00OxvOXdxY+xECIXjW6Gv8BRrXu6gAWbv/9XKrvfJ5i5DCokDW7RYE50LRoK092ew==",
+      "dependencies": {
+        "d3-dispatch": "1 - 2",
+        "d3-quadtree": "1 - 2",
+        "d3-timer": "1 - 2"
+      }
+    },
     "node_modules/d3-hierarchy": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-2.0.0.tgz",
@@ -6208,6 +6436,11 @@
         "d3-color": "1"
       }
     },
+    "node_modules/d3-quadtree": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-2.0.0.tgz",
+      "integrity": "sha512-b0Ed2t1UUalJpc3qXzKi+cPGxeXRr4KU9YSlocN74aTzp6R/Ud43t79yLLqxHRWZfsvWXmbDWPpoENK1K539xw=="
+    },
     "node_modules/d3-regression": {
       "version": "1.3.10",
       "resolved": "https://registry.npmjs.org/d3-regression/-/d3-regression-1.3.10.tgz",
@@ -6218,6 +6451,26 @@
       "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz",
       "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw=="
     },
+    "node_modules/dagre": {
+      "version": "0.8.5",
+      "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz",
+      "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==",
+      "dependencies": {
+        "graphlib": "^2.1.8",
+        "lodash": "^4.17.15"
+      }
+    },
+    "node_modules/dagre-compound": {
+      "version": "0.0.11",
+      "resolved": "https://registry.npmjs.org/dagre-compound/-/dagre-compound-0.0.11.tgz",
+      "integrity": "sha512-UrSgRP9LtOZCYb9e5doolZXpc7xayyszgyOs7uakTK4n4KsLegLVTRRtq01GpQd/iZjYw5fWMapx9ed+c80MAQ==",
+      "engines": {
+        "node": ">=6.0.0"
+      },
+      "peerDependencies": {
+        "dagre": "^0.8.5"
+      }
+    },
     "node_modules/de-indent": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz",
@@ -7777,8 +8030,7 @@
     "node_modules/eventemitter3": {
       "version": "4.0.7",
       "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-4.0.7.tgz",
-      "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
-      "dev": true
+      "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
     },
     "node_modules/events": {
       "version": "3.3.0",
@@ -8336,6 +8588,11 @@
       "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz",
       "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA=="
     },
+    "node_modules/gl-vec2": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/gl-vec2/-/gl-vec2-1.3.0.tgz",
+      "integrity": "sha512-YiqaAuNsheWmUV0Sa8k94kBB0D6RWjwZztyO+trEYS8KzJ6OQB/4686gdrf59wld4hHFIvaxynO3nRxpk1Ij/A=="
+    },
     "node_modules/glob": {
       "version": "7.2.0",
       "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.0.tgz",
@@ -8400,6 +8657,14 @@
       "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.9.tgz",
       "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ=="
     },
+    "node_modules/graphlib": {
+      "version": "2.1.8",
+      "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz",
+      "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==",
+      "dependencies": {
+        "lodash": "^4.17.15"
+      }
+    },
     "node_modules/gzip-size": {
       "version": "6.0.0",
       "resolved": "https://registry.npmmirror.com/gzip-size/-/gzip-size-6.0.0.tgz",
@@ -8826,6 +9091,11 @@
       "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
       "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
     },
+    "node_modules/insert-css": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/insert-css/-/insert-css-2.0.0.tgz",
+      "integrity": "sha512-xGq5ISgcUP5cvGkS2MMFLtPDBtrtQPSFfC6gA6U8wHKqfjTIMZLZNxOItQnoSjdOzlXOLU/yD32RKC4SvjNbtA=="
+    },
     "node_modules/interactjs": {
       "version": "1.10.17",
       "resolved": "https://registry.npmjs.org/interactjs/-/interactjs-1.10.17.tgz",
@@ -8880,6 +9150,11 @@
         "node": ">= 10"
       }
     },
+    "node_modules/is-any-array": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-any-array/-/is-any-array-2.0.1.tgz",
+      "integrity": "sha512-UtilS7hLRu++wb/WBAw9bNuP1Eg04Ivn1vERJck8zJthEvXCBEBpGR/33u/xLKWEQf95803oalHrVDptcAvFdQ=="
+    },
     "node_modules/is-arguments": {
       "version": "1.1.1",
       "resolved": "https://registry.npmmirror.com/is-arguments/-/is-arguments-1.1.1.tgz",
@@ -10274,6 +10549,41 @@
         "mkdirp": "bin/cmd.js"
       }
     },
+    "node_modules/ml-array-max": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/ml-array-max/-/ml-array-max-1.2.4.tgz",
+      "integrity": "sha512-BlEeg80jI0tW6WaPyGxf5Sa4sqvcyY6lbSn5Vcv44lp1I2GR6AWojfUvLnGTNsIXrZ8uqWmo8VcG1WpkI2ONMQ==",
+      "dependencies": {
+        "is-any-array": "^2.0.0"
+      }
+    },
+    "node_modules/ml-array-min": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/ml-array-min/-/ml-array-min-1.2.3.tgz",
+      "integrity": "sha512-VcZ5f3VZ1iihtrGvgfh/q0XlMobG6GQ8FsNyQXD3T+IlstDv85g8kfV0xUG1QPRO/t21aukaJowDzMTc7j5V6Q==",
+      "dependencies": {
+        "is-any-array": "^2.0.0"
+      }
+    },
+    "node_modules/ml-array-rescale": {
+      "version": "1.3.7",
+      "resolved": "https://registry.npmjs.org/ml-array-rescale/-/ml-array-rescale-1.3.7.tgz",
+      "integrity": "sha512-48NGChTouvEo9KBctDfHC3udWnQKNKEWN0ziELvY3KG25GR5cA8K8wNVzracsqSW1QEkAXjTNx+ycgAv06/1mQ==",
+      "dependencies": {
+        "is-any-array": "^2.0.0",
+        "ml-array-max": "^1.2.4",
+        "ml-array-min": "^1.2.3"
+      }
+    },
+    "node_modules/ml-matrix": {
+      "version": "6.10.4",
+      "resolved": "https://registry.npmjs.org/ml-matrix/-/ml-matrix-6.10.4.tgz",
+      "integrity": "sha512-rUyEhfNPzqFsltYwvjNeYQXlYEaVea3KgzcJKJteQUj2WVAGFx9fLNRjtMR9mg2B6bd5buxlmkZmxM4hmO+SKg==",
+      "dependencies": {
+        "is-any-array": "^2.0.0",
+        "ml-array-rescale": "^1.3.7"
+      }
+    },
     "node_modules/module-alias": {
       "version": "2.2.2",
       "resolved": "https://registry.npmmirror.com/module-alias/-/module-alias-2.2.2.tgz",
@@ -11659,6 +11969,17 @@
         "node": ">= 0.6"
       }
     },
+    "node_modules/probe.gl": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/probe.gl/-/probe.gl-3.6.0.tgz",
+      "integrity": "sha512-19JydJWI7+DtR4feV+pu4Mn1I5TAc0xojuxVgZdXIyfmTLfUaFnk4OloWK1bKbPtkgGKLr2lnbnCXmpZEcEp9g==",
+      "dependencies": {
+        "@babel/runtime": "^7.0.0",
+        "@probe.gl/env": "3.6.0",
+        "@probe.gl/log": "3.6.0",
+        "@probe.gl/stats": "3.6.0"
+      }
+    },
     "node_modules/process-nextick-args": {
       "version": "2.0.1",
       "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -11996,6 +12317,11 @@
         "jsesc": "bin/jsesc"
       }
     },
+    "node_modules/regl": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/regl/-/regl-1.7.0.tgz",
+      "integrity": "sha512-bEAtp/qrtKucxXSJkD4ebopFZYP0q1+3Vb2WECWv/T8yQEgKxDxJ7ztO285tAMaYZVR6mM1GgI6CCn8FROtL1w=="
+    },
     "node_modules/relateurl": {
       "version": "0.2.7",
       "resolved": "https://registry.npmmirror.com/relateurl/-/relateurl-0.2.7.tgz",
@@ -12523,6 +12849,19 @@
       "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
       "dev": true
     },
+    "node_modules/simple-swizzle": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+      "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
+      "dependencies": {
+        "is-arrayish": "^0.3.1"
+      }
+    },
+    "node_modules/simple-swizzle/node_modules/is-arrayish": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+      "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
+    },
     "node_modules/sirv": {
       "version": "1.0.19",
       "resolved": "https://registry.npmmirror.com/sirv/-/sirv-1.0.19.tgz",
@@ -13376,6 +13715,11 @@
       "resolved": "https://registry.npmmirror.com/tiny-warning/-/tiny-warning-1.0.3.tgz",
       "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
     },
+    "node_modules/tinycolor2": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz",
+      "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="
+    },
     "node_modules/to-fast-properties": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
@@ -15634,6 +15978,14 @@
         "@jridgewell/trace-mapping": "^0.3.0"
       }
     },
+    "@ant-design/colors": {
+      "version": "4.0.5",
+      "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-4.0.5.tgz",
+      "integrity": "sha512-3mnuX2prnWOWvpFTS2WH2LoouWlOgtnIpc6IarWN6GOzzLF8dW/U8UctuvIPhoboETehZfJ61XP+CGakBEPJ3Q==",
+      "requires": {
+        "tinycolor2": "^1.4.1"
+      }
+    },
     "@antv/adjust": {
       "version": "0.2.5",
       "resolved": "https://registry.npmjs.org/@antv/adjust/-/adjust-0.2.5.tgz",
@@ -15650,6 +16002,15 @@
         }
       }
     },
+    "@antv/algorithm": {
+      "version": "0.1.25",
+      "resolved": "https://registry.npmjs.org/@antv/algorithm/-/algorithm-0.1.25.tgz",
+      "integrity": "sha512-TGwPyFoAu4+iEJd0y1l0gHdBXCbUj8a4gR7P3GzZRfEfRnWfk+gswApzOSTd7c6HP402JOEF64PAJQKxQgSPSQ==",
+      "requires": {
+        "@antv/util": "^2.0.13",
+        "tslib": "^2.0.0"
+      }
+    },
     "@antv/attr": {
       "version": "0.3.3",
       "resolved": "https://registry.npmjs.org/@antv/attr/-/attr-0.3.3.tgz",
@@ -15768,6 +16129,40 @@
         "tslib": "^2.0.3"
       }
     },
+    "@antv/g-webgpu": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/@antv/g-webgpu/-/g-webgpu-0.7.2.tgz",
+      "integrity": "sha512-kw+oYGsdvj5qeUfy5DPb/jztZBV+2fmqBd3Vv8NlKatfBmv8AirYX/CCW74AUSdWm99rEiLyxFB1VdRZ6b/wnQ==",
+      "requires": {
+        "@antv/g-webgpu-core": "^0.7.2",
+        "@antv/g-webgpu-engine": "^0.7.2",
+        "gl-matrix": "^3.1.0",
+        "gl-vec2": "^1.3.0",
+        "lodash": "^4.17.15"
+      }
+    },
+    "@antv/g-webgpu-core": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/@antv/g-webgpu-core/-/g-webgpu-core-0.7.2.tgz",
+      "integrity": "sha512-xUMmop7f3Rs34zFYKXLqHhDR1CQTeDl/7vI7Sn3X/73BqJc3X3HIIRvm83Fg2CjVACaOzw4WeLRXNaOCp9fz9w==",
+      "requires": {
+        "eventemitter3": "^4.0.0",
+        "gl-matrix": "^3.1.0",
+        "lodash": "^4.17.15",
+        "probe.gl": "^3.1.1"
+      }
+    },
+    "@antv/g-webgpu-engine": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/@antv/g-webgpu-engine/-/g-webgpu-engine-0.7.2.tgz",
+      "integrity": "sha512-lx8Y93IW2cnJvdoDRKyMmTdYqSC1pOmF0nyG3PGGyA0NI9vBYVgO0KTF6hkyWjdTWVq7XDZyf/h8CJridLh3lg==",
+      "requires": {
+        "@antv/g-webgpu-core": "^0.7.2",
+        "gl-matrix": "^3.1.0",
+        "lodash": "^4.17.15",
+        "regl": "^1.3.11"
+      }
+    },
     "@antv/g2": {
       "version": "4.2.2",
       "resolved": "https://registry.npmjs.org/@antv/g2/-/g2-4.2.2.tgz",
@@ -15806,6 +16201,126 @@
         "tslib": "^2.0.3"
       }
     },
+    "@antv/g6": {
+      "version": "4.8.17",
+      "resolved": "https://registry.npmjs.org/@antv/g6/-/g6-4.8.17.tgz",
+      "integrity": "sha512-THpCDHjTyQWrFhM0xwahkpYUe+nHFtq33Ayrq0XA3nbnJw1AmJXnpPJE21rpkoluZhHKhFlXazl739Hb22e+5Q==",
+      "requires": {
+        "@antv/g6-pc": "0.8.18"
+      }
+    },
+    "@antv/g6-core": {
+      "version": "0.8.17",
+      "resolved": "https://registry.npmjs.org/@antv/g6-core/-/g6-core-0.8.17.tgz",
+      "integrity": "sha512-XKwZO1mQQTSQxM/1mV5t50ai0AqN4f7ofKubE454tE3lm2br6zDeZ3objq3w7gZWF4uVccsRJE2wiMW/UA1n0g==",
+      "requires": {
+        "@antv/algorithm": "^0.1.8",
+        "@antv/dom-util": "^2.0.1",
+        "@antv/event-emitter": "~0.1.0",
+        "@antv/g-base": "^0.5.1",
+        "@antv/g-math": "^0.1.1",
+        "@antv/matrix-util": "^3.1.0-beta.3",
+        "@antv/path-util": "^2.0.3",
+        "@antv/util": "~2.0.5",
+        "ml-matrix": "^6.5.0",
+        "tslib": "^2.1.0"
+      }
+    },
+    "@antv/g6-element": {
+      "version": "0.8.17",
+      "resolved": "https://registry.npmjs.org/@antv/g6-element/-/g6-element-0.8.17.tgz",
+      "integrity": "sha512-b9jmrr+xf+dSDOwNyvSA5i+nHvJZR7JLLJgWreZOSyHKICRR5yXt+GKYl5+k9qBaImBusbqML4W+Zr82OXCy5Q==",
+      "requires": {
+        "@antv/g-base": "^0.5.1",
+        "@antv/g6-core": "0.8.17",
+        "@antv/util": "~2.0.5"
+      }
+    },
+    "@antv/g6-pc": {
+      "version": "0.8.18",
+      "resolved": "https://registry.npmjs.org/@antv/g6-pc/-/g6-pc-0.8.18.tgz",
+      "integrity": "sha512-dUxjplQm1XgziaQ5GQLU+SLW+jArHF2rCVWHS1ewt1sKtJoIOzP0xPk1gMLE7DmRR+LpnWV2Ne4aQkQqPEDoMQ==",
+      "requires": {
+        "@ant-design/colors": "^4.0.5",
+        "@antv/algorithm": "^0.1.8",
+        "@antv/dom-util": "^2.0.1",
+        "@antv/event-emitter": "~0.1.0",
+        "@antv/g-base": "^0.5.1",
+        "@antv/g-canvas": "^0.5.2",
+        "@antv/g-math": "^0.1.1",
+        "@antv/g-svg": "^0.5.1",
+        "@antv/g6-core": "0.8.17",
+        "@antv/g6-element": "0.8.17",
+        "@antv/g6-plugin": "0.8.17",
+        "@antv/hierarchy": "^0.6.10",
+        "@antv/layout": "^0.3.0",
+        "@antv/matrix-util": "^3.1.0-beta.3",
+        "@antv/path-util": "^2.0.3",
+        "@antv/util": "~2.0.5",
+        "color": "^3.1.3",
+        "d3-force": "^2.0.1",
+        "dagre": "^0.8.5",
+        "insert-css": "^2.0.0",
+        "ml-matrix": "^6.5.0"
+      }
+    },
+    "@antv/g6-plugin": {
+      "version": "0.8.17",
+      "resolved": "https://registry.npmjs.org/@antv/g6-plugin/-/g6-plugin-0.8.17.tgz",
+      "integrity": "sha512-nAqUTG08ss+Y17AgP0R6FzF7P9Y3xhX8dYv12UyyAop0bxch5jX0l6YvC5jCDf9WDjQaXMf/YdCUqFpB8rh9Pg==",
+      "requires": {
+        "@antv/dom-util": "^2.0.2",
+        "@antv/g-base": "^0.5.1",
+        "@antv/g-canvas": "^0.5.2",
+        "@antv/g-svg": "^0.5.2",
+        "@antv/g6-core": "0.8.17",
+        "@antv/g6-element": "0.8.17",
+        "@antv/matrix-util": "^3.1.0-beta.3",
+        "@antv/path-util": "^2.0.3",
+        "@antv/scale": "^0.3.4",
+        "@antv/util": "^2.0.9",
+        "insert-css": "^2.0.0"
+      }
+    },
+    "@antv/graphlib": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@antv/graphlib/-/graphlib-1.2.0.tgz",
+      "integrity": "sha512-hhJOMThec51nU4Fe5p/viLlNIL71uDEgYFzKPajWjr2715SFG1HAgiP6AVylIeqBcAZ04u3Lw7usjl/TuI5RuQ=="
+    },
+    "@antv/hierarchy": {
+      "version": "0.6.11",
+      "resolved": "https://registry.npmjs.org/@antv/hierarchy/-/hierarchy-0.6.11.tgz",
+      "integrity": "sha512-RJVhEMCuu4vj+Dt25lXIiNdd7jaqm/fqWGYikiELha4S5tnzdJoTUaUvvpfWlxLx4B0RsS9XRwBs1bOKN71TKg==",
+      "requires": {
+        "@antv/util": "^2.0.7"
+      }
+    },
+    "@antv/layout": {
+      "version": "0.3.23",
+      "resolved": "https://registry.npmjs.org/@antv/layout/-/layout-0.3.23.tgz",
+      "integrity": "sha512-F/CyfQuc1WSgCVemX0jA3pE3XuDRbDJmMueY1cL8WgL6nhdzm3/jg5UPamwbBVnhLk+rzNUDYdEIyX+RJbpcMA==",
+      "requires": {
+        "@antv/g-webgpu": "0.7.2",
+        "@antv/graphlib": "^1.0.0",
+        "@antv/util": "^3.3.2",
+        "d3-force": "^2.1.1",
+        "d3-quadtree": "^2.0.0",
+        "dagre-compound": "^0.0.11",
+        "ml-matrix": "^6.5.0"
+      },
+      "dependencies": {
+        "@antv/util": {
+          "version": "3.3.2",
+          "resolved": "https://registry.npmjs.org/@antv/util/-/util-3.3.2.tgz",
+          "integrity": "sha512-uvyQxEOugdJs/FVlpz/+8pKxn70z8jEVydPqv+LI62cpIF7YDjVnMfNIsoMqwEoTzPUJ9TJalyLqZhT5rYez0w==",
+          "requires": {
+            "fast-deep-equal": "^3.1.3",
+            "gl-matrix": "^3.3.0",
+            "tslib": "^2.3.1"
+          }
+        }
+      }
+    },
     "@antv/matrix-util": {
       "version": "3.1.0-beta.3",
       "resolved": "https://registry.npmjs.org/@antv/matrix-util/-/matrix-util-3.1.0-beta.3.tgz",
@@ -17460,6 +17975,31 @@
       "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==",
       "dev": true
     },
+    "@probe.gl/env": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/@probe.gl/env/-/env-3.6.0.tgz",
+      "integrity": "sha512-4tTZYUg/8BICC3Yyb9rOeoKeijKbZHRXBEKObrfPmX4sQmYB15ZOUpoVBhAyJkOYVAM8EkPci6Uw5dLCwx2BEQ==",
+      "requires": {
+        "@babel/runtime": "^7.0.0"
+      }
+    },
+    "@probe.gl/log": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/@probe.gl/log/-/log-3.6.0.tgz",
+      "integrity": "sha512-hjpyenpEvOdowgZ1qMeCJxfRD4JkKdlXz0RC14m42Un62NtOT+GpWyKA4LssT0+xyLULCByRAtG2fzZorpIAcA==",
+      "requires": {
+        "@babel/runtime": "^7.0.0",
+        "@probe.gl/env": "3.6.0"
+      }
+    },
+    "@probe.gl/stats": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/@probe.gl/stats/-/stats-3.6.0.tgz",
+      "integrity": "sha512-JdALQXB44OP4kUBN/UrQgzbJe4qokbVF4Y8lkIA8iVCFnjVowWIgkD/z/0QO65yELT54tTrtepw1jScjKB+rhQ==",
+      "requires": {
+        "@babel/runtime": "^7.0.0"
+      }
+    },
     "@riophae/vue-treeselect": {
       "version": "0.4.0",
       "resolved": "https://registry.npmmirror.com/@riophae/vue-treeselect/-/vue-treeselect-0.4.0.tgz",
@@ -20108,6 +20648,15 @@
       "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
       "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA=="
     },
+    "color": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
+      "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
+      "requires": {
+        "color-convert": "^1.9.3",
+        "color-string": "^1.6.0"
+      }
+    },
     "color-convert": {
       "version": "1.9.3",
       "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz",
@@ -20121,6 +20670,15 @@
       "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz",
       "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
     },
+    "color-string": {
+      "version": "1.9.1",
+      "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
+      "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+      "requires": {
+        "color-name": "^1.0.0",
+        "simple-swizzle": "^0.2.2"
+      }
+    },
     "colord": {
       "version": "2.9.2",
       "resolved": "https://registry.npmmirror.com/colord/-/colord-2.9.2.tgz",
@@ -20608,11 +21166,26 @@
       "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz",
       "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q=="
     },
+    "d3-dispatch": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-2.0.0.tgz",
+      "integrity": "sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA=="
+    },
     "d3-ease": {
       "version": "1.0.7",
       "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz",
       "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ=="
     },
+    "d3-force": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-2.1.1.tgz",
+      "integrity": "sha512-nAuHEzBqMvpFVMf9OX75d00OxvOXdxY+xECIXjW6Gv8BRrXu6gAWbv/9XKrvfJ5i5DCokDW7RYE50LRoK092ew==",
+      "requires": {
+        "d3-dispatch": "1 - 2",
+        "d3-quadtree": "1 - 2",
+        "d3-timer": "1 - 2"
+      }
+    },
     "d3-hierarchy": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-2.0.0.tgz",
@@ -20626,6 +21199,11 @@
         "d3-color": "1"
       }
     },
+    "d3-quadtree": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-2.0.0.tgz",
+      "integrity": "sha512-b0Ed2t1UUalJpc3qXzKi+cPGxeXRr4KU9YSlocN74aTzp6R/Ud43t79yLLqxHRWZfsvWXmbDWPpoENK1K539xw=="
+    },
     "d3-regression": {
       "version": "1.3.10",
       "resolved": "https://registry.npmjs.org/d3-regression/-/d3-regression-1.3.10.tgz",
@@ -20636,6 +21214,21 @@
       "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz",
       "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw=="
     },
+    "dagre": {
+      "version": "0.8.5",
+      "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz",
+      "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==",
+      "requires": {
+        "graphlib": "^2.1.8",
+        "lodash": "^4.17.15"
+      }
+    },
+    "dagre-compound": {
+      "version": "0.0.11",
+      "resolved": "https://registry.npmjs.org/dagre-compound/-/dagre-compound-0.0.11.tgz",
+      "integrity": "sha512-UrSgRP9LtOZCYb9e5doolZXpc7xayyszgyOs7uakTK4n4KsLegLVTRRtq01GpQd/iZjYw5fWMapx9ed+c80MAQ==",
+      "requires": {}
+    },
     "de-indent": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz",
@@ -21832,8 +22425,7 @@
     "eventemitter3": {
       "version": "4.0.7",
       "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-4.0.7.tgz",
-      "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
-      "dev": true
+      "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
     },
     "events": {
       "version": "3.3.0",
@@ -22302,6 +22894,11 @@
       "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz",
       "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA=="
     },
+    "gl-vec2": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/gl-vec2/-/gl-vec2-1.3.0.tgz",
+      "integrity": "sha512-YiqaAuNsheWmUV0Sa8k94kBB0D6RWjwZztyO+trEYS8KzJ6OQB/4686gdrf59wld4hHFIvaxynO3nRxpk1Ij/A=="
+    },
     "glob": {
       "version": "7.2.0",
       "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.0.tgz",
@@ -22354,6 +22951,14 @@
       "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.9.tgz",
       "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ=="
     },
+    "graphlib": {
+      "version": "2.1.8",
+      "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz",
+      "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==",
+      "requires": {
+        "lodash": "^4.17.15"
+      }
+    },
     "gzip-size": {
       "version": "6.0.0",
       "resolved": "https://registry.npmmirror.com/gzip-size/-/gzip-size-6.0.0.tgz",
@@ -22690,6 +23295,11 @@
       "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
       "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
     },
+    "insert-css": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/insert-css/-/insert-css-2.0.0.tgz",
+      "integrity": "sha512-xGq5ISgcUP5cvGkS2MMFLtPDBtrtQPSFfC6gA6U8wHKqfjTIMZLZNxOItQnoSjdOzlXOLU/yD32RKC4SvjNbtA=="
+    },
     "interactjs": {
       "version": "1.10.17",
       "resolved": "https://registry.npmjs.org/interactjs/-/interactjs-1.10.17.tgz",
@@ -22735,6 +23345,11 @@
       "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==",
       "dev": true
     },
+    "is-any-array": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-any-array/-/is-any-array-2.0.1.tgz",
+      "integrity": "sha512-UtilS7hLRu++wb/WBAw9bNuP1Eg04Ivn1vERJck8zJthEvXCBEBpGR/33u/xLKWEQf95803oalHrVDptcAvFdQ=="
+    },
     "is-arguments": {
       "version": "1.1.1",
       "resolved": "https://registry.npmmirror.com/is-arguments/-/is-arguments-1.1.1.tgz",
@@ -23804,6 +24419,41 @@
         "minimist": "^1.2.5"
       }
     },
+    "ml-array-max": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/ml-array-max/-/ml-array-max-1.2.4.tgz",
+      "integrity": "sha512-BlEeg80jI0tW6WaPyGxf5Sa4sqvcyY6lbSn5Vcv44lp1I2GR6AWojfUvLnGTNsIXrZ8uqWmo8VcG1WpkI2ONMQ==",
+      "requires": {
+        "is-any-array": "^2.0.0"
+      }
+    },
+    "ml-array-min": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/ml-array-min/-/ml-array-min-1.2.3.tgz",
+      "integrity": "sha512-VcZ5f3VZ1iihtrGvgfh/q0XlMobG6GQ8FsNyQXD3T+IlstDv85g8kfV0xUG1QPRO/t21aukaJowDzMTc7j5V6Q==",
+      "requires": {
+        "is-any-array": "^2.0.0"
+      }
+    },
+    "ml-array-rescale": {
+      "version": "1.3.7",
+      "resolved": "https://registry.npmjs.org/ml-array-rescale/-/ml-array-rescale-1.3.7.tgz",
+      "integrity": "sha512-48NGChTouvEo9KBctDfHC3udWnQKNKEWN0ziELvY3KG25GR5cA8K8wNVzracsqSW1QEkAXjTNx+ycgAv06/1mQ==",
+      "requires": {
+        "is-any-array": "^2.0.0",
+        "ml-array-max": "^1.2.4",
+        "ml-array-min": "^1.2.3"
+      }
+    },
+    "ml-matrix": {
+      "version": "6.10.4",
+      "resolved": "https://registry.npmjs.org/ml-matrix/-/ml-matrix-6.10.4.tgz",
+      "integrity": "sha512-rUyEhfNPzqFsltYwvjNeYQXlYEaVea3KgzcJKJteQUj2WVAGFx9fLNRjtMR9mg2B6bd5buxlmkZmxM4hmO+SKg==",
+      "requires": {
+        "is-any-array": "^2.0.0",
+        "ml-array-rescale": "^1.3.7"
+      }
+    },
     "module-alias": {
       "version": "2.2.2",
       "resolved": "https://registry.npmmirror.com/module-alias/-/module-alias-2.2.2.tgz",
@@ -24825,6 +25475,17 @@
       "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==",
       "dev": true
     },
+    "probe.gl": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/probe.gl/-/probe.gl-3.6.0.tgz",
+      "integrity": "sha512-19JydJWI7+DtR4feV+pu4Mn1I5TAc0xojuxVgZdXIyfmTLfUaFnk4OloWK1bKbPtkgGKLr2lnbnCXmpZEcEp9g==",
+      "requires": {
+        "@babel/runtime": "^7.0.0",
+        "@probe.gl/env": "3.6.0",
+        "@probe.gl/log": "3.6.0",
+        "@probe.gl/stats": "3.6.0"
+      }
+    },
     "process-nextick-args": {
       "version": "2.0.1",
       "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -25100,6 +25761,11 @@
         }
       }
     },
+    "regl": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/regl/-/regl-1.7.0.tgz",
+      "integrity": "sha512-bEAtp/qrtKucxXSJkD4ebopFZYP0q1+3Vb2WECWv/T8yQEgKxDxJ7ztO285tAMaYZVR6mM1GgI6CCn8FROtL1w=="
+    },
     "relateurl": {
       "version": "0.2.7",
       "resolved": "https://registry.npmmirror.com/relateurl/-/relateurl-0.2.7.tgz",
@@ -25541,6 +26207,21 @@
       "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
       "dev": true
     },
+    "simple-swizzle": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+      "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
+      "requires": {
+        "is-arrayish": "^0.3.1"
+      },
+      "dependencies": {
+        "is-arrayish": {
+          "version": "0.3.2",
+          "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+          "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
+        }
+      }
+    },
     "sirv": {
       "version": "1.0.19",
       "resolved": "https://registry.npmmirror.com/sirv/-/sirv-1.0.19.tgz",
@@ -26217,6 +26898,11 @@
       "resolved": "https://registry.npmmirror.com/tiny-warning/-/tiny-warning-1.0.3.tgz",
       "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
     },
+    "tinycolor2": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz",
+      "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="
+    },
     "to-fast-properties": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz",

+ 1 - 0
package.json

@@ -11,6 +11,7 @@
   "dependencies": {
     "@antv/g2": "^4.1.46",
     "@antv/g2plot": "^2.4.8",
+    "@antv/g6": "^4.8.17",
     "@riophae/vue-treeselect": "^0.4.0",
     "@sv-print/vue": "^0.1.4",
     "@wangeditor/editor": "^5.1.1",

+ 5 - 1
src/HDrpManagement/projectChange/modules/detail.vue

@@ -17,6 +17,7 @@
 <!--    <tagPanl slot="tags" :data="tagObj" ownertable="sa_project" :id="mainData.sa_projectid" @onSuccess="queryMainData"/>-->
     <div slot="customOperation">
       <!-- 此区域提供了自定义操作按钮 -->
+      <mindmap class="inline-16" :id="this.$route.query.id" name="project"></mindmap>
       <putPeople style=" display: inline-block !important;" @putSuccess="putSuccess" v-if="flagTag !== ''" :rowData="mainData" :flagTag="flagTag" :disabled="mainData.disabled"/>
       <projectRecovery class="inline-16" :data="mainData" v-if="tool.checkAuth($route.name,'recovery')  && mainData.status === '已失败'" :disabled="mainData.disabled" @onRecovery="onSuccess"></projectRecovery>
       <duplicatesProject class="inline-16" :data="mainData" v-if="tool.checkAuth($route.name,'queryDuplicates') " :disabled="mainData.disabled" @dialogClose="dialogClose"></duplicatesProject>
@@ -90,6 +91,8 @@ import contacts from './modules/contacts/index'
 import contract from './modules/contract/index'
 import duplicatesProject from "@/components/duplicatesData/duplicatesProject";
 import projectRecovery from "@/components/duplicatesCheck/projectRecovery";
+import mindmap from "@/components/mindmap/index.vue";
+
 export default {
   components:{
     Quotation,
@@ -109,7 +112,8 @@ export default {
     contacts,
     contract,
     duplicatesProject,
-    projectRecovery
+    projectRecovery,
+    mindmap
   },
   data () {
     return {

+ 4 - 1
src/HManagement/marketing2/saler/area/detail/index.vue

@@ -16,6 +16,7 @@
       <div slot="tags">
       </div>
       <div slot="customOperation" >
+        <mindmap class="inline-16" :id="mainData.hrid" name="saler"></mindmap>
         <el-button class="inline-16" v-if="tool.checkAuth($route.name,'delete')" type="primary" size="mini" @click="deleteSaler">删 除</el-button>
       </div>
       <div slot="slot0" >
@@ -35,8 +36,10 @@
 import detailed from './modules/detailedData'
 import TradefieldList from './modules/tradefieldList'
 import areaBase from './modules/areaBase/index'
+import mindmap from "@/components/mindmap/index.vue";
+
 export default {
-  components:{detailed,TradefieldList,areaBase},
+  components:{detailed,TradefieldList,areaBase,mindmap},
   data () {
     return {
       mainData:{},

+ 5 - 2
src/SDrpManagement/salerPrivatecustomer/detail/customerDetail.vue

@@ -20,13 +20,14 @@
       </div>
       <div slot="customOperation" >
         <!-- 此区域提供了自定义操作按钮 -->
+        <mindmap class="inline-16" :id="this.$route.query.id" name="custom"></mindmap>
         <statusChange class="inline-16" v-if="tool.checkAuth($route.name,'statusChange')" :disabled="mainData.disabled" :id="mainData.sa_customersid"  @statusChangeSuccess="statusChangeSuccess"></statusChange>
         <share class="inline-16" v-if="tool.checkAuth($route.name,'share') && mainData.sourcepoolname === ''" :disabled="mainData.disabled" :id="mainData.sa_customersid" @onshow="onSuccess" @shareSuccess="onSuccess"></share>
         <toBack class="inline-16" v-if="tool.checkAuth($route.name,'back') && mainData.sa_customerpoolid_source !== 0" :disabled="mainData.disabled" :data="mainData" @backSuccess="onSuccess"></toBack>
         <duplicatesCustomer class="inline-16" v-if="tool.checkAuth($route.name,'queryDuplicates')" :data="mainData"  @onSuccessTag="onSuccessTag"></duplicatesCustomer>
         <to_void class="inline-16" v-if="tool.checkAuth($route.name,'toVoid')" :id="mainData.sa_customersid" :disabled="mainData.disabled" @onshow="onSuccess" @toVoidSuccess="onSuccess"></to_void>
         <recovery class="inline-16" v-if="tool.checkAuth($route.name,'recovery') && mainData.sa_customerpoolid_source !== 0 " :data="mainData" @onshow="onSuccess" @backSuccess="onSuccess"></recovery>
-
+        
       </div>
       <div slot="slot0" >
         <detailed :data="mainData" v-if="Object.keys(mainData).length > 1" ref="baseDetail"></detailed>
@@ -84,6 +85,7 @@ import contract from './modules/contract/index'
 import accountMoney from './modules/accountMoney/index'
 import bankCard from './modules/bankCard/index'
 import duplicatesCustomer from "@/components/duplicatesData/duplicatesCustomer";
+import mindmap from "@/components/mindmap/index.vue";
 export default {
   name: "detail",
   data() {
@@ -128,7 +130,8 @@ export default {
     contract,
     accountMoney,
     bankCard,
-    duplicatesCustomer
+    duplicatesCustomer,
+    mindmap
   },
   watch:{
    async mainData(val) {

+ 563 - 0
src/components/mindmap/custom.vue

@@ -0,0 +1,563 @@
+<template>
+  <div style="background:#f1f2f3" >
+    <div id="container"></div>
+  </div>
+</template>
+
+<script>
+import G6 from '@antv/g6';
+let graph;
+const fittingString = (str, maxWidth, fontSize) => {
+  const ellipsis = "...";
+  const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0];
+  let currentWidth = 0;
+  let res = str;
+  const pattern = new RegExp("[\u4E00-\u9FA5]+"); // distinguish the Chinese charactors and letters
+  str.split("").forEach((letter, i) => {
+    if (currentWidth > maxWidth - ellipsisLength) return;
+    if (pattern.test(letter)) {
+      // Chinese charactors
+      currentWidth += fontSize;
+    } else {
+      // get the width of single letter according to the fontSize
+      currentWidth += G6.Util.getLetterWidth(letter, fontSize);
+    }
+    if (currentWidth > maxWidth - ellipsisLength) {
+      res = `${str.substr(0, i)}${ellipsis}`;
+    }
+  });
+  return res;
+};
+const ERROR_COLOR = 'red';
+const getNodeConfig = (node) => {
+  if (node.nodeUrl) {
+    return {
+      basicColor: ERROR_COLOR,
+      fontColor: '#FFF',
+      borderColor: ERROR_COLOR,
+      bgColor: '#ff5722',
+    };
+  }
+  let config = {
+    basicColor: '#fff',
+    fontColor: '#333',
+    borderColor: '#fff',
+    bgColor: '#fff',
+  };
+  switch (node.type) {
+    case 'root': {
+      config = {
+        basicColor: '#E3E6E8',
+        fontColor: 'rgba(0,0,0,0.85)',
+        borderColor: '#E3E6E8',
+        bgColor: '#5b8ff9',
+      };
+      break;
+    }
+    default:
+      break;
+  }
+  return config;
+};
+
+const COLLAPSE_ICON = function COLLAPSE_ICON(x, y, r) {
+  return [
+    ['M', x - r, y],
+    ['a', r, r, 0, 1, 0, r * 2, 0],
+    ['a', r, r, 0, 1, 0, -r * 2, 0],
+    ['M', x - r + 4, y],
+    ['L', x - r + 2 * r - 4, y],
+  ];
+};
+const EXPAND_ICON = function EXPAND_ICON(x, y, r) {
+  return [
+    ['M', x - r, y],
+    ['a', r, r, 0, 1, 0, r * 2, 0],
+    ['a', r, r, 0, 1, 0, -r * 2, 0],
+    ['M', x - r + 4, y],
+    ['L', x - r + 2 * r - 4, y],
+    ['M', x - r + r, y - r + 4],
+    ['L', x, y + r - 4],
+  ];
+};
+const nodeBasicMethod = {
+  createNodeBox: (group, config, w, h, isRoot) => {
+    /* 最外面的大矩形 */
+    const container = group.addShape('rect', {
+      attrs: {
+        x: 0,
+        y: 0,
+        width: w,
+        height: h,
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'big-rect-shape',
+    });
+    if (!isRoot) {
+      /* 左边的小圆点 */
+      group.addShape('circle', {
+        attrs: {
+          x: 3,
+          y: h / 2,
+          r: 0,
+          fill: config.basicColor,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'left-dot-shape',
+      });
+    }
+    /* 矩形 */
+    group.addShape('rect', {
+      attrs: {
+        x: 3,
+        y: 0,
+        width: w - 19,
+        height: h,
+        fill: config.bgColor,
+        stroke: config.borderColor,
+        radius: 2,
+        cursor: 'pointer',
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'rect-shape',
+    });
+
+    /* 左边的粗线 */
+    group.addShape('rect', {
+      attrs: {
+        x: 3,
+        y: 0,
+        width: 3,
+        height: h,
+        fill: config.basicColor,
+        radius: 1.5,
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'left-border-shape',
+    });
+    return container;
+  },
+  /* 生成树上的 marker */
+  createNodeMarker: (group, collapsed, x, y) => {
+    group.addShape('circle', {
+      attrs: {
+        x,
+        y,
+        r: 13,
+        fill: 'rgba(47, 84, 235, 0.05)',
+        opacity: 0,
+        zIndex: -2,
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'collapse-icon-bg',
+    });
+    group.addShape('marker', {
+      attrs: {
+        x,
+        y,
+        r: 7,
+        symbol: collapsed ? EXPAND_ICON : COLLAPSE_ICON,
+        stroke: 'rgba(0,0,0,0.25)',
+        fill: 'rgba(0,0,0,0)',
+        lineWidth: 1,
+        cursor: 'pointer',
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'collapse-icon',
+    });
+  },
+  afterDraw: (cfg, group) => {
+    /* 操作 marker 的背景色显示隐藏 */
+    const icon = group.find((element) => element.get('id') === 'collapse-icon');
+    if (icon) {
+      const bg = group.find((element) => element.get('id') === 'collapse-icon-bg');
+      icon.on('mouseenter', () => {
+        bg.attr('opacity', 1);
+        graph.get('canvas').draw();
+      });
+      icon.on('mouseleave', () => {
+        bg.attr('opacity', 0);
+        graph.get('canvas').draw();
+      });
+    }
+    /* ip 显示 */
+    const ipBox = group.find((element) => element.get('id') === 'ip-box');
+    if (ipBox) {
+      /* ip 复制的几个元素 */
+      const ipLine = group.find((element) => element.get('id') === 'ip-cp-line');
+      const ipBG = group.find((element) => element.get('id') === 'ip-cp-bg');
+      const ipIcon = group.find((element) => element.get('id') === 'ip-cp-icon');
+      const ipCPBox = group.find((element) => element.get('id') === 'ip-cp-box');
+
+      const onMouseEnter = () => {
+        ipLine.attr('opacity', 1);
+        ipBG.attr('opacity', 1);
+        ipIcon.attr('opacity', 1);
+        graph.get('canvas').draw();
+      };
+      const onMouseLeave = () => {
+        ipLine.attr('opacity', 0);
+        ipBG.attr('opacity', 0);
+        ipIcon.attr('opacity', 0);
+        graph.get('canvas').draw();
+      };
+      ipBox.on('mouseenter', () => {
+        onMouseEnter();
+      });
+      ipBox.on('mouseleave', () => {
+        onMouseLeave();
+      });
+      ipCPBox.on('mouseenter', () => {
+        onMouseEnter();
+      });
+      ipCPBox.on('mouseleave', () => {
+        onMouseLeave();
+      });
+      ipCPBox.on('click', () => { });
+    }
+  },
+  setState: (name, value, item) => {
+    const hasOpacityClass = [
+      'ip-cp-line',
+      'ip-cp-bg',
+      'ip-cp-icon',
+      'ip-cp-box',
+      'ip-box',
+      'collapse-icon-bg',
+    ];
+    const group = item.getContainer();
+    const childrens = group.get('children');
+    graph.setAutoPaint(false);
+    if (name === 'emptiness') {
+      if (value) {
+        childrens.forEach((shape) => {
+          if (hasOpacityClass.indexOf(shape.get('id')) > -1) {
+            return;
+          }
+          shape.attr('opacity', 0.4);
+        });
+      } else {
+        childrens.forEach((shape) => {
+          if (hasOpacityClass.indexOf(shape.get('id')) > -1) {
+            return;
+          }
+          shape.attr('opacity', 1);
+        });
+      }
+    }
+    graph.setAutoPaint(true);
+  },
+};
+
+G6.registerNode('card-node', {
+  options: {
+    style: {
+      stroke: '#ccc',
+    },
+  },
+  draw: (cfg, group) => {
+    
+    const config = getNodeConfig(cfg);
+    const isRoot = cfg.dataType === 'root';
+    const nodeUrl = cfg.nodeUrl;
+    /* the biggest rect */
+    const container = nodeBasicMethod.createNodeBox(group, config, 243, 64, isRoot);
+
+    if (cfg.dataType !== 'root') {
+      /* the type text */
+      group.addShape('text', {
+        attrs: {
+          text: cfg.dataType,
+          x: 3,
+          y: -10,
+          fontSize: 12,
+          textAlign: 'left',
+          textBaseline: 'middle',
+          fill: 'rgba(0,0,0,0.65)',
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'type-text-shape',
+      });
+    }
+
+    if (cfg.ip) {
+      /* ip start */
+      /* ipBox */
+      const ipRect = group.addShape('rect', {
+        attrs: {
+          fill: nodeUrl ? null : '#FFF',
+          stroke: nodeUrl ? 'rgba(255,255,255,0.65)' : null,
+          radius: 2,
+          cursor: 'pointer',
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-container-shape',
+      });
+
+      /* ip */
+      const ipText = group.addShape('text', {
+        attrs: {
+          text: '666',
+          x: 0,
+          y: 19,
+          fontSize: 12,
+          textAlign: 'left',
+          textBaseline: 'middle',
+          fill: nodeUrl ? 'rgba(255,255,255,0.85)' : 'rgba(0,0,0,0.65)',
+          cursor: 'pointer',
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-text-shape',
+      });
+
+      const ipBBox = ipText.getBBox();
+      /* the distance from the IP to the right is 12px */
+      ipText.attr({
+        x: 224 - 12 - ipBBox.width,
+      });
+      /* ipBox */
+      ipRect.attr({
+        x: 224 - 12 - ipBBox.width - 4,
+        y: ipBBox.minY - 5,
+        width: ipBBox.width + 8,
+        height: ipBBox.height + 10,
+      });
+
+      /* a transparent shape on the IP for click listener */
+      group.addShape('rect', {
+        attrs: {
+          stroke: '',
+          cursor: 'pointer',
+          x: 224 - 12 - ipBBox.width - 4,
+          y: ipBBox.minY - 5,
+          width: ipBBox.width + 8,
+          height: ipBBox.height + 10,
+          fill: '#fff',
+          opacity: 0,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-box',
+      });
+
+      /* copyIpLine */
+      group.addShape('rect', {
+        attrs: {
+          x: 194,
+          y: 7,
+          width: 1,
+          height: 24,
+          fill: '#E3E6E8',
+          opacity: 0,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-cp-line',
+      });
+      /* copyIpBG */
+      group.addShape('rect', {
+        attrs: {
+          x: 195,
+          y: 8,
+          width: 22,
+          height: 22,
+          fill: '#FFF',
+          cursor: 'pointer',
+          opacity: 0,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-cp-bg',
+      });
+      /* copyIpIcon */
+      group.addShape('image', {
+        attrs: {
+          x: 200,
+          y: 13,
+          height: 12,
+          width: 10,
+          img: 'https://os.alipayobjects.com/rmsportal/DFhnQEhHyPjSGYW.png',
+          cursor: 'pointer',
+          opacity: 0,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-cp-icon',
+      });
+      /* a transparent rect on the icon area for click listener */
+      group.addShape('rect', {
+        attrs: {
+          x: 195,
+          y: 8,
+          width: 22,
+          height: 22,
+          fill: '#FFF',
+          cursor: 'pointer',
+          opacity: 0,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-cp-box',
+        tooltip: 'Copy the IP',
+      });
+
+      /* ip end */
+    }
+
+    /* name */
+    group.addShape('text', {
+      attrs: {
+        text: cfg.id,
+        x: 19,
+        y: 19,
+        fontSize: 14,
+        fontWeight: 700,
+        textAlign: 'left',
+        textBaseline: 'middle',
+        fill: config.fontColor,
+        cursor: 'pointer',
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'name-text-shape',
+    });
+
+    /* the description text */
+    group.addShape('text', {
+      attrs: {
+        // text: cfg.value !== cfg.id?cfg.value : "-",
+        text: fittingString(cfg.value, 243 - 50, 14),
+        x: 19,
+        y: 45,
+        fontSize: 14,
+        textAlign: 'left',
+        textBaseline: 'middle',
+        fill: config.fontColor,
+        cursor: 'pointer',
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'bottom-text-shape',
+    });
+
+    if (nodeUrl) {
+      group.addShape('text', {
+        attrs: {
+          x: 191,
+          y: 62,
+          text: '⇢',
+          fill: '#fff',
+          fontSize: 18,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'error-text-shape',
+      });
+    }
+
+    const hasChildren = cfg.children && cfg.children.length > 0;
+    if (hasChildren) {
+      nodeBasicMethod.createNodeMarker(group, cfg.collapsed, 236, 32);
+    }
+    return container;
+  },
+  afterDraw: nodeBasicMethod.afterDraw,
+  setState: nodeBasicMethod.setState,
+});
+export default {
+  props:['id'],
+  data () {
+    return {
+
+    }
+  },
+  mounted () {
+    // this.getData()
+  },
+  methods:{
+    createMenu (array) {
+      var that = this
+      let arr = []
+      const HASLINKS = ['有效项目','合同','服务工单数']
+      function convertToElementTree(node) {
+        // 新节点
+        var elNode = {
+          id: node['name'],
+          nodeid:node['id'],
+          value:node['labor']?node['labor'] !== node['name']?node['labor']:'-':'-',
+          children: [],
+          nodeUrl:HASLINKS.includes(node['name'])?'123':null
+        }
+          
+        if (node.children && node.children.length > 0) {
+          // 如果存在子节点
+          for (var index = 0; index < node.children.length; index++) {
+          // 遍历子节点, 把每个子节点看做一颗独立的树, 传入递归构造子树, 并把结果放回到新node的children中
+          elNode.children.push(convertToElementTree(node.children[index]));
+          }
+        }
+        return elNode;
+      }
+      array.forEach((element) => {
+        arr.push(convertToElementTree(element))
+      });
+      return arr
+    },
+    async getData () {
+      const res = await this.$api.requested({
+        "id": 20230620143204,
+        "content": {
+          "sa_customersid": this.id
+        }
+      })
+      // this.data = this.createMenu([res.data.data])
+      const container = document.getElementById('container');
+      const width = container.scrollWidth;
+      const height = container.scrollHeight || 500;
+      const graph = new G6.TreeGraph({
+        container: 'container',
+        width,
+        height,
+        linkCenter: true,
+        fitCenter: true,
+        modes: {
+          default: ['drag-canvas','zoom-canvas','collapse-expand','drag-node', 'lasso-select'],
+        },
+        defaultNode: {
+          /* node type, the priority is lower than the type in the node data */
+          type: 'card-node',
+        },
+        defaultEdge: {
+          type: 'cubic-horizontal',
+        },
+        layout: {
+          type: 'dendrogram',
+          direction: 'RL',
+          nodeSep: 100,
+          rankSep: 350,
+          radial: true,
+        },
+      });
+
+      graph.node(function (node) {
+        return {
+          label: node.id,
+        };
+      });
+
+      graph.data(this.createMenu([res.data])[0]);
+      graph.render();
+      graph.fitView();
+      graph.on('node:click', evt => {
+        const item = evt.item;
+        console.log(item)
+      })
+      if (typeof window !== 'undefined')
+        window.onresize = () => {
+          if (!graph || graph.get('destroyed')) return;
+          if (!container || !container.scrollWidth || !container.scrollHeight) return;
+          graph.changeSize(container.scrollWidth, container.scrollHeight);
+        };
+    }
+  },
+}
+
+</script>
+<style>
+#container{
+  height: 100vh;
+  width: 100vw;
+}
+</style>

+ 59 - 0
src/components/mindmap/index.vue

@@ -0,0 +1,59 @@
+<template>
+  <div>
+    <el-button size="mini" type="primary" @click="onShow">360°画像</el-button>
+    <el-drawer
+      :visible.sync="drawer"
+      append-to-body
+      size="100%"
+      :with-header="false">
+      <custom ref="custom" v-if="name === 'custom'" :id="id"/>
+      <project ref="project" v-else-if="name === 'project'" :id="id"/>
+      <saler ref="saler" v-else :id="id"/>
+    </el-drawer>
+
+  </div>
+</template>
+
+<script>
+import custom from './custom.vue'
+import project from './project.vue'
+import saler from './saler.vue'
+export default {
+  props:['id','name'],
+  components:{
+    custom,
+    project,
+    saler
+  },
+  data() {
+    return {
+      drawer: false,
+    };
+  },
+  methods:{
+    onShow () {
+      this.drawer = true
+      next(() => {
+        switch (this.name) {
+          case 'custom':
+            console.log(this.$refs.custom)
+            this.$refs.custom.getData()
+            break;
+          case 'project':
+            console.log(this.$refs.project)
+            this.$refs.project.getData()
+            break;
+          default:
+            console.log(this.$refs.saler)
+            this.$refs.saler.getData()
+            break;
+        }
+      }, 0);
+      
+    }
+  }
+}
+
+</script>
+<style>
+</style>

+ 562 - 0
src/components/mindmap/project.vue

@@ -0,0 +1,562 @@
+<template>
+  <div style="background:#f1f2f3" >
+    <div id="container"></div>
+  </div>
+</template>
+
+<script>
+import G6 from '@antv/g6';
+import axios from 'axios'
+let graph;
+const fittingString = (str, maxWidth, fontSize) => {
+  const ellipsis = "...";
+  const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0];
+  let currentWidth = 0;
+  let res = str;
+  const pattern = new RegExp("[\u4E00-\u9FA5]+"); // distinguish the Chinese charactors and letters
+  str.split("").forEach((letter, i) => {
+    if (currentWidth > maxWidth - ellipsisLength) return;
+    if (pattern.test(letter)) {
+      // Chinese charactors
+      currentWidth += fontSize;
+    } else {
+      // get the width of single letter according to the fontSize
+      currentWidth += G6.Util.getLetterWidth(letter, fontSize);
+    }
+    if (currentWidth > maxWidth - ellipsisLength) {
+      res = `${str.substr(0, i)}${ellipsis}`;
+    }
+  });
+  return res;
+};
+const ERROR_COLOR = 'red';
+const getNodeConfig = (node) => {
+  if (node.nodeUrl) {
+    return {
+      basicColor: ERROR_COLOR,
+      fontColor: '#FFF',
+      borderColor: ERROR_COLOR,
+      bgColor: '#ff5722',
+    };
+  }
+  let config = {
+    basicColor: '#fff',
+    fontColor: '#333',
+    borderColor: '#fff',
+    bgColor: '#fff',
+  };
+  switch (node.type) {
+    case 'root': {
+      config = {
+        basicColor: '#E3E6E8',
+        fontColor: 'rgba(0,0,0,0.85)',
+        borderColor: '#E3E6E8',
+        bgColor: '#5b8ff9',
+      };
+      break;
+    }
+    default:
+      break;
+  }
+  return config;
+};
+
+const COLLAPSE_ICON = function COLLAPSE_ICON(x, y, r) {
+  return [
+    ['M', x - r, y],
+    ['a', r, r, 0, 1, 0, r * 2, 0],
+    ['a', r, r, 0, 1, 0, -r * 2, 0],
+    ['M', x - r + 4, y],
+    ['L', x - r + 2 * r - 4, y],
+  ];
+};
+const EXPAND_ICON = function EXPAND_ICON(x, y, r) {
+  return [
+    ['M', x - r, y],
+    ['a', r, r, 0, 1, 0, r * 2, 0],
+    ['a', r, r, 0, 1, 0, -r * 2, 0],
+    ['M', x - r + 4, y],
+    ['L', x - r + 2 * r - 4, y],
+    ['M', x - r + r, y - r + 4],
+    ['L', x, y + r - 4],
+  ];
+};
+const nodeBasicMethod = {
+  createNodeBox: (group, config, w, h, isRoot) => {
+    /* 最外面的大矩形 */
+    const container = group.addShape('rect', {
+      attrs: {
+        x: 0,
+        y: 0,
+        width: w,
+        height: h,
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'big-rect-shape',
+    });
+    if (!isRoot) {
+      /* 左边的小圆点 */
+      group.addShape('circle', {
+        attrs: {
+          x: 3,
+          y: h / 2,
+          r: 0,
+          fill: config.basicColor,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'left-dot-shape',
+      });
+    }
+    /* 矩形 */
+    group.addShape('rect', {
+      attrs: {
+        x: 3,
+        y: 0,
+        width: w - 19,
+        height: h,
+        fill: config.bgColor,
+        stroke: config.borderColor,
+        radius: 2,
+        cursor: 'pointer',
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'rect-shape',
+    });
+
+    /* 左边的粗线 */
+    group.addShape('rect', {
+      attrs: {
+        x: 3,
+        y: 0,
+        width: 3,
+        height: h,
+        fill: config.basicColor,
+        radius: 1.5,
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'left-border-shape',
+    });
+    return container;
+  },
+  /* 生成树上的 marker */
+  createNodeMarker: (group, collapsed, x, y) => {
+    group.addShape('circle', {
+      attrs: {
+        x,
+        y,
+        r: 13,
+        fill: 'rgba(47, 84, 235, 0.05)',
+        opacity: 0,
+        zIndex: -2,
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'collapse-icon-bg',
+    });
+    group.addShape('marker', {
+      attrs: {
+        x,
+        y,
+        r: 7,
+        symbol: collapsed ? EXPAND_ICON : COLLAPSE_ICON,
+        stroke: 'rgba(0,0,0,0.25)',
+        fill: 'rgba(0,0,0,0)',
+        lineWidth: 1,
+        cursor: 'pointer',
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'collapse-icon',
+    });
+  },
+  afterDraw: (cfg, group) => {
+    /* 操作 marker 的背景色显示隐藏 */
+    const icon = group.find((element) => element.get('id') === 'collapse-icon');
+    if (icon) {
+      const bg = group.find((element) => element.get('id') === 'collapse-icon-bg');
+      icon.on('mouseenter', () => {
+        bg.attr('opacity', 1);
+        graph.get('canvas').draw();
+      });
+      icon.on('mouseleave', () => {
+        bg.attr('opacity', 0);
+        graph.get('canvas').draw();
+      });
+    }
+    /* ip 显示 */
+    const ipBox = group.find((element) => element.get('id') === 'ip-box');
+    if (ipBox) {
+      /* ip 复制的几个元素 */
+      const ipLine = group.find((element) => element.get('id') === 'ip-cp-line');
+      const ipBG = group.find((element) => element.get('id') === 'ip-cp-bg');
+      const ipIcon = group.find((element) => element.get('id') === 'ip-cp-icon');
+      const ipCPBox = group.find((element) => element.get('id') === 'ip-cp-box');
+
+      const onMouseEnter = () => {
+        ipLine.attr('opacity', 1);
+        ipBG.attr('opacity', 1);
+        ipIcon.attr('opacity', 1);
+        graph.get('canvas').draw();
+      };
+      const onMouseLeave = () => {
+        ipLine.attr('opacity', 0);
+        ipBG.attr('opacity', 0);
+        ipIcon.attr('opacity', 0);
+        graph.get('canvas').draw();
+      };
+      ipBox.on('mouseenter', () => {
+        onMouseEnter();
+      });
+      ipBox.on('mouseleave', () => {
+        onMouseLeave();
+      });
+      ipCPBox.on('mouseenter', () => {
+        onMouseEnter();
+      });
+      ipCPBox.on('mouseleave', () => {
+        onMouseLeave();
+      });
+      ipCPBox.on('click', () => { });
+    }
+  },
+  setState: (name, value, item) => {
+    const hasOpacityClass = [
+      'ip-cp-line',
+      'ip-cp-bg',
+      'ip-cp-icon',
+      'ip-cp-box',
+      'ip-box',
+      'collapse-icon-bg',
+    ];
+    const group = item.getContainer();
+    const childrens = group.get('children');
+    graph.setAutoPaint(false);
+    if (name === 'emptiness') {
+      if (value) {
+        childrens.forEach((shape) => {
+          if (hasOpacityClass.indexOf(shape.get('id')) > -1) {
+            return;
+          }
+          shape.attr('opacity', 0.4);
+        });
+      } else {
+        childrens.forEach((shape) => {
+          if (hasOpacityClass.indexOf(shape.get('id')) > -1) {
+            return;
+          }
+          shape.attr('opacity', 1);
+        });
+      }
+    }
+    graph.setAutoPaint(true);
+  },
+};
+
+G6.registerNode('card-node', {
+  options: {
+    style: {
+      stroke: '#ccc',
+    },
+  },
+  draw: (cfg, group) => {
+    
+    const config = getNodeConfig(cfg);
+    const isRoot = cfg.dataType === 'root';
+    const nodeUrl = cfg.nodeUrl;
+    /* the biggest rect */
+    const container = nodeBasicMethod.createNodeBox(group, config, 243, 64, isRoot);
+
+    if (cfg.dataType !== 'root') {
+      /* the type text */
+      group.addShape('text', {
+        attrs: {
+          text: cfg.dataType,
+          x: 3,
+          y: -10,
+          fontSize: 12,
+          textAlign: 'left',
+          textBaseline: 'middle',
+          fill: 'rgba(0,0,0,0.65)',
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'type-text-shape',
+      });
+    }
+
+    if (cfg.ip) {
+      /* ip start */
+      /* ipBox */
+      const ipRect = group.addShape('rect', {
+        attrs: {
+          fill: nodeUrl ? null : '#FFF',
+          stroke: nodeUrl ? 'rgba(255,255,255,0.65)' : null,
+          radius: 2,
+          cursor: 'pointer',
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-container-shape',
+      });
+
+      /* ip */
+      const ipText = group.addShape('text', {
+        attrs: {
+          text: '666',
+          x: 0,
+          y: 19,
+          fontSize: 12,
+          textAlign: 'left',
+          textBaseline: 'middle',
+          fill: nodeUrl ? 'rgba(255,255,255,0.85)' : 'rgba(0,0,0,0.65)',
+          cursor: 'pointer',
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-text-shape',
+      });
+
+      const ipBBox = ipText.getBBox();
+      /* the distance from the IP to the right is 12px */
+      ipText.attr({
+        x: 224 - 12 - ipBBox.width,
+      });
+      /* ipBox */
+      ipRect.attr({
+        x: 224 - 12 - ipBBox.width - 4,
+        y: ipBBox.minY - 5,
+        width: ipBBox.width + 8,
+        height: ipBBox.height + 10,
+      });
+
+      /* a transparent shape on the IP for click listener */
+      group.addShape('rect', {
+        attrs: {
+          stroke: '',
+          cursor: 'pointer',
+          x: 224 - 12 - ipBBox.width - 4,
+          y: ipBBox.minY - 5,
+          width: ipBBox.width + 8,
+          height: ipBBox.height + 10,
+          fill: '#fff',
+          opacity: 0,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-box',
+      });
+
+      /* copyIpLine */
+      group.addShape('rect', {
+        attrs: {
+          x: 194,
+          y: 7,
+          width: 1,
+          height: 24,
+          fill: '#E3E6E8',
+          opacity: 0,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-cp-line',
+      });
+      /* copyIpBG */
+      group.addShape('rect', {
+        attrs: {
+          x: 195,
+          y: 8,
+          width: 22,
+          height: 22,
+          fill: '#FFF',
+          cursor: 'pointer',
+          opacity: 0,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-cp-bg',
+      });
+      /* copyIpIcon */
+      group.addShape('image', {
+        attrs: {
+          x: 200,
+          y: 13,
+          height: 12,
+          width: 10,
+          img: 'https://os.alipayobjects.com/rmsportal/DFhnQEhHyPjSGYW.png',
+          cursor: 'pointer',
+          opacity: 0,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-cp-icon',
+      });
+      /* a transparent rect on the icon area for click listener */
+      group.addShape('rect', {
+        attrs: {
+          x: 195,
+          y: 8,
+          width: 22,
+          height: 22,
+          fill: '#FFF',
+          cursor: 'pointer',
+          opacity: 0,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-cp-box',
+        tooltip: 'Copy the IP',
+      });
+
+      /* ip end */
+    }
+
+    /* name */
+    group.addShape('text', {
+      attrs: {
+        text: cfg.id,
+        x: 19,
+        y: 19,
+        fontSize: 14,
+        fontWeight: 700,
+        textAlign: 'left',
+        textBaseline: 'middle',
+        fill: config.fontColor,
+        cursor: 'pointer',
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'name-text-shape',
+    });
+
+    /* the description text */
+    group.addShape('text', {
+      attrs: {
+        text: fittingString(cfg.value, 243 - 50, 14),
+        x: 19,
+        y: 45,
+        fontSize: 14,
+        textAlign: 'left',
+        textBaseline: 'middle',
+        fill: config.fontColor,
+        cursor: 'pointer',
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'bottom-text-shape',
+    });
+
+    if (nodeUrl) {
+      group.addShape('text', {
+        attrs: {
+          x: 191,
+          y: 62,
+          text: '⇢',
+          fill: '#fff',
+          fontSize: 18,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'error-text-shape',
+      });
+    }
+
+    const hasChildren = cfg.children && cfg.children.length > 0;
+    if (hasChildren) {
+      nodeBasicMethod.createNodeMarker(group, cfg.collapsed, 236, 32);
+    }
+    return container;
+  },
+  afterDraw: nodeBasicMethod.afterDraw,
+  setState: nodeBasicMethod.setState,
+});
+export default {
+  props:['id'],
+  data () {
+    return {
+
+    }
+  },
+  mounted () {
+    // this.getData()
+  },
+  methods:{
+    createMenu (array) {
+      var that = this
+      let arr = []
+      const HASLINKS = ['关联客户','竞争对手','报价单有效数','合同有效数']
+      function convertToElementTree(node) {
+        // 新节点
+        var elNode = {
+          id: node['name'],
+          nodeid:node['id'],
+          value:node['labor']?node['labor'] !== node['name']?node['labor']:'-':'-',
+          children: [],
+          nodeUrl:HASLINKS.includes(node['name'])?'123':null
+        }
+          
+        if (node.children && node.children.length > 0) {
+          // 如果存在子节点
+          for (var index = 0; index < node.children.length; index++) {
+          // 遍历子节点, 把每个子节点看做一颗独立的树, 传入递归构造子树, 并把结果放回到新node的children中
+          elNode.children.push(convertToElementTree(node.children[index]));
+          }
+        }
+        return elNode;
+      }
+      array.forEach((element) => {
+        arr.push(convertToElementTree(element))
+      });
+      return arr
+    },
+    async getData () {
+      const res = await this.$api.requested({
+        "id": 20230619141904,
+        "content": {
+          "sa_projectid": this.id
+        }
+      })
+      const container = document.getElementById('container');
+      const width = container.scrollWidth;
+      const height = container.scrollHeight || 500;
+      const graph = new G6.TreeGraph({
+        container: 'container',
+        width,
+        height,
+        linkCenter: true,
+        fitCenter: true,
+        modes: {
+          default: ['drag-canvas','zoom-canvas','collapse-expand','drag-node', 'lasso-select'],
+        },
+        defaultNode: {
+          /* node type, the priority is lower than the type in the node data */
+          type: 'card-node',
+        },
+        defaultEdge: {
+          type: 'cubic-horizontal',
+        },
+        layout: {
+          type: 'dendrogram',
+          direction: 'RL',
+          nodeSep: 100,
+          rankSep: 250,
+          radial: true,
+        },
+      });
+
+      graph.node(function (node) {
+        return {
+          label: node.id,
+        };
+      });
+
+      graph.data(this.createMenu([res.data])[0]);
+      graph.render();
+      graph.fitView();
+      graph.on('node:click', evt => {
+        const item = evt.item;
+        console.log(item)
+      })
+      if (typeof window !== 'undefined')
+        window.onresize = () => {
+          if (!graph || graph.get('destroyed')) return;
+          if (!container || !container.scrollWidth || !container.scrollHeight) return;
+          graph.changeSize(container.scrollWidth, container.scrollHeight);
+        };
+    }
+  },
+}
+
+</script>
+<style>
+#container{
+  height: 100vh;
+  width: 100vw;
+}
+</style>

+ 562 - 0
src/components/mindmap/saler.vue

@@ -0,0 +1,562 @@
+<template>
+  <div style="background:#f1f2f3" >
+    <div id="container"></div>
+  </div>
+</template>
+
+<script>
+import G6 from '@antv/g6';
+import axios from 'axios'
+let graph;
+const fittingString = (str, maxWidth, fontSize) => {
+  const ellipsis = "...";
+  const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0];
+  let currentWidth = 0;
+  let res = str;
+  const pattern = new RegExp("[\u4E00-\u9FA5]+"); // distinguish the Chinese charactors and letters
+  str.split("").forEach((letter, i) => {
+    if (currentWidth > maxWidth - ellipsisLength) return;
+    if (pattern.test(letter)) {
+      // Chinese charactors
+      currentWidth += fontSize;
+    } else {
+      // get the width of single letter according to the fontSize
+      currentWidth += G6.Util.getLetterWidth(letter, fontSize);
+    }
+    if (currentWidth > maxWidth - ellipsisLength) {
+      res = `${str.substr(0, i)}${ellipsis}`;
+    }
+  });
+  return res;
+};
+const ERROR_COLOR = 'red';
+const getNodeConfig = (node) => {
+  if (node.nodeUrl) {
+    return {
+      basicColor: ERROR_COLOR,
+      fontColor: '#FFF',
+      borderColor: ERROR_COLOR,
+      bgColor: '#ff5722',
+    };
+  }
+  let config = {
+    basicColor: '#fff',
+    fontColor: '#333',
+    borderColor: '#fff',
+    bgColor: '#fff',
+  };
+  switch (node.type) {
+    case 'root': {
+      config = {
+        basicColor: '#E3E6E8',
+        fontColor: 'rgba(0,0,0,0.85)',
+        borderColor: '#E3E6E8',
+        bgColor: '#5b8ff9',
+      };
+      break;
+    }
+    default:
+      break;
+  }
+  return config;
+};
+
+const COLLAPSE_ICON = function COLLAPSE_ICON(x, y, r) {
+  return [
+    ['M', x - r, y],
+    ['a', r, r, 0, 1, 0, r * 2, 0],
+    ['a', r, r, 0, 1, 0, -r * 2, 0],
+    ['M', x - r + 4, y],
+    ['L', x - r + 2 * r - 4, y],
+  ];
+};
+const EXPAND_ICON = function EXPAND_ICON(x, y, r) {
+  return [
+    ['M', x - r, y],
+    ['a', r, r, 0, 1, 0, r * 2, 0],
+    ['a', r, r, 0, 1, 0, -r * 2, 0],
+    ['M', x - r + 4, y],
+    ['L', x - r + 2 * r - 4, y],
+    ['M', x - r + r, y - r + 4],
+    ['L', x, y + r - 4],
+  ];
+};
+const nodeBasicMethod = {
+  createNodeBox: (group, config, w, h, isRoot) => {
+    /* 最外面的大矩形 */
+    const container = group.addShape('rect', {
+      attrs: {
+        x: 0,
+        y: 0,
+        width: w,
+        height: h,
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'big-rect-shape',
+    });
+    if (!isRoot) {
+      /* 左边的小圆点 */
+      group.addShape('circle', {
+        attrs: {
+          x: 3,
+          y: h / 2,
+          r: 0,
+          fill: config.basicColor,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'left-dot-shape',
+      });
+    }
+    /* 矩形 */
+    group.addShape('rect', {
+      attrs: {
+        x: 3,
+        y: 0,
+        width: w - 19,
+        height: h,
+        fill: config.bgColor,
+        stroke: config.borderColor,
+        radius: 2,
+        cursor: 'pointer',
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'rect-shape',
+    });
+
+    /* 左边的粗线 */
+    group.addShape('rect', {
+      attrs: {
+        x: 3,
+        y: 0,
+        width: 3,
+        height: h,
+        fill: config.basicColor,
+        radius: 1.5,
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'left-border-shape',
+    });
+    return container;
+  },
+  /* 生成树上的 marker */
+  createNodeMarker: (group, collapsed, x, y) => {
+    group.addShape('circle', {
+      attrs: {
+        x,
+        y,
+        r: 13,
+        fill: 'rgba(47, 84, 235, 0.05)',
+        opacity: 0,
+        zIndex: -2,
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'collapse-icon-bg',
+    });
+    group.addShape('marker', {
+      attrs: {
+        x,
+        y,
+        r: 7,
+        symbol: collapsed ? EXPAND_ICON : COLLAPSE_ICON,
+        stroke: 'rgba(0,0,0,0.25)',
+        fill: 'rgba(0,0,0,0)',
+        lineWidth: 1,
+        cursor: 'pointer',
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'collapse-icon',
+    });
+  },
+  afterDraw: (cfg, group) => {
+    /* 操作 marker 的背景色显示隐藏 */
+    const icon = group.find((element) => element.get('id') === 'collapse-icon');
+    if (icon) {
+      const bg = group.find((element) => element.get('id') === 'collapse-icon-bg');
+      icon.on('mouseenter', () => {
+        bg.attr('opacity', 1);
+        graph.get('canvas').draw();
+      });
+      icon.on('mouseleave', () => {
+        bg.attr('opacity', 0);
+        graph.get('canvas').draw();
+      });
+    }
+    /* ip 显示 */
+    const ipBox = group.find((element) => element.get('id') === 'ip-box');
+    if (ipBox) {
+      /* ip 复制的几个元素 */
+      const ipLine = group.find((element) => element.get('id') === 'ip-cp-line');
+      const ipBG = group.find((element) => element.get('id') === 'ip-cp-bg');
+      const ipIcon = group.find((element) => element.get('id') === 'ip-cp-icon');
+      const ipCPBox = group.find((element) => element.get('id') === 'ip-cp-box');
+
+      const onMouseEnter = () => {
+        ipLine.attr('opacity', 1);
+        ipBG.attr('opacity', 1);
+        ipIcon.attr('opacity', 1);
+        graph.get('canvas').draw();
+      };
+      const onMouseLeave = () => {
+        ipLine.attr('opacity', 0);
+        ipBG.attr('opacity', 0);
+        ipIcon.attr('opacity', 0);
+        graph.get('canvas').draw();
+      };
+      ipBox.on('mouseenter', () => {
+        onMouseEnter();
+      });
+      ipBox.on('mouseleave', () => {
+        onMouseLeave();
+      });
+      ipCPBox.on('mouseenter', () => {
+        onMouseEnter();
+      });
+      ipCPBox.on('mouseleave', () => {
+        onMouseLeave();
+      });
+      ipCPBox.on('click', () => { });
+    }
+  },
+  setState: (name, value, item) => {
+    const hasOpacityClass = [
+      'ip-cp-line',
+      'ip-cp-bg',
+      'ip-cp-icon',
+      'ip-cp-box',
+      'ip-box',
+      'collapse-icon-bg',
+    ];
+    const group = item.getContainer();
+    const childrens = group.get('children');
+    graph.setAutoPaint(false);
+    if (name === 'emptiness') {
+      if (value) {
+        childrens.forEach((shape) => {
+          if (hasOpacityClass.indexOf(shape.get('id')) > -1) {
+            return;
+          }
+          shape.attr('opacity', 0.4);
+        });
+      } else {
+        childrens.forEach((shape) => {
+          if (hasOpacityClass.indexOf(shape.get('id')) > -1) {
+            return;
+          }
+          shape.attr('opacity', 1);
+        });
+      }
+    }
+    graph.setAutoPaint(true);
+  },
+};
+
+G6.registerNode('card-node', {
+  options: {
+    style: {
+      stroke: '#ccc',
+    },
+  },
+  draw: (cfg, group) => {
+    
+    const config = getNodeConfig(cfg);
+    const isRoot = cfg.dataType === 'root';
+    const nodeUrl = cfg.nodeUrl;
+    /* the biggest rect */
+    const container = nodeBasicMethod.createNodeBox(group, config, 243, 64, isRoot);
+
+    if (cfg.dataType !== 'root') {
+      /* the type text */
+      group.addShape('text', {
+        attrs: {
+          text: cfg.dataType,
+          x: 3,
+          y: -10,
+          fontSize: 12,
+          textAlign: 'left',
+          textBaseline: 'middle',
+          fill: 'rgba(0,0,0,0.65)',
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'type-text-shape',
+      });
+    }
+
+    if (cfg.ip) {
+      /* ip start */
+      /* ipBox */
+      const ipRect = group.addShape('rect', {
+        attrs: {
+          fill: nodeUrl ? null : '#FFF',
+          stroke: nodeUrl ? 'rgba(255,255,255,0.65)' : null,
+          radius: 2,
+          cursor: 'pointer',
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-container-shape',
+      });
+
+      /* ip */
+      const ipText = group.addShape('text', {
+        attrs: {
+          text: '666',
+          x: 0,
+          y: 19,
+          fontSize: 12,
+          textAlign: 'left',
+          textBaseline: 'middle',
+          fill: nodeUrl ? 'rgba(255,255,255,0.85)' : 'rgba(0,0,0,0.65)',
+          cursor: 'pointer',
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-text-shape',
+      });
+
+      const ipBBox = ipText.getBBox();
+      /* the distance from the IP to the right is 12px */
+      ipText.attr({
+        x: 224 - 12 - ipBBox.width,
+      });
+      /* ipBox */
+      ipRect.attr({
+        x: 224 - 12 - ipBBox.width - 4,
+        y: ipBBox.minY - 5,
+        width: ipBBox.width + 8,
+        height: ipBBox.height + 10,
+      });
+
+      /* a transparent shape on the IP for click listener */
+      group.addShape('rect', {
+        attrs: {
+          stroke: '',
+          cursor: 'pointer',
+          x: 224 - 12 - ipBBox.width - 4,
+          y: ipBBox.minY - 5,
+          width: ipBBox.width + 8,
+          height: ipBBox.height + 10,
+          fill: '#fff',
+          opacity: 0,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-box',
+      });
+
+      /* copyIpLine */
+      group.addShape('rect', {
+        attrs: {
+          x: 194,
+          y: 7,
+          width: 1,
+          height: 24,
+          fill: '#E3E6E8',
+          opacity: 0,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-cp-line',
+      });
+      /* copyIpBG */
+      group.addShape('rect', {
+        attrs: {
+          x: 195,
+          y: 8,
+          width: 22,
+          height: 22,
+          fill: '#FFF',
+          cursor: 'pointer',
+          opacity: 0,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-cp-bg',
+      });
+      /* copyIpIcon */
+      group.addShape('image', {
+        attrs: {
+          x: 200,
+          y: 13,
+          height: 12,
+          width: 10,
+          img: 'https://os.alipayobjects.com/rmsportal/DFhnQEhHyPjSGYW.png',
+          cursor: 'pointer',
+          opacity: 0,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-cp-icon',
+      });
+      /* a transparent rect on the icon area for click listener */
+      group.addShape('rect', {
+        attrs: {
+          x: 195,
+          y: 8,
+          width: 22,
+          height: 22,
+          fill: '#FFF',
+          cursor: 'pointer',
+          opacity: 0,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'ip-cp-box',
+        tooltip: 'Copy the IP',
+      });
+
+      /* ip end */
+    }
+
+    /* name */
+    group.addShape('text', {
+      attrs: {
+        text: cfg.id,
+        x: 19,
+        y: 19,
+        fontSize: 14,
+        fontWeight: 700,
+        textAlign: 'left',
+        textBaseline: 'middle',
+        fill: config.fontColor,
+        cursor: 'pointer',
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'name-text-shape',
+    });
+
+    /* the description text */
+    group.addShape('text', {
+      attrs: {
+        text: fittingString(cfg.value, 243 - 50, 14),
+        x: 19,
+        y: 45,
+        fontSize: 14,
+        textAlign: 'left',
+        textBaseline: 'middle',
+        fill: config.fontColor,
+        cursor: 'pointer',
+      },
+      // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+      name: 'bottom-text-shape',
+    });
+
+    if (nodeUrl) {
+      group.addShape('text', {
+        attrs: {
+          x: 191,
+          y: 62,
+          text: '⇢',
+          fill: '#fff',
+          fontSize: 18,
+        },
+        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
+        name: 'error-text-shape',
+      });
+    }
+
+    const hasChildren = cfg.children && cfg.children.length > 0;
+    if (hasChildren) {
+      nodeBasicMethod.createNodeMarker(group, cfg.collapsed, 236, 32);
+    }
+    return container;
+  },
+  afterDraw: nodeBasicMethod.afterDraw,
+  setState: nodeBasicMethod.setState,
+});
+export default {
+  props:['id'],
+  data () {
+    return {
+
+    }
+  },
+  mounted () {
+    // this.getData()
+  },
+  methods:{
+    createMenu (array) {
+      var that = this
+      let arr = []
+      const HASLINKS = ['有效线索数','有效项目数']
+      function convertToElementTree(node) {
+        // 新节点
+        var elNode = {
+          id: node['name'],
+          nodeid:node['id'],
+          value:node['labor'] ? node['labor'] !== node['name'] ? node['labor']:'-':'-',
+          children: [],
+          nodeUrl:HASLINKS.includes(node['name'])?'123':null
+        }
+          
+        if (node.children && node.children.length > 0) {
+          // 如果存在子节点
+          for (var index = 0; index < node.children.length; index++) {
+          // 遍历子节点, 把每个子节点看做一颗独立的树, 传入递归构造子树, 并把结果放回到新node的children中
+          elNode.children.push(convertToElementTree(node.children[index]));
+          }
+        }
+        return elNode;
+      }
+      array.forEach((element) => {
+        arr.push(convertToElementTree(element))
+      });
+      return arr
+    },
+    async getData () {
+      const res = await this.$api.requested({
+        "id": 20230625101004,
+        "content": {
+          "hrid": this.id
+        }
+      })
+      const container = document.getElementById('container');
+      const width = container.scrollWidth;
+      const height = container.scrollHeight || 500;
+      const graph = new G6.TreeGraph({
+        container: 'container',
+        width,
+        height,
+        linkCenter: true,
+        fitCenter: true,
+        modes: {
+          default: ['drag-canvas','zoom-canvas','collapse-expand','drag-node', 'lasso-select'],
+        },
+        defaultNode: {
+          /* node type, the priority is lower than the type in the node data */
+          type: 'card-node',
+        },
+        defaultEdge: {
+          type: 'cubic-horizontal',
+        },
+        layout: {
+          type: 'dendrogram',
+          direction: 'RL',
+          nodeSep: 100,
+          rankSep: 250,
+          radial: true,
+        },
+      });
+
+      graph.node(function (node) {
+        return {
+          label: node.id,
+        };
+      });
+
+      graph.data(this.createMenu([res.data])[0]);
+      graph.render();
+      graph.fitView();
+      graph.on('node:click', evt => {
+        const item = evt.item;
+        console.log(item)
+      })
+      if (typeof window !== 'undefined')
+        window.onresize = () => {
+          if (!graph || graph.get('destroyed')) return;
+          if (!container || !container.scrollWidth || !container.scrollHeight) return;
+          graph.changeSize(container.scrollWidth, container.scrollHeight);
+        };
+    }
+  },
+}
+
+</script>
+<style>
+#container{
+  height: 100vh;
+  width: 100vw;
+}
+</style>

+ 24 - 0
src/router/index.js

@@ -102,6 +102,30 @@ let routes = [
           ast_nav:true
         },
         component: () => import(/* webpackChunkName: "about" */ '@/views/printmodel/design/index.vue')
+      },{
+        path: '/customerportrait',
+        name: 'customerportrait',
+        meta: {
+          title: '客户画像',
+          ast_nav:true
+        },
+        component: () => import(/* webpackChunkName: "about" */ '@/components/mindmap/custom.vue')
+      },{
+        path: '/projectportrait',
+        name: 'projectportrait',
+        meta: {
+          title: '项目画像',
+          ast_nav:true
+        },
+        component: () => import(/* webpackChunkName: "about" */ '@/components/mindmap/project.vue')
+      },{
+        path: '/salerportrait',
+        name: 'salerportrait',
+        meta: {
+          title: '业务员画像',
+          ast_nav:true
+        },
+        component: () => import(/* webpackChunkName: "about" */ '@/components/mindmap/saler.vue')
       }]
   }
 ];

+ 1 - 0
src/utils/tool.js

@@ -6,6 +6,7 @@ export default {
   checkAuth (appname,auth) {
     // await this.sleep(3000)
     let _haveAuth = false
+    
     let app = JSON.parse(sessionStorage.getItem('activeApp'))
     // 获取当前应用权限
     let auth_list = app.meta.auth

+ 0 - 9
src/views/printmodel/design/index.vue

@@ -859,17 +859,8 @@ export default {
   font-weight: bold;
 }
 
-<<<<<<< HEAD
-/* /deep/ .hiprint-printElement-image-content {
-  img {
-    // content: url("~@/assets/logo.png");
-  }
-} */
-
-=======
 
 
->>>>>>> xiaoqin
 /deep/ .toplineOfPosition {
   border: 0;
   border-top: 1px dashed purple;