From 30b6c01972cc74152b733a94edcc0c2a614a2268 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期三, 14 四月 2021 19:15:31 +0800
Subject: [PATCH] 2021-04-14

---
 src/tabviews/custom/components/chart/antv-dashboard/index.scss           |  105 +++
 src/pc/modulesource/option.jsx                                           |    4 
 package-lock.json                                                        |  241 ++++--
 src/menu/components/chart/antv-dashboard/chartcompile/index.jsx          |  355 ++++++++++
 src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx           |    9 
 src/tabviews/custom/components/chart/antv-dashboard/index.jsx            |  467 +++++++++++++
 src/menu/components/group/groupcomponents/index.jsx                      |    1 
 src/mob/mobshell/index.jsx                                               |    5 
 src/assets/mobimg/dashboard.png                                          |    0 
 src/mob/modulesource/option.jsx                                          |    4 
 src/tabviews/custom/components/share/normalTable/index.scss              |   32 
 src/pc/menushell/index.jsx                                               |    5 
 src/menu/components/tabs/tabcomponents/index.jsx                         |    1 
 src/views/billprint/index.scss                                           |    6 
 src/tabviews/custom/components/share/normalTable/index.jsx               |    3 
 src/menu/components/chart/antv-dashboard/chartcompile/formconfig.jsx     |  145 ++++
 src/menu/components/table/normal-table/columns/index.scss                |   30 
 src/menu/menushell/card.jsx                                              |    3 
 src/menu/components/chart/antv-dashboard/index.scss                      |   45 +
 src/views/mobdesign/index.jsx                                            |    2 
 src/menu/components/chart/antv-dashboard/chartcompile/index.scss         |   39 +
 src/views/menudesign/index.jsx                                           |    2 
 src/menu/modulesource/option.jsx                                         |    4 
 src/tabviews/custom/components/share/tabtransfer/index.jsx               |    7 
 src/views/pcdesign/index.jsx                                             |    2 
 src/tabviews/custom/components/group/normal-group/index.jsx              |    7 
 src/tabviews/custom/components/table/normal-table/index.jsx              |   10 
 src/menu/components/chart/antv-pie/index.jsx                             |   40 
 src/menu/components/group/groupcomponents/card.jsx                       |    3 
 src/menu/components/chart/antv-dashboard/index.jsx                       |  391 +++++++++++
 src/tabviews/custom/index.jsx                                            |   11 
 src/menu/components/table/normal-table/wrapsetting/settingform/index.jsx |   33 
 package.json                                                             |    3 
 src/menu/components/table/normal-table/columns/index.jsx                 |   11 
 src/menu/components/tabs/tabcomponents/card.jsx                          |    3 
 src/menu/menushell/index.jsx                                             |    5 
 36 files changed, 1,903 insertions(+), 131 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index fd8ff65..80d8c73 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -60,47 +60,74 @@
       }
     },
     "@antv/color-util": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/@antv/color-util/-/color-util-2.0.5.tgz",
-      "integrity": "sha512-eQktA9YDnWCj03rfjpg0ajvCfRkHXzBzsZa9z94pY6Jb7e3XtPUp7vDpB8KhaKm9GjPtGzQDneh+gnqkEK8mtQ==",
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/@antv/color-util/-/color-util-2.0.6.tgz",
+      "integrity": "sha512-KnPEaAH+XNJMjax9U35W67nzPI+QQ2x27pYlzmSIWrbj4/k8PGrARXfzDTjwoozHJY8qG62Z+Ww6Alhu2FctXQ==",
       "requires": {
         "@antv/util": "^2.0.9",
-        "tslib": "^1.10.0"
+        "tslib": "^2.0.3"
       },
       "dependencies": {
         "@antv/util": {
-          "version": "2.0.9",
-          "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.9.tgz",
-          "integrity": "sha512-JblWzne7msAPDdxkUhEk8zAz0Wd6igKwqymGbvIeyOydGrhBhGjA3nEayFj4IlG+XixCvGFKsCB4yuFS4glRIA==",
+          "version": "2.0.13",
+          "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.13.tgz",
+          "integrity": "sha512-mfYL7K8XJIeDmal33K+6abr8Yb526YXKg5XQlddNo+X1Doll+gun6HxnbdySoLv21vW4bLkcbVPjqxWl7ZJAFA==",
           "requires": {
-            "tslib": "^1.10.0"
+            "tslib": "^2.0.3"
           }
+        },
+        "tslib": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
+          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
         }
       }
     },
     "@antv/component": {
-      "version": "0.8.2",
-      "resolved": "https://registry.npmjs.org/@antv/component/-/component-0.8.2.tgz",
-      "integrity": "sha512-aU65T9jD85H+3WhhmgPz8kiuqxJGPuHFgRiBYmR+vQUnAA2nOW2bCafiNx/bSEAqmVgsr+8e+9IDQZ6PowIgtQ==",
+      "version": "0.8.11",
+      "resolved": "https://registry.npmjs.org/@antv/component/-/component-0.8.11.tgz",
+      "integrity": "sha512-7hl7IPPF/QmE25lrZhppEW8BYJzU3SE6IGq4/NhrvcDk79Xhm1L4KOcAAcZ0zYBRaOwQL3yMcraIL+/Z1UhLjw==",
       "requires": {
         "@antv/dom-util": "~2.0.1",
-        "@antv/g-base": "~0.5.0",
+        "@antv/g-base": "0.5.6",
         "@antv/matrix-util": "^3.1.0-beta.1",
         "@antv/path-util": "~2.0.7",
         "@antv/scale": "~0.3.1",
         "@antv/util": "~2.0.0",
         "fecha": "~4.2.0",
-        "tslib": "^1.10.0"
+        "tslib": "^2.0.3"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
+          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
+        }
       }
     },
     "@antv/coord": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/@antv/coord/-/coord-0.3.0.tgz",
-      "integrity": "sha512-lm5Ct+r62mFVqhziKoDFN3PQjnkNBMOoOG+kBsPq3M3GqlQt5Jc7euOHMFcYSZM9HJmsKkGcih6EWDVVliMEZg==",
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/@antv/coord/-/coord-0.3.1.tgz",
+      "integrity": "sha512-rFE94C8Xzbx4xmZnHh2AnlB3Qm1n5x0VT3OROy257IH6Rm4cuzv1+tZaUBATviwZd99S+rOY9telw/+6C9GbRw==",
       "requires": {
         "@antv/matrix-util": "^3.1.0-beta.2",
-        "@antv/util": "~2.0.3",
-        "tslib": "^1.10.0"
+        "@antv/util": "~2.0.12",
+        "tslib": "^2.1.0"
+      },
+      "dependencies": {
+        "@antv/util": {
+          "version": "2.0.13",
+          "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.13.tgz",
+          "integrity": "sha512-mfYL7K8XJIeDmal33K+6abr8Yb526YXKg5XQlddNo+X1Doll+gun6HxnbdySoLv21vW4bLkcbVPjqxWl7ZJAFA==",
+          "requires": {
+            "tslib": "^2.0.3"
+          }
+        },
+        "tslib": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
+          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
+        }
       }
     },
     "@antv/data-set": {
@@ -127,11 +154,18 @@
       }
     },
     "@antv/dom-util": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/@antv/dom-util/-/dom-util-2.0.2.tgz",
-      "integrity": "sha512-i/rh385casRd6OA4rbpbA2jyiwY/w7PtkA+74mH43PiBzOcLpDg1jEWR9dMO0tIqUzHQWWqKNNjmXVubl4GS6g==",
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/@antv/dom-util/-/dom-util-2.0.3.tgz",
+      "integrity": "sha512-dUHsUT4U9X1T1/Y9bH3jRMe0MzvWJk2jSQm1vm3w9NX+Ra0ftq5VUBiGTNbthm3nFwG0fFFjip904rYjl50g4A==",
       "requires": {
-        "tslib": "^1.10.0"
+        "tslib": "^2.0.3"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
+          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
+        }
       }
     },
     "@antv/event-emitter": {
@@ -140,81 +174,105 @@
       "integrity": "sha512-6C6NJOdoNVptCr5y9BVOhKkCgW7LFs/SpcRyAExUeSjAm0zJqcqNkSIRGsXYhj4PJI+CZICHzGwwiSnIsE68Ug=="
     },
     "@antv/g-base": {
-      "version": "0.5.1",
-      "resolved": "https://registry.npmjs.org/@antv/g-base/-/g-base-0.5.1.tgz",
-      "integrity": "sha512-gbv+uz/SvzM4/p3PLjAiEZUp6kdzKkCbVWTCdBXB1cvNMttlEzWEB8MOFbEkcIAy7TtjQJJRv8ThI/ngFzU+fg==",
+      "version": "0.5.6",
+      "resolved": "https://registry.npmjs.org/@antv/g-base/-/g-base-0.5.6.tgz",
+      "integrity": "sha512-szxqFQ/xdCnfaeSEEC2kVjXdKxJnvKKJNT0MvaOG3UXOfsjPDLgb3IKLr+bU3sLvTAQfPhsbtYh7mWb03+mGjA==",
       "requires": {
         "@antv/event-emitter": "^0.1.1",
-        "@antv/g-math": "^0.1.5",
+        "@antv/g-math": "^0.1.6",
         "@antv/matrix-util": "^3.1.0-beta.1",
         "@antv/path-util": "~2.0.5",
         "@antv/util": "~2.0.0",
-        "@types/d3-timer": "^1.0.9",
+        "@types/d3-timer": "^2.0.0",
         "d3-ease": "^1.0.5",
         "d3-interpolate": "^1.3.2",
         "d3-timer": "^1.0.9",
-        "detect-browser": "^5.1.0"
+        "detect-browser": "^5.1.0",
+        "tslib": "^2.0.3"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
+          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
+        }
       }
     },
     "@antv/g-canvas": {
-      "version": "0.5.3",
-      "resolved": "https://registry.npmjs.org/@antv/g-canvas/-/g-canvas-0.5.3.tgz",
-      "integrity": "sha512-80k1BbiY05heHKUm4o6IL6KVRZS+uAgzdIF2OaC9grQc6KxrJoK2dCxKpmna3NBHTU9Sm+/rsiGcL7lp7S+ecQ==",
+      "version": "0.5.6",
+      "resolved": "https://registry.npmjs.org/@antv/g-canvas/-/g-canvas-0.5.6.tgz",
+      "integrity": "sha512-r6f6KqYuNZWunf2Vnf1ACopn8aic6TBFhaN3XuckenhQNqR+/PI/4Mft7z14zo7WH58X2Xs2Npq9awJXBEUzaw==",
       "requires": {
-        "@antv/g-base": "^0.5.1",
-        "@antv/g-math": "^0.1.5",
+        "@antv/g-base": "^0.5.3",
+        "@antv/g-math": "^0.1.6",
         "@antv/matrix-util": "^3.1.0-beta.1",
         "@antv/path-util": "~2.0.5",
         "@antv/util": "~2.0.0",
-        "gl-matrix": "^3.0.0"
+        "gl-matrix": "^3.0.0",
+        "tslib": "^2.0.3"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
+          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
+        }
       }
     },
     "@antv/g-math": {
-      "version": "0.1.5",
-      "resolved": "https://registry.npmjs.org/@antv/g-math/-/g-math-0.1.5.tgz",
-      "integrity": "sha512-29B3p33jzUPIyx1xYfNCexbp7jvahD6bD8FKKyWqfYZHQbvrFfV8ZNUu66RJLfDrl0KaKT6C5whfKs/WrVaflQ==",
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/@antv/g-math/-/g-math-0.1.7.tgz",
+      "integrity": "sha512-xGyXaloD1ynfp7gS4VuV+MjSptZIwHvLHr8ekXJSFAeWPYLu84yOW2wOZHDdp1bzDAIuRv6xDBW58YGHrWsFcA==",
       "requires": {
         "@antv/util": "~2.0.0",
         "gl-matrix": "^3.0.0"
       }
     },
     "@antv/g-svg": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/@antv/g-svg/-/g-svg-0.5.2.tgz",
-      "integrity": "sha512-T0PYjIM+WX6zv3yUgSkyRcHFq4hlio0MeRGoJR60P5U5MNSdkZnblcu79cpU2i42Z7wBr404Kv1dplCGxC38PA==",
+      "version": "0.5.6",
+      "resolved": "https://registry.npmjs.org/@antv/g-svg/-/g-svg-0.5.6.tgz",
+      "integrity": "sha512-Xve1EUGk4HMbl2nq4ozR4QLh6GyoZ8Xw/+9kHYI4B5P2lIUQU95MuRsaLFfW5NNpZDx85ZeH97tqEmC9L96E7A==",
       "requires": {
-        "@antv/g-base": "^0.5.1",
-        "@antv/g-math": "^0.1.5",
+        "@antv/g-base": "^0.5.3",
+        "@antv/g-math": "^0.1.6",
         "@antv/util": "~2.0.0",
-        "detect-browser": "^5.0.0"
+        "detect-browser": "^5.0.0",
+        "tslib": "^2.0.3"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
+          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
+        }
       }
     },
     "@antv/g2": {
-      "version": "4.1.0-beta.18",
-      "resolved": "https://registry.npmjs.org/@antv/g2/-/g2-4.1.0-beta.18.tgz",
-      "integrity": "sha512-RW3e95V2aUtys36guS7PNHbfgyYZgigu18OLSYPkgyRLF0pPABcSrIot+xnVGQ4Cx0ZDmhJVTvpXjU4QMa96kw==",
+      "version": "4.1.14",
+      "resolved": "https://registry.npmjs.org/@antv/g2/-/g2-4.1.14.tgz",
+      "integrity": "sha512-JdU+0suxkDqjTZNyG915zQ7eM+bdT2fHV48VGc1LvCroUHzCncCnbx5HZ19aZhvuij2hM6eh52vb8mwIXIzMBw==",
       "requires": {
         "@antv/adjust": "^0.2.1",
         "@antv/attr": "^0.3.1",
         "@antv/color-util": "^2.0.2",
-        "@antv/component": "^0.8.0",
+        "@antv/component": "^0.8.7",
         "@antv/coord": "^0.3.0",
         "@antv/dom-util": "^2.0.2",
         "@antv/event-emitter": "~0.1.0",
-        "@antv/g-base": "^0.5.0",
-        "@antv/g-canvas": "^0.5.0",
-        "@antv/g-svg": "^0.5.0",
+        "@antv/g-base": "0.5.6",
+        "@antv/g-canvas": "0.5.6",
+        "@antv/g-svg": "0.5.6",
         "@antv/matrix-util": "^3.1.0-beta.1",
         "@antv/path-util": "^2.0.3",
-        "@antv/scale": "^0.3.1",
+        "@antv/scale": "^0.3.7",
         "@antv/util": "~2.0.5",
         "tslib": "^2.0.0"
       },
       "dependencies": {
         "tslib": {
-          "version": "2.0.3",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
-          "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
+          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
         }
       }
     },
@@ -237,38 +295,50 @@
       },
       "dependencies": {
         "@antv/util": {
-          "version": "2.0.9",
-          "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.9.tgz",
-          "integrity": "sha512-JblWzne7msAPDdxkUhEk8zAz0Wd6igKwqymGbvIeyOydGrhBhGjA3nEayFj4IlG+XixCvGFKsCB4yuFS4glRIA==",
+          "version": "2.0.13",
+          "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.13.tgz",
+          "integrity": "sha512-mfYL7K8XJIeDmal33K+6abr8Yb526YXKg5XQlddNo+X1Doll+gun6HxnbdySoLv21vW4bLkcbVPjqxWl7ZJAFA==",
           "requires": {
-            "tslib": "^1.10.0"
+            "tslib": "^2.0.3"
+          },
+          "dependencies": {
+            "tslib": {
+              "version": "2.2.0",
+              "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
+              "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
+            }
           }
         }
       }
     },
     "@antv/path-util": {
-      "version": "2.0.8",
-      "resolved": "https://registry.npmjs.org/@antv/path-util/-/path-util-2.0.8.tgz",
-      "integrity": "sha512-g5gt12MY1oEzh/j5XfLNRCfJU7E+Us+2yM5Hqc0y8xeWhb5l013XG5BPV37KmOf6WAys9KNxklNniHCZ6SqCKw==",
+      "version": "2.0.9",
+      "resolved": "https://registry.npmjs.org/@antv/path-util/-/path-util-2.0.9.tgz",
+      "integrity": "sha512-kunEz4dNheQMVn4rVFsoBDx+n9Knfi3uRLvDk9SojZAqpninsjFhdoiYtbExwJGz1FYGtiV10Y6N1tp73kZFcg==",
       "requires": {
         "@antv/util": "^2.0.9",
-        "tslib": "^1.10.0"
+        "tslib": "^2.0.3"
       },
       "dependencies": {
         "@antv/util": {
-          "version": "2.0.9",
-          "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.9.tgz",
-          "integrity": "sha512-JblWzne7msAPDdxkUhEk8zAz0Wd6igKwqymGbvIeyOydGrhBhGjA3nEayFj4IlG+XixCvGFKsCB4yuFS4glRIA==",
+          "version": "2.0.13",
+          "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.13.tgz",
+          "integrity": "sha512-mfYL7K8XJIeDmal33K+6abr8Yb526YXKg5XQlddNo+X1Doll+gun6HxnbdySoLv21vW4bLkcbVPjqxWl7ZJAFA==",
           "requires": {
-            "tslib": "^1.10.0"
+            "tslib": "^2.0.3"
           }
+        },
+        "tslib": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
+          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
         }
       }
     },
     "@antv/scale": {
-      "version": "0.3.4",
-      "resolved": "https://registry.npmjs.org/@antv/scale/-/scale-0.3.4.tgz",
-      "integrity": "sha512-mZaf3MtMoQJtd+KAgTANVbvKpaXVpzLAFbKO/wSKaLFpnWO0bwMVDYzrs+5DZhfEfMbZpP/A7qUZ2/DLh0T3Tg==",
+      "version": "0.3.9",
+      "resolved": "https://registry.npmjs.org/@antv/scale/-/scale-0.3.9.tgz",
+      "integrity": "sha512-m56Rs4Zta7XnuF+aNbJXMsgBqATO1M4kvu+dEmhzLYsPK5D3dHpJTOGh/Zy55eirekb9F7jiu29SJqPNnhxq+g==",
       "requires": {
         "@antv/util": "~2.0.3",
         "fecha": "~4.2.0",
@@ -276,18 +346,25 @@
       },
       "dependencies": {
         "tslib": {
-          "version": "2.0.3",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
-          "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
+          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
         }
       }
     },
     "@antv/util": {
-      "version": "2.0.8",
-      "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.8.tgz",
-      "integrity": "sha512-G9QRygQJ8UNGMi8L1dfMIa4SofbEO+jkXwvRY4ek/MLd04Q01UN0U28JeMFzw6FCKJdxiFu+2uwT/zjoFr3QoQ==",
+      "version": "2.0.13",
+      "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.13.tgz",
+      "integrity": "sha512-mfYL7K8XJIeDmal33K+6abr8Yb526YXKg5XQlddNo+X1Doll+gun6HxnbdySoLv21vW4bLkcbVPjqxWl7ZJAFA==",
       "requires": {
-        "tslib": "^1.10.0"
+        "tslib": "^2.0.3"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
+          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
+        }
       }
     },
     "@babel/code-frame": {
@@ -2376,9 +2453,9 @@
       "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
     },
     "@types/d3-timer": {
-      "version": "1.0.10",
-      "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-1.0.10.tgz",
-      "integrity": "sha512-ZnAbquVqy+4ZjdW0cY6URp+qF/AzTVNda2jYyOzpR2cPT35FTXl78s15Bomph9+ckOiI1TtkljnWkwbIGAb6rg=="
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-2.0.0.tgz",
+      "integrity": "sha512-l6stHr1VD1BWlW6u3pxrjLtJfpPZq9I3XmKIQtq7zHM/s6fwEtI1Yn6Sr5/jQTrUDCC5jkS6gWqlFGCDArDqNg=="
     },
     "@types/eslint-visitor-keys": {
       "version": "1.0.0",
@@ -8435,9 +8512,9 @@
       }
     },
     "fecha": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz",
-      "integrity": "sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg=="
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz",
+      "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q=="
     },
     "figgy-pudding": {
       "version": "3.5.1",
diff --git a/package.json b/package.json
index 5ca8645..14489ff 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,8 @@
   "private": true,
   "dependencies": {
     "@antv/data-set": "^0.11.4",
-    "@antv/g2": "^4.1.0-beta.18",
+    "@antv/g2": "^4.1.14",
+    "@antv/util": "^2.0.13",
     "@babel/core": "7.5.5",
     "@svgr/webpack": "4.3.2",
     "@typescript-eslint/eslint-plugin": "1.13.0",
diff --git a/src/assets/mobimg/dashboard.png b/src/assets/mobimg/dashboard.png
new file mode 100644
index 0000000..9769128
--- /dev/null
+++ b/src/assets/mobimg/dashboard.png
Binary files differ
diff --git a/src/menu/components/chart/antv-dashboard/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-dashboard/chartcompile/formconfig.jsx
new file mode 100644
index 0000000..3449d39
--- /dev/null
+++ b/src/menu/components/chart/antv-dashboard/chartcompile/formconfig.jsx
@@ -0,0 +1,145 @@
+// import zhCN from '@/locales/zh-CN/model.js'
+// import enUS from '@/locales/en-US/model.js'
+
+// const Formdict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
+
+/**
+ * @description 鑾峰彇鍥捐〃瑙嗗浘閰嶇疆琛ㄥ崟
+ * @param {object} card       // 鍥捐〃瀵硅薄
+ */
+export function getBaseForm (card) {
+  let roleList = sessionStorage.getItem('sysRoles')
+  if (roleList) {
+    try {
+      roleList = JSON.parse(roleList)
+    } catch {
+      roleList = []
+    }
+  } else {
+    roleList = []
+  }
+
+  return [
+    {
+      type: 'text',
+      key: 'title',
+      label: '鏍囬',
+      initVal: card.title,
+      required: false
+    },
+    {
+      type: 'text',
+      key: 'name',
+      label: '缁勪欢鍚嶇О',
+      initVal: card.name,
+      tooltip: '鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�',
+      required: true
+    },
+    {
+      type: 'number',
+      key: 'width',
+      label: '瀹藉害',
+      initVal: card.width,
+      tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��',
+      min: 1,
+      max: 24,
+      decimal: 0,
+      required: true
+    },
+    {
+      type: 'number',
+      key: 'height',
+      label: '楂樺害',
+      initVal: card.height,
+      min: 100,
+      max: 1000,
+      decimal: 0,
+      required: true
+    },
+    {
+      type: 'select',
+      key: 'blacklist',
+      label: '榛戝悕鍗�',
+      initVal: card.blacklist || [],
+      multi: true,
+      required: false,
+      options: roleList
+    }
+  ]
+}
+/**
+ * @description 鑾峰彇鍥捐〃瑙嗗浘閰嶇疆琛ㄥ崟
+ * @param {object} card       // 鍥捐〃瀵硅薄
+ * @param {Array}  columns    // 鏄剧ず鍒�
+ */
+export function getOptionForm (card, columns) {
+  let yfields = columns.filter(item => /^(Int|Decimal)/ig.test(item.datatype))
+
+  return [
+    {
+      type: 'text',
+      key: 'label',
+      label: '鎸囨爣鍚嶇О',
+      initVal: card.label || '',
+      required: false
+    },
+    {
+      type: 'select',
+      key: 'valueField',
+      label: '鏄剧ず鍊�',
+      initVal: card.valueField || '',
+      required: true,
+      options: yfields
+    },
+    {
+      type: 'number',
+      key: 'maxValue',
+      label: '鏈�澶у��',
+      initVal: card.maxValue || 100,
+      tooltip: '浠〃鐩樻渶澶у埢搴﹀��',
+      min: 0,
+      max: 999999,
+      decimal: 1,
+      required: true
+    },
+    {
+      type: 'number',
+      key: 'tickInterval',
+      label: '闂撮殧',
+      initVal: card.tickInterval || 10,
+      tooltip: '浠〃鐩樺埢搴﹂棿闅斿�笺��',
+      min: 0,
+      max: 999999,
+      decimal: 1,
+      required: true
+    },
+    {
+      type: 'radio',
+      key: 'percent',
+      label: '鐧惧垎鐜�',
+      initVal: card.percent || 'true',
+      required: false,
+      options: [{
+        value: 'true',
+        text: '浣跨敤'
+      }, {
+        value: 'false',
+        text: '涓嶄娇鐢�'
+      }]
+    },
+    {
+      type: 'color',
+      key: 'tickColor',
+      label: '鍒诲害绾�',
+      initVal: card.tickColor || '#CBCBCB',
+      required: false
+    },
+    {
+      type: 'color',
+      key: 'labelColor',
+      label: '鎸囨爣棰滆壊',
+      initVal: card.labelColor || '#545454',
+      required: false
+    }
+  ]
+}
diff --git a/src/menu/components/chart/antv-dashboard/chartcompile/index.jsx b/src/menu/components/chart/antv-dashboard/chartcompile/index.jsx
new file mode 100644
index 0000000..051a639
--- /dev/null
+++ b/src/menu/components/chart/antv-dashboard/chartcompile/index.jsx
@@ -0,0 +1,355 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { fromJS } from 'immutable'
+import { Modal, Form, Row, Col, Select, Icon, Radio, Tooltip, Input, InputNumber, Tabs, Button } from 'antd'
+
+import Utils from '@/utils/utils.js'
+import { getBaseForm, getOptionForm } from './formconfig'
+import asyncComponent from '@/utils/asyncComponent'
+import ColorSketch from '@/mob/colorsketch'
+import './index.scss'
+
+const { TabPane } = Tabs
+
+const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
+const NormalForm = asyncComponent(() => import('@/menu/components/share/normalform'))
+
+class LineChartDrawerForm extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,
+    plot: PropTypes.object,
+    config: PropTypes.object,
+    plotchange: PropTypes.func
+  }
+
+  state = {
+    visible: false,
+    plot: null,
+    formlist: null,
+    baseFormlist: null,
+    view: 'normal',
+    colorColumns: [
+      {
+        title: '鎸囨爣',
+        dataIndex: 'tick',
+        inputType: 'number',
+        editable: true,
+        width: '40%'
+      },
+      {
+        title: '棰滆壊',
+        dataIndex: 'color',
+        inputType: 'color',
+        editable: true,
+        width: '40%',
+        render: (text, record) => {
+          return (<div style={{width: '80px', height: '23px', background: text}}></div>)
+        }
+      },
+    ]
+  }
+
+  showDrawer = () => {
+    const { config } = this.props
+
+    this.setState({
+      visible: true,
+      view: 'normal',
+      plot: fromJS(config.plot).toJS(),
+      baseFormlist: getBaseForm(config.plot),
+      formlist: getOptionForm(config.plot, config.columns)
+    })
+  }
+
+  radioChange = (e, key) => {
+    const { formlist } = this.state
+    let val = e.target.value
+
+    if (key === 'shape') {
+      this.setState({
+        formlist: formlist.map(item => {
+          if (item.key === 'innerRadius') {
+            item.hidden = val === 'pie'
+          }
+          return item
+        })
+      }, () => {
+        if (val === 'ring') {
+          this.props.form.setFieldsValue({innerRadius: 50})
+        } else if (val === 'nightingale') {
+          this.props.form.setFieldsValue({innerRadius: 0})
+        }
+      })
+    }
+  }
+
+  getFields() {
+    const { formlist } = this.state
+    const { getFieldDecorator } = this.props.form
+    const fields = []
+
+    if (!formlist) {
+      return fields
+    }
+
+    formlist.forEach((item, index) => {
+      if (item.hidden || item.forbid) return
+      
+      if (item.type === 'text') {
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={item.tooltip ?
+              <Tooltip placement="topLeft" title={item.tooltip}>
+                <Icon type="question-circle" />
+                {item.label}
+              </Tooltip> : item.label
+            }>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal,
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: this.props.dict['form.required.input'] + item.label + '!'
+                  }
+                ]
+              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.onSubmit}/>)}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'number') {
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={item.tooltip ?
+              <Tooltip placement="topLeft" title={item.tooltip}>
+                <Icon type="question-circle" />
+                {item.label}
+              </Tooltip> : item.label
+            }>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal,
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: this.props.dict['form.required.input'] + item.label + '!'
+                  }
+                ]
+              })(<InputNumber min={item.min} max={item.max} precision={item.decimal} onPressEnter={this.onSubmit}/>)}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'select') { // 涓嬫媺
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={item.tooltip ?
+              <Tooltip placement="topLeft" title={item.tooltip}>
+                <Icon type="question-circle" />
+                {item.label}
+              </Tooltip> : item.label
+            }>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal,
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: this.props.dict['form.required.select'] + item.label + '!'
+                  }
+                ]
+              })(
+                <Select mode={item.multi ? 'multiple' : ''}>
+                  {item.options.map((option, index) =>
+                    <Select.Option key={index} value={option.field}>
+                      {option.label}
+                    </Select.Option>
+                  )}
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'radio') {
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={item.tooltip ?
+              <Tooltip placement="topLeft" title={item.tooltip}>
+                <Icon type="question-circle" />
+                {item.label}
+              </Tooltip> : item.label
+            }>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal,
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: this.props.dict['form.required.select'] + item.label + '!'
+                  }
+                ]
+              })(
+                <Radio.Group disabled={item.readonly} onChange={(e) => this.radioChange(e, item.key)}>
+                  {item.options.map(option => {
+                    return (
+                      <Radio key={option.value} value={option.value}>{option.text}</Radio>
+                    )
+                  })}
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'color') {
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={item.tooltip ?
+              <Tooltip placement="topLeft" title={item.tooltip}>
+                <Icon type="question-circle" />
+                {item.label}
+              </Tooltip> : item.label
+            }>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal
+              })(
+                <ColorSketch />
+              )}
+            </Form.Item>
+          </Col>
+        )
+      }
+    })
+    return fields
+  }
+
+  onSubmit = () => {
+    const { config } = this.props
+    const { plot, view } = this.state
+
+    if (view === 'normal') {
+      this.props.form.validateFieldsAndScroll((err, values) => {
+        if (!err) {
+          let _plot = {...plot, ...values}
+          
+          this.setState({
+            plot: _plot,
+            visible: false
+          })
+  
+          this.props.plotchange({...config, plot: _plot})
+        }
+      })
+    } else if (view === 'base') {
+      this.baseRef.handleConfirm().then(res => {
+        let _plot = {...plot, ...res}
+
+        this.setState({
+          plot: _plot,
+          visible: false
+        })
+
+        this.props.plotchange({...config, plot: _plot})
+      })
+    } else {
+      this.setState({
+        visible: false
+      })
+
+      this.props.plotchange({...config, plot: plot})
+    }
+  }
+
+  changeTab = (tab) => {
+    const { plot, view } = this.state
+
+    if (view === 'normal') {
+      this.props.form.validateFieldsAndScroll((err, values) => {
+        if (!err) {
+          let _plot = {...plot, ...values}
+
+          this.setState({
+            plot: _plot,
+            view: tab
+          })
+        }
+      })
+    } else if (view === 'base') {
+      this.baseRef.handleConfirm().then(res => {
+        let _plot = {...plot, ...res}
+
+        this.setState({
+          plot: _plot,
+          view: tab
+        })
+      })
+    } else {
+      this.setState({
+        view: tab
+      })
+    }
+  }
+
+  addColor = () => {
+    let plot = fromJS(this.state.plot).toJS()
+    plot.colors = plot.colors || []
+
+    plot.colors.push({
+      uuid: Utils.getuuid(),
+      tick: plot.maxValue || 1,
+      color: '#1890ff'
+    })
+
+    this.setState({plot})
+  }
+
+  changeColor = (colors) => {
+    const { plot } = this.state
+
+    this.setState({plot: {...plot, colors}})
+  }
+
+  render() {
+    const { visible, plot, colorColumns, view, baseFormlist } = this.state
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 6 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 18 }
+      }
+    }
+
+    return (
+      <div className="line-chart-drawer-form">
+        <Icon type="edit" title="缂栬緫" onClick={this.showDrawer} />
+        <Modal
+          wrapClassName="popview-modal menu-chart-edit-modal"
+          title="鍥捐〃缂栬緫"
+          visible={visible}
+          width={850}
+          maskClosable={false}
+          onOk={this.onSubmit}
+          onCancel={() => { this.setState({ visible: false }) }}
+          destroyOnClose
+        >
+          <Tabs activeKey={view} className="menu-chart-edit-box" onChange={this.changeTab}>
+            <TabPane tab="缁勪欢璁剧疆" key="base">
+              <NormalForm dict={this.props.dict} formlist={baseFormlist} inputSubmit={this.onSubmit} wrappedComponentRef={(inst) => this.baseRef = inst}/>
+            </TabPane>
+            <TabPane tab="鍥捐〃璁剧疆" key="normal">
+              <Form {...formItemLayout}>
+                <Row gutter={16}>{this.getFields()}</Row>
+              </Form>
+            </TabPane>
+            {plot ? <TabPane tab="棰滆壊璁剧疆" key="color">
+              <div>
+                <Button className="color-add mk-green" onClick={this.addColor}>{this.props.dict['model.add']}</Button>
+                <EditTable actions={['edit', 'move', 'del']} data={plot.colors || []} columns={colorColumns} onChange={this.changeColor}/>
+              </div>
+            </TabPane> : null}
+          </Tabs>
+          
+        </Modal>
+      </div>
+    );
+  }
+}
+
+export default Form.create()(LineChartDrawerForm)
\ No newline at end of file
diff --git a/src/menu/components/chart/antv-dashboard/chartcompile/index.scss b/src/menu/components/chart/antv-dashboard/chartcompile/index.scss
new file mode 100644
index 0000000..25a7c53
--- /dev/null
+++ b/src/menu/components/chart/antv-dashboard/chartcompile/index.scss
@@ -0,0 +1,39 @@
+.line-chart-drawer-form {
+  display: inline-block;
+  > .anticon-edit {
+    color: #1890ff;
+  }
+}
+.menu-chart-edit-modal {
+  .ant-modal {
+    top: 50px;
+    .ant-modal-body {
+      min-height: 50vh;
+      max-height: calc(100vh - 190px);
+      padding-top: 10px;
+      .anticon-question-circle {
+        color: #c49f47;
+        position: relative;
+        left: -3px;
+      }
+      .ant-input-number {
+        width: 100%;
+      }
+      .ant-tabs-nav-wrap {
+        text-align: center;
+      }
+      .color-sketch-block {
+        position: relative;
+        top: 5px;
+        width: 240px;
+      }
+      .color-add {
+        float: right;
+        margin-bottom: 10px;
+        position: relative;
+        z-index: 1;
+      }
+    }
+  }
+}
+
diff --git a/src/menu/components/chart/antv-dashboard/index.jsx b/src/menu/components/chart/antv-dashboard/index.jsx
new file mode 100644
index 0000000..1e395b6
--- /dev/null
+++ b/src/menu/components/chart/antv-dashboard/index.jsx
@@ -0,0 +1,391 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Icon, Popover } from 'antd'
+import { Chart, registerShape } from '@antv/g2'
+
+import MKEmitter from '@/utils/events.js'
+import asyncComponent from '@/utils/asyncComponent'
+import asyncIconComponent from '@/utils/asyncIconComponent'
+import { resetStyle } from '@/utils/utils-custom.js'
+import zhCN from '@/locales/zh-CN/model.js'
+import enUS from '@/locales/en-US/model.js'
+import './index.scss'
+
+const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
+const ChartCompileForm = asyncIconComponent(() => import('./chartcompile'))
+const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
+const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
+const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
+const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
+
+registerShape('point', 'pointer', {
+  draw(cfg, container) {
+    const group = container.addGroup({});
+    // 鑾峰彇鏋佸潗鏍囩郴涓嬬敾甯冧腑蹇冪偣
+    const center = this.parsePoint({ x: 0, y: 0 });
+    // 缁樺埗鎸囬拡
+    group.addShape('line', {
+      attrs: {
+        x1: center.x,
+        y1: center.y,
+        x2: cfg.x,
+        y2: cfg.y,
+        stroke: cfg.color,
+        lineWidth: 5,
+        lineCap: 'round',
+      },
+    });
+    group.addShape('circle', {
+      attrs: {
+        x: center.x,
+        y: center.y,
+        r: 9.75,
+        stroke: cfg.color,
+        lineWidth: 4.5,
+        fill: '#fff',
+      },
+    });
+    return group;
+  },
+})
+
+class antvDashboardChart extends Component {
+  static propTpyes = {
+    card: PropTypes.object,
+    updateConfig: PropTypes.func,
+    deletecomponent: PropTypes.func,
+  }
+
+  state = {
+    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
+    card: null,
+    ismob: sessionStorage.getItem('appType') === 'mob',
+    eventListener: null
+  }
+
+  UNSAFE_componentWillMount () {
+    const { card, ismob } = this.props
+
+    if (card.isNew) {
+      let _plot = {
+        width: card.width || 12,
+        height: 400,
+        label: '',
+        valueField: '',
+        name: card.name,
+        maxValue: 100,
+        tickInterval: 10,
+        labelColor: '#545454',
+        tickColor: '#CBCBCB',
+        percent: 'true'
+      }
+
+      if (ismob) {
+        _plot.width = 24
+      }
+
+      let _card = {
+        uuid: card.uuid,
+        type: card.type,
+        floor: card.floor,
+        tabId: card.tabId || '',
+        parentId: card.parentId || '',
+        format: 'object',   // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡
+        pageable: false,    // 缁勪欢灞炴�� - 鏄惁鍙垎椤�
+        switchable: false,  // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹�
+        dataName: card.dataName || '',
+        width: _plot.width,
+        name: _plot.name,
+        subtype: card.subtype,
+        setting: { interType: 'system' },
+        style: {
+          borderWidth: '1px', borderColor: 'rgb(217, 217, 217)',
+          marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px'
+        },
+        headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
+        columns: [],
+        scripts: [],
+        search: [],
+        action: [],
+        plot: _plot,
+        btnlog: [],
+      }
+
+      if (card.config) {
+        let config = fromJS(card.config).toJS()
+
+        _card.plot = config.plot
+        _card.plot.name = card.name
+        _card.style = config.style
+        _card.headerStyle = config.headerStyle
+      }
+
+      this.props.updateConfig(_card)
+      this.setState({
+        card: _card
+      })
+    } else {
+      this.setState({
+        card: fromJS(card).toJS()
+      })
+    }
+  }
+
+  componentDidMount () {
+    this.dashboardrender()
+    MKEmitter.addListener('tabsChange', this.handleTabsChange)
+    MKEmitter.addListener('submitStyle', this.getStyle)
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('tabsChange', this.handleTabsChange)
+    MKEmitter.removeListener('submitStyle', this.getStyle)
+  }
+
+  handleTabsChange = (parentId) => {
+    const { card } = this.state
+
+    if (parentId === card.parentId) {
+      let _element = document.getElementById(card.uuid + 'canvas')
+      if (_element) {
+        _element.innerHTML = ''
+      }
+
+      setTimeout(this.dashboardrender, 100)
+    }
+  }
+
+  getdata = () => {
+    const { card } = this.state
+
+    const data = [];
+    const val = (Math.random() * card.plot.maxValue).toFixed(1);
+    data.push({ value: +val });
+    return data;
+  }
+
+  dashboardrender = () => {
+    const { card } = this.state
+    const plot = card.plot
+    const data = this.getdata()
+
+    const chart = new Chart({
+      container: card.uuid + 'dashboard',
+      autoFit: true,
+      height: plot.height ? (plot.height - 80) : 320,
+      padding: [0, 0, 0, 0],
+    })
+    chart.data(data);
+    chart.scale('value', {
+      min: 0,
+      max: plot.maxValue,
+      tickInterval: plot.tickInterval,
+    });
+    chart.coordinate('polar', {
+      startAngle: (-9 / 8) * Math.PI,
+      endAngle: (1 / 8) * Math.PI,
+      radius: 0.75,
+    });
+
+    chart.axis('1', false);
+    chart.axis('value', {
+      line: null,
+      label: {
+        offset: -36,
+        style: {
+          fontSize: 18,
+          fill: plot.tickColor,
+          textAlign: 'center',
+          textBaseline: 'middle',
+        },
+      },
+      tickLine: {
+        length: -24,
+        style: {
+          stroke: plot.tickColor
+        }
+      },
+      grid: null,
+    });
+    chart.legend(false);
+    chart.tooltip(false);
+    chart
+      .point()
+      .position('value*1')
+      .shape('pointer')
+      .color('value', (val) => {
+        let _color = '#1890FF'
+        if (plot.colors && plot.colors.length > 0) {
+          _color = plot.colors[plot.colors.length - 1].color || '#1890FF'
+          plot.colors.some(item => {
+            if (item.tick > val) {
+              _color = item.color
+              return true
+            }
+            return false
+          })
+        }
+        return _color
+      })
+      .animate({
+        appear: {
+          animation: 'fade-in'
+        }
+      });
+
+    // 缁樺埗浠〃鐩樿儗鏅�
+    chart.annotation().arc({
+      top: false,
+      start: [0, 1],
+      end: [plot.maxValue, 1],
+      style: {
+        stroke: '#CBCBCB',
+        lineWidth: 18,
+        lineDash: null,
+      },
+    })
+
+    if (!plot.colors || plot.colors.length === 0) {
+      chart.annotation().arc({
+        start: [0, 1],
+        end: [plot.maxValue, 1],
+        style: {
+          stroke: '#1890FF',
+          lineWidth: 18,
+          lineDash: null,
+        },
+      });
+    } else {
+      let start = 0
+      plot.colors.forEach(item => {
+        chart.annotation().arc({
+          start: [start, 1],
+          end: [item.tick, 1],
+          style: {
+            stroke: item.color,
+            lineWidth: 18,
+            lineDash: null,
+          },
+        })
+        start = item.tick
+      })
+    }
+
+    if (plot.label) {
+      chart.annotation().text({
+        position: ['50%', '85%'],
+        content: plot.label,
+        style: {
+          fontSize: 20,
+          fill: plot.labelColor,
+          textAlign: 'center',
+        },
+      })
+    }
+
+    let val = data[0].value
+    if (plot.percent !== 'false' && plot.maxValue) {
+      val = +(val / plot.maxValue * 100).toFixed(2) + ' %'
+    }
+
+    chart.annotation().text({
+      position: ['50%', '90%'],
+      content: val,
+      style: {
+        fontSize: 36,
+        fill: plot.labelColor,
+        textAlign: 'center',
+      },
+      offsetY: 15,
+    });
+
+    chart.render()
+  }
+
+  updateComponent = (component) => {
+    const card = fromJS(this.state.card).toJS()
+    let refresh = false
+    if (!is(fromJS(component.plot), fromJS(card.plot)) || !is(fromJS(component.style), fromJS(card.style))) {
+      let _element = document.getElementById(card.uuid + 'dashboard')
+      if (_element) {
+        _element.innerHTML = ''
+      }
+      refresh = true
+    }
+
+    component.width = component.plot.width
+    component.name = component.plot.name
+    
+    this.setState({
+      card: component
+    }, () => {
+      if (refresh) {
+        setTimeout(() => {
+          this.dashboardrender()
+        }, 100)
+      }
+    })
+    this.props.updateConfig(component)
+  }
+
+  changeStyle = () => {
+    const { card } = this.state
+
+    MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style)
+  }
+
+  getStyle = (comIds, style) => {
+    const { card } = this.state
+
+    if (comIds[0] !== card.uuid || comIds.length > 1) return
+
+    let _card = {...card, style}
+
+    this.updateComponent(_card)
+  }
+
+  clickComponent = (e) => {
+    if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
+      e.stopPropagation()
+      MKEmitter.emit('clickComponent', this.state.card)
+    }
+  }
+
+  render() {
+    const { card } = this.state
+    let _style = resetStyle(card.style)
+
+    return (
+      <div className="menu-dashboard-edit-box" style={{..._style, height: card.plot.height || 400}} onClick={this.clickComponent} id={card.uuid}>
+        <NormalHeader config={card} updateComponent={this.updateComponent}/>
+        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+          <div className="mk-popover-control">
+            <ChartCompileForm config={card} dict={this.state.dict} plotchange={this.updateComponent}/>
+            <CopyComponent type="dashboard" card={card}/>
+            <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" />
+            <ClockComponent config={card} updateConfig={this.updateComponent}/>
+            <UserComponent config={card}/>
+            <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
+            <SettingComponent config={card} updateConfig={this.updateComponent}/>
+          </div>
+        } trigger="hover">
+          <Icon type="tool" />
+        </Popover>
+        <div className="canvas" id={card.uuid + 'dashboard'}></div>
+      </div>
+    )
+  }
+}
+
+export default antvDashboardChart
\ No newline at end of file
diff --git a/src/menu/components/chart/antv-dashboard/index.scss b/src/menu/components/chart/antv-dashboard/index.scss
new file mode 100644
index 0000000..0efe48d
--- /dev/null
+++ b/src/menu/components/chart/antv-dashboard/index.scss
@@ -0,0 +1,45 @@
+.menu-dashboard-edit-box {
+  position: relative;
+  box-sizing: border-box;
+  background: #ffffff;
+  background-position: center center;
+  background-repeat: no-repeat;
+  background-size: cover;
+  
+  .canvas {
+    margin: 0px;
+    letter-spacing: 0px;
+  }
+
+  >.anticon-tool {
+    position: absolute;
+    right: 1px;
+    top: 1px;
+    z-index: 2;
+    font-size: 16px;
+    padding: 5px;
+    cursor: pointer;
+    color: rgba(0, 0, 0, 0.85);
+    background: rgba(255, 255, 255, 0.55);
+  }
+
+  .model-menu-action-list {
+    position: absolute;
+    right: 0px;
+    z-index: 4;
+    padding-top: 10px;
+    font-size: 16px;
+  
+    .ant-row .anticon-plus {
+      float: right;
+    }
+  
+    .page-card {
+      float: right;
+    }
+  }
+}
+.menu-dashboard-edit-box:hover {
+  z-index: 1;
+  box-shadow: 0px 0px 4px #1890ff;
+}
diff --git a/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx
index 6c4e322..107b8b7 100644
--- a/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx
+++ b/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx
@@ -274,14 +274,7 @@
       label: '鑹茬郴',
       initVal: card.color || 'rgba(0, 0, 0, 0.85)',
       tooltip: '鍧愭爣杞村強绀轰緥绛夋彁绀烘枃瀛椾娇鐢ㄧ殑棰滆壊銆�',
-      required: false,
-      options: [{
-        value: 'black',
-        text: '榛戣壊'
-      }, {
-        value: 'white',
-        text: '鐧借壊'
-      }]
+      required: false
     }
   ]
 }
diff --git a/src/menu/components/chart/antv-pie/index.jsx b/src/menu/components/chart/antv-pie/index.jsx
index 6275356..cbc63d6 100644
--- a/src/menu/components/chart/antv-pie/index.jsx
+++ b/src/menu/components/chart/antv-pie/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Icon, Popover, notification } from 'antd'
+import { Icon, Popover } from 'antd'
 import { Chart } from '@antv/g2'
 import DataSet from '@antv/data-set'
 
@@ -18,7 +18,6 @@
 const ChartCompileForm = asyncIconComponent(() => import('./chartcompile'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
-const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
 const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
@@ -38,7 +37,7 @@
   }
 
   UNSAFE_componentWillMount () {
-    const { card } = this.props
+    const { card, ismob } = this.props
 
     if (card.isNew) {
       let _plot = {
@@ -47,6 +46,10 @@
         height: 400,
         label: 'outer',
         name: card.name
+      }
+
+      if (ismob) {
+        _plot.width = 24
       }
 
       if (card.subtype === 'ring') {
@@ -167,7 +170,7 @@
 
   pierender = () => {
     const { card } = this.state
-    let plot = {...card.plot, height: card.plot.height - 80}
+    const plot = card.plot
     let color = plot.color || 'rgba(0, 0, 0, 0.85)'
 
     let X_axis = plot.Xaxis || 'x'
@@ -181,7 +184,7 @@
     const chart = new Chart({
       container: card.uuid + 'canvas',
       autoFit: true,
-      height: plot.height || 400
+      height: card.plot.height ? (card.plot.height - 80) : 320
     })
 
     if (plot.shape !== 'nightingale' && plot.show !== 'value') {
@@ -411,32 +414,6 @@
     this.updateComponent(_card)
   }
 
-  handleLog = (type, logs, item) => {
-    let card = fromJS(this.state.card).toJS()
-
-    if (type === 'revert') {
-      card.action = card.action ? [...card.action, item] : [item]
-      card.btnlog = logs
-
-      this.setState({ card })
-      this.props.updateConfig(card)
-      notification.success({
-        top: 92,
-        message: '鎭㈠鎴愬姛锛�',
-        duration: 2
-      })
-    } else {
-      card.btnlog = logs
-      this.setState({ card })
-      this.props.updateConfig(card)
-      notification.success({
-        top: 92,
-        message: '娓呴櫎鎴愬姛锛�',
-        duration: 2
-      })
-    }
-  }
-
   clickComponent = (e) => {
     if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
       e.stopPropagation()
@@ -458,7 +435,6 @@
             <CopyComponent type="pie" card={card}/>
             <PasteComponent config={card} options={['search', 'form']} updateConfig={this.updateComponent} />
             <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" />
-            <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} />
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
             <UserComponent config={card}/>
             <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
diff --git a/src/menu/components/group/groupcomponents/card.jsx b/src/menu/components/group/groupcomponents/card.jsx
index 99d3e95..a68f461 100644
--- a/src/menu/components/group/groupcomponents/card.jsx
+++ b/src/menu/components/group/groupcomponents/card.jsx
@@ -11,6 +11,7 @@
 const TableCard = asyncComponent(() => import('@/menu/components/card/table-card'))
 const NormalTable = asyncComponent(() => import('@/menu/components/table/normal-table'))
 const BraftEditor = asyncComponent(() => import('@/menu/components/editor/braft-editor'))
+const AntvDashboard = asyncComponent(() => import('@/menu/components/chart/antv-dashboard'))
 
 const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => {
   const originalIndex = findCard(id).index
@@ -50,6 +51,8 @@
       return (<AntvBar card={card} updateConfig={updateConfig} deletecomponent={delCard} />)
     } else if (card.type === 'pie') {
       return (<AntvPie card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
+    } else if (card.type === 'dashboard') {
+      return (<AntvDashboard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     } else if (card.type === 'card' && card.subtype === 'datacard') {
       return (<DataCard card={card} updateConfig={updateConfig} deletecomponent={delCard} />)
     } else if (card.type === 'card' && card.subtype === 'propcard') {
diff --git a/src/menu/components/group/groupcomponents/index.jsx b/src/menu/components/group/groupcomponents/index.jsx
index 7a8719e..0baa248 100644
--- a/src/menu/components/group/groupcomponents/index.jsx
+++ b/src/menu/components/group/groupcomponents/index.jsx
@@ -104,6 +104,7 @@
         pie: '楗煎浘',
         table: '琛ㄦ牸',
         editor: '瀵屾枃鏈�',
+        dashboard: '浠〃鐩�',
         card: '鍗$墖'
       }
       let i = 1
diff --git a/src/menu/components/table/normal-table/columns/index.jsx b/src/menu/components/table/normal-table/columns/index.jsx
index 06139cc..0ddcf33 100644
--- a/src/menu/components/table/normal-table/columns/index.jsx
+++ b/src/menu/components/table/normal-table/columns/index.jsx
@@ -496,8 +496,16 @@
 
     const columns = this.handlecolumns(this.state.columns, fields, config)
 
+    let style = {}
+    if (config.wrap.color) {
+      style.color = config.wrap.color
+    }
+    if (config.wrap.fontSize) {
+      style.fontSize = config.wrap.fontSize
+    }
+
     return (
-      <div className={`normal-table-columns ${config.setting.laypage} ${config.wrap.tableType}`} id={tableId}>
+      <div className={`normal-table-columns ${config.setting.laypage} ${config.wrap.tableType} ${config.wrap.mode || ''}`} id={tableId}>
         <div className="col-control">
           <Icon title="澶嶅埗" type="copy" onClick={this.copycolumn} />
           <MarkColumn columns={fields} type="line" marks={lineMarks} onSubmit={this.updateLineMarks} />
@@ -508,6 +516,7 @@
             rowKey="uuid"
             size={config.wrap.size || 'middle'}
             rowClassName="editable-row"
+            style={style}
             bordered={config.wrap.bordered !== 'false'}
             components={components}
             dataSource={this.state.data}
diff --git a/src/menu/components/table/normal-table/columns/index.scss b/src/menu/components/table/normal-table/columns/index.scss
index 41f4111..5c733b7 100644
--- a/src/menu/components/table/normal-table/columns/index.scss
+++ b/src/menu/components/table/normal-table/columns/index.scss
@@ -1,5 +1,9 @@
 .normal-table-columns {
   position: relative;
+  .ant-table {
+    color: inherit;
+    font-size: inherit;
+  }
   .ant-table-body {
     overflow-x: auto;
     tr {
@@ -89,3 +93,29 @@
     border-radius: 0;
   }
 }
+
+.normal-table-columns.ghost {
+  .ant-table-thead > tr {
+    > th {
+      color: inherit;
+      background: transparent;
+      .ant-table-column-sorter .ant-table-column-sorter-inner {
+        color: inherit;
+      }
+    }
+    > th:hover {
+      background: transparent;
+    }
+  }
+  .ant-table-body {
+    overflow-x: auto;
+    tr {
+      td {
+        background: transparent;
+      }
+    }
+    tr:hover td {
+      background: transparent!important;
+    }
+  }
+}
diff --git a/src/menu/components/table/normal-table/wrapsetting/settingform/index.jsx b/src/menu/components/table/normal-table/wrapsetting/settingform/index.jsx
index 77ea6f9..b811a4e 100644
--- a/src/menu/components/table/normal-table/wrapsetting/settingform/index.jsx
+++ b/src/menu/components/table/normal-table/wrapsetting/settingform/index.jsx
@@ -163,6 +163,39 @@
               </Form.Item>
             </Col>
             <Col span={12}>
+              <Form.Item label="妯″紡">
+                {getFieldDecorator('mode', {
+                  initialValue: wrap.mode || 'default'
+                })(
+                  <Radio.Group>
+                    <Radio key="default" value="default"> 甯歌 </Radio>
+                    <Radio key="ghost" value="ghost"> 閫忔槑 </Radio>
+                  </Radio.Group>
+                )}
+              </Form.Item>
+            </Col>
+            <Col span={12} style={{height: '64px'}}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="榛樿鍊� rgba(0, 0, 0, 0.65)銆�">
+                  <Icon type="question-circle" />
+                  瀛椾綋棰滆壊
+                </Tooltip>
+              }>
+                {getFieldDecorator('color', {
+                  initialValue: wrap.color || 'rgba(0, 0, 0, 0.65)'
+                })(
+                  <ColorSketch />
+                )}
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item label="瀛椾綋澶у皬">
+                {getFieldDecorator('fontSize', {
+                  initialValue: wrap.fontSize || 14
+                })(<InputNumber min={14} max={30} precision={0} />)}
+              </Form.Item>
+            </Col>
+            <Col span={12}>
               <Form.Item label={
                 <Tooltip placement="topLeft" title="鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��">
                   <Icon type="question-circle" />
diff --git a/src/menu/components/tabs/tabcomponents/card.jsx b/src/menu/components/tabs/tabcomponents/card.jsx
index ca9c1fe..9cac701 100644
--- a/src/menu/components/tabs/tabcomponents/card.jsx
+++ b/src/menu/components/tabs/tabcomponents/card.jsx
@@ -7,6 +7,7 @@
 const AntvBar = asyncComponent(() => import('@/menu/components/chart/antv-bar'))
 const MainSearch = asyncComponent(() => import('@/menu/components/search/main-search'))
 const AntvPie = asyncComponent(() => import('@/menu/components/chart/antv-pie'))
+const AntvDashboard = asyncComponent(() => import('@/menu/components/chart/antv-dashboard'))
 const AntvTabs = asyncComponent(() => import('@/menu/components/tabs/antv-tabs'))
 const DataCard = asyncComponent(() => import('@/menu/components/card/data-card'))
 const PropCard = asyncComponent(() => import('@/menu/components/card/prop-card'))
@@ -57,6 +58,8 @@
       return (<MainSearch card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     } else if (card.type === 'pie') {
       return (<AntvPie card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
+    } else if (card.type === 'dashboard') {
+      return (<AntvDashboard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     } else if (card.type === 'tabs') {
       return (<AntvTabs tabs={card} updateConfig={updateConfig} deletecomponent={delCard} />)
     } else if (card.type === 'card' && card.subtype === 'datacard') {
diff --git a/src/menu/components/tabs/tabcomponents/index.jsx b/src/menu/components/tabs/tabcomponents/index.jsx
index 7a913bc..9b34445 100644
--- a/src/menu/components/tabs/tabcomponents/index.jsx
+++ b/src/menu/components/tabs/tabcomponents/index.jsx
@@ -98,6 +98,7 @@
         group: '鍒嗙粍',
         editor: '瀵屾枃鏈�',
         carousel: '杞挱',
+        dashboard: '浠〃鐩�',
         card: '鍗$墖'
       }
       let i = 1
diff --git a/src/menu/menushell/card.jsx b/src/menu/menushell/card.jsx
index b89e539..17310a5 100644
--- a/src/menu/menushell/card.jsx
+++ b/src/menu/menushell/card.jsx
@@ -7,6 +7,7 @@
 const AntvBar = asyncComponent(() => import('@/menu/components/chart/antv-bar'))
 const MainSearch = asyncComponent(() => import('@/menu/components/search/main-search'))
 const AntvPie = asyncComponent(() => import('@/menu/components/chart/antv-pie'))
+const AntvDashboard = asyncComponent(() => import('@/menu/components/chart/antv-dashboard'))
 const AntvTabs = asyncComponent(() => import('@/menu/components/tabs/antv-tabs'))
 const DataCard = asyncComponent(() => import('@/menu/components/card/data-card'))
 const PropCard = asyncComponent(() => import('@/menu/components/card/prop-card'))
@@ -59,6 +60,8 @@
       return (<MainSearch card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     } else if (card.type === 'pie') {
       return (<AntvPie card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
+    } else if (card.type === 'dashboard') {
+      return (<AntvDashboard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     } else if (card.type === 'form') {
       return (<NormalForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     } else if (card.type === 'tabs') {
diff --git a/src/menu/menushell/index.jsx b/src/menu/menushell/index.jsx
index 6ac5ace..5121c17 100644
--- a/src/menu/menushell/index.jsx
+++ b/src/menu/menushell/index.jsx
@@ -19,6 +19,10 @@
     handleList({...menu, components: _cards})
     setCards(_cards)
   }
+
+  if (menu.components.length > cards.length) {
+    setCards(menu.components)
+  }
   
   const findCard = id => {
     const card = cards.filter(c => `${c.uuid}` === id)[0]
@@ -93,6 +97,7 @@
         code: '鑷畾涔�',
         carousel: '杞挱',
         form: '琛ㄥ崟',
+        dashboard: '浠〃鐩�',
         card: '鍗$墖'
       }
       let i = 1
diff --git a/src/menu/modulesource/option.jsx b/src/menu/modulesource/option.jsx
index e88ceca..0161c6f 100644
--- a/src/menu/modulesource/option.jsx
+++ b/src/menu/modulesource/option.jsx
@@ -17,6 +17,7 @@
 import Carousel from '@/assets/mobimg/carousel.png'
 import Carousel1 from '@/assets/mobimg/carousel1.png'
 import form from '@/assets/mobimg/form.png'
+import dashboard from '@/assets/mobimg/dashboard.png'
 
 // 缁勪欢閰嶇疆淇℃伅
 export const menuOptions = [
@@ -35,8 +36,9 @@
   { type: 'menu', url: bar1, component: 'bar', subtype: 'bar1', title: '鏉″舰鍥�', width: 24 },
   { type: 'menu', url: Pie, component: 'pie', subtype: 'pie', title: '楗煎浘', width: 12 },
   { type: 'menu', url: Pie1, component: 'pie', subtype: 'ring', title: '鐜浘', width: 12 },
+  { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '鍗椾竵鏍煎皵鍥�', width: 12 },
+  { type: 'menu', url: dashboard, component: 'dashboard', subtype: 'dashboard', title: '浠〃鐩�', width: 12 },
   { type: 'menu', url: Editor, component: 'editor', subtype: 'brafteditor', title: '瀵屾枃鏈�', width: 24 },
   { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '鑷畾涔�', width: 24 },
-  { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '鍗椾竵鏍煎皵鍥�', width: 12 },
   { type: 'menu', url: group, component: 'group', subtype: 'normalgroup', title: '鍒嗙粍', width: 24, forbid: ['billPrint'] },
 ]
diff --git a/src/mob/mobshell/index.jsx b/src/mob/mobshell/index.jsx
index 7a0dc49..aa8fe6b 100644
--- a/src/mob/mobshell/index.jsx
+++ b/src/mob/mobshell/index.jsx
@@ -19,6 +19,10 @@
     handleList({...menu, components: _cards})
     setCards(_cards)
   }
+
+  if (menu.components.length > cards.length) {
+    setCards(menu.components)
+  }
   
   const findCard = id => {
     const card = cards.filter(c => `${c.uuid}` === id)[0]
@@ -92,6 +96,7 @@
         editor: '瀵屾枃鏈�',
         code: '鑷畾涔�',
         carousel: '杞挱',
+        dashboard: '浠〃鐩�',
         form: '琛ㄥ崟',
         card: '鍗$墖',
         login: '鐧诲綍'
diff --git a/src/mob/modulesource/option.jsx b/src/mob/modulesource/option.jsx
index cf25dae..12af60a 100644
--- a/src/mob/modulesource/option.jsx
+++ b/src/mob/modulesource/option.jsx
@@ -18,6 +18,7 @@
 import Carousel1 from '@/assets/mobimg/carousel1.png'
 import form from '@/assets/mobimg/form.png'
 import Login from '@/assets/mobimg/login.png'
+import dashboard from '@/assets/mobimg/dashboard.png'
 
 // 缁勪欢閰嶇疆淇℃伅
 export const menuOptions = [
@@ -37,8 +38,9 @@
   { type: 'menu', url: bar1, component: 'bar', subtype: 'bar1', title: '鏉″舰鍥�', width: 24 },
   { type: 'menu', url: Pie, component: 'pie', subtype: 'pie', title: '楗煎浘', width: 24 },
   { type: 'menu', url: Pie1, component: 'pie', subtype: 'ring', title: '鐜浘', width: 24 },
-  { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '鑷畾涔�', width: 24 },
   { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '鍗椾竵鏍煎皵鍥�', width: 24 },
+  { type: 'menu', url: dashboard, component: 'dashboard', subtype: 'dashboard', title: '浠〃鐩�', width: 12 },
+  { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '鑷畾涔�', width: 24 },
   { type: 'menu', url: group, component: 'group', subtype: 'normalgroup', title: '鍒嗙粍', width: 24 },
   { type: 'menu', url: Login, component: 'login', subtype: 'normallogin', title: '鐧诲綍', width: 24 },
 ]
diff --git a/src/pc/menushell/index.jsx b/src/pc/menushell/index.jsx
index 969e9ab..024490a 100644
--- a/src/pc/menushell/index.jsx
+++ b/src/pc/menushell/index.jsx
@@ -19,6 +19,10 @@
     handleList({...menu, components: _cards})
     setCards(_cards)
   }
+
+  if (menu.components.length > cards.length) {
+    setCards(menu.components)
+  }
   
   const findCard = id => {
     const card = cards.filter(c => `${c.uuid}` === id)[0]
@@ -102,6 +106,7 @@
         code: '鑷畾涔�',
         navbar: '瀵艰埅鏍�',
         carousel: '杞挱',
+        dashboard: '浠〃鐩�',
         card: '鍗$墖',
         login: '鐧诲綍'
       }
diff --git a/src/pc/modulesource/option.jsx b/src/pc/modulesource/option.jsx
index 189416d..c38e815 100644
--- a/src/pc/modulesource/option.jsx
+++ b/src/pc/modulesource/option.jsx
@@ -19,6 +19,7 @@
 import Carousel1 from '@/assets/mobimg/carousel1.png'
 import form from '@/assets/mobimg/form.png'
 import Login from '@/assets/mobimg/login.png'
+import dashboard from '@/assets/mobimg/dashboard.png'
 
 // 缁勪欢閰嶇疆淇℃伅
 export const menuOptions = [
@@ -38,9 +39,10 @@
   { type: 'menu', url: bar1, component: 'bar', subtype: 'bar1', title: '鏉″舰鍥�', width: 24 },
   { type: 'menu', url: Pie, component: 'pie', subtype: 'pie', title: '楗煎浘', width: 12 },
   { type: 'menu', url: Pie1, component: 'pie', subtype: 'ring', title: '鐜浘', width: 12 },
+  { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '鍗椾竵鏍煎皵鍥�', width: 12 },
+  { type: 'menu', url: dashboard, component: 'dashboard', subtype: 'dashboard', title: '浠〃鐩�', width: 12 },
   { type: 'menu', url: Editor, component: 'editor', subtype: 'brafteditor', title: '瀵屾枃鏈�', width: 24 },
   { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '鑷畾涔�', width: 24 },
-  { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '鍗椾竵鏍煎皵鍥�', width: 12 },
   { type: 'menu', url: group, component: 'group', subtype: 'normalgroup', title: '鍒嗙粍', width: 24 },
   { type: 'menu', url: Login, component: 'login', subtype: 'normallogin', title: '鐧诲綍', width: 24 },
 ]
diff --git a/src/tabviews/custom/components/chart/antv-dashboard/index.jsx b/src/tabviews/custom/components/chart/antv-dashboard/index.jsx
new file mode 100644
index 0000000..46a23ab
--- /dev/null
+++ b/src/tabviews/custom/components/chart/antv-dashboard/index.jsx
@@ -0,0 +1,467 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Chart, registerShape } from '@antv/g2'
+import { Spin, notification } from 'antd'
+import moment from 'moment'
+
+import Api from '@/api'
+import Utils from '@/utils/utils.js'
+import asyncComponent from '@/utils/asyncComponent'
+import UtilsDM from '@/utils/utils-datamanage.js'
+import MKEmitter from '@/utils/events.js'
+import './index.scss'
+
+const NormalHeader = asyncComponent(() => import('@/tabviews/custom/components/share/normalheader'))
+
+registerShape('point', 'pointer', {
+  draw(cfg, container) {
+    const group = container.addGroup({});
+    // 鑾峰彇鏋佸潗鏍囩郴涓嬬敾甯冧腑蹇冪偣
+    const center = this.parsePoint({ x: 0, y: 0 });
+    // 缁樺埗鎸囬拡
+    group.addShape('line', {
+      attrs: {
+        x1: center.x,
+        y1: center.y,
+        x2: cfg.x,
+        y2: cfg.y,
+        stroke: cfg.color,
+        lineWidth: 5,
+        lineCap: 'round',
+      },
+    });
+    group.addShape('circle', {
+      attrs: {
+        x: center.x,
+        y: center.y,
+        r: 9.75,
+        stroke: cfg.color,
+        lineWidth: 4.5,
+        fill: '#fff',
+      },
+    });
+    return group;
+  },
+})
+
+class DashboardChart extends Component {
+  static propTpyes = {
+    BID: PropTypes.any,              // 鐖剁骇Id
+    data: PropTypes.array,           // 缁熶竴鏌ヨ鏁版嵁
+    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
+    mainSearch: PropTypes.any,       // 澶栧眰鎼滅储鏉′欢
+    menuType: PropTypes.any,         // 鑿滃崟绫诲瀷
+  }
+
+  state = {
+    BID: '',                   // 涓婄骇ID
+    config: null,              // 鍥捐〃閰嶇疆淇℃伅
+    loading: false,            // 鏁版嵁鍔犺浇鐘舵��
+    chartId: Utils.getuuid(),  // 鍥捐〃Id
+    title: '',                 // 缁勪欢鏍囬
+    sync: false,               // 鏄惁缁熶竴璇锋眰鏁版嵁
+    plot: null,                // 鍥捐〃璁剧疆
+    data: null,                // 鏁版嵁
+  }
+
+  UNSAFE_componentWillMount () {
+    const { config, data, initdata, BID } = this.props
+    let _config = fromJS(config).toJS()
+
+    let _data = {}
+    let _sync = _config.setting.sync === 'true'
+    
+    if (_sync && data) {
+      _data = data[_config.dataName] || {}
+      if (_data && Array.isArray(_data)) {
+        _data = _data[0] || {}
+      }
+      _sync = false
+    } else if (_sync && initdata) {
+      _data = initdata || {}
+      if (_data && Array.isArray(_data)) {
+        _data = _data[0] || {}
+      }
+      _sync = false
+    }
+
+
+    if (_config.style) {
+      _config.style = {..._config.style, minHeight: (config.plot.height || 400)}
+    } else {
+      _config.style = {minHeight: (config.plot.height || 400)}
+    }
+
+    this.setState({
+      config: _config,
+      data: _data,
+      BID: BID || '',
+      arr_field: _config.columns.map(col => col.field).join(','),
+      plot: _config.plot,
+      sync: _sync,
+      title: config.plot.title
+    }, () => {
+      if (config.setting.sync !== 'true' && config.setting.onload === 'true') {
+        this.loadData()
+      } else if (config.setting.sync === 'true' && _data) {
+        this.handleData()
+      }
+    })
+  }
+
+  /**
+   * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
+   */
+  UNSAFE_componentWillReceiveProps (nextProps) {
+    const { sync, config } = this.state
+
+    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
+      let _data = {}
+      if (nextProps.data && nextProps.data[config.dataName]) {
+        _data = nextProps.data[config.dataName] || {}
+      }
+      if (_data.hasOwnProperty(config.plot.valueField)) {
+        _data.value = _data[config.plot.valueField]
+      }
+
+      this.setState({sync: false, data: _data}, () => {
+        this.handleData()
+      })
+    } else if (nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
+      if (config.setting.syncRefresh === 'true') {
+        this.setState({}, () => {
+          this.loadData()
+        })
+      }
+    }
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  componentDidMount () {
+    MKEmitter.addListener('reloadData', this.reloadData)
+    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
+    this.handleTimer()
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
+   */
+  componentWillUnmount () {
+    clearTimeout(this.timer)
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+  }
+
+  handleTimer = () => {
+    const { config } = this.state
+
+    if (!config.timer) return
+
+    const _change = {
+      '15s': 15000,
+      '30s': 30000,
+      '1min': 60000,
+      '5min': 300000,
+      '10min': 600000,
+      '15min': 900000,
+      '30min': 1800000,
+      '1hour': 3600000
+    }
+
+    let timer = _change[config.timer]
+
+    if (!timer) return
+
+    let _param = {
+      func: 's_get_timers_role',
+      LText: `select '${window.GLOB.appkey || ''}','${config.uuid}'`,
+      timer_type: config.timer,
+      component_id: config.uuid
+    }
+    
+    _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')          // 鏃堕棿鎴�
+    _param.LText = Utils.formatOptions(_param.LText)                   // 鍏抽敭瀛楃鏇挎崲锛宐ase64鍔犲瘑
+    _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)   // md5瀵嗛挜
+
+    Api.getSystemConfig(_param).then(result => {
+      if (!result.status) {
+        notification.warning({
+          top: 92,
+          message: result.message,
+          duration: 5
+        })
+        return
+      } else if (result.run_type) {
+        this.setState({timer})
+        this.timer = setTimeout(() => {
+          this.timerTask()
+        }, timer)
+      }
+    })
+  }
+
+  timerTask = () => {
+    const { timer } = this.state
+    if (!timer) return
+    
+    this.loadData(true)
+    
+    this.timer = setTimeout(() => {
+      this.timerTask()
+    }, timer)
+  }
+
+  reloadData = (menuId) => {
+    const { config } = this.state
+
+    if (config.uuid !== menuId) return
+
+    this.loadData()
+  }
+
+  resetParentParam = (MenuID, id) => {
+    const { config } = this.state
+
+    if (!config.setting.supModule || config.setting.supModule !== MenuID) return
+    if (id !== this.state.BID) {
+      this.setState({ BID: id }, () => {
+        this.loadData()
+      })
+    }
+  }
+
+  handleData = () => {
+    let _element = document.getElementById(this.state.chartId)
+    if (_element) {
+      _element.innerHTML = ''
+    }
+    this.dashboardrender()
+  }
+
+  async loadData (hastimer) {
+    const { mainSearch, menuType } = this.props
+    const { config, arr_field, BID } = this.state
+
+    if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
+      this.setState({
+        data: {}
+      }, () => {
+        this.handleData()
+      })
+      return
+    }
+
+    let searches = []
+    if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
+      let keys = []
+      mainSearch.forEach(item => {
+        if (!keys.includes(item.key)) {
+          searches.push(item)
+        }
+      })
+    }
+
+    if (!hastimer) {
+      this.setState({
+        loading: true
+      })
+    }
+
+    let _orderBy = config.setting.order || ''
+    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, '', '', BID, menuType)
+
+    let result = await Api.genericInterface(param)
+    if (result.status) {
+      let data = {}
+      if (result.data && result.data[0] && result.data[0].hasOwnProperty(config.plot.valueField)) {
+        data.value = result.data[0][config.plot.valueField]
+      }
+
+      this.setState({
+        data,
+        loading: false
+      }, () => {
+        this.handleData()
+      })
+    } else {
+      this.setState({
+        loading: false,
+        timer: null
+      })
+      notification.error({
+        top: 92,
+        message: result.message,
+        duration: 10
+      })
+    }
+  }
+
+  /**
+   * @description 楗煎浘娓叉煋
+   */
+  dashboardrender = () => {
+    const { plot, chartId, data } = this.state
+    const chart = new Chart({
+      container: chartId,
+      autoFit: true,
+      height: plot.height ? (plot.height - 80) : 320,
+      padding: [0, 0, 0, 0],
+    })
+    chart.data([data]);
+    chart.scale('value', {
+      min: 0,
+      max: plot.maxValue,
+      tickInterval: plot.tickInterval,
+    });
+    chart.coordinate('polar', {
+      startAngle: (-9 / 8) * Math.PI,
+      endAngle: (1 / 8) * Math.PI,
+      radius: 0.75,
+    });
+
+    chart.axis('1', false);
+    chart.axis('value', {
+      line: null,
+      label: {
+        offset: -36,
+        style: {
+          fontSize: 18,
+          fill: plot.tickColor,
+          textAlign: 'center',
+          textBaseline: 'middle',
+        },
+      },
+      tickLine: {
+        length: -24,
+        style: {
+          stroke: plot.tickColor
+        }
+      },
+      grid: null,
+    });
+    chart.legend(false);
+    chart.tooltip(false);
+    chart
+      .point()
+      .position('value*1')
+      .shape('pointer')
+      .color('value', (val) => {
+        if (!val && val !== 0) return 'transparent'
+        let _color = '#1890FF'
+        if (plot.colors && plot.colors.length > 0) {
+          _color = plot.colors[plot.colors.length - 1].color || '#1890FF'
+          plot.colors.some(item => {
+            if (item.tick > val) {
+              _color = item.color
+              return true
+            }
+            return false
+          })
+        }
+        return _color
+      })
+      .animate({
+        appear: {
+          animation: 'fade-in'
+        }
+      });
+
+    // 缁樺埗浠〃鐩樿儗鏅�
+    chart.annotation().arc({
+      top: false,
+      start: [0, 1],
+      end: [plot.maxValue, 1],
+      style: {
+        stroke: '#CBCBCB',
+        lineWidth: 18,
+        lineDash: null,
+      },
+    })
+
+    if (!plot.colors || plot.colors.length === 0) {
+      chart.annotation().arc({
+        start: [0, 1],
+        end: [plot.maxValue, 1],
+        style: {
+          stroke: '#1890FF',
+          lineWidth: 18,
+          lineDash: null,
+        },
+      });
+    } else {
+      let start = 0
+      plot.colors.forEach(item => {
+        chart.annotation().arc({
+          start: [start, 1],
+          end: [item.tick, 1],
+          style: {
+            stroke: item.color,
+            lineWidth: 18,
+            lineDash: null,
+          },
+        })
+        start = item.tick
+      })
+    }
+
+    if (plot.label) {
+      chart.annotation().text({
+        position: ['50%', '85%'],
+        content: plot.label,
+        style: {
+          fontSize: 20,
+          fill: plot.labelColor,
+          textAlign: 'center',
+        },
+      })
+    }
+
+    if (data.hasOwnProperty('value')) {
+      let val = data.value
+      if (plot.percent !== 'false' && plot.maxValue) {
+        val = +(val / plot.maxValue * 100).toFixed(2) + ' %'
+      }
+  
+      chart.annotation().text({
+        position: ['50%', '90%'],
+        content: val,
+        style: {
+          fontSize: 36,
+          fill: plot.labelColor,
+          textAlign: 'center',
+        },
+        offsetY: 15,
+      });
+    }
+
+    chart.render()
+  }
+
+  render() {
+    const { config, loading, empty } = this.state
+
+    return (
+      <div className="custom-dashboard-plot-box" style={config.style}>
+        {loading ?
+          <div className="loading-mask">
+            <div className="ant-spin-blur"></div>
+            <Spin />
+          </div> : null
+        }
+        <NormalHeader config={config} />
+        <div className="canvas-wrap">
+          <div className={'canvas' + (empty ? ' empty' : '')} id={this.state.chartId}></div>
+        </div>
+      </div>
+    )
+  }
+}
+
+export default DashboardChart
\ No newline at end of file
diff --git a/src/tabviews/custom/components/chart/antv-dashboard/index.scss b/src/tabviews/custom/components/chart/antv-dashboard/index.scss
new file mode 100644
index 0000000..f90d8c7
--- /dev/null
+++ b/src/tabviews/custom/components/chart/antv-dashboard/index.scss
@@ -0,0 +1,105 @@
+.custom-dashboard-plot-box {
+  position: relative;
+  background: #ffffff;
+  background-position: center center;
+  background-repeat: no-repeat;
+  background-size: cover;
+  min-height: 100px;
+  
+  .canvas-wrap {
+    margin: 0 0px;
+    position: relative;
+    .chart-action {
+      position: absolute;
+      top: 2px;
+      right: 5px;
+      z-index: 1;
+    }
+    .chart-action.with-title {
+      top: 35px;
+    }
+  }
+
+  .canvas {
+    margin: 0;
+    padding: 15px;
+    letter-spacing: 0px;
+  }
+  .canvas.empty {
+    div {
+      opacity: 0;
+    }
+  }
+  .ant-empty {
+    position: absolute;
+    top: calc(50% - 34px);
+    left: calc(50% - 92px);
+
+    .ant-empty-image {
+      height: 60px;
+    }
+  }
+  .loading-mask {
+    position: absolute;
+    left: 0px;
+    top: 0;
+    right: 0px;
+    bottom: 0px;
+    z-index: 1;
+
+    .ant-spin-blur {
+      position: absolute;
+      width: 100%;
+      height: 100%;
+      opacity: 0.5;
+      background: #ffffff;
+    }
+  }
+  > .ant-select {
+    width: 150px;
+    float: right;
+    position: relative;
+    z-index: 1;
+    .ant-select-selection {
+      min-height: 24px;
+      height: 28px;
+      li {
+        background: unset;
+        border: 0;
+        width: 99%;
+        padding: 0;
+        margin-right: 0;
+        cursor: pointer;
+
+        .type-label {
+          overflow: hidden;
+          word-break: break-word;
+          white-space: nowrap;
+          text-overflow: ellipsis;
+        }
+      }
+      li + li {
+        margin-top: 0;
+        width: 1%;
+        opacity: 0;
+      }
+    }
+  }
+  > .ant-select.ant-select-focused {
+    .ant-select-selection {
+      li {
+        width: 50%;
+      }
+      li + li {
+        width: 49%;
+        opacity: 1;
+      }
+    }
+  }
+  .g2-tooltip-list{
+    display: none;
+  }
+  .g2-tooltip-title + .g2-tooltip-list{
+    display: block;
+  }
+}
diff --git a/src/tabviews/custom/components/group/normal-group/index.jsx b/src/tabviews/custom/components/group/normal-group/index.jsx
index a977b63..066f8c7 100644
--- a/src/tabviews/custom/components/group/normal-group/index.jsx
+++ b/src/tabviews/custom/components/group/normal-group/index.jsx
@@ -15,6 +15,7 @@
 // 閫氱敤缁勪欢
 const AntvBarAndLine = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-bar-line'))
 const AntvPie = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-pie'))
+const AntvDashboard = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-dashboard'))
 const DataCard = asyncComponent(() => import('@/tabviews/custom/components/card/data-card'))
 const TableCard = asyncComponent(() => import('@/tabviews/custom/components/card/table-card'))
 const NormalTable = asyncComponent(() => import('@/tabviews/custom/components/table/normal-table'))
@@ -253,6 +254,12 @@
             <AntvPie data={data} config={item} BID={_bid} mainSearch={mainSearch} menuType={menuType} />
           </Col>
         )
+      } else if (item.type === 'dashboard') {
+        return (
+          <Col span={item.width} key={item.uuid}>
+            <AntvDashboard config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} />
+          </Col>
+        )
       } else if (item.type === 'card' && item.subtype === 'datacard') {
         return (
           <Col span={item.width} key={item.uuid}>
diff --git a/src/tabviews/custom/components/share/normalTable/index.jsx b/src/tabviews/custom/components/share/normalTable/index.jsx
index 454217a..e32c343 100644
--- a/src/tabviews/custom/components/share/normalTable/index.jsx
+++ b/src/tabviews/custom/components/share/normalTable/index.jsx
@@ -803,12 +803,13 @@
     }
 
     return (
-      <div className={'normal-custom-table ' + setting.tableHeader} id={tableId}>
+      <div className={`normal-custom-table ${setting.tableHeader || ''} ${setting.mode || ''}`} id={tableId}>
         {(setting.tableType === 'radio' || setting.tableType === 'checkbox') && data && data.length > 0 ?
           <Switch title="鏀惰捣" className="main-pickup" checkedChildren="寮�" unCheckedChildren="鍏�" checked={pickup} onChange={this.pickupChange} /> : null
         }
         <Table
           components={components}
+          style={setting.style}
           size={setting.size || 'middle'}
           bordered={setting.bordered !== 'false'}
           rowSelection={rowSelection}
diff --git a/src/tabviews/custom/components/share/normalTable/index.scss b/src/tabviews/custom/components/share/normalTable/index.scss
index 19301ac..edacf90 100644
--- a/src/tabviews/custom/components/share/normalTable/index.scss
+++ b/src/tabviews/custom/components/share/normalTable/index.scss
@@ -14,6 +14,10 @@
     position: relative;
     z-index: 1;
   }
+  .ant-table {
+    color: inherit;
+    font-size: inherit;
+  }
 
   table {
     max-width: 100%;
@@ -163,6 +167,34 @@
     display: none;
   }
 }
+.normal-custom-table.ghost {
+  .main-pickup {
+    display: none;
+  }
+  .ant-table-thead > tr {
+    > th {
+      color: inherit;
+      background: transparent;
+      .ant-table-column-sorter .ant-table-column-sorter-inner {
+        color: inherit;
+      }
+    }
+    > th:hover {
+      background: transparent;
+    }
+  }
+  .ant-table-body {
+    overflow-x: auto;
+    tr {
+      td {
+        background: transparent!important;
+      }
+    }
+    tr:hover td {
+      background: transparent!important;
+    }
+  }
+}
 .image-scale-modal {
   width: 70vw;
   min-height: 80vh;
diff --git a/src/tabviews/custom/components/share/tabtransfer/index.jsx b/src/tabviews/custom/components/share/tabtransfer/index.jsx
index 2251ea6..855a989 100644
--- a/src/tabviews/custom/components/share/tabtransfer/index.jsx
+++ b/src/tabviews/custom/components/share/tabtransfer/index.jsx
@@ -16,6 +16,7 @@
 const AntvBarAndLine = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-bar-line'))
 const MainSearch = asyncComponent(() => import('@/tabviews/zshare/topSearch'))
 const AntvPie = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-pie'))
+const AntvDashboard = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-dashboard'))
 const AntvTabs = asyncComponent(() => import('@/tabviews/custom/components/tabs/antv-tabs'))
 const DataCard = asyncComponent(() => import('@/tabviews/custom/components/card/data-card'))
 const TableCard = asyncComponent(() => import('@/tabviews/custom/components/card/table-card'))
@@ -272,6 +273,12 @@
             <AntvPie data={data} config={item} BID={BID} mainSearch={mainSearch} menuType={menuType} />
           </Col>
         )
+      } else if (item.type === 'dashboard') {
+        return (
+          <Col span={item.width} key={item.uuid}>
+            <AntvDashboard config={item} data={data} BID={BID} mainSearch={mainSearch} menuType={menuType} />
+          </Col>
+        )
       } else if (item.type === 'search') {
         return (
           <Col span={item.width} key={item.uuid}>
diff --git a/src/tabviews/custom/components/table/normal-table/index.jsx b/src/tabviews/custom/components/table/normal-table/index.jsx
index 86035b3..da8380d 100644
--- a/src/tabviews/custom/components/table/normal-table/index.jsx
+++ b/src/tabviews/custom/components/table/normal-table/index.jsx
@@ -95,13 +95,21 @@
       }
     })
 
+    let setting = {..._config.setting, ..._config.wrap, style: {}}
+    if (setting.color) {
+      setting.style.color = setting.color
+    }
+    if (setting.fontSize) {
+      setting.style.fontSize = setting.fontSize
+    }
+
     this.setState({
       BID: BID || '',
       title: _config.wrap.title,
       sync: _sync,
       data: _data,
       config: _config,
-      setting: {..._config.setting, ..._config.wrap},
+      setting: setting,
       searchlist: _config.search,
       actions: _config.action,
       columns: _config.cols,
diff --git a/src/tabviews/custom/index.jsx b/src/tabviews/custom/index.jsx
index 6fb6711..ed3932d 100644
--- a/src/tabviews/custom/index.jsx
+++ b/src/tabviews/custom/index.jsx
@@ -21,6 +21,7 @@
 const AntvBarAndLine = asyncComponent(() => import('./components/chart/antv-bar-line'))
 const AntvPie = asyncComponent(() => import('./components/chart/antv-pie'))
 const AntvTabs = asyncComponent(() => import('./components/tabs/antv-tabs'))
+const AntvDashboard = asyncComponent(() => import('./components/chart/antv-dashboard'))
 const DataCard = asyncComponent(() => import('./components/card/data-card'))
 const PropCard = asyncComponent(() => import('./components/card/prop-card'))
 const NormalForm = asyncComponent(() => import('./components/form/normal-form'))
@@ -477,14 +478,14 @@
         }
 
         item.components = this.filterComponent(item.components, roleId, permAction, permMenus)
-      } else if (item.type === 'pie' || item.type === 'bar' || item.type === 'line') {
+      } else if (item.type === 'pie' || item.type === 'bar' || item.type === 'line' || item.type === 'dashboard') {
         if (
           item.plot.blacklist && item.plot.blacklist.length > 0 &&
           item.plot.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0
         ) {
           return false
         }
-      } else {
+      } else if (item.wrap) {
         if (
           item.wrap.blacklist && item.wrap.blacklist.length > 0 &&
           item.wrap.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0
@@ -1005,6 +1006,12 @@
             <AntvPie config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} />
           </Col>
         )
+      } else if (item.type === 'dashboard') {
+        return (
+          <Col span={item.width} key={item.uuid}>
+            <AntvDashboard config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} />
+          </Col>
+        )
       } else if (item.type === 'form') {
         return (
           <Col span={item.width} key={item.uuid}>
diff --git a/src/views/billprint/index.scss b/src/views/billprint/index.scss
index 2c5512e..80dd4f8 100644
--- a/src/views/billprint/index.scss
+++ b/src/views/billprint/index.scss
@@ -32,17 +32,23 @@
 }
 
 .print-page {
+  color: rgba(0,0,0,1);
   table {
+    color: rgba(0,0,0,1);
     border-radius: 0!important;
     .ant-table-column-sorter {
       display: none!important;
     }
   }
   .ant-table-thead > tr > th {
+    color: rgba(0,0,0,1);
     background: transparent!important;
     border-radius: 0!important;
   }
 }
+.print-page:last-child {
+  height: auto!important;
+}
 
 .normal-custom-table .main-pickup {
   display: none!important;
diff --git a/src/views/menudesign/index.jsx b/src/views/menudesign/index.jsx
index 199ef51..825a9ca 100644
--- a/src/views/menudesign/index.jsx
+++ b/src/views/menudesign/index.jsx
@@ -857,6 +857,8 @@
           if (!item.plot.Xaxis) {
             error = `缁勪欢銆�${item.name}銆嬪浘琛ㄥ瓧娈靛皻鏈缃紒`
           }
+        } else if (item.type === 'dashboard' && !item.plot.valueField) {
+          error = `缁勪欢銆�${item.name}銆嬫樉绀哄�煎皻鏈缃紒`
         }
       })
     }
diff --git a/src/views/mobdesign/index.jsx b/src/views/mobdesign/index.jsx
index 7e6a2cd..81fabf1 100644
--- a/src/views/mobdesign/index.jsx
+++ b/src/views/mobdesign/index.jsx
@@ -1300,6 +1300,8 @@
           if (!item.plot.Xaxis) {
             error = `缁勪欢銆�${item.name}銆嬪浘琛ㄥ瓧娈靛皻鏈缃紒`
           }
+        } else if (item.type === 'dashboard' && !item.plot.valueField) {
+          error = `缁勪欢銆�${item.name}銆嬫樉绀哄�煎皻鏈缃紒`
         }
       })
     }
diff --git a/src/views/pcdesign/index.jsx b/src/views/pcdesign/index.jsx
index ab58d77..806e36d 100644
--- a/src/views/pcdesign/index.jsx
+++ b/src/views/pcdesign/index.jsx
@@ -1345,6 +1345,8 @@
           if (!item.plot.Xaxis) {
             error = `缁勪欢銆�${item.name}銆嬪浘琛ㄥ瓧娈靛皻鏈缃紒`
           }
+        } else if (item.type === 'dashboard' && !item.plot.valueField) {
+          error = `缁勪欢銆�${item.name}銆嬫樉绀哄�煎皻鏈缃紒`
         }
       })
     }

--
Gitblit v1.8.0