From 407c0f1765c7d085218a91ad8842784977383d05 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期五, 23 十月 2020 00:18:13 +0800
Subject: [PATCH] 2020-10-23

---
 src/menu/modalconfig/controller.jsx                            |   70 +
 package-lock.json                                              |  229 ++-
 src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx |  202 +++
 src/tabviews/formtab/index.jsx                                 |    8 
 src/tabviews/formtab/actionList/index.jsx                      |   49 
 src/templates/formtabconfig/index.jsx                          |    6 
 src/menu/actioncomponent/index.jsx                             |    1 
 src/templates/zshare/verifycard/customscript/index.jsx         |    2 
 src/menu/components/chart/antv-bar/index.jsx                   |    7 
 src/menu/components/tabs/tabcomponents/index.jsx               |   26 
 src/menu/components/chart/antv-pie/chartcompile/index.scss     |   31 
 src/templates/formtabconfig/source.jsx                         |    2 
 src/menu/menushell/card.jsx                                    |   10 
 src/templates/formtabconfig/dragelement/card.jsx               |  121 +-
 src/templates/formtabconfig/index.scss                         |   91 -
 src/views/menudesign/index.jsx                                 |    2 
 src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx |   26 
 src/templates/modalconfig/index.scss                           |    7 
 src/menu/components/card/cardcellcomponent/index.jsx           |   80 +
 src/menu/components/chart/antv-pie/chartcompile/index.jsx      |  258 ++++
 src/templates/zshare/verifycard/index.jsx                      |  637 +++--------
 src/assets/mobimg/nightingale.png                              |    0 
 src/menu/components/chart/antv-pie/index.scss                  |   63 +
 src/assets/mobimg/ring.png                                     |    0 
 src/templates/formtabconfig/actionform/index.jsx               |   64 
 src/menu/components/card/data-card/index.jsx                   |   38 
 src/menu/components/chart/antv-pie/index.jsx                   |  433 ++++++++
 src/menu/modelsource/option.jsx                                |   10 
 src/menu/modalconfig/index.scss                                |    8 
 src/templates/sharecomponent/actioncomponent/index.jsx         |    1 
 src/menu/modalconfig/index.jsx                                 |  604 +---------
 package.json                                                   |    3 
 src/assets/mobimg/pie.png                                      |    0 
 src/menu/components/tabs/tabcomponents/card.jsx                |   10 
 src/menu/menushell/index.jsx                                   |   29 
 src/views/login/index.jsx                                      |   93 
 36 files changed, 1,783 insertions(+), 1,438 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 4323d73..586361c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -36,9 +36,9 @@
       }
     },
     "@antv/adjust": {
-      "version": "0.2.2",
-      "resolved": "https://registry.npmjs.org/@antv/adjust/-/adjust-0.2.2.tgz",
-      "integrity": "sha512-b5cABT0WWgKU8pfhW2ssID4FBXDBnHPuxU/HAV3nOMq1lso2BI2/r1hHnrVMZId5Dntb7YrVTOsokiD9DFZ2+w==",
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/@antv/adjust/-/adjust-0.2.3.tgz",
+      "integrity": "sha512-rihqcCdS7piQnK1nRlCvbIaj2QeaqghxINXiMpTJp+0c9cKlTUwL7/2r+gv9YN5R0P1WzSHTmK2Sn+bQCJDo0Q==",
       "requires": {
         "@antv/util": "~2.0.0",
         "tslib": "^1.10.0"
@@ -55,34 +55,45 @@
       }
     },
     "@antv/color-util": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/@antv/color-util/-/color-util-2.0.4.tgz",
-      "integrity": "sha512-CM9bIuykFTKPKbp8iDv2hHfY9QoaAOAyqFKWoV7ux1ZlFOA3KfRwcBDJtk0WlMdhzuZyhMGq0sBlxHCs9YBsVQ==",
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/@antv/color-util/-/color-util-2.0.5.tgz",
+      "integrity": "sha512-eQktA9YDnWCj03rfjpg0ajvCfRkHXzBzsZa9z94pY6Jb7e3XtPUp7vDpB8KhaKm9GjPtGzQDneh+gnqkEK8mtQ==",
       "requires": {
-        "@antv/util": "^2.0.7",
+        "@antv/util": "^2.0.9",
         "tslib": "^1.10.0"
+      },
+      "dependencies": {
+        "@antv/util": {
+          "version": "2.0.9",
+          "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.9.tgz",
+          "integrity": "sha512-JblWzne7msAPDdxkUhEk8zAz0Wd6igKwqymGbvIeyOydGrhBhGjA3nEayFj4IlG+XixCvGFKsCB4yuFS4glRIA==",
+          "requires": {
+            "tslib": "^1.10.0"
+          }
+        }
       }
     },
     "@antv/component": {
-      "version": "0.5.6",
-      "resolved": "https://registry.npmjs.org/@antv/component/-/component-0.5.6.tgz",
-      "integrity": "sha512-xT9s+gS6b8P+t/tc1ulOBxNe2nveQ0hHQWB5jyCXnpS57B9GINgwjDv0uI280PScIQCa8rkn1eRZYzV1OMeb2w==",
+      "version": "0.7.9",
+      "resolved": "https://registry.npmjs.org/@antv/component/-/component-0.7.9.tgz",
+      "integrity": "sha512-K0nephuK9+6wrR9SCcfDHLCN+C5caKaWC3V739G0ZcYAJ23616Eq5iwl2JsGnjZOebxmYqDxhwTu7csftebkKg==",
       "requires": {
         "@antv/dom-util": "~2.0.1",
-        "@antv/g-base": "~0.4.0",
-        "@antv/matrix-util": "~2.0.4",
+        "@antv/g-base": "~0.5.0",
+        "@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"
       }
     },
     "@antv/coord": {
-      "version": "0.2.7",
-      "resolved": "https://registry.npmjs.org/@antv/coord/-/coord-0.2.7.tgz",
-      "integrity": "sha512-0xfUYANsmvvvjmCm0ZuT2Bw1448Mm5EbizeBKJlPIlaV4Cf3Fz+ZdDVnRdhcVs7psSromRX+LqrjkxvT3GikLQ==",
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/@antv/coord/-/coord-0.3.0.tgz",
+      "integrity": "sha512-lm5Ct+r62mFVqhziKoDFN3PQjnkNBMOoOG+kBsPq3M3GqlQt5Jc7euOHMFcYSZM9HJmsKkGcih6EWDVVliMEZg==",
       "requires": {
-        "@antv/matrix-util": "~2.0.1-beta.1",
+        "@antv/matrix-util": "^3.1.0-beta.2",
         "@antv/util": "~2.0.3",
         "tslib": "^1.10.0"
       }
@@ -124,99 +135,83 @@
       "integrity": "sha512-6C6NJOdoNVptCr5y9BVOhKkCgW7LFs/SpcRyAExUeSjAm0zJqcqNkSIRGsXYhj4PJI+CZICHzGwwiSnIsE68Ug=="
     },
     "@antv/g-base": {
-      "version": "0.4.4",
-      "resolved": "https://registry.npmjs.org/@antv/g-base/-/g-base-0.4.4.tgz",
-      "integrity": "sha512-P5qptpFy4QiEiQsESNVxvLJsfJJkTuJyfgchP4tUv/g3Ir6xn3Hj8mFbyjesOJ4/wWyhABYTpekK0HNWr1WiXA==",
+      "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==",
       "requires": {
         "@antv/event-emitter": "^0.1.1",
-        "@antv/g-math": "^0.1.3",
-        "@antv/matrix-util": "^2.0.4",
+        "@antv/g-math": "^0.1.5",
+        "@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",
         "d3-ease": "^1.0.5",
         "d3-interpolate": "^1.3.2",
-        "d3-timer": "^1.0.9"
+        "d3-timer": "^1.0.9",
+        "detect-browser": "^5.1.0"
       }
     },
     "@antv/g-canvas": {
-      "version": "0.4.8",
-      "resolved": "https://registry.npmjs.org/@antv/g-canvas/-/g-canvas-0.4.8.tgz",
-      "integrity": "sha512-OR9n+w4sCEnTgscjEr5mk2Y48JEKfdetZiX/2rRnJXdETH3oqoogHTmrQkT5AqS2vKNdi6xErXIO/Wg2fQs1aA==",
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/@antv/g-canvas/-/g-canvas-0.5.1.tgz",
+      "integrity": "sha512-m132AyMrILm0wYTbXSlmDaz8M7OoEIvSZuW59apDS+F3jHAxsJrBvKXJjJJ26CItdIbTmeLLMcfoGIj9IzXvDw==",
       "requires": {
-        "@antv/g-base": "^0.4.4",
-        "@antv/g-math": "^0.1.3",
+        "@antv/g-base": "^0.5.1",
+        "@antv/g-math": "^0.1.5",
+        "@antv/matrix-util": "^3.1.0-beta.1",
         "@antv/path-util": "~2.0.5",
         "@antv/util": "~2.0.0",
         "gl-matrix": "^3.0.0"
       }
     },
     "@antv/g-math": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/@antv/g-math/-/g-math-0.1.3.tgz",
-      "integrity": "sha512-m4jF1Xm9bSTDLU35u3bSW9UcqJJVxU+E+bKtJgNfXUiDwHILYJey825+ApsZ8yjU7SD1kDP6GH6NTGzmChszEQ==",
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/@antv/g-math/-/g-math-0.1.5.tgz",
+      "integrity": "sha512-29B3p33jzUPIyx1xYfNCexbp7jvahD6bD8FKKyWqfYZHQbvrFfV8ZNUu66RJLfDrl0KaKT6C5whfKs/WrVaflQ==",
       "requires": {
         "@antv/util": "~2.0.0",
         "gl-matrix": "^3.0.0"
       }
     },
     "@antv/g-svg": {
-      "version": "0.4.4",
-      "resolved": "https://registry.npmjs.org/@antv/g-svg/-/g-svg-0.4.4.tgz",
-      "integrity": "sha512-oHhfT3OhckGpBNlLM+FY5l6ysA044pqJ3CQ/NNqS269PwAXqswu7GbIIDmiy6lUURtaAVgyYxbAddoCnCvZ1Kg==",
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/@antv/g-svg/-/g-svg-0.5.1.tgz",
+      "integrity": "sha512-UALLDneKlpOaAZXMIRsUjDrmuceXGR0shXwj4gv+UzIgYe/4hNxTll+1RsA+R+tYmQKAhsilhzsm3eMmPzwbtA==",
       "requires": {
-        "@antv/g-base": "^0.4.4",
-        "@antv/g-math": "^0.1.3",
+        "@antv/g-base": "^0.5.1",
+        "@antv/g-math": "^0.1.5",
         "@antv/util": "~2.0.0",
-        "detect-browser": "^4.6.0"
+        "detect-browser": "^5.0.0"
       }
     },
     "@antv/g2": {
-      "version": "4.0.7",
-      "resolved": "https://registry.npmjs.org/@antv/g2/-/g2-4.0.7.tgz",
-      "integrity": "sha512-Eacs+kehvkfuQkgWbhIpc2xlaruZtNSOAG4wzFFtskPGcTgL1mcKr6+H/ByTWYug79f8FBax4PSqdj4e+iLSNw==",
+      "version": "4.1.0-beta.13",
+      "resolved": "https://registry.npmjs.org/@antv/g2/-/g2-4.1.0-beta.13.tgz",
+      "integrity": "sha512-wmDUbeTbRKg/GZ5cP9HfaszraPgbi9lzYBbGPDjddajYKxCG25jbbGYVBMjByAkXuq7pGCXa8xixh+G4cmPcPg==",
       "requires": {
         "@antv/adjust": "^0.2.1",
         "@antv/attr": "^0.3.1",
         "@antv/color-util": "^2.0.2",
-        "@antv/component": "^0.5.0",
-        "@antv/coord": "^0.2.6",
+        "@antv/component": "^0.7.0",
+        "@antv/coord": "^0.3.0",
+        "@antv/dom-util": "^2.0.2",
         "@antv/event-emitter": "~0.1.0",
-        "@antv/g-base": "^0.4.3",
-        "@antv/g-canvas": "^0.4.0",
-        "@antv/g-svg": "^0.4.0",
-        "@antv/matrix-util": "^2.0.4",
+        "@antv/g-base": "^0.5.0",
+        "@antv/g-canvas": "^0.5.0",
+        "@antv/g-svg": "^0.5.0",
+        "@antv/matrix-util": "^3.1.0-beta.1",
         "@antv/path-util": "^2.0.3",
         "@antv/scale": "^0.3.1",
         "@antv/util": "~2.0.5",
-        "tslib": "^1.10.0"
+        "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=="
+        }
       }
-    },
-    "@antv/g2plot": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/@antv/g2plot/-/g2plot-1.0.3.tgz",
-      "integrity": "sha512-328WdD4sf9P/Q49QQDOszyOIscmmh4azXg2gYJNiULHZSLeCtEd+Car/PrL4lcfKUgL0Y4Ah5kyuC45WmHkg4g==",
-      "requires": {
-        "@antv/component": "~0.5.0",
-        "@antv/coord": "~0.2.4",
-        "@antv/dom-util": "~2.0.2",
-        "@antv/event-emitter": "~0.1.1",
-        "@antv/g-base": "~0.4.0",
-        "@antv/g-canvas": "~0.4.0",
-        "@antv/g-svg": "~0.4.0",
-        "@antv/g2": "~4.0.3",
-        "@antv/matrix-util": "~2.0.5",
-        "@antv/scale": "~0.3.1",
-        "@antv/util": "~2.0.7",
-        "d3-regression": "~1.3.4",
-        "resize-observer-polyfill": "^1.5.1",
-        "warning": "^4.0.3"
-      }
-    },
-    "@antv/gl-matrix": {
-      "version": "2.7.1",
-      "resolved": "https://registry.npmjs.org/@antv/gl-matrix/-/gl-matrix-2.7.1.tgz",
-      "integrity": "sha512-oOWcVNlpELIKi9x+Mm1Vwbz8pXfkbJKykoCIOJ/dNK79hSIANbpXJ5d3Rra9/wZqK6MC961B7sybFhPlLraT3Q=="
     },
     "@antv/hierarchy": {
       "version": "0.6.3",
@@ -227,32 +222,59 @@
       }
     },
     "@antv/matrix-util": {
-      "version": "2.0.7",
-      "resolved": "https://registry.npmjs.org/@antv/matrix-util/-/matrix-util-2.0.7.tgz",
-      "integrity": "sha512-bogifQY8jplWtSTZsPqBOdBlDdkM7IwDqYL8eMYL8OaSyOPCS7l9bnEQjQ9qTAwfCd7wHTuPoCnCpbiR8BYFvQ==",
+      "version": "3.1.0-beta.2",
+      "resolved": "https://registry.npmjs.org/@antv/matrix-util/-/matrix-util-3.1.0-beta.2.tgz",
+      "integrity": "sha512-Efwp0ZHxVDK/8RUa/RRWN7HKFHJmjn7Oq5HaNBbCmsxd7JTla3Zsoq1AZrjWMDlq0lplo77urclwI+XIW8NEHw==",
       "requires": {
-        "@antv/gl-matrix": "^2.7.1",
-        "@antv/util": "^2.0.7",
+        "@antv/util": "^2.0.9",
+        "gl-matrix": "^3.3.0",
         "tslib": "^1.10.0"
+      },
+      "dependencies": {
+        "@antv/util": {
+          "version": "2.0.9",
+          "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.9.tgz",
+          "integrity": "sha512-JblWzne7msAPDdxkUhEk8zAz0Wd6igKwqymGbvIeyOydGrhBhGjA3nEayFj4IlG+XixCvGFKsCB4yuFS4glRIA==",
+          "requires": {
+            "tslib": "^1.10.0"
+          }
+        }
       }
     },
     "@antv/path-util": {
-      "version": "2.0.7",
-      "resolved": "https://registry.npmjs.org/@antv/path-util/-/path-util-2.0.7.tgz",
-      "integrity": "sha512-1gvgPxYjQ7QGqeFLJC8C3cQd7hP+3GQSdSTKoSSW4Q7nVXdibVx8D521kJe2NkketdKLwsT8gmwJWcu+NU43+w==",
+      "version": "2.0.8",
+      "resolved": "https://registry.npmjs.org/@antv/path-util/-/path-util-2.0.8.tgz",
+      "integrity": "sha512-g5gt12MY1oEzh/j5XfLNRCfJU7E+Us+2yM5Hqc0y8xeWhb5l013XG5BPV37KmOf6WAys9KNxklNniHCZ6SqCKw==",
       "requires": {
-        "@antv/util": "^2.0.7",
+        "@antv/util": "^2.0.9",
         "tslib": "^1.10.0"
+      },
+      "dependencies": {
+        "@antv/util": {
+          "version": "2.0.9",
+          "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.9.tgz",
+          "integrity": "sha512-JblWzne7msAPDdxkUhEk8zAz0Wd6igKwqymGbvIeyOydGrhBhGjA3nEayFj4IlG+XixCvGFKsCB4yuFS4glRIA==",
+          "requires": {
+            "tslib": "^1.10.0"
+          }
+        }
       }
     },
     "@antv/scale": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/@antv/scale/-/scale-0.3.1.tgz",
-      "integrity": "sha512-bl1IAuiwVasrCpgeeT/aXYpiCiL5T3vJSWgFiRLPJeWhMGCTfsMYP/XKp6gqpD0nVj/WsF2VsoUhJG4VlyY3Pw==",
+      "version": "0.3.4",
+      "resolved": "https://registry.npmjs.org/@antv/scale/-/scale-0.3.4.tgz",
+      "integrity": "sha512-mZaf3MtMoQJtd+KAgTANVbvKpaXVpzLAFbKO/wSKaLFpnWO0bwMVDYzrs+5DZhfEfMbZpP/A7qUZ2/DLh0T3Tg==",
       "requires": {
         "@antv/util": "~2.0.3",
-        "fecha": "~3.0.3",
-        "tslib": "^1.10.0"
+        "fecha": "~4.2.0",
+        "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=="
+        }
       }
     },
     "@antv/util": {
@@ -2349,9 +2371,9 @@
       "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
     },
     "@types/d3-timer": {
-      "version": "1.0.9",
-      "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-1.0.9.tgz",
-      "integrity": "sha512-WvfJ3LFxBbWjqRGz9n7GJt08RrTHPJDVsIwwoCMROlqF+iDacYiAFjf9oqnq0mXpb2juA2N/qjKP+MKdal3YNQ=="
+      "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=="
     },
     "@types/eslint-visitor-keys": {
       "version": "1.0.0",
@@ -5359,9 +5381,9 @@
       "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A=="
     },
     "d3-color": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.0.tgz",
-      "integrity": "sha512-TzNPeJy2+iEepfiL92LAAB7fvnp/dV2YwANPVHdDWmYMm23qIJBYww3qT8I8C1wXrmrg4UWs7BKc2tKIgyjzHg=="
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz",
+      "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q=="
     },
     "d3-composite-projections": {
       "version": "1.3.2",
@@ -5393,9 +5415,9 @@
       }
     },
     "d3-ease": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.6.tgz",
-      "integrity": "sha512-SZ/lVU7LRXafqp7XtIcBdxnWl8yyLpgOmzAk0mWBI9gXNzLDx5ybZgnRbH9dN/yY5tzVBqCQ9avltSnqVwessQ=="
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz",
+      "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ=="
     },
     "d3-geo": {
       "version": "1.6.4",
@@ -5440,11 +5462,6 @@
       "version": "1.0.9",
       "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz",
       "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="
-    },
-    "d3-regression": {
-      "version": "1.3.4",
-      "resolved": "https://registry.npmjs.org/d3-regression/-/d3-regression-1.3.4.tgz",
-      "integrity": "sha512-o5nwONeooEfy+L98Ej+WPccb6LgLKtsnXLuWzXb8Ta1mN95Jy0Aw9X2TxV+S+OW+NcrBfEjxSURoSlQfVAEkrg=="
     },
     "d3-sankey": {
       "version": "0.9.1",
@@ -5718,9 +5735,9 @@
       "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
     },
     "detect-browser": {
-      "version": "4.8.0",
-      "resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-4.8.0.tgz",
-      "integrity": "sha512-f4h2dFgzHUIpjpBLjhnDIteXv8VQiUm8XzAuzQtYUqECX/eKh67ykuiVoyb7Db7a0PUSmJa3OGXStG0CbQFUVw=="
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-5.2.0.tgz",
+      "integrity": "sha512-tr7XntDAu50BVENgQfajMLzacmSe34D+qZc4zjnniz0ZVuw/TZcLcyxHQjYpJTM36sGEkZZlYLnIM1hH7alTMA=="
     },
     "detect-indent": {
       "version": "4.0.0",
@@ -8283,9 +8300,9 @@
       }
     },
     "fecha": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/fecha/-/fecha-3.0.3.tgz",
-      "integrity": "sha512-6LQK/1jud/FZnfEEZJ7y81vw7ge81DNd/XEsX0hgMUjhS+QMljkb1C0czBaP7dMNRVrd5mw/J2J7qI2Nw+TWZw=="
+      "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=="
     },
     "figgy-pudding": {
       "version": "3.5.1",
diff --git a/package.json b/package.json
index 4649cec..a7a7776 100644
--- a/package.json
+++ b/package.json
@@ -4,8 +4,7 @@
   "private": true,
   "dependencies": {
     "@antv/data-set": "^0.11.4",
-    "@antv/g2": "^4.0.7",
-    "@antv/g2plot": "^1.0.3",
+    "@antv/g2": "^4.1.0-beta.13",
     "@babel/core": "7.5.5",
     "@svgr/webpack": "4.3.2",
     "@typescript-eslint/eslint-plugin": "1.13.0",
diff --git a/src/assets/mobimg/nightingale.png b/src/assets/mobimg/nightingale.png
new file mode 100644
index 0000000..3a01a4d
--- /dev/null
+++ b/src/assets/mobimg/nightingale.png
Binary files differ
diff --git a/src/assets/mobimg/pie.png b/src/assets/mobimg/pie.png
new file mode 100644
index 0000000..a0c10a3
--- /dev/null
+++ b/src/assets/mobimg/pie.png
Binary files differ
diff --git a/src/assets/mobimg/ring.png b/src/assets/mobimg/ring.png
new file mode 100644
index 0000000..a55d575
--- /dev/null
+++ b/src/assets/mobimg/ring.png
Binary files differ
diff --git a/src/menu/actioncomponent/index.jsx b/src/menu/actioncomponent/index.jsx
index 65886d2..364806f 100644
--- a/src/menu/actioncomponent/index.jsx
+++ b/src/menu/actioncomponent/index.jsx
@@ -514,7 +514,6 @@
         >
           {card && !card.execMode && card.OpenType !== 'excelIn' && card.OpenType !== 'excelOut' ?
             <VerifyCard
-              floor={this.props.type}
               card={card}
               dict={dict}
               config={config}
diff --git a/src/menu/components/card/cardcellcomponent/index.jsx b/src/menu/components/card/cardcellcomponent/index.jsx
index 6d5917b..7853bdf 100644
--- a/src/menu/components/card/cardcellcomponent/index.jsx
+++ b/src/menu/components/card/cardcellcomponent/index.jsx
@@ -25,7 +25,6 @@
 const VerifyPrint = asyncComponent(() => import('@/menu/actioncomponent/verifyprint'))
 const VerifyExcelIn = asyncComponent(() => import('@/menu/actioncomponent/verifyexcelin'))
 const VerifyExcelOut = asyncComponent(() => import('@/menu/actioncomponent/verifyexcelout'))
-// const ModalConfig = asyncComponent(() => import('@/menu/modalconfig'))
 
 class CardCellComponent extends Component {
   static propTpyes = {
@@ -43,7 +42,7 @@
     elements: null,      // 鎸夐挳缁�
     visible: false,      // 妯℃�佹鎺у埗
     actvisible: false,   // 鎸夐挳缂栬緫妯℃�佹
-    profVisible: false
+    profVisible: false,  // 楠岃瘉淇℃伅缂栬緫
   }
 
   /**
@@ -60,6 +59,7 @@
   componentDidMount () {
     MKEmitter.addListener('cardAddElement', this.cardAddElement)
     MKEmitter.addListener('submitStyle', this.getStyle)
+    MKEmitter.addListener('submitModal', this.handleSave)
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -82,6 +82,8 @@
       return
     }
     MKEmitter.removeListener('cardAddElement', this.cardAddElement)
+    MKEmitter.removeListener('submitStyle', this.getStyle)
+    MKEmitter.removeListener('submitModal', this.handleSave)
   }
 
   cardAddElement = (ids, element) => {
@@ -406,9 +408,7 @@
     this.actionFormRef.handleConfirm().then(ele => {
       let _elements = elements.map(cell => {
         if (cell.uuid === ele.uuid) {
-          ele.eleType = 'button'
-          ele.style = cell.style || {}
-          ele.btnstyle = cell.btnstyle || {}
+          ele = {...cell, ...ele}
           return ele
         }
 
@@ -460,14 +460,12 @@
    * @description 楠岃瘉淇℃伅淇濆瓨
    */
   verifySubmit = () => {
-    const { elements } = this.state
-    
+    const { elements, card } = this.state
+
     this.verifyRef.handleConfirm().then(res => {
       let _elements = elements.map(cell => {
-        if (cell.uuid === res.uuid) {
-          res.eleType = 'button'
-          res.style = cell.style || {}
-          return res
+        if (cell.uuid === card.uuid) {
+          cell.verify = res
         }
 
         return cell
@@ -475,7 +473,7 @@
 
       this.setState({
         elements: _elements,
-        actvisible: false
+        profVisible: false
       }, () => {
         this.props.updateElement(_elements)
       })
@@ -483,7 +481,52 @@
   }
 
   handleSubConfig = (item) => {
+    const { cards } = this.props
 
+    if (item.eleType !== 'button') return
+    if (item.OpenType === 'pop') {
+      let btn = fromJS(item).toJS()
+      if (!btn.modal) {
+        btn.modal = {
+          setting: {
+            title: btn.label,
+            width: 60,
+            cols: '2',
+            container: 'tab',
+            focus: '',
+            finish: 'close',
+            clickouter: 'unclose',
+            display: 'modal'
+          },
+          tables: [],
+          groups: [],
+          fields: []
+        }
+      }
+
+      MKEmitter.emit('changeModal', cards, btn)
+    }
+  }
+
+  handleSave = (_cards, btn, modal) => {
+    const { cards } = this.props
+    const { elements } = this.state
+
+    if (cards.uuid !== _cards.uuid) return
+
+    let _elements = elements.map(cell => {
+      if (cell.uuid === btn.uuid) {
+        cell.modal = modal
+      }
+
+      return cell
+    })
+
+    this.setState({
+      elements: _elements
+    }, () => {
+      this.props.updateElement(_elements)
+    })
   }
 
   render() {
@@ -501,18 +544,6 @@
           handleSubConfig={this.handleSubConfig}
           deleteMenu={this.deleteElement}
         />
-          {/* <ModalConfig
-            menu={this.state.editMenu}
-            editTab={this.state.editTab}
-            tabConfig={this.state.tabConfig}
-            editSubTab={this.state.editSubTab}
-            subTabConfig={this.state.subTabConfig}
-            btnTab={this.state.btnTab}
-            btnTabConfig={this.state.btnTabConfig}
-            editAction={this.state.editAction}
-            subConfig={this.state.subConfig}
-            handleView={this.handleView}
-          /> */}
         {/* 缂栬緫鎸夐挳锛氬鍒躲�佺紪杈� */}
         <Modal
           title={'缂栬緫鍏冪礌'}
@@ -571,7 +602,6 @@
         >
           {card && !card.execMode && card.OpenType !== 'excelIn' && card.OpenType !== 'excelOut' ?
             <VerifyCard
-              // floor={this.props.type}
               card={card}
               dict={dict}
               config={cards}
diff --git a/src/menu/components/card/data-card/index.jsx b/src/menu/components/card/data-card/index.jsx
index 0069951..c7d9847 100644
--- a/src/menu/components/card/data-card/index.jsx
+++ b/src/menu/components/card/data-card/index.jsx
@@ -47,6 +47,33 @@
         }
       }
 
+      let subcards = null
+
+      if (card.config) {
+        subcards = JSON.parse(card.config)
+        subcards = subcards.map(scard => {
+          scard.uuid = Utils.getuuid()
+          scard.elements = scard.elements.map(elem => {
+            elem.uuid = Utils.getuuid()
+            return elem
+          })
+          scard.backElements = scard.backElements.map(elem => {
+            elem.uuid = Utils.getuuid()
+            return elem
+          })
+          return scard
+        })
+      } else {
+        subcards = [{
+          uuid: Utils.getuuid(),
+          setting: { width: 6, type: 'simple'},
+          style: {borderWidth: '1px', borderColor: '#e8e8e8', paddingTop: '15px', paddingBottom: '15px', paddingLeft: '15px', paddingRight: '15px'},
+          backStyle: {},
+          elements: [],
+          backElements: []
+        }]
+      }
+
       let _card = {
         uuid: card.uuid,
         type: card.type,
@@ -62,17 +89,10 @@
         subtype: card.subtype,
         setting: { interType: 'system' },
         wrap: { name: card.name, width: 24, addable: 'false', switch: 'false' },
-        style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' },
+        style: { marginLeft: '0px', marginRight: '0px', marginTop: '8px', marginBottom: '8px' },
         columns: [],
         scripts: [],
-        subcards: [{
-          uuid: Utils.getuuid(),
-          setting: { width: 6, type: 'simple'},
-          style: {borderWidth: '1px', borderColor: '#e8e8e8', paddingTop: '15px', paddingBottom: '15px', paddingLeft: '15px', paddingRight: '15px'},
-          backStyle: {},
-          elements: [],
-          backElements: []
-        }]
+        subcards: subcards
       }
       this.setState({
         card: _card
diff --git a/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx
index e49d7a3..98682dc 100644
--- a/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx
+++ b/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx
@@ -128,19 +128,19 @@
       initVal: card.legend || 'bottom',
       required: false,
       options: [
-        { field: 'top', label: 'top' },
-        { field: 'top-left', label: 'top-left' },
-        { field: 'top-right', label: 'top-right' },
-        { field: 'right', label: 'right' },
-        { field: 'right-top', label: 'right-top' },
-        { field: 'right-bottom', label: 'right-bottom' },
-        { field: 'left', label: 'left' },
-        { field: 'left-top', label: 'left-top' },
-        { field: 'left-bottom', label: 'left-bottom' },
-        { field: 'bottom', label: 'bottom' },
-        { field: 'bottom-left', label: 'bottom-left' },
-        { field: 'bottom-right', label: 'bottom-right' },
-        { field: 'hidden', label: 'hidden' }
+        { field: 'bottom', label: '涓�' },
+        { field: 'bottom-left', label: '涓嬪乏' },
+        { field: 'bottom-right', label: '涓嬪彸' },
+        { field: 'top', label: '涓�' },
+        { field: 'top-left', label: '涓婂乏' },
+        { field: 'top-right', label: '涓婂彸' },
+        { field: 'right', label: '鍙�' },
+        { field: 'right-top', label: '鍙充笂' },
+        { field: 'right-bottom', label: '鍙充笅' },
+        { field: 'left', label: '宸�' },
+        { field: 'left-top', label: '宸︿笂' },
+        { field: 'left-bottom', label: '宸︿笅' },
+        { field: 'hidden', label: '闅愯棌' }
       ]
     },
     {
diff --git a/src/menu/components/chart/antv-bar/index.jsx b/src/menu/components/chart/antv-bar/index.jsx
index a0656da..bdf0665 100644
--- a/src/menu/components/chart/antv-bar/index.jsx
+++ b/src/menu/components/chart/antv-bar/index.jsx
@@ -84,7 +84,11 @@
         name: _plot.name,
         subtype: card.subtype,
         setting: { interType: 'system' },
-        style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px', fontSize: '16px' },
+        style: {
+          fontSize: '16px',
+          borderWidth: '1px', borderColor: 'rgb(217, 217, 217)',
+          marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px'
+        },
         columns: [],
         scripts: [],
         search: [],
@@ -752,7 +756,6 @@
           type="chart"
           plus="false"
           config={card}
-          // setSubConfig={(_btn) => this.setSubConfig(_btn, 'button')}
           updateaction={this.updateComponent}
         />
         <div className="canvas" id={card.uuid}></div>
diff --git a/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx
new file mode 100644
index 0000000..9427926
--- /dev/null
+++ b/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx
@@ -0,0 +1,202 @@
+// import zhCN from '@/locales/zh-CN/model.js'
+// import enUS from '@/locales/en-US/model.js'
+
+// const Formdict = localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
+
+/**
+ * @description 鑾峰彇鍥捐〃瑙嗗浘閰嶇疆琛ㄥ崟
+ * @param {object} card       // 鍥捐〃瀵硅薄
+ * @param {Array}  columns    // 鏄剧ず鍒�
+ */
+export function getPieChartOptionForm (card, columns) {
+
+  let xfields = columns.filter(item => /^Nvarchar/ig.test(item.datatype))
+  let yfields = columns.filter(item => /^(Int|Decimal)/ig.test(item.datatype))
+
+  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: 'radio',
+      key: 'shape',
+      label: '褰㈢姸',
+      initVal: card.shape || 'pie',
+      required: false,
+      options: [
+        { value: 'pie', text: '楗煎浘' },
+        { value: 'ring', text: '鐜浘' },
+        { value: 'nightingale', text: '鍗椾竵鏍煎皵鍥�' }
+      ]
+    },
+    {
+      type: 'select',
+      key: 'Xaxis',
+      label: 'X-杞�',
+      initVal: card.Xaxis || '',
+      required: true,
+      options: xfields
+    },
+    {
+      type: 'select',
+      key: 'Yaxis',
+      label: 'Y-杞�',
+      initVal: card.Yaxis || '',
+      required: true,
+      options: yfields
+    },
+    {
+      type: 'select',
+      key: 'legend',
+      label: '鍥句緥浣嶇疆',
+      initVal: card.legend || 'bottom',
+      required: false,
+      options: [
+        { field: 'bottom', label: '涓�' },
+        { field: 'bottom-left', label: '涓嬪乏' },
+        { field: 'bottom-right', label: '涓嬪彸' },
+        { field: 'top', label: '涓�' },
+        { field: 'top-left', label: '涓婂乏' },
+        { field: 'top-right', label: '涓婂彸' },
+        { field: 'right', label: '鍙�' },
+        { field: 'right-top', label: '鍙充笂' },
+        { field: 'right-bottom', label: '鍙充笅' },
+        { field: 'left', label: '宸�' },
+        { field: 'left-top', label: '宸︿笂' },
+        { field: 'left-bottom', label: '宸︿笅' },
+        { field: 'hidden', label: '闅愯棌' }
+      ]
+    },
+    {
+      type: 'number',
+      key: 'radius',
+      label: '澶栫幆',
+      initVal: card.radius || 75,
+      tooltip: '鍥惧舰鎵�鍗犲尯鍩熺殑鐧惧垎鐜囥��',
+      min: 30,
+      max: 100,
+      decimal: 0,
+      required: true
+    },
+    {
+      type: 'number',
+      key: 'innerRadius',
+      label: '鍐呯幆',
+      initVal: card.innerRadius || 0,
+      tooltip: '鍐呴儴绌虹櫧鍖哄煙鍗犲浘褰㈢殑鐧惧垎鐜囥��',
+      min: 0,
+      max: 90,
+      decimal: 0,
+      hidden: !card.shape || card.shape === 'pie',
+      required: true
+    },
+    {
+      type: 'radio',
+      key: 'tooltip',
+      label: '鎻愮ず淇℃伅',
+      initVal: card.tooltip || 'true',
+      required: false,
+      options: [{
+        value: 'true',
+        text: '鏄剧ず'
+      }, {
+        value: 'false',
+        text: '闅愯棌'
+      }]
+    },
+    {
+      type: 'radio',
+      key: 'show',
+      label: '鏄剧ず鍊�',
+      initVal: card.show || 'value',
+      required: false,
+      options: [{
+        value: 'percent',
+        text: '鐧惧垎姣�'
+      }, {
+        value: 'value',
+        text: '鏁板��'
+      }]
+    },
+    {
+      type: 'radio',
+      key: 'label',
+      label: '鏍囨敞',
+      initVal: card.label || 'false',
+      required: false,
+      options: [{
+        value: 'false',
+        text: '闅愯棌'
+      }, {
+        value: 'inner',
+        text: '鍐呬晶'
+      }, {
+        value: 'outer',
+        text: '澶栦晶'
+      }]
+    }, {
+      type: 'radio',
+      key: 'repeat',
+      label: '閲嶅鏁版嵁',
+      initVal: card.repeat || 'unrepeat',
+      required: false,
+      options: [{
+        value: 'unrepeat',
+        text: '鍘婚噸'
+      }, {
+        value: 'average',
+        text: '骞冲潎'
+      }, {
+        value: 'cumsum',
+        text: '绱姞'
+      }]
+    }, {
+      type: 'color',
+      key: 'color',
+      label: '鑹茬郴',
+      initVal: card.color || 'rgba(0, 0, 0, 0.85)',
+      tooltip: '鍧愭爣杞村強绀轰緥绛夋彁绀烘枃瀛椾娇鐢ㄧ殑棰滆壊銆�',
+      required: false,
+      options: [{
+        value: 'black',
+        text: '榛戣壊'
+      }, {
+        value: 'white',
+        text: '鐧借壊'
+      }]
+    }
+  ]
+}
diff --git a/src/menu/components/chart/antv-pie/chartcompile/index.jsx b/src/menu/components/chart/antv-pie/chartcompile/index.jsx
new file mode 100644
index 0000000..c2df8d4
--- /dev/null
+++ b/src/menu/components/chart/antv-pie/chartcompile/index.jsx
@@ -0,0 +1,258 @@
+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 } from 'antd'
+
+import { getPieChartOptionForm } from './formconfig'
+import ColorSketch from '@/mob/colorsketch'
+import './index.scss'
+
+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
+  }
+
+  showDrawer = () => {
+    const { config } = this.props
+
+    this.setState({
+      visible: true,
+      plot: fromJS(config.plot).toJS(),
+      formlist: getPieChartOptionForm(config.plot, config.columns, config.setting)
+    })
+  }
+
+  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
+        })
+      })
+    }
+  }
+
+  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}/>)}
+            </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} />)}
+            </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
+  }
+
+  axisChange = (e) => {
+    const { plot } = this.state
+    let val = e.target.value
+    let fieldvalue = {}
+
+    plot.customs.forEach(item => {
+      if (this.props.form.getFieldValue(item.field + '$axis') === val) {
+        fieldvalue[item.field + '$axis'] = 'unset'
+      }
+    })
+    
+    this.props.form.setFieldsValue(fieldvalue)
+  }
+
+  enabledChange = (e) => {
+    let val = e.target.value
+
+    this.setState({enabled: val})
+  }
+
+  onSubmit = () => {
+    const { config } = this.props
+    const { plot } = this.state
+
+    this.props.form.validateFieldsAndScroll((err, values) => {
+      if (!err) {
+        let _plot = {...plot, ...values}
+        
+        this.setState({
+          plot: _plot,
+          visible: false
+        })
+
+        this.props.plotchange({...config, plot: _plot})
+      }
+    })
+  }
+
+
+  render() {
+    const { visible } = 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" 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
+        >
+          <Form {...formItemLayout}>
+            <Row gutter={16}>{this.getFields()}</Row>
+          </Form>
+        </Modal>
+      </div>
+    );
+  }
+}
+
+export default Form.create()(LineChartDrawerForm)
\ No newline at end of file
diff --git a/src/menu/components/chart/antv-pie/chartcompile/index.scss b/src/menu/components/chart/antv-pie/chartcompile/index.scss
new file mode 100644
index 0000000..0d83076
--- /dev/null
+++ b/src/menu/components/chart/antv-pie/chartcompile/index.scss
@@ -0,0 +1,31 @@
+.line-chart-drawer-form {
+  display: inline-block;
+  > .anticon-edit {
+    color: #1890ff;
+  }
+}
+.menu-chart-edit-modal {
+  .ant-modal {
+    top: 50px;
+    .ant-modal-body {
+      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;
+      }
+    }
+  }
+}
+
diff --git a/src/menu/components/chart/antv-pie/index.jsx b/src/menu/components/chart/antv-pie/index.jsx
new file mode 100644
index 0000000..2785f76
--- /dev/null
+++ b/src/menu/components/chart/antv-pie/index.jsx
@@ -0,0 +1,433 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import {connect} from 'react-redux'
+import { is, fromJS } from 'immutable'
+import { Icon, Popover } from 'antd'
+import { Chart } from '@antv/g2'
+import DataSet from '@antv/data-set'
+
+import MKEmitter from '@/utils/events.js'
+import asyncComponent from '@/utils/asyncComponent'
+import asyncIconComponent from '@/utils/asyncIconComponent'
+
+import Utils from '@/utils/utils.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 SearchComponent = asyncComponent(() => import('@/menu/searchcomponent'))
+const ChartCompileForm = asyncIconComponent(() => import('./chartcompile'))
+
+class antvBarLineChart extends Component {
+  static propTpyes = {
+    card: PropTypes.object,
+    updateConfig: PropTypes.func,
+    deletecomponent: PropTypes.func,
+  }
+
+  state = {
+    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
+    card: null,
+    eventListener: null
+  }
+
+  UNSAFE_componentWillMount () {
+    const { card, menu } = this.props
+
+    if (card.isNew) {
+      let _plot = {
+        shape: card.subtype, // 鍥捐〃绫诲瀷
+        width: 12,
+        height: 400,
+        name: card.name
+      }
+
+      let dataName = ''
+
+      if (card.floor === 1) {
+        while (!dataName) {
+          let _dataName = Utils.getdataName()
+          if (menu.components.filter(com => com.dataName === _dataName).length === 0) {
+            dataName = _dataName
+          }
+        }
+      }
+
+      let _card = {
+        uuid: card.uuid,
+        type: card.type,
+        floor: card.floor,
+        tabId: card.tabId || '',
+        parentId: card.parentId || '',
+        format: 'array',   // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡
+        pageable: false,   // 缁勪欢灞炴�� - 鏄惁鍙垎椤�
+        switchable: false, // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹�
+        dataName: dataName,
+        width: _plot.width,
+        name: _plot.name,
+        subtype: card.subtype,
+        setting: { interType: 'system' },
+        style: {
+          fontSize: '16px',
+          borderWidth: '1px', borderColor: 'rgb(217, 217, 217)',
+          marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px'
+        },
+        columns: [],
+        scripts: [],
+        search: [],
+        action: [],
+        plot: _plot
+      }
+      this.props.updateConfig(_card)
+      this.setState({
+        card: _card
+      })
+    } else {
+      this.setState({
+        card: fromJS(card).toJS()
+      })
+    }
+  }
+
+  componentDidMount () {
+    this.pierender()
+    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)
+      if (_element) {
+        _element.innerHTML = ''
+      }
+
+      setTimeout(this.pierender, 100)
+    }
+  }
+
+  getdata = (X_axis, Y_axis) => {
+    let xdata = [
+      { label: '2001', value: 41.8 },
+      { label: '2002', value: 38 },
+      { label: '2003', value: 33.7 },
+      { label: '2004', value: 30.7 },
+      { label: '2005', value: 25.8 },
+      { label: '2006', value: 31.7 },
+      { label: '2007', value: 33 },
+      { label: '2008', value: 46 },
+      { label: '2009', value: 38.3 },
+      { label: '2010', value: 28 },
+      { label: '2011', value: 42.5 },
+      { label: '2012', value: 30.3 }
+    ]
+
+    let data = xdata.map(item => {
+      return {
+        [X_axis]: item.label,
+        [Y_axis]: item.value,
+      }
+    })
+
+    return data
+  }
+
+  pierender = () => {
+    const { card } = this.state
+    let plot = {...card.plot, height: card.plot.height - 80}
+    // let color = plot.color || 'rgba(0, 0, 0, 0.85)'
+
+    let transfield = {}
+    card.columns.forEach(col => {
+      if (col.field) {
+        transfield[col.field] = col.label
+      }
+    })
+    let X_axis = plot.Xaxis || 'x'
+    let Y_axis = plot.Yaxis || 'y'
+
+    let data = this.getdata(X_axis, Y_axis)
+
+    const ds = new DataSet()
+    const dv = ds.createView().source(data)
+    
+    const chart = new Chart({
+      container: card.uuid,
+      autoFit: true,
+      height: plot.height || 400
+    })
+
+    if (plot.shape !== 'nightingale' && plot.show !== 'value') {
+      dv.transform({
+        type: 'percent',
+        field: Y_axis,
+        dimension: X_axis,
+        as: 'percent'
+      })
+
+      chart.scale('percent', {
+        formatter: (val) => {
+          val = val * 100 + '%'
+          return val
+        }
+      })
+
+      Y_axis = 'percent' // 鏄剧ず鐧惧垎姣�
+    }
+    chart.data(dv.rows)
+
+    if (plot.shape === 'nightingale') {
+      chart.coordinate('polar', {
+        innerRadius: plot.innerRadius ? (plot.innerRadius / 100) : 0,
+        radius: plot.radius ? (plot.radius / 100) : 0.75,
+      })
+    } else {
+      chart.coordinate('theta', {
+        innerRadius: plot.shape !== 'pie' && plot.innerRadius ? (plot.innerRadius / 100) : 0,
+        radius: plot.radius ? (plot.radius / 100) : 0.75,
+      })
+    }
+
+    if (!plot.legend || plot.legend === 'hidden') {
+      chart.legend(false)
+    } else if (plot.shape === 'nightingale') {
+      chart.legend(X_axis, {
+        position: plot.legend,
+      })
+    } else {
+      chart.legend({
+        position: plot.legend
+      })
+    }
+
+    if (plot.tooltip !== 'true') {
+      chart.tooltip(false)
+    } else {
+      chart.tooltip({
+        showTitle: false,
+        showMarkers: false
+      })
+    }
+
+    if (plot.shape !== 'nightingale') {
+      let _chart = chart
+        .interval()
+        .adjust('stack')
+        .position(Y_axis)
+        .color(X_axis)
+        .tooltip(`${X_axis}*${Y_axis}`, (name, value) => {
+          if (plot.show !== 'value') {
+            value = (value * 100).toFixed(2) + '%'
+          }
+          return {
+            name: name,
+            value: value
+          }
+        })
+      if (plot.label !== 'false') {
+        if (plot.label === 'inner') {
+          _chart.label(Y_axis, {
+            offset: -30,
+            content: (data) => {
+              let _label = ''
+              let _val = ''
+              if (plot.show !== 'value') {
+                _val = `${(data[Y_axis] * 100).toFixed(2)}%`
+              } else {
+                _val = `${data[Y_axis]}`
+              }
+              if (plot.label === 'inner') {
+                _label = _val
+              } else {
+                _label = `${data[X_axis]}: ${_val}`
+              }
+              return _label
+            },
+            style: {
+              textAlign: 'center',
+              fontSize: 16,
+              shadowBlur: 2,
+              shadowColor: 'rgba(0, 0, 0, .45)',
+              fill: '#fff',
+            }
+          })
+        } else {
+          _chart.label(Y_axis, {
+            layout: { type: 'pie-spider' },
+            labelHeight: 20,
+            content: (data) => {
+              let _label = ''
+              let _val = ''
+              if (plot.show !== 'value') {
+                _val = `${(data[Y_axis] * 100).toFixed(2)}%`
+              } else {
+                _val = `${data[Y_axis]}`
+              }
+              if (plot.label === 'inner') {
+                _label = _val
+              } else {
+                _label = `${data[X_axis]}: ${_val}`
+              }
+              return _label
+            },
+            labelLine: {
+              style: {
+                lineWidth: 0.5,
+              },
+            }
+          })
+        }
+      }
+      chart.interaction('element-active')
+    } else {
+      chart.axis(false)
+      chart.interaction('element-highlight')
+      let _chart = chart
+        .interval()
+        .position(`${X_axis}*${Y_axis}`)
+        .color(X_axis)
+
+        if (plot.label !== 'false') {
+          let _label = {}
+          if (plot.label === 'inner') {
+            _label = {
+              offset: -15,
+            }
+          }
+
+          _chart.label(X_axis, _label)
+          .style({
+            lineWidth: 1,
+            stroke: '#fff',
+          })
+        }
+    }
+
+    chart.render()
+  }
+
+  updateComponent = (component) => {
+    const card = fromJS(this.state.card).toJS()
+    let refresh = false
+    if (!is(fromJS(component.plot), fromJS(card.plot))) {
+      let _element = document.getElementById(card.uuid)
+      if (_element) {
+        _element.innerHTML = ''
+      }
+      refresh = true
+    }
+
+    component.width = component.plot.width
+    component.name = component.plot.name
+    
+    this.setState({
+      card: component
+    }, () => {
+      if (refresh) {
+        setTimeout(() => {
+          this.pierender()
+        }, 100)
+      }
+    })
+    this.props.updateConfig(component)
+  }
+
+  addSearch = () => {
+    const { card } = this.state
+
+    let newcard = {}
+    newcard.uuid = Utils.getuuid()
+    newcard.focus = true
+
+    newcard.label = 'label'
+    newcard.initval = ''
+    newcard.type = 'select'
+    newcard.resourceType = '0'
+    newcard.options = []
+    newcard.setAll = 'false'
+    newcard.orderType = 'asc'
+    newcard.display = 'dropdown'
+    newcard.match = '='
+
+    // 娉ㄥ唽浜嬩欢-娣诲姞鎼滅储
+    MKEmitter.emit('addSearch', card.uuid, newcard)
+  }
+
+  changeStyle = () => {
+    const { card } = this.state
+
+    MKEmitter.emit('changeStyle', [card.uuid], ['font', 'background', 'border', 'padding', 'margin'], card.style)
+  }
+
+  getStyle = (comIds, style) => {
+    const { card } = this.state
+
+    if (comIds.length !== 1 || comIds[0] !== card.uuid) return
+
+    let _card = {...card, style}
+
+    this.setState({
+      card: _card
+    })
+    
+    this.props.updateConfig(_card)
+  }
+
+  render() {
+    const { card } = this.state
+
+    return (
+      <div className="menu-pie-chart-edit-box" style={{...card.style, height: card.plot.height || 400}}>
+        <div className="chart-header">
+          <span className="chart-title">{card.plot.title || ''}</span>
+          <SearchComponent
+            config={card}
+            updatesearch={this.updateComponent}
+          />
+          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+            <div className="mk-popover-control">
+              <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" />
+              <ChartCompileForm config={card} dict={this.state.dict} plotchange={this.updateComponent}/>
+              <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" />
+              <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>
+        <div className="canvas" id={card.uuid}></div>
+      </div>
+    )
+  }
+}
+
+const mapStateToProps = (state) => {
+  return {
+    menu: state.customMenu
+  }
+}
+
+const mapDispatchToProps = () => {
+  return {}
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(antvBarLineChart)
\ No newline at end of file
diff --git a/src/menu/components/chart/antv-pie/index.scss b/src/menu/components/chart/antv-pie/index.scss
new file mode 100644
index 0000000..eb8c69b
--- /dev/null
+++ b/src/menu/components/chart/antv-pie/index.scss
@@ -0,0 +1,63 @@
+.menu-pie-chart-edit-box {
+  position: relative;
+  box-sizing: border-box;
+  background: #ffffff;
+  border-style: solid;
+  border-width: 0;
+  
+  .canvas {
+    margin: 0px;
+    padding: 15px;
+    letter-spacing: 0px;
+  }
+
+  .chart-header {
+    position: relative;
+    height: 45px;
+    border-bottom: 1px solid #e8e8e8;
+    overflow: hidden;
+    padding-right: 35px;
+    text-decoration: inherit;
+    font-weight: inherit;
+    font-style: inherit;
+
+    >.anticon-tool {
+      position: absolute;
+      right: 1px;
+      top: 1px;
+      font-size: 16px;
+      padding: 5px;
+      cursor: pointer;
+      color: rgba(0, 0, 0, 0.85);
+      background: #ffffff;
+    }
+
+    .chart-title {
+      text-decoration: inherit;
+      font-weight: inherit;
+      font-style: inherit;
+      float: left;
+      line-height: 45px;
+      margin-left: 10px;
+    }
+  }
+
+  .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-line-chart-edit-box:hover {
+  box-shadow: 0px 0px 2px #e8e8e8;
+}
diff --git a/src/menu/components/tabs/tabcomponents/card.jsx b/src/menu/components/tabs/tabcomponents/card.jsx
index c42c262..e5f121e 100644
--- a/src/menu/components/tabs/tabcomponents/card.jsx
+++ b/src/menu/components/tabs/tabcomponents/card.jsx
@@ -5,10 +5,11 @@
 import './index.scss'
 
 const AntvBar = asyncComponent(() => import('@/menu/components/chart/antv-bar'))
+const AntvPie = asyncComponent(() => import('@/menu/components/chart/antv-pie'))
 const AntvTabs = asyncComponent(() => import('@/menu/components/tabs/antv-tabs'))
 const DataCard = asyncComponent(() => import('@/menu/components/card/data-card'))
 
-const Card = ({ id, card, moveCard, findCard, delCard, hasDrop, updateConfig }) => {
+const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => {
   const originalIndex = findCard(id).index
   const [{ isDragging }, drag] = useDrag({
     item: { type: 'menu', id, originalIndex, floor: card.floor },
@@ -19,9 +20,10 @@
   const [, drop] = useDrop({
     accept: 'menu',
     canDrop: () => true,
-    drop: ({ id: draggedId, originalIndex, floor }) => {
+    drop: (item) => {
+      const { id: draggedId, originalIndex, floor } = item
       if (originalIndex === undefined) {
-        hasDrop(card)
+        item.dropTargetId = id
       } else if (draggedId && floor === card.floor) {
         if (draggedId !== id) {
           const { index: overIndex } = findCard(id)
@@ -39,6 +41,8 @@
   const getCardComponent = () => {
     if (card.type === 'bar' || card.type === 'line') {
       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 === '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 b7613f6..2608e82 100644
--- a/src/menu/components/tabs/tabcomponents/index.jsx
+++ b/src/menu/components/tabs/tabcomponents/index.jsx
@@ -11,8 +11,6 @@
 const { confirm } = Modal
 
 const Container = ({ config, handleList }) => {
-  let target = null
-
   const [cards, setCards] = useState(config.components)
   const moveCard = (id, atIndex) => {
     const { card, index } = findCard(id)
@@ -30,10 +28,6 @@
       card,
       index: cards.indexOf(card),
     }
-  }
-
-  const hasDrop = (item) => {
-    target = item
   }
 
   const updateConfig = (element) => {
@@ -93,6 +87,7 @@
         bar: '鏌辩姸鍥�',
         line: '鎶樼嚎鍥�',
         tabs: '鏍囩缁�',
+        pie: '楗煎浘',
         card: '鍗$墖'
       }
       let i = 1
@@ -111,25 +106,25 @@
         parentId: config.parentId,
         type: item.component,
         subtype: item.subtype,
+        config: item.config,
+        width: item.width || 24,
         name: name,
         floor: config.floor ? (config.floor + 1) : 2, // 缁勪欢鐨勫眰绾�
         isNew: true                                   // 鏂版坊鍔犳爣蹇楋紝鐢ㄤ簬鍒濆鍖�
       }
       
-      let targetId = cards.length > 0 ? cards[cards.length - 1].uuid : 0
-      if (target) {
-        targetId = target.uuid
+      let targetId = '0'
+
+      if (item.dropTargetId) {
+        targetId = item.dropTargetId
+      } else if (cards.length > 0) {
+        targetId = cards[cards.length - 1].uuid
       }
 
       const { index: overIndex } = findCard(`${targetId}`)
-      let targetIndex = overIndex
-
-      targetIndex++
-
-      const _cards = update(cards, { $splice: [[targetIndex, 0, newcard]] })
+      const _cards = update(cards, { $splice: [[overIndex + 1, 0, newcard]] })
 
       handleList({...config, components: _cards})
-      target = null
     }
   })
 
@@ -144,7 +139,6 @@
           moveCard={moveCard}
           delCard={deleteCard}
           findCard={findCard}
-          hasDrop={hasDrop}
           updateConfig={updateConfig}
         />
       ))}
diff --git a/src/menu/menushell/card.jsx b/src/menu/menushell/card.jsx
index 2a3ec44..e359ec6 100644
--- a/src/menu/menushell/card.jsx
+++ b/src/menu/menushell/card.jsx
@@ -5,10 +5,11 @@
 import './index.scss'
 
 const AntvBar = asyncComponent(() => import('@/menu/components/chart/antv-bar'))
+const AntvPie = asyncComponent(() => import('@/menu/components/chart/antv-pie'))
 const AntvTabs = asyncComponent(() => import('@/menu/components/tabs/antv-tabs'))
 const DataCard = asyncComponent(() => import('@/menu/components/card/data-card'))
 
-const Card = ({ id, card, moveCard, findCard, delCard, hasDrop, doubleClickCard, updateConfig }) => {
+const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => {
   const originalIndex = findCard(id).index
   const [{ isDragging }, drag] = useDrag({
     item: { type: 'menu', id, originalIndex, floor: card.floor },
@@ -19,9 +20,10 @@
   const [, drop] = useDrop({
     accept: 'menu',
     canDrop: () => true,
-    drop: ({ id: draggedId, originalIndex, floor }) => {
+    drop: (item) => {
+      const { id: draggedId, originalIndex, floor } = item
       if (originalIndex === undefined) {
-        hasDrop(card)
+        item.dropTargetId = id
       } else if (draggedId && floor === card.floor) {
         if (draggedId !== id) {
           const { index: overIndex } = findCard(id)
@@ -39,6 +41,8 @@
   const getCardComponent = () => {
     if (card.type === 'bar' || card.type === 'line') {
       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 === 'tabs') {
       return (<AntvTabs tabs={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     } else if (card.type === 'card' && card.subtype === 'datacard') {
diff --git a/src/menu/menushell/index.jsx b/src/menu/menushell/index.jsx
index f5b7a2d..a48ece6 100644
--- a/src/menu/menushell/index.jsx
+++ b/src/menu/menushell/index.jsx
@@ -10,9 +10,7 @@
 
 const { confirm } = Modal
 
-const Container = ({menu, handleList, doubleClickCard }) => {
-  let target = null
-
+const Container = ({menu, handleList }) => {
   const [cards, setCards] = useState(menu.components)
   const moveCard = (id, atIndex) => {
     const { card, index } = findCard(id)
@@ -30,10 +28,6 @@
       card,
       index: cards.indexOf(card),
     }
-  }
-
-  const hasDrop = (item) => {
-    target = item
   }
 
   const updateConfig = (element) => {
@@ -85,6 +79,7 @@
         bar: '鏌辩姸鍥�',
         line: '鎶樼嚎鍥�',
         tabs: '鏍囩缁�',
+        pie: '楗煎浘',
         card: '鍗$墖'
       }
       let i = 1
@@ -101,25 +96,25 @@
         uuid: Utils.getuuid(),
         type: item.component,
         subtype: item.subtype,
+        config: item.config,
+        width: item.width || 24,
         name: name,
         floor: 1,   // 缁勪欢鐨勫眰绾�
         isNew: true // 鏂版坊鍔犳爣蹇楋紝鐢ㄤ簬鍒濆鍖�
       }
       
-      let targetId = cards.length > 0 ? cards[cards.length - 1].uuid : 0
-      if (target) {
-        targetId = target.uuid
+      let targetId = '0'
+
+      if (item.dropTargetId) {
+        targetId = item.dropTargetId
+      } else if (cards.length > 0) {
+        targetId = cards[cards.length - 1].uuid
       }
 
       const { index: overIndex } = findCard(`${targetId}`)
-      let targetIndex = overIndex
-
-      targetIndex++
-
-      const _cards = update(cards, { $splice: [[targetIndex, 0, newcard]] })
+      const _cards = update(cards, { $splice: [[overIndex + 1, 0, newcard]] })
 
       handleList({...menu, components: _cards})
-      target = null
     }
   })
 
@@ -134,9 +129,7 @@
             moveCard={moveCard}
             delCard={deleteCard}
             findCard={findCard}
-            hasDrop={hasDrop}
             updateConfig={updateConfig}
-            doubleClickCard={doubleClickCard}
           />
         ))}
       </div>
diff --git a/src/menu/modalconfig/controller.jsx b/src/menu/modalconfig/controller.jsx
new file mode 100644
index 0000000..6cae222
--- /dev/null
+++ b/src/menu/modalconfig/controller.jsx
@@ -0,0 +1,70 @@
+import React, {Component} from 'react'
+import { is, fromJS } from 'immutable'
+
+import MKEmitter from '@/utils/events.js'
+import ModalConfig from '@/menu/modalconfig'
+
+class ModalController extends Component {
+  state = {
+    btn: null,
+    config: null,
+    visible: false
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  componentDidMount () {
+    MKEmitter.addListener('changeModal', this.initConfig)
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('changeModal', this.initConfig)
+  }
+
+  initConfig = (config, btn) => {
+    this.setState({
+      visible: true,
+      config: fromJS(config).toJS(),
+      btn: fromJS(btn).toJS()
+    })
+  }
+
+  handleBack = () => {
+    this.setState({
+      visible: false,
+      config: null,
+      btn: null
+    })
+  }
+  
+  handleSave = (modal) => {
+    const { config, btn } = this.state
+    MKEmitter.emit('submitModal', config, btn, modal)
+
+    this.setState({
+      visible: false,
+      config: null,
+      btn: null
+    })
+  }
+
+  render () {
+    const { config, btn, visible } = this.state
+
+    if (!visible) return null
+
+    return (
+      <ModalConfig btn={btn} componentConfig={config} handleBack={this.handleBack} handleSave={this.handleSave}/>
+    )
+  }
+}
+
+export default ModalController
\ No newline at end of file
diff --git a/src/menu/modalconfig/index.jsx b/src/menu/modalconfig/index.jsx
index 3f5e59e..9998550 100644
--- a/src/menu/modalconfig/index.jsx
+++ b/src/menu/modalconfig/index.jsx
@@ -5,14 +5,13 @@
 import { DndProvider } from 'react-dnd'
 import HTML5Backend from 'react-dnd-html5-backend'
 import moment from 'moment'
-import { Button, Card, Modal, Collapse, notification, Select, List, Icon, Empty, Popover } from 'antd'
+import { Button, Card, Modal, Collapse, notification, Icon, Empty, Popover } from 'antd'
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
 import zhCN from '@/locales/zh-CN/model.js'
 import enUS from '@/locales/en-US/model.js'
 import { getModalForm } from '@/templates/zshare/formconfig'
-import { queryTableSql } from '@/utils/option.js'
 
 import ModalForm from '@/templates/zshare/modalform'
 import DragElement from '@/templates/modalconfig/dragelement'
@@ -20,28 +19,19 @@
 import SettingForm from '@/templates/modalconfig/settingform'
 import GroupForm from '@/templates/modalconfig/groupform'
 import EditCard from '@/templates/modalconfig/editcard'
-import MenuForm from '@/templates/modalconfig/menuform'
 import EditComponent from '@/templates/zshare/editcomponent'
-import { BaseConfig, SearchItems } from '@/templates/modalconfig/source'
+import { SearchItems } from '@/templates/modalconfig/source'
 import './index.scss'
 
 const { Panel } = Collapse
-const { Option } = Select
 const { confirm } = Modal
 const CommonDict = localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
 
 class ComModalConfig extends Component {
   static propTpyes = {
-    menu: PropTypes.any,
-    editTab: PropTypes.any,
-    editSubTab: PropTypes.any,
-    tabConfig: PropTypes.any,
-    subTabConfig: PropTypes.any,
-    btnTab: PropTypes.any,
-    btnTabConfig: PropTypes.any,
-    editAction: PropTypes.object,
-    subConfig: PropTypes.any,
-    handleView: PropTypes.func
+    btn: PropTypes.object,
+    handleSave: PropTypes.func,
+    handleBack: PropTypes.func
   }
 
   state = {
@@ -49,14 +39,11 @@
     dict: CommonDict,      // 瀛楀吀
     config: null,          // 椤甸潰閰嶇疆锛屽寘鎷ā鏉跨被鍨嬨�佹ā鎬佹璁剧疆銆佹坊鍔犺〃鍚嶃�佽〃鍗曞垪琛�
     visible: false,        // 琛ㄥ崟缂栬緫妯℃�佹锛屾樉绀烘帶鍒�
-    modalType: null,       // 琛ㄥ崟缂栬緫绫诲瀷锛岀紪杈戞垨澶嶅埗
     tableVisible: false,   // 鏁版嵁琛ㄥ瓧娈靛垪琛ㄦā鎬佹锛屾樉绀烘帶鍒�
     tableColumns: [],      // 琛ㄦ牸瀛楁鍚嶅垪琛�
     fields: null,          // 琛ㄥ崟锛屽彲閫夊瓧娈碉紙鍘婚噸鍚庯級
-    modalformlist: null,   // 鍩烘湰淇℃伅琛ㄥ崟瀛楁
     formlist: null,        // 琛ㄥ崟缂栬緫妯℃�佹锛屽彲缂栬緫瀛楁
     card: null,            // 缂栬緫鍏冪礌
-    menuloading: false,    // 鑿滃崟淇濆瓨涓�
     closeloading: false,   // 鑿滃崟淇濆瓨涓�
     settingVisible: false, // 鍏ㄥ眬閰嶇疆妯℃�佹
     closeVisible: false,   // 鍏抽棴妯℃�佹
@@ -72,73 +59,15 @@
 
   /**
    * @description 鏁版嵁棰勫鐞�
-   * 1銆佹寜閽厤缃瓨鍦ㄦ椂浣跨敤鎸夐挳閰嶇疆锛屼笉瀛樺湪鏃朵娇鐢ㄩ粯璁ら厤缃紙绀轰緥锛�
-   * 2銆佹ā鎬佹鏍囬涓嶅瓨鍦ㄦ椂锛屼娇鐢ㄦ寜閽爣棰�
-   * 3銆佽缃凡閫夎〃
-   * 4銆佽缃寜閽熀鏈俊鎭�
    */
   UNSAFE_componentWillMount () {
-    const {menu, editAction, tabConfig, subTabConfig, subConfig} = this.props
+    const { btn } = this.props
 
-    let _config = ''
-    let _tab = subTabConfig ? subTabConfig : tabConfig
-
-    let _menu = { // 涓婄骇鑿滃崟鏄笁绾ц彍鍗曟垨鏍囩椤�
-      type: _tab ? _tab.Template : menu.type,
-      tables: _tab ? _tab.tables : menu.LongParam.tables,
-      MenuID: _tab ? _tab.uuid : menu.MenuID,
-      MenuNo: _tab ? _tab.tabNo : menu.MenuNo,
-      MenuName: _tab ? _tab.tabName : menu.MenuName
-    }
-
-    if (subConfig) {
-      _config = subConfig
-    } else {
-      _config = JSON.parse(JSON.stringify(BaseConfig))
-    }
-
-    if (!_config.setting.title) {
-      _config.setting.title = editAction.label
-    }
-
-    // 涓昏彍鍗曞凡鏈夐�夋嫨鐨勮〃鍚嶏紝妯℃�佹娌℃湁琛ㄥ悕鏃讹紝澶嶅埗涓昏彍鍗曡〃鍚�
-    _config.tables = _config.tables.length === 0 ? _menu.tables : _config.tables
-
-    let _source = JSON.parse(JSON.stringify(SearchItems))
-    if (!!this.props.editTab) {
-      _source.push({
-        type: 'form',
-        label: this.state.dict['header.form.linkMain'],
-        subType: 'linkMain',
-        url: ''
-      })
-    }
+    let _config = btn.modal
 
     this.setState({
-      openEdition: editAction.open_edition || '',
-      menu: _menu,
-      source: _source,
       config: _config,
-      selectedTables: _config.tables || [],
-      originConfig: JSON.parse(JSON.stringify(_config)),
-      modalformlist: [
-        {
-          type: 'text',
-          key: 'supMenu',
-          label: this.state.dict['model.super'] + this.state.dict['model.menu'],
-          initVal: _menu.MenuName,
-          required: true,
-          readonly: true
-        },
-        {
-          type: 'text',
-          key: 'btnName',
-          label: '鎸夐挳鍚嶇О',
-          initVal: editAction.label,
-          required: true,
-          readonly: true
-        }
-      ]
+      originConfig: fromJS(_config).toJS()
     })
   }
 
@@ -148,90 +77,7 @@
    * 2銆佹牴鎹凡閫夎〃鍚嶏紝鑾峰彇琛ㄦ牸瀛楁鍒楄〃
    */
   componentDidMount () {
-    let param = {
-      func: 'sPC_Get_SelectedList',
-      LText: queryTableSql,
-      obj_name: 'data',
-      arr_field: 'TbName,Remark'
-    }
-
-    param.LText = Utils.formatOptions(param.LText)
-    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
-
-    param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 浜戠鏁版嵁楠岃瘉
-
-    Api.getSystemConfig(param).then(res => {
-      if (res.status) {
-        this.setState({
-          tables: res.data
-        })
-      } else {
-        notification.warning({
-          top: 92,
-          message: res.message,
-          duration: 10
-        })
-      }
-    })
-
-    let deffers = this.state.selectedTables.map(item => {
-      return new Promise(resolve => {
-        Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: item.TbName}).then(res => {
-          res.TBName = item.TbName
-          resolve(res)
-        })
-      })
-    })
-
-    // 鑾峰彇瀛楁鍚庢暟鎹鐞嗭紝鏍规嵁绫诲瀷鍒嗕负text銆乶umber銆乨atetime銆乨ate
-    Promise.all(deffers).then(response => {
-      let _columns = []
-      response.forEach(res => {
-        if (res.status) {
-          let tabmsg = {
-            tableName: res.TBName,
-            columns: res.FDName.map(item => {
-              let _type = item.FieldType.toLowerCase()
-              let _decimal = 0
-              if (/^nvarchar/.test(_type)) {
-                _type = 'text'
-              } else if (/^int/.test(_type)) {
-                _type = 'number'
-              } else if (/^decimal/.test(_type)) {
-                _decimal = _type.split(',')[1]
-                _decimal = parseInt(_decimal)
-                _type = 'number'
-              } else if (/^datetime/.test(_type)) {
-                _type = 'datetime'
-              } else if (/^date/.test(_type)) {
-                _type = 'date'
-              } else {
-                _type = 'text'
-              }
-  
-              return {
-                field: item.FieldName,
-                label: item.FieldDec,
-                type: _type,
-                decimal: _decimal
-              }
-            })
-          }
-          _columns.push(tabmsg)
-        } else {
-          notification.warning({
-            top: 92,
-            message: res.message,
-            duration: 10
-          })
-        }
-      })
-
-      this.setState({
-        tableColumns: _columns
-      })
-    })
+    
   }
 
   /**
@@ -243,28 +89,6 @@
     }
   }
 
-  // 椤甸潰杩斿洖
-  handleViewBack = () => {
-    const {menu, editTab, editSubTab, tabConfig, subTabConfig, btnTab, btnTabConfig} = this.props
-
-    let _view = (subTabConfig && subTabConfig.Template) || (tabConfig && tabConfig.Template) || menu.LongParam.Template
-    
-    let param = {
-      editMenu: menu,
-      editTab: editTab,
-      tabConfig: tabConfig,
-      editSubTab: editSubTab,
-      subTabConfig: subTabConfig,
-      btnTab: btnTab,
-      btnTabConfig: btnTabConfig,
-      editAction: null,
-      subConfig: subTabConfig || tabConfig || null,
-      tabview: _view
-    }
-
-    this.props.handleView(param)
-  }
-
   /**
    * @description 琛ㄥ崟鍙樺寲
    * 1銆佽〃鍗曟嫋鎷芥坊鍔犳椂锛屾鏌ユ槸鍚﹀瓨鍦ㄧず渚嬭〃鍗曪紝濡傚瓨鍦ㄥ垯鍘婚櫎绀轰緥
@@ -272,7 +96,7 @@
    * 3銆佹柊澧炶〃鍗曟椂锛岀洿鎺ユ墦寮�缂栬緫妗�
    */
   handleList = (list, group, elementId, newcard) => {
-    let _config = JSON.parse(JSON.stringify(this.state.config))
+    let _config = fromJS(this.state.config).toJS()
 
     if (!group && !elementId) {
       // 娌℃湁鍒嗙粍鏃讹紙鎷栨嫿娣诲姞锛�
@@ -352,31 +176,9 @@
    * 2銆佷繚瀛樼紪杈戦」-card
    * 3銆佽缃紪杈戝弬鏁伴」-formlist
    */
-  handleForm = (_card, type) => {
-    const {menu, tabConfig, subTabConfig} = this.props
-    let card = JSON.parse(JSON.stringify(_card))
-
-    if (type === 'copy') {
-      card.originUuid = card.uuid
-      card.uuid = Utils.getuuid()
-      card.focus = true
-
-      // 澶嶅埗鍒板壀鍒囨澘
-      let oInput = document.createElement('input')
-      let val = JSON.parse(JSON.stringify(card))
-      val.copyType = 'form'
-      val.uuid = Utils.getuuid()
-
-      delete val.originUuid
-
-      oInput.value = window.btoa(window.encodeURIComponent(JSON.stringify(val)))
-      document.body.appendChild(oInput)
-      oInput.select()
-      document.execCommand('Copy')
-      oInput.className = 'oInput'
-      oInput.style.display = 'none'
-      document.body.removeChild(oInput)
-    }
+  handleForm = (_card) => {
+    const { componentConfig } = this.props
+    let card = fromJS(_card).toJS()
 
     const { config } = this.state
     let _inputfields = []
@@ -419,40 +221,17 @@
       }
     })
 
-    if (subTabConfig) {
-      subTabConfig.columns.forEach(col => {
-        if (col.field && !uniq.has(col.field)) {
-          uniq.set(col.field, true)
+    componentConfig.columns.forEach(col => {
+      if (col.field && !uniq.has(col.field)) {
+        uniq.set(col.field, true)
 
-          _linkableFields.push({
-            value: col.field,
-            text: col.label + ' (鏄剧ず鍒�)'
-          })
-        }
-      })
-    } else if (tabConfig) {
-      tabConfig.columns.forEach(col => {
-        if (col.field && !uniq.has(col.field)) {
-          uniq.set(col.field, true)
-
-          _linkableFields.push({
-            value: col.field,
-            text: col.label + ' (鏄剧ず鍒�)'
-          })
-        }
-      })
-    } else if (menu.LongParam) {
-      menu.LongParam.columns.forEach(col => {
-        if (col.field && !uniq.has(col.field)) {
-          uniq.set(col.field, true)
-
-          _linkableFields.push({
-            value: col.field,
-            text: col.label + ' (鏄剧ず鍒�)'
-          })
-        }
-      })
-    }
+        _linkableFields.push({
+          value: col.field,
+          text: col.label + ' (鏄剧ず鍒�)'
+        })
+      }
+    })
+    
 
     if (card.linkSubField && card.linkSubField.length > 0) {
       let fields = _inputfields.map(item => item.field)
@@ -472,7 +251,6 @@
 
     this.setState({
       visible: true,
-      modalType: type,
       card: card,
       formlist: getModalForm(card, _inputfields, _linkableFields, _linksupFields, !!this.props.editTab, roleList)
     })
@@ -485,70 +263,14 @@
    * 3銆侀�氳繃loading鍒锋柊
    */
   handleSubmit = () => {
-    const { card, modalType } = this.state
-
     this.formRef.handleConfirm().then(res => {
-      let _config = JSON.parse(JSON.stringify(this.state.config))
+      let _config = fromJS(this.state.config).toJS()
       let fieldrepet = false // 瀛楁閲嶅
       let labelrepet = false // 鎻愮ず鏂囧瓧閲嶅
 
-      if (modalType === 'copy' && card.originUuid) {
-        if (_config.groups.length > 0) {
-          _config.groups = _config.groups.map(group => {
-            let _index = null
-            group.sublist.forEach((item, index) => {
-              if (item.uuid === card.originUuid) {
-                _index = index
-              }
-
-              if (item.uuid !== res.uuid && item.field === res.field) {
-                fieldrepet = true
-              } else if (item.uuid !== res.uuid && item.label === res.label) {
-                labelrepet = true
-              }
-            })
-
-            if (_index !== null) {
-              group.sublist.splice(_index + 1, 0, res)
-            }
-
-            return group
-          })
-        } else {
-          let _index = null
-          _config.fields.forEach((item, index) => {
-            if (item.uuid === card.originUuid) {
-              _index = index
-            }
-
-            if (item.uuid !== res.uuid && item.field === res.field) {
-              fieldrepet = true
-            } else if (item.uuid !== res.uuid && item.label === res.label) {
-              labelrepet = true
-            }
-          })
-
-          _config.fields.splice(_index + 1, 0, res)
-        }
-      } else {
-        if (_config.groups.length > 0) {
-          _config.groups.forEach(group => {
-            group.sublist = group.sublist.map(item => {
-              if (item.uuid !== res.uuid && item.field === res.field) {
-                fieldrepet = true
-              } else if (item.uuid !== res.uuid && item.label === res.label) {
-                labelrepet = true
-              }
-
-              if (item.uuid === res.uuid) {
-                return res
-              } else {
-                return item
-              }
-            })
-          })
-        } else {
-          _config.fields = _config.fields.map(item => {
+      if (_config.groups.length > 0) {
+        _config.groups.forEach(group => {
+          group.sublist = group.sublist.map(item => {
             if (item.uuid !== res.uuid && item.field === res.field) {
               fieldrepet = true
             } else if (item.uuid !== res.uuid && item.label === res.label) {
@@ -561,7 +283,21 @@
               return item
             }
           })
-        }
+        })
+      } else {
+        _config.fields = _config.fields.map(item => {
+          if (item.uuid !== res.uuid && item.field === res.field) {
+            fieldrepet = true
+          } else if (item.uuid !== res.uuid && item.label === res.label) {
+            labelrepet = true
+          }
+
+          if (item.uuid === res.uuid) {
+            return res
+          } else {
+            return item
+          }
+        })
       }
 
       if (fieldrepet) {
@@ -607,7 +343,6 @@
             this.setState({
               sqlVerifing: false,
               config: _config,
-              modalType: null,
               card: null,
               visible: false
             })
@@ -622,7 +357,6 @@
       } else {
         this.setState({
           config: _config,
-          modalType: null,
           card: null,
           visible: false
         })
@@ -639,7 +373,7 @@
     confirm({
       content: `纭畾鍒犻櫎<<${card.label}>>鍚楋紵`,
       onOk() {
-        let _config = JSON.parse(JSON.stringify(_this.state.config))
+        let _config = fromJS(_this.state.config).toJS()
 
         if (_config.groups.length > 0) {
           _config.groups.forEach(group => {
@@ -658,108 +392,20 @@
   }
 
   submitConfig = () => {
-    const { editAction } = this.props
-    const { config, menu, openEdition } = this.state
+    const { config } = this.state
 
-    if ((!config.groups[0] && !config.fields[0]) || (config.fields[0] && config.fields[0].origin)) {
-      notification.warning({
-        top: 92,
-        message: '璇锋坊鍔犺〃鍗�',
-        duration: 10
-      })
-      return
-    }
-
-    let _LongParam = ''
-    let _config = {...config, tables: this.state.selectedTables}
-
-    try {
-      _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_config)))
-    } catch (e) {
-      notification.warning({
-        top: 92,
-        message: '缂栬瘧閿欒',
-        duration: 10
-      })
-      return
-    }
-
-    let param = {
-      func: 'sPC_ButtonParam_AddUpt',
-      ParentID: menu.MenuID,
-      MenuID: editAction.uuid,
-      MenuNo: menu.MenuNo,
-      Template: 'Modal',
-      MenuName: editAction.label,
-      PageParam: JSON.stringify({Template: 'Modal'}),
-      LongParam: _LongParam
-    }
-
-    if (openEdition) {
-      param.open_edition = openEdition
-    }
-
-    if (this.state.closeVisible) {
-      this.setState({
-        closeloading: true
-      })
-    } else {
-      this.setState({
-        menuloading: true
-      })
-    }
-
-    Api.getSystemConfig(param).then(response => {
-      if (response.status) {
-        this.setState({
-          openEdition: response.open_edition || '',
-          menuloading: false,
-          closeloading: false,
-          closeVisible: false,
-          originConfig: _config,
-          config: _config
-        })
-        notification.success({
-          top: 92,
-          message: '淇濆瓨鎴愬姛',
-          duration: 2
-        })
-      } else {
-        this.setState({
-          closeloading: false,
-          menuloading: false
-        })
-        notification.warning({
-          top: 92,
-          message: response.message,
-          duration: 10
-        })
-      }
-    })
+    this.props.handleSave(config)
   }
 
   cancelConfig = () => {
     const { config, originConfig } = this.state
-    let _this = this
 
-    let isOrigin = config.fields.filter(item => item.origin).length > 0
-    if (isOrigin) {
-      confirm({
-        content: '灏氭湭鎻愪氦锛岀‘瀹氭斁寮冧繚瀛樺悧锛�',
-        onOk() {
-          _this.handleViewBack()
-        },
-        onCancel() {}
+    if (!is(fromJS(config), fromJS(originConfig))) {
+      this.setState({
+        closeVisible: true
       })
     } else {
-
-      if (!is(fromJS(config), fromJS(originConfig))) {
-        this.setState({
-          closeVisible: true
-        })
-      } else {
-        this.handleViewBack()
-      }
+      this.props.handleBack()
     }
   }
 
@@ -770,8 +416,10 @@
    * 3銆佹鏌ヨ〃鍗曚腑鐨勫凡閫夊瓧娈碉紝骞舵爣璁板凡閫�
    */
   queryField = () => {
-    const {selectedTables, tableColumns, config} = this.state
-    if (selectedTables.length === 0) {
+    const { menu } = this.props
+    const { config } = this.state
+
+    if (menu.tables.length === 0) {
       notification.warning({
         top: 92,
         message: '璇烽�夋嫨琛ㄥ悕锛�',
@@ -781,7 +429,7 @@
     }
 
     let columns = new Map()
-    tableColumns.forEach(table => {
+    menu.tableFields.forEach(table => {
       table.columns.forEach(column => {
         columns.set(column.field, column)
       })
@@ -823,7 +471,7 @@
       })
     }
 
-    let _config = JSON.parse(JSON.stringify(this.state.config))
+    let _config = fromJS(this.state.config).toJS()
 
     let cards = this.refs.searchcard.state.selectCards
     let columns = new Map()
@@ -865,11 +513,6 @@
           resourceType: '0',
           setAll: 'false',
           options: [],
-          dataSource: '',
-          linkField: '',
-          valueField: '',
-          valueText: '',
-          orderBy: '',
           orderType: 'asc',
           decimal: 0,
           min: '',
@@ -912,11 +555,6 @@
             resourceType: '0',
             setAll: 'false',
             options: [],
-            dataSource: '',
-            linkField: '',
-            valueField: '',
-            valueText: '',
-            orderBy: '',
             orderType: 'asc',
             readonly: 'false',
             required: 'true'
@@ -936,79 +574,6 @@
       top: 92,
       message: '娣诲姞鎴愬姛',
       duration: 2
-    })
-  }
-
-  /**
-   * @description 娣诲姞琛ㄥ悕
-   * 1銆佽幏鍙栬〃淇℃伅
-   * 2銆佹楠屾槸鍚﹀凡缁忔坊鍔狅紝宸叉坊鍔犳椂璺宠繃
-   * 3銆侀�氳繃琛ㄥ悕鑾峰彇瀛楁闆嗭紝骞惰缃暟鎹被鍨�
-   */
-  onTableChange = (value) => {
-    const {tables, selectedTables, tableColumns} = this.state
-
-    let _table = tables.filter(item => item.TbName === value)[0]
-    let isSelected = !!selectedTables.filter(cell => cell.TbName === value)[0]
-
-    if (isSelected) return
-
-    this.setState({
-      selectedTables: [...selectedTables, _table]
-    })
-    Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: value}).then(res => {
-      if (res.status) {
-        let tabmsg = {
-          tableName: _table.name,
-          columns: res.FDName.map(item => {
-            let _type = item.FieldType.toLowerCase()
-            let _decimal = 0
-            if (/^nvarchar/.test(_type)) {
-              _type = 'text'
-            } else if (/^int/.test(_type)) {
-              _type = 'number'
-            } else if (/^decimal/.test(_type)) {
-              _decimal = _type.split(',')[1]
-              _decimal = parseInt(_decimal)
-              _type = 'number'
-            } else if (/^datetime/.test(_type)) {
-              _type = 'datetime'
-            } else if (/^date/.test(_type)) {
-              _type = 'date'
-            } else {
-              _type = 'text'
-            }
-
-            return {
-              field: item.FieldName,
-              label: item.FieldDec,
-              type: _type,
-              decimal: _decimal
-            }
-          })
-        }
-        this.setState({
-          tableColumns: [...tableColumns, tabmsg]
-        })
-      } else {
-        notification.warning({
-          top: 92,
-          message: res.message,
-          duration: 10
-        })
-      }
-    })
-  }
-
-  /**
-   * @description 鍒犻櫎琛ㄥ悕锛屽垹闄ゅ搴斿瓧娈甸泦
-   */
-  deleteTable = (table) => {
-    const {selectedTables, tableColumns} = this.state
-
-    this.setState({
-      selectedTables: selectedTables.filter(item => item.TbName !== table.TbName),
-      tableColumns: tableColumns.filter(item => item.tableName !== table.TbName)
     })
   }
 
@@ -1061,7 +626,7 @@
     confirm({
       content: `纭畾鍒犻櫎鍒嗙粍<<${group.label}>>鍚楋紵`,
       onOk() {
-        let _config = JSON.parse(JSON.stringify(_this.state.config))
+        let _config = fromJS(_this.state.config).toJS()
         _config.groups = _config.groups.filter(item => !(item.uuid === group.uuid))
         let _length = _config.groups.length
         
@@ -1081,8 +646,8 @@
   }
 
   handleGroupSave = () => {
-    let _group = JSON.parse(JSON.stringify(this.state.curgroup))
-    let config = JSON.parse(JSON.stringify(this.state.config))
+    let _group = fromJS(this.state.curgroup).toJS()
+    let config = fromJS(this.state.config).toJS()
 
     this.groupRef.handleConfirm().then(res => {
       _group = {..._group, ...res.target}
@@ -1169,54 +734,16 @@
   }
 
   render () {
-    const { config, source } = this.state
+    const { config } = this.state
 
     return (
       <div className="modal-form-board">
         <DndProvider backend={HTML5Backend}>
           <div className="tools">
             <Collapse accordion defaultActiveKey="1" bordered={false}>
-              <Panel header={this.state.dict['header.menu.basedata']} key="0" id="modal-basedata">
-                <MenuForm
-                  dict={this.state.dict}
-                  formlist={this.state.modalformlist}
-                />
-                <div className="ant-col ant-form-item-label">
-                  <label title={this.state.dict['header.menu.table.add']}>
-                    {this.state.dict['header.menu.table.add']}
-                  </label>
-                </div>
-                <Select
-                  showSearch
-                  showArrow={false}
-                  className="tables"
-                  style={{ width: '100%' }}
-                  optionFilterProp="children"
-                  value={this.state.dict['header.menu.table.placeholder']}
-                  onChange={this.onTableChange}
-                  getPopupContainer={() => document.getElementById('modal-basedata')}
-                  filterOption={(input, option) => {
-                    return option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
-                  }}
-                > 
-                  {this.state.tables.map((table, index) => (
-                    <Option key={index} title={table.TbName} value={table.TbName}>{table.Remark}</Option>
-                  ))}
-                </Select>
-                {this.state.selectedTables.length > 0 && <List
-                  size="small"
-                  bordered
-                  dataSource={this.state.selectedTables}
-                  renderItem={(item, index) => <List.Item key={index} title={item.Remark + ' (' + item.TbName + ')'}>
-                    {item.Remark + ' (' + item.TbName + ')'}
-                    <Icon type="close" onClick={() => this.deleteTable(item)}/>
-                    <div className="bottom-mask"></div>
-                  </List.Item>}
-                />}
-              </Panel>
               <Panel header={this.state.dict['header.menu.form']} key="1">
                 <div className="search-element">
-                  {source.map((item, index) => {
+                  {SearchItems.map((item, index) => {
                     return (<SourceElement key={index} content={item}/>)
                   })}
                 </div>
@@ -1229,8 +756,8 @@
             <Card title={this.state.dict['header.menu.form.configurable']} bordered={false} extra={
               <div>
                 <EditComponent dict={this.state.dict} type="form" config={this.state.config} refresh={this.updateConfig}/>
-                <Button type="primary" onClick={this.submitConfig} loading={this.state.menuloading}>{this.state.dict['model.save']}</Button>
-                <Button onClick={this.cancelConfig}>{this.state.dict['model.back']}</Button>
+                <Button type="primary" onClick={this.submitConfig}>{this.state.dict['model.confirm']}</Button>
+                <Button onClick={this.cancelConfig}>{this.state.dict['model.cancel']}</Button>
               </div>
             } style={{ width: '100%' }}>
               <Icon type="setting" onClick={this.changeSetting} />
@@ -1299,7 +826,7 @@
           </div>
         </DndProvider>
         <Modal
-          title={this.state.modalType !== 'copy' ? this.state.dict['model.edit'] : this.state.dict['header.modal.form.copy']}
+          title={this.state.dict['model.edit']}
           visible={this.state.visible}
           width={700}
           onCancel={this.editModalCancel}
@@ -1359,7 +886,7 @@
           onCancel={() => { this.setState({closeVisible: false}) }}
           footer={[
             <Button key="save" className="mk-btn mk-green" loading={this.state.closeloading} onClick={this.submitConfig}>{this.state.dict['model.save']}</Button>,
-            <Button key="confirm" className="mk-btn mk-yellow" onClick={this.handleViewBack}>{this.state.dict['model.notsave']}</Button>,
+            <Button key="confirm" className="mk-btn mk-yellow" onClick={this.props.handleBack}>{this.state.dict['model.notsave']}</Button>,
             <Button key="cancel" onClick={() => { this.setState({closeVisible: false}) }}>{this.state.dict['model.cancel']}</Button>
           ]}
           destroyOnClose
@@ -1390,7 +917,8 @@
 
 const mapStateToProps = (state) => {
   return {
-    sysRoles: state.sysRoles
+    sysRoles: state.sysRoles,
+    menu: state.customMenu
   }
 }
 
diff --git a/src/menu/modalconfig/index.scss b/src/menu/modalconfig/index.scss
index 1576160..b997e5f 100644
--- a/src/menu/modalconfig/index.scss
+++ b/src/menu/modalconfig/index.scss
@@ -132,6 +132,7 @@
           position: relative;
           z-index: 10;
           background: transparent;
+          min-height: 50px;
         }
         .ant-modal-close {
           opacity: 0.3;
@@ -150,7 +151,6 @@
           bottom: 0px;
         }
       }
-
       .modal-form {
         padding: 0px 24px;
         min-height: 87px;
@@ -236,8 +236,10 @@
       > .anticon-setting {
         position: absolute;
         font-size: 16px;
-        right: 15px;
-        top: 10px;
+        right: 5px;
+        top: 5px;
+        padding: 10px;
+        cursor: pointer;
       }
       .paste-Icon {
         position: absolute;
diff --git a/src/menu/modelsource/option.jsx b/src/menu/modelsource/option.jsx
index 0efb911..adb04f4 100644
--- a/src/menu/modelsource/option.jsx
+++ b/src/menu/modelsource/option.jsx
@@ -7,16 +7,22 @@
 import tabs from '@/assets/mobimg/tabs.png'
 import card1 from '@/assets/mobimg/card1.png'
 import card2 from '@/assets/mobimg/card2.png'
+import Pie from '@/assets/mobimg/pie.png'
+import Pie1 from '@/assets/mobimg/ring.png'
+import Pie2 from '@/assets/mobimg/nightingale.png'
 
 // const _dict =  sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
 
 // 缁勪欢閰嶇疆淇℃伅
 export const menuOptions = [
-  { type: 'menu', url: tabs, component: 'tabs', subtype: 'tabs', title: '鏍囩椤�' },
-  { type: 'menu', url: card1, component: 'card', subtype: 'datacard', title: '鏁版嵁鍗�' },
+  { type: 'menu', url: tabs, component: 'tabs', subtype: 'tabs', title: '鏍囩椤�', width: 24 },
+  { type: 'menu', url: card1, component: 'card', subtype: 'datacard', title: '鏁版嵁鍗�', config: `[{"uuid":"160135809128212dm7i29fim9ksto9od","setting":{"width":6},"style":{"paddingTop":"15px","marginTop":"4px","paddingRight":"15px","marginRight":"8px","marginLeft":"8px","backgroundColor":"rgba(255, 255, 255, 1)","borderColor":"#e8e8e8","paddingLeft":"15px","marginBottom":"4px","borderWidth":"1px","paddingBottom":"10px"},"backStyle":{},"elements":[{"datatype":"static","width":12,"marks":null,"height":1,"value":"鍏冲崟","style":{},"prefix":"","postfix":"","format":"","eleType":"text","uuid":"160231860159931untbea62sgokunc5s"},{"datatype":"dynamic","width":12,"marks":null,"style":{"color":"rgba(250, 219, 20, 1)","textAlign":"right"},"btnstyle":{},"eleType":"icon","icon":"question-circle","field":"nvarchar2","uuid":"1602318768361nv8ql4t47sgcsn88b0u"},{"datatype":"static","width":24,"marks":null,"height":1,"value":"100","style":{"fontSize":"24px","fontWeight":"500","color":"rgba(0, 0, 0, 1)"},"prefix":"","btnstyle":{},"postfix":"","format":"","eleType":"text","uuid":"1602318817884v70gtgb65ubnm8mbcvv"},{"color":"#1890ff","width":24,"marks":null,"maxValue":100,"style":{"color":"rgba(250, 140, 22, 1)","paddingTop":"20px","paddingBottom":"10px"},"btnstyle":{},"eleType":"slider","field":"int1","uuid":"16023188871233rkktuvpp1h077igrsu"},{"eleType":"splitline","width":24,"color":"#e8e8e8","uuid":"1602320017038n31bk9o831ggug0tu0b","marks":null,"style":{"marginTop":"10px","marginBottom":"10px"},"btnstyle":{}},{"datatype":"static","width":12,"marks":null,"height":1,"value":"100","style":{"marginTop":"6px"},"prefix":"鍏冲崟","btnstyle":{},"postfix":"","format":"","eleType":"text","uuid":"1602320061243drd7lf3agvn04kgr175"}],"backElements":[]}]` },
   { type: 'menu', url: card2, component: 'card', subtype: 'propcard', title: '灞炴�у崱' },
   { type: 'menu', url: line, component: 'line', subtype: 'line', title: '鎶樼嚎鍥�' },
   { type: 'menu', url: line1, component: 'line', subtype: 'line1', title: '闃舵鎶樼嚎鍥�' },
   { type: 'menu', url: bar, component: 'bar', subtype: 'bar', title: '鏌辩姸鍥�' },
   { type: 'menu', url: bar1, component: 'bar', subtype: 'bar1', title: '鏉″舰鍥�' },
+  { 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 },
 ]
diff --git a/src/tabviews/formtab/actionList/index.jsx b/src/tabviews/formtab/actionList/index.jsx
index 6d45e05..e2a213e 100644
--- a/src/tabviews/formtab/actionList/index.jsx
+++ b/src/tabviews/formtab/actionList/index.jsx
@@ -71,15 +71,41 @@
     let _primaryId = primaryId
 
     if (btn.intertype === 'inner') {
-      // 浣跨敤鍐呴儴鎺ュ彛鏃讹紝鍐呴儴鍑芥暟鍜屾暟鎹簮涓嶅彲鍚屾椂涓虹┖, 浣跨敤绯荤粺鍑芥暟鏃讹紝绫诲瀷涓嶅彲涓虹┖
-      if (!btn.innerFunc && (!btn.sql || (btn.sql && !btn.sqlType))) {
+      let param = { // 绯荤粺瀛樺偍杩囩▼
+        func: btn.innerFunc,
+        BID: ''
+      }
+
+      param[setting.primaryKey] = primaryId
+
+      formdata.forEach(_data => {
+        param[_data.key] = _data.value
+      })
+
+      if (!param[setting.primaryKey]) {
+        param[setting.primaryKey] = Utils.getguid()
+      }
+
+      _primaryId = param[setting.primaryKey]
+
+      Api.genericInterface(param).then((res) => {
+        if (res.status) {
+          this.execSuccess(btn, res, _primaryId, formdata)
+        } else {
+          this.execError(res, btn)
+        }
+        _resolve()
+      })
+    } else if (btn.intertype === 'system') {
+      // 浣跨敤绯荤粺鎺ュ彛鏃讹紝鏁版嵁婧愪笉鍙负绌�, 浣跨敤绯荤粺鍑芥暟鏃讹紝绫诲瀷涓嶅彲涓虹┖
+      if (!btn.sql || !btn.sqlType) {
         this.actionSettingError()
         _resolve()
         return
       }
 
       // 鍒涘缓鍑瘉鏃讹紝闇�瑕侀�夋嫨琛屾椂
-      if (!data && !btn.innerFunc && btn.verify && btn.verify.voucher && btn.verify.voucher.enabled) {
+      if (!data && btn.verify && btn.verify.voucher && btn.verify.voucher.enabled) {
         notification.warning({
           top: 92,
           message: '浣跨敤鍒涘缓鍑瘉鍑芥暟锛岄渶瑕侀�夋嫨琛岋紒',
@@ -93,22 +119,7 @@
         BID: ''
       }
 
-      if (btn.innerFunc) {
-        param.func = btn.innerFunc
-
-        param[setting.primaryKey] = primaryId
-
-        formdata.forEach(_data => {
-          param[_data.key] = _data.value
-        })
-
-        if (!param[setting.primaryKey]) {
-          param[setting.primaryKey] = Utils.getguid()
-        }
-
-        _primaryId = param[setting.primaryKey]
-
-      } else if (btn.sql && btn.sqlType === 'insert') { // 绯荤粺鍑芥暟娣诲姞鏃讹紝鐢熸垚uuid
+      if (btn.sql && btn.sqlType === 'insert') { // 绯荤粺鍑芥暟娣诲姞鏃讹紝鐢熸垚uuid
         param.ID = Utils.getguid()
         param.LText = Utils.getSysDefaultSql(btn, setting, formdata, param, data, logcolumns) // 鏁版嵁婧�
         
diff --git a/src/tabviews/formtab/index.jsx b/src/tabviews/formtab/index.jsx
index bafa7fd..c618b94 100644
--- a/src/tabviews/formtab/index.jsx
+++ b/src/tabviews/formtab/index.jsx
@@ -117,6 +117,14 @@
         })
       }
 
+      // 鎸夐挳绫诲瀷鍏煎
+      config.action = config.action.map(item => {
+        if (item.intertype === 'inner' && !item.innerFunc) {
+          item.intertype = 'system'
+        }
+        return item
+      })
+
       let _arrField = [config.setting.primaryKey]     // 瀛楁闆� , 榛樿娣诲姞涓婚敭
 
       config.groups.forEach(group => {
diff --git a/src/templates/formtabconfig/actionform/index.jsx b/src/templates/formtabconfig/actionform/index.jsx
index 8ff11bf..c6adf76 100644
--- a/src/templates/formtabconfig/actionform/index.jsx
+++ b/src/templates/formtabconfig/actionform/index.jsx
@@ -56,13 +56,15 @@
   UNSAFE_componentWillMount () {
     const { card } = this.props
     let _intertype = ''
-    let _options = null
     let _success = 'close'
     let _error = 'notclose'
 
     this.props.formlist.forEach(form => {
       if (form.key === 'intertype') {
         _intertype = form.initVal
+        if (card.btnType !== 'confirm') {
+          form.options = form.options.filter(op => op.value !== 'system')
+        }
       } else if (form.key === 'afterExecSuccess') {
         _success = form.initVal
       } else if (form.key === 'afterExecError') {
@@ -70,21 +72,7 @@
       }
     })
 
-    if (card.btnType === 'cancel') {
-      _options = ['label', 'OpenType', 'icon', 'class', 'execSuccess']
-    } else if (card.btnType === 'confirm') {
-      if (_intertype === 'outer') {
-        _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'interface', 'outerFunc', 'callbackFunc', 'sysInterface', 'icon', 'class', 'execSuccess', 'execError', 'afterExecSuccess', 'afterExecError']
-      } else {
-        _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'execSuccess', 'execError', 'sql', 'sqlType', 'afterExecSuccess', 'afterExecError']
-      }
-    } else {
-      if (_intertype === 'outer') {
-        _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'interface', 'outerFunc', 'callbackFunc', 'sysInterface', 'icon', 'class', 'execSuccess', 'execError', 'afterExecSuccess', 'afterExecError']
-      } else {
-        _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'execSuccess', 'execError', 'afterExecSuccess', 'afterExecError']
-      }
-    }
+    let _options = this.getOptions(card.btnType, _intertype)
 
     this.setState({
       formlist: this.props.formlist.map(item => {
@@ -144,6 +132,30 @@
     }
   }
 
+  getOptions = (btnType, intertype) => {
+    let _options = []
+
+    if (btnType === 'cancel') {
+      _options = ['label', 'OpenType', 'icon', 'class', 'execSuccess']
+    } else if (btnType === 'confirm') {
+      if (intertype === 'outer') {
+        _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'interface', 'outerFunc', 'callbackFunc', 'sysInterface', 'icon', 'class', 'execSuccess', 'execError', 'afterExecSuccess', 'afterExecError']
+      } else if (intertype === 'system') {
+        _options = ['label', 'OpenType', 'intertype', 'icon', 'class', 'execSuccess', 'execError', 'sql', 'sqlType', 'afterExecSuccess', 'afterExecError']
+      } else {
+        _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'execSuccess', 'execError', 'afterExecSuccess', 'afterExecError']
+      }
+    } else {
+      if (intertype === 'outer') {
+        _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'interface', 'outerFunc', 'callbackFunc', 'sysInterface', 'icon', 'class', 'execSuccess', 'execError', 'afterExecSuccess', 'afterExecError']
+      } else {
+        _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'execSuccess', 'execError', 'afterExecSuccess', 'afterExecError']
+      }
+    }
+
+    return _options
+  }
+
   selectChange = (key, value) => {
     if (key === 'afterExecSuccess') {
       this.setState({
@@ -188,21 +200,7 @@
     let value = e.target.value
 
     if (key === 'intertype') {
-      let _options = null
-
-      if (card.btnType === 'confirm') {
-        if (value === 'outer') {
-          _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'interface', 'outerFunc', 'callbackFunc', 'sysInterface', 'icon', 'class', 'execSuccess', 'execError', 'afterExecSuccess', 'afterExecError']
-        } else {
-          _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'execSuccess', 'execError', 'sql', 'sqlType', 'afterExecSuccess', 'afterExecError']
-        }
-      } else {
-        if (value === 'outer') {
-          _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'interface', 'outerFunc', 'callbackFunc', 'sysInterface', 'icon', 'class', 'execSuccess', 'execError', 'afterExecSuccess', 'afterExecError']
-        } else {
-          _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'execSuccess', 'execError', 'afterExecSuccess', 'afterExecError']
-        }
-      }
+      let _options = this.getOptions(card.btnType, value)
 
       this.setState({
         interType: value,
@@ -213,9 +211,9 @@
             item.readonly = false
           } else if (item.key === 'sysInterface') {
             item.initVal = 'false'
-          } else if (item.key === 'innerFunc' && card.btnType !== 'confirm' && value === 'inner') {
+          } else if (item.key === 'innerFunc' && value === 'inner') {
             item.required = true
-          } else if (item.key === 'innerFunc' && card.btnType !== 'confirm' && value === 'outer') {
+          } else if (item.key === 'innerFunc' && value === 'outer') {
             item.required = false
           }
 
diff --git a/src/templates/formtabconfig/dragelement/card.jsx b/src/templates/formtabconfig/dragelement/card.jsx
index e1014e1..5141b81 100644
--- a/src/templates/formtabconfig/dragelement/card.jsx
+++ b/src/templates/formtabconfig/dragelement/card.jsx
@@ -1,6 +1,6 @@
 import React from 'react'
 import { useDrag, useDrop } from 'react-dnd'
-import { Icon, Button, Select, DatePicker, Input, InputNumber } from 'antd'
+import { Icon, Button, Select, DatePicker, Input, InputNumber, Popover } from 'antd'
 import moment from 'moment'
 import ItemTypes from './itemtypes'
 import './index.scss'
@@ -91,66 +91,69 @@
   }
 
   return (
-    <div className="page-card" style={{ opacity: opacity}}>
-      <div ref={node => drag(drop(node))}>
-        {type === 'search' ?
-          <div className="ant-row ant-form-item">
-            <div className={'ant-col ant-form-item-label ant-col-xs-24 ' + labelCol}>
-              <label title={card.label}>{card.label}</label>
-              <Icon className="edit" title="缂栬緫" type="edit" onClick={edit} />
-              <Icon className="edit copy" title="澶嶅埗" type="copy" onClick={copy} />
-              <Icon className="edit close" title="鍒犻櫎" type="close" onClick={del} />
-            </div>
-            <div className={'ant-col ant-form-item-control-wrapper ant-col-xs-24 ' + wrapCol}>
-              {card.type === 'text' ?
-                <Input style={{marginTop: '4px'}} defaultValue={card.initval} /> : null
-              }
-              {card.type === 'number' ?
-                <InputNumber defaultValue={card.initval} precision={card.decimal} /> : null
-              }
-              {(card.type === 'multiselect' || card.type === 'select' || card.type === 'link') ?
-                <Select defaultValue={_defaultValue}></Select> : null
-              }
-              {card.type === 'date' ?
-                <DatePicker defaultValue={card.initval ? moment().subtract(card.initval, 'days') : null} /> : null
-              }
-              {card.type === 'datemonth' ?
-                <MonthPicker defaultValue={card.initval ? moment().subtract(card.initval, 'month') : null} /> : null
-              }
-              {card.type === 'datetime' ?
-                <DatePicker showTime defaultValue={card.initval ? moment().subtract(card.initval, 'days') : null} /> : null
-              }
-              {card.type === 'textarea' ?
-                <TextArea defaultValue={card.initval} autosize={{ minRows: 2, maxRows: 6 }} /> : null
-              }
-              {card.type === 'funcvar' &&
-                <Input style={{marginTop: '4px'}} defaultValue={card.linkfield} />
-              }
-              {card.type === 'fileupload' ?
-                <Button>
-                  <Icon type="upload" /> 鐐瑰嚮涓婁紶
-                </Button> : null
-              }
-              <div className="input-mask"></div>
-            </div>
-          </div> : null
+    <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+      <div className="mk-popover-control">
+        <Icon className="edit" title="缂栬緫" type="edit" onClick={edit} />
+        {type === 'search' ? <Icon className="edit copy" title="澶嶅埗" type="copy" onClick={copy} /> : null}
+        {type === 'action' && card.btnType !== 'cancel' ?
+          <Icon className="edit profile" title="鏍¢獙瑙勫垯" type="profile" onClick={profile} /> : null
         }
-        {type === 'action' ?
-          <Button
-            className={'mk-btn mk-' + card.class}
-            icon={card.icon}
-            key={card.uuid}
-          >
-            {card.label}{card.position === 'grid' && <Icon type="table" />}
-          </Button> : null
-        }
+        {type === 'search' || (type === 'action' && card.btnType !== 'confirm' && card.btnType !== 'cancel') ? <Icon className="edit close" title="鍒犻櫎" type="close" onClick={del} /> : null}
       </div>
-      {type === 'action' ? <Icon className="edit" title="缂栬緫" type="edit" onClick={edit} /> : null}
-      {type === 'action' && card.btnType !== 'cancel' ?
-        <Icon className="edit profile" title="鏍¢獙瑙勫垯" type="profile" onClick={profile} /> : null
-      }
-      {type === 'action' && card.btnType !== 'confirm' && card.btnType !== 'cancel' && <Icon className="edit close" title="鍒犻櫎" type="close" onClick={del} />}
-    </div>
+    } trigger="hover">
+      <div className="page-card" style={{ opacity: opacity}}>
+        <div ref={node => drag(drop(node))}>
+          {type === 'search' ?
+            <div className="ant-row ant-form-item">
+              <div className={'ant-col ant-form-item-label ant-col-xs-24 ' + labelCol}>
+                <label title={card.label}>{card.label}</label>
+              </div>
+              <div className={'ant-col ant-form-item-control-wrapper ant-col-xs-24 ' + wrapCol}>
+                {card.type === 'text' ?
+                  <Input style={{marginTop: '4px'}} defaultValue={card.initval} /> : null
+                }
+                {card.type === 'number' ?
+                  <InputNumber defaultValue={card.initval} precision={card.decimal} /> : null
+                }
+                {(card.type === 'multiselect' || card.type === 'select' || card.type === 'link') ?
+                  <Select defaultValue={_defaultValue}></Select> : null
+                }
+                {card.type === 'date' ?
+                  <DatePicker defaultValue={card.initval ? moment().subtract(card.initval, 'days') : null} /> : null
+                }
+                {card.type === 'datemonth' ?
+                  <MonthPicker defaultValue={card.initval ? moment().subtract(card.initval, 'month') : null} /> : null
+                }
+                {card.type === 'datetime' ?
+                  <DatePicker showTime defaultValue={card.initval ? moment().subtract(card.initval, 'days') : null} /> : null
+                }
+                {card.type === 'textarea' ?
+                  <TextArea defaultValue={card.initval} autosize={{ minRows: 2, maxRows: 6 }} /> : null
+                }
+                {card.type === 'funcvar' &&
+                  <Input style={{marginTop: '4px'}} defaultValue={card.linkfield} />
+                }
+                {card.type === 'fileupload' ?
+                  <Button>
+                    <Icon type="upload" /> 鐐瑰嚮涓婁紶
+                  </Button> : null
+                }
+                <div className="input-mask"></div>
+              </div>
+            </div> : null
+          }
+          {type === 'action' ?
+            <Button
+              className={'mk-btn mk-' + card.class}
+              icon={card.icon}
+              key={card.uuid}
+            >
+              {card.label}{card.position === 'grid' && <Icon type="table" />}
+            </Button> : null
+          }
+        </div>
+      </div>
+    </Popover>
   )
 }
 export default Card
diff --git a/src/templates/formtabconfig/index.jsx b/src/templates/formtabconfig/index.jsx
index 4fd31c3..627a566 100644
--- a/src/templates/formtabconfig/index.jsx
+++ b/src/templates/formtabconfig/index.jsx
@@ -128,6 +128,12 @@
 
     // 閰嶇疆榛樿鍊硷紝鍏煎
     _config.Template = 'FormTab'
+    _config.action = _config.action.map(item => {
+      if (item.intertype === 'inner' && !item.innerFunc) {
+        item.intertype = 'system'
+      }
+      return item
+    })
 
     this.setState({
       config: _config,
diff --git a/src/templates/formtabconfig/index.scss b/src/templates/formtabconfig/index.scss
index 9ef7485..2fe6ff6 100644
--- a/src/templates/formtabconfig/index.scss
+++ b/src/templates/formtabconfig/index.scss
@@ -253,55 +253,10 @@
                   }
                 }
               }
-              .edit {
-                position: absolute;
-                right: 100px;
-                top: -5px;
-                color: #1890ff;
-                cursor: pointer;
-                display: none;
-              }
-              .edit.close {
-                right: 60px;
-                color: #ff4d4f;
-              }
-              .edit.copy {
-                right: 80px;
-                color: #26C281;
-              }
-            }
-            .page-card:hover {
-              .edit {
-                display: inline-block;
-              }
             }
             .ant-calendar-picker {
               min-width: 100px!important;
               width: 100%;
-            }
-
-            .ant-col-6 .page-card {
-              .edit {
-                right: 60px;
-              }
-              .edit.close {
-                right: 20px;
-              }
-              .edit.copy {
-                right: 40px;
-              }
-            }
-            // 澶氳鏂囨湰
-            .ant-col-24 .textarea-line.ant-col-sm-2 {
-              .edit {
-                right: 60px;
-              }
-              .edit.close {
-                right: 20px;
-              }
-              .edit.copy {
-                right: 40px;
-              }
             }
           }
           .anticon-snippets {
@@ -325,31 +280,13 @@
         }
         .page-card {
           display: inline-block;
-          margin: 0px 0px 0px 0px;
-          padding: 15px 10px 0 0;
+          padding: 0px;
+          margin: 15px 10px 0 0;
           position: relative;
           div {
             cursor: move;
           }
-          .edit {
-            position: absolute;
-            left: 0;
-            top: 0px;
-            color: #1890ff;
-            cursor: pointer;
-            display: none;
-          }
-          .edit.profile {
-            left: 20px;
-            color: purple;
-          }
-          .edit.close {
-            left: 20px;
-            color: #ff4d4f;
-          }
-          .edit.profile + .edit.close {
-            left: 40px;
-          }
+          
           button {
             cursor: move;
             min-width: 70px;
@@ -363,11 +300,6 @@
               right: 1px;
               bottom: 0px;
             }
-          }
-        }
-        .page-card:hover {
-          .edit {
-            display: inline-block;
           }
         }
         .anticon-question-circle {
@@ -395,26 +327,9 @@
           }
           .ant-tabs-tab {
             cursor: default;
-            .edit {
-              position: absolute;
-              left: 0;
-              top: 0px;
-              color: #1890ff;
-              cursor: pointer;
-              display: none;
-            }
-            .edit.close {
-              left: 20px;
-              color: #ff4d4f;
-            }
           }
           .ant-tabs-bar {
             min-height: 55px;
-          }
-          .ant-tabs-tab:hover {
-            .edit {
-              display: inline-block;
-            }
           }
           .ant-tabs-content {
             .ant-tabs-tabpane img {
diff --git a/src/templates/formtabconfig/source.jsx b/src/templates/formtabconfig/source.jsx
index bd2b9ff..8306f96 100644
--- a/src/templates/formtabconfig/source.jsx
+++ b/src/templates/formtabconfig/source.jsx
@@ -63,7 +63,7 @@
         btnType: 'confirm',
         uuid: Utils.getuuid(),
         label: '纭畾',
-        intertype: 'inner',
+        intertype: 'system',
         innerFunc: '',
         interface: '',
         outerFunc: '',
diff --git a/src/templates/modalconfig/index.scss b/src/templates/modalconfig/index.scss
index c4c262f..6e91986 100644
--- a/src/templates/modalconfig/index.scss
+++ b/src/templates/modalconfig/index.scss
@@ -132,6 +132,7 @@
           position: relative;
           z-index: 10;
           background: transparent;
+          min-height: 50px;
         }
         .ant-modal-close {
           opacity: 0.3;
@@ -263,8 +264,10 @@
       > .anticon-setting {
         position: absolute;
         font-size: 16px;
-        right: 15px;
-        top: 10px;
+        right: 5px;
+        top: 5px;
+        padding: 10px;
+        cursor: pointer;
       }
       .paste-Icon {
         position: absolute;
diff --git a/src/templates/sharecomponent/actioncomponent/index.jsx b/src/templates/sharecomponent/actioncomponent/index.jsx
index e834674..1c9d9bc 100644
--- a/src/templates/sharecomponent/actioncomponent/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/index.jsx
@@ -900,7 +900,6 @@
         >
           {card && !card.execMode && card.OpenType !== 'excelIn' && card.OpenType !== 'excelOut' ?
             <VerifyCard
-              floor={this.props.type}
               card={card}
               dict={dict}
               config={config}
diff --git a/src/templates/zshare/verifycard/customscript/index.jsx b/src/templates/zshare/verifycard/customscript/index.jsx
index 7348876..7495890 100644
--- a/src/templates/zshare/verifycard/customscript/index.jsx
+++ b/src/templates/zshare/verifycard/customscript/index.jsx
@@ -14,6 +14,7 @@
     btn: PropTypes.object,          // 鎸夐挳淇℃伅
     usefulfields: PropTypes.string, // 鍙敤瀛楁
     initsql: PropTypes.string,      // sql鍓嶇紑
+    defaultsql: PropTypes.array,    // 榛樿sql
     systemScripts: PropTypes.array, // 绯荤粺鑴氭湰
     customScripts: PropTypes.array, // 鑷畾涔夎剼鏈�
     scriptsChange: PropTypes.func   // 琛ㄥ崟
@@ -220,6 +221,7 @@
                 onChange={this.selectScript}
                 getPopupContainer={() => document.getElementById('verify-custom-scripts')}
               >
+                <Select.Option key="default" value={this.props.defaultsql}>榛樿sql</Select.Option>
                 {systemScripts.map((option, i) =>
                   <Select.Option key={i} value={option.value}>{option.name}</Select.Option>
                 )}
diff --git a/src/templates/zshare/verifycard/index.jsx b/src/templates/zshare/verifycard/index.jsx
index bf578fe..4a557df 100644
--- a/src/templates/zshare/verifycard/index.jsx
+++ b/src/templates/zshare/verifycard/index.jsx
@@ -21,7 +21,6 @@
 
 class VerifyCard extends Component {
   static propTpyes = {
-    floor: PropTypes.any,      // 鏄惁涓哄瓙琛�
     btnTab: PropTypes.any,     // 琛ㄥ崟鏍囩椤碉紙鎸夐挳锛夊弬鏁�
     config: PropTypes.any,     // 琛ㄥ崟鏍囩椤靛弬鏁�
     dict: PropTypes.object,    // 瀛楀吀椤�
@@ -439,8 +438,8 @@
   }
 
   UNSAFE_componentWillMount() {
-    const { columns, config, card } = this.props
-    let _verify = this.props.card.verify || {}
+    const { columns, config, card, btnTab } = this.props
+    let _verify = card.verify || {}
 
     let _invalid = _verify.invalid
 
@@ -468,55 +467,123 @@
       verify: _verify
     })
 
-    // 鎸夐挳-琛ㄥ崟鏍囩椤�
-    if (this.props.card.btnType) {
+    new Promise(resolve => {
       let _fields = []
-
-      config.groups.forEach(group => {
-        _fields.push(...group.sublist)
-      })
-
+      if (config.Template === 'FormTab') {
+        config.groups.forEach(group => {
+          _fields.push(...group.sublist)
+        })
+        resolve(_fields)
+      } else if (card.modal) {
+        if (card.modal.groups && card.modal.groups.length > 0) {
+          card.modal.groups.forEach(group => {
+            _fields.push(...group.sublist)
+          })
+        } else {
+          _fields = card.modal.fields || []
+        }
+        resolve(_fields)
+      } else if (card.OpenType === 'pop') {
+        Api.getSystemConfig({
+          func: 'sPC_Get_LongParam',
+          MenuID: card.uuid
+        }).then(res => {
+          if (res.status) {
+            let _LongParam = ''
+            if (res.LongParam) {
+              try {
+                _LongParam = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
+              } catch (e) {
+                console.warn('Parse Failure')
+                _LongParam = ''
+              }
+            }
+            
+            if (!_LongParam) {
+              notification.warning({
+                top: 92,
+                message: '鏈幏鍙栧埌琛ㄥ崟淇℃伅锛岄儴鍒嗛獙璇佸皢鏃犳硶璁剧疆锛�',
+                duration: 5
+              })
+            } else {
+              if (_LongParam.groups.length > 0) {
+                _LongParam.groups.forEach(group => {
+                  _fields.push(...group.sublist)
+                })
+              } else {
+                _fields = _LongParam.fields || []
+              }
+            }
+          } else {
+            notification.warning({
+              top: 92,
+              message: res.message,
+              duration: 5
+            })
+          }
+          resolve(_fields)
+        })
+      }
+    }).then(_fields => {
       let _usefulfields = ['BID', 'ID', 'LoginUID', 'SessionUid', 'UserID', 'Appkey', 'UserName', 'FullName', 'BillCode', 'BVoucher', 'FIBVoucherDate', 'FiYear', 'ModularDetailCode']
       let _declare = ['@UserName nvarchar(50)', '@FullName nvarchar(50)', '@ErrorCode nvarchar(50)', '@retmsg nvarchar(4000)', '@BillCode nvarchar(50)', '@BVoucher nvarchar(50)', '@FIBVoucherDate nvarchar(50)', '@FiYear nvarchar(50)', '@ModularDetailCode nvarchar(50)']
       let _select = ['@UserName=\'\'', '@FullName=\'\'', '@ErrorCode=\'\'', '@retmsg=\'\'', '@BillCode=\'\'', '@BVoucher=\'\'', '@FIBVoucherDate=\'\'', '@FiYear=\'\'', '@ModularDetailCode=\'\'']
       let fieldArr = _usefulfields.map(_f => _f.toLowerCase())
+      let hasBid = false
 
+      _fields = _fields.filter(_f => _f.field)
       _fields.forEach(_f => {
-        if (_f.field) {
-          if (fieldArr.includes(_f.field.toLowerCase())) return
-          fieldArr.push(_f.field.toLowerCase())
+        if (fieldArr.includes(_f.field.toLowerCase())) return
 
-          _usefulfields.push(_f.field)
+        fieldArr.push(_f.field.toLowerCase())
 
-          let _fieldlen = _f.fieldlength || 50
+        _usefulfields.push(_f.field)
 
-          if (['textarea', 'fileupload', 'multiselect'].includes(_f.type)) {
-            _fieldlen = _f.fieldlength || 512
-          } else if (_f.type === 'number') {
-            _fieldlen = _f.decimal ? _f.decimal : 0
-          }
+        let _fieldlen = _f.fieldlength || 50
 
-          if (_fieldlen > 2048) {
-            _fieldlen = 'max'
-          }
+        if (_f.type === 'number') {
+          _fieldlen = _f.decimal ? _f.decimal : 0
+        }
 
-          let _type = `nvarchar(${_fieldlen})`
+        if (_fieldlen > 2048) {
+          _fieldlen = 'max'
+        }
 
-          if (_f.type.match(/date/ig)) {
-            _type = 'datetime'
-            _select.push(`@${_f.field}='1900-01-01'`)
-          } else if (_f.type === 'number') {
-            _type = `decimal(18,${_fieldlen})`
-            _select.push(`@${_f.field}=0`)
-          } else {
-            _select.push(`@${_f.field}=''`)
-          }
+        let _type = `nvarchar(${_fieldlen})`
 
-          _declare.push(`@${_f.field} ${_type}`)
+        if (_f.type.match(/date/ig)) {
+          _type = 'datetime'
+          _select.push(`@${_f.field}='1900-01-01'`)
+        } else if (_f.type === 'number') {
+          _type = `decimal(18,${_fieldlen})`
+          _select.push(`@${_f.field}=0`)
+        } else {
+          _select.push(`@${_f.field}=''`)
+        }
+
+        _declare.push(`@${_f.field} ${_type}`)
+
+        if (_f.field.toLowerCase() === 'bid') {
+          hasBid = true
         }
       })
 
-      if (columns && columns.length > 0 && this.props.btnTab.Ot !== 'notRequired' && this.props.btnTab.Ot !== 'requiredOnce') {
+      if (!hasBid) { // 琛ㄥ崟涓鍔燘ID
+        _fields.unshift({ uuid: 'BID', field: 'BID', label: 'BID', type: 'text' })
+      }
+
+      let hasColumn = false
+      if (columns && columns.length > 0) {
+        if (btnTab) { // 琛ㄥ崟鏍囩
+          if (btnTab.Ot !== 'notRequired' && btnTab.Ot !== 'requiredOnce') {
+            hasColumn = true
+          }
+        } else if (card.Ot !== 'notRequired' && card.Ot !== 'requiredOnce') {
+          hasColumn = true
+        }
+      }
+
+      if (hasColumn) {
         columns.forEach(_f => {
           if (!_f.field || fieldArr.includes(_f.field.toLowerCase())) return
 
@@ -524,11 +591,18 @@
 
           _usefulfields.push(_f.field)
 
-          let _fieldlen = _f.fieldlength || 50
+          if (_f.datatype) { // 鑷畾涔夊瓧娈�
+            if (/decimal/ig.test(_f.datatype)) {
+              _select.push(`@${_f.field}=0`)
+            } else {
+              _select.push(`@${_f.field}=''`)
+            }
 
-          if (_f.type === 'picture' || _f.type === 'textarea') {
-            _fieldlen = _f.fieldlength || 512
+            _declare.push(`@${_f.field} ${_f.datatype}`)
+            return
           }
+
+          let _fieldlen = _f.fieldlength || 50
 
           if (_fieldlen > 2048) {
             _fieldlen = 'max'
@@ -552,16 +626,16 @@
         })
       }
 
-      _usefulfields = _usefulfields.join(', ')
       let _sql = `Declare ${_declare.join(', ')}
         Select ${_select.join(', ')}
       `
 
       // 榛樿sql
+      let _defaultsql = ''
       let _insertsql = ''
       let _updatesql = ''
 
-      if (this.props.card.sqlType === 'insert' || this.props.card.sqlType === 'insertOrUpdate') {
+      if (card.sqlType === 'insert' || card.sqlType === 'insertOrUpdate') {
         let keys = []
         let values = []
         _fields.forEach(item => {
@@ -594,10 +668,10 @@
   
         keys = keys.join(', ')
         values = values.join(', ')
-        _insertsql = `insert into ${this.props.card.sql} (${keys}) select ${values};`
+        _insertsql = `insert into ${card.sql} (${keys}) select ${values};`
       }
       
-      if (this.props.card.sqlType === 'update' || this.props.card.sqlType === 'insertOrUpdate') {
+      if (card.sqlType === 'update' || card.sqlType === 'audit' || card.sqlType === 'insertOrUpdate') {
         let _form = []
         let _arr = []
 
@@ -608,11 +682,20 @@
           _form.push(item.field + '=@' + item.field)
         })
 
-        if (!_arr.includes('modifydate')) {
-          _form.push('modifydate=getdate()')
-        }
-        if (!_arr.includes('modifyuserid')) {
-          _form.push('modifyuserid=@userid@')
+        if (this.props.card.sqlType === 'audit') {
+          if (!_arr.includes('submitdate')) {
+            _form.push('submitdate=getdate()')
+          }
+          if (!_arr.includes('submituserid')) {
+            _form.push('submituserid=@userid@')
+          }
+        } else {
+          if (!_arr.includes('modifydate')) {
+            _form.push('modifydate=getdate()')
+          }
+          if (!_arr.includes('modifyuserid')) {
+            _form.push('modifyuserid=@userid@')
+          }
         }
 
         if (_verify.voucher && _verify.voucher.enabled) {
@@ -628,18 +711,16 @@
         }
 
         _form = _form.join(', ')
-        _updatesql = `update ${this.props.card.sql} set ${_form} where ${config.setting.primaryKey}=@ID@;`
+        _updatesql = `update ${card.sql} set ${_form} where ${config.setting.primaryKey}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
       }
 
-      let _defaultsql = ''
-
-      if (this.props.card.sqlType === 'insert') {
+      if (card.sqlType === 'insert') {
         _defaultsql = _insertsql
-      } else if (this.props.card.sqlType === 'update') {
+      } else if (card.sqlType === 'update' || card.sqlType === 'audit') {
         _defaultsql = _updatesql
-      } else if (this.props.card.sqlType === 'insertOrUpdate') {
+      } else if (card.sqlType === 'insertOrUpdate') {
         _defaultsql += `select @tbid=''
-          select @tbid='X' from ${this.props.card.sql} where ${config.setting.primaryKey}=@ID@
+          select @tbid='X' from ${card.sql} where ${config.setting.primaryKey}=@ID@
           if @tbid=''
             begin
             ${_insertsql}
@@ -649,341 +730,47 @@
             ${_updatesql}
             end
         `
-      }
-
-      this.setState({
-        fields: _fields,
-        initsql: _sql,
-        defaultsql: _defaultsql,
-        usefulfields: _usefulfields
-      }, () => {
-        this.getsysScript()
-      })
-
-      return
-    }
-
-    // 閫氱敤鎸夐挳
-    if (this.props.card.OpenType === 'pop') {
-      Api.getSystemConfig({
-        func: 'sPC_Get_LongParam',
-        MenuID: this.props.card.uuid
-      }).then(res => {
-        if (res.status) {
-          let _LongParam = ''
-          if (res.LongParam) {
-            try {
-              _LongParam = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
-            } catch (e) {
-              console.warn('Parse Failure')
-              _LongParam = ''
-            }
-          }
-  
-          if (!_LongParam) {
-            notification.warning({
-              top: 92,
-              message: '琛ㄥ崟鏈坊鍔犳垨瑙f瀽閿欒锛岃妫�鏌ヨ〃鍗曡缃紒',
-              duration: 5
-            })
-
-            this.getsysScript()
-
-            return
-          }
-          
-          let _fields = []
-          if (_LongParam.groups.length > 0) {
-            _LongParam.groups.forEach(group => {
-              _fields.push(...group.sublist)
-            })
-          } else {
-            _fields = _LongParam.fields
-          }
-
-          let _usefulfields = ['BID', 'ID', 'LoginUID', 'SessionUid', 'UserID', 'Appkey', 'UserName', 'FullName', 'BillCode', 'BVoucher', 'FIBVoucherDate', 'FiYear', 'ModularDetailCode']
-          let _declare = ['@UserName nvarchar(50)', '@FullName nvarchar(50)', '@ErrorCode nvarchar(50)', '@retmsg nvarchar(4000)', '@BillCode nvarchar(50)', '@BVoucher nvarchar(50)', '@FIBVoucherDate nvarchar(50)', '@FiYear nvarchar(50)', '@ModularDetailCode nvarchar(50)']
-          let _select = ['@UserName=\'\'', '@FullName=\'\'', '@ErrorCode=\'\'', '@retmsg=\'\'', '@BillCode=\'\'', '@BVoucher=\'\'', '@FIBVoucherDate=\'\'', '@FiYear=\'\'', '@ModularDetailCode=\'\'']
-          let hasBid = false
-          let fieldArr = _usefulfields.map(_f => _f.toLowerCase())
-          let _defaultfields = fromJS(_fields).toJS()
-
-          _fields.forEach(_f => {
-            if (_f.field) {
-              if (fieldArr.includes(_f.field.toLowerCase())) return
-              fieldArr.push(_f.field.toLowerCase())
-
-              _usefulfields.push(_f.field)
-
-              let _fieldlen = _f.fieldlength || 50
-
-              if (['textarea', 'fileupload', 'multiselect'].includes(_f.type)) {
-                _fieldlen = _f.fieldlength || 512
-              } else if (_f.type === 'number') {
-                _fieldlen = _f.decimal ? _f.decimal : 0
-              }
-
-              if (_fieldlen > 2048) {
-                _fieldlen = 'max'
-              }
-
-              let _type = `nvarchar(${_fieldlen})`
-
-              if (_f.type.match(/date/ig)) {
-                _type = 'datetime'
-                _select.push(`@${_f.field}='1900-01-01'`)
-              } else if (_f.type === 'number') {
-                _type = `decimal(18,${_fieldlen})`
-                _select.push(`@${_f.field}=0`)
-              } else {
-                _select.push(`@${_f.field}=''`)
-              }
-
-              _declare.push(`@${_f.field} ${_type}`)
-            }
-            if (_f.field && _f.field.toLowerCase() === 'bid') {
-              hasBid = true
-            }
-          })
-
-          if (this.props.floor === 'subtable' && !hasBid) { // 瀛愯〃琛ㄥ崟涓鍔燘ID
-            _fields.unshift({
-              uuid: 'BID',
-              field: 'BID',
-              label: 'BID',
-              type: 'text'
-            })
-          }
-
-          if (columns && columns.length > 0 && this.props.card.Ot !== 'notRequired' && this.props.card.Ot !== 'requiredOnce') {
-            columns.forEach(_f => {
-              if (!_f.field || fieldArr.includes(_f.field.toLowerCase())) return
-
-              fieldArr.push(_f.field.toLowerCase())
-
-              _usefulfields.push(_f.field)
-
-              let _fieldlen = _f.fieldlength || 50
-
-              if (_f.type === 'picture' || _f.type === 'textarea') {
-                _fieldlen = _f.fieldlength || 512
-              }
-
-              if (_fieldlen > 2048) {
-                _fieldlen = 'max'
-              }
-
-              let _type = `nvarchar(${_fieldlen})`
-
-              if (_f.type === 'number') {
-                _type = `decimal(18,${_f.decimal ? _f.decimal : 0})`
-              } else if (_f.type === 'picture' || _f.type === 'textarea') {
-                _type = `nvarchar(${_fieldlen})`
-              }
-
-              if (_f.type === 'number') {
-                _select.push(`@${_f.field}=0`)
-              } else {
-                _select.push(`@${_f.field}=''`)
-              }
-    
-              _declare.push(`@${_f.field} ${_type}`)
-            })
-          }
-
-          _usefulfields = _usefulfields.join(', ')
-          let _sql = `Declare ${_declare.join(', ')}
-            Select ${_select.join(', ')}
-          `
-
-          // 榛樿sql
-          let _defaultsql = ''
-
-          if (this.props.card.sqlType === 'insert') {
-            let keys = []
-            let values = []
-            _defaultfields.forEach(item => {
-              if (!item.field) return
-
-              keys.push(item.field.toLowerCase())
-              values.push('@' + item.field)
-            })
-
-            if (config.setting.primaryKey && !keys.includes(config.setting.primaryKey.toLowerCase())) {
-              keys.push(config.setting.primaryKey.toLowerCase())
-              values.push('@ID@')
-            }
-            if (!keys.includes('createuserid')) {
-              keys.push('createuserid')
-              values.push('@userid@')
-            }
-            if (!keys.includes('createuser')) {
-              keys.push('createuser')
-              values.push('@username')
-            }
-            if (!keys.includes('createstaff')) {
-              keys.push('createstaff')
-              values.push('@fullname')
-            }
-            if (!keys.includes('bid')) {
-              keys.push('bid')
-              values.push('@BID@')
-            }
-      
-            keys = keys.join(', ')
-            values = values.join(', ')
-            _defaultsql = `insert into ${this.props.card.sql} (${keys}) select ${values};`
-          } else if (this.props.card.sqlType === 'update' || this.props.card.sqlType === 'audit') {
-            let _form = []
-            let _arr = []
-
-            _defaultfields.forEach(item => {
-              if (!item.field) return
-
-              _arr.push(item.field.toLowerCase())
-              _form.push(item.field + '=@' + item.field)
-            })
-
-            if (this.props.card.sqlType === 'audit') {
-              if (!_arr.includes('submitdate')) {
-                _form.push('submitdate=getdate()')
-              }
-              if (!_arr.includes('submituserid')) {
-                _form.push('submituserid=@userid@')
-              }
-            } else {
-              if (!_arr.includes('modifydate')) {
-                _form.push('modifydate=getdate()')
-              }
-              if (!_arr.includes('modifyuserid')) {
-                _form.push('modifyuserid=@userid@')
-              }
-            }
-
-            if (_verify.voucher && _verify.voucher.enabled) {
-              if (!_arr.includes('bvoucher')) {
-                _form.push('BVoucher=@BVoucher')
-              }
-              if (!_arr.includes('fibvoucherdate')) {
-                _form.push('FIBVoucherDate=@FIBVoucherDate')
-              }
-              if (!_arr.includes('fiyear')) {
-                _form.push('FiYear=@FiYear')
-              }
-            }
-
-            _form = _form.join(', ')
-            _defaultsql = `update ${this.props.card.sql} set ${_form} where ${config.setting.primaryKey}${this.props.card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
-          }
-          
-          this.setState({
-            fields: _fields,
-            initsql: _sql,
-            defaultsql: _defaultsql,
-            usefulfields: _usefulfields
-          }, () => {
-            this.getsysScript()
-          })
-        } else {
-          notification.warning({
-            top: 92,
-            message: res.message,
-            duration: 5
-          })
-          this.getsysScript()
-        }
-      })
-    } else {
-      let _usefulfields = ['BID', 'ID', 'LoginUID', 'SessionUid', 'UserID', 'Appkey', 'UserName', 'FullName', 'BillCode', 'BVoucher', 'FIBVoucherDate', 'FiYear', 'ModularDetailCode']
-      let _declare = ['@UserName nvarchar(50)', '@FullName nvarchar(50)', '@ErrorCode nvarchar(50)', '@retmsg nvarchar(4000)', '@BillCode nvarchar(50)', '@BVoucher nvarchar(50)', '@FIBVoucherDate nvarchar(50)', '@FiYear nvarchar(50)', '@ModularDetailCode nvarchar(50)']
-      let _select = ['@UserName=\'\'', '@FullName=\'\'', '@ErrorCode=\'\'', '@retmsg=\'\'', '@BillCode=\'\'', '@BVoucher=\'\'', '@FIBVoucherDate=\'\'', '@FiYear=\'\'', '@ModularDetailCode=\'\'']
-      let fieldArr = _usefulfields.map(_f => _f.toLowerCase())
-
-      if (columns && columns.length > 0 && this.props.card.Ot !== 'notRequired' && this.props.card.Ot !== 'requiredOnce') {
-        columns.forEach(_f => {
-          if (!_f.field || fieldArr.includes(_f.field.toLowerCase())) return
-
-          fieldArr.push(_f.field.toLowerCase())
-
-          _usefulfields.push(_f.field)
-
-          let _fieldlen = _f.fieldlength || 50
-
-          if (_f.type === 'picture' || _f.type === 'textarea') {
-            _fieldlen = _f.fieldlength || 512
-          }
-
-          if (_fieldlen > 2048) {
-            _fieldlen = 'max'
-          }
-
-          let _type = `nvarchar(${_fieldlen})`
-
-          if (_f.type === 'number') {
-            _type = `decimal(18,${_f.decimal ? _f.decimal : 0})`
-          } else if (_f.type === 'picture' || _f.type === 'textarea') {
-            _type = `nvarchar(${_fieldlen})`
-          }
-
-          if (_f.type === 'number') {
-            _select.push(`@${_f.field}=0`)
-          } else {
-            _select.push(`@${_f.field}=''`)
-          }
-
-          _declare.push(`@${_f.field} ${_type}`)
-        })
-      }
-
-      _usefulfields = _usefulfields.join(', ')
-      let _sql = `Declare ${_declare.join(', ')}
-        Select ${_select.join(', ')}
-      `
-
-      // 榛樿sql
-      let _defaultsql = ''
-
-      if (this.props.card.sqlType === 'LogicDelete') {
-        _defaultsql = `update ${this.props.card.sql} set deleted=1,modifydate=getdate(),modifyuserid=@userid@ where ${config.setting.primaryKey}${this.props.card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
-      } else if (this.props.card.sqlType === 'delete') {
+      } else if (card.sqlType === 'LogicDelete') {
+        _defaultsql = `update ${card.sql} set deleted=1,modifydate=getdate(),modifyuserid=@userid@ where ${config.setting.primaryKey}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
+      } else if (card.sqlType === 'delete') {
         let _msg = ''
-        if (columns && columns.length > 0 && this.props.card.Ot !== 'notRequired' && this.props.card.Ot !== 'requiredOnce') {
+        if (columns && columns.length > 0 && card.Ot !== 'notRequired' && card.Ot !== 'requiredOnce') {
           let _index = 0
           columns.forEach(col => {
-            if (col.field && col.Hide !== 'true' && _index < 4) {
-              _msg += col.label + '=\'\','
-              _index++
-            }
+            if (!col.field || col.Hide === 'true' || _index >= 4) return
+
+            _msg += col.label + '=\'\','
+            _index++
           })
         }
-        _defaultsql += `insert into snote (remark,createuserid,CreateUser,CreateStaff) select left('鍒犻櫎琛�:${this.props.card.sql} 鏁版嵁: ${_msg}${config.setting.primaryKey}='+@ID@,200),@userid@,@username,@fullname delete ${this.props.card.sql} where ${config.setting.primaryKey}${this.props.card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
+        _defaultsql += `insert into snote (remark,createuserid,CreateUser,CreateStaff) select left('鍒犻櫎琛�:${card.sql} 鏁版嵁: ${_msg}${config.setting.primaryKey}='+@ID@,200),@userid@,@username,@fullname delete ${card.sql} where ${config.setting.primaryKey}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
       }
 
+      let _columns = []
+      if (columns) {
+        _columns = fromJS(columns).toJS()
+        let hasbid = false
+        _columns = _columns.filter(col => {
+          if (col.field.toLowerCase() === 'bid') {
+            hasbid = true
+          }
+
+          return !!col.field
+        })
+
+        if (!hasbid) {
+          _columns.unshift({ uuid: 'BID', field: 'BID', label: 'BID', type: 'text' })
+        }
+      }
+      
       this.setState({
+        fields: _fields,
+        columnsFields: _columns,
         initsql: _sql,
         defaultsql: _defaultsql,
-        usefulfields: _usefulfields
-      }, () => {
-        this.getsysScript()
+        usefulfields: _usefulfields.join(', ')
       })
-    }
-
-    if (this.props.card.Ot === 'requiredOnce') {
-      let _columns = fromJS(config.columns).toJS()
-      _columns = _columns.filter(col => col.field)
-
-      if (this.props.floor === 'subtable' && _columns.filter(col => col.field.toLowerCase() === 'bid').length === 0) { // 瀛愯〃琛ㄥ崟涓鍔燘ID
-        _columns.unshift({
-          uuid: 'BID',
-          field: 'BID',
-          label: 'BID',
-          type: 'text'
-        })
-      }
-      this.setState({
-        columnsFields: _columns
-      })
-    }
+    })
   }
 
   componentDidMount() {
@@ -1012,6 +799,11 @@
         obj_name: 'noteCodes',
         arr_field: 'templatecode,describe',
         LText: window.btoa(window.encodeURIComponent(`select templatecode,'['+SignName+']'+describe as describe from (select * from bd_msn_sms_temp where  deleted=0 and TypeDesc='QX' and status=20 ) t inner join (select openid from susers where uid=@userid@) u on t.openid =t.openid`))
+      },
+      {
+        obj_name: 'scripts',
+        arr_field: 'funcname,longparam',
+        LText: window.btoa(window.encodeURIComponent(`Select distinct func+Remark as funcname,longparam, s.Sort from s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`))
       }
     ]
 
@@ -1028,7 +820,6 @@
     mutilparam.LText = Utils.formatOptions(mutilparam.LText)
     mutilparam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
     mutilparam.secretkey = Utils.encrypt(mutilparam.LText, mutilparam.timestamp)
-
     mutilparam.open_key = Utils.encryptOpenKey(mutilparam.secretkey, mutilparam.timestamp)
 
     Api.getCloudCacheConfig(mutilparam).then(res => {
@@ -1043,58 +834,13 @@
               name: item.describe,
               value: item.templatecode
             }
+          }),
+          systemScripts: res.scripts.map(item => {
+            return {
+              name: item.funcname,
+              value: Utils.UnformatOptions(item.longparam)
+            }
           })
-        })
-      } else {
-        notification.warning({
-          top: 92,
-          message: res.message,
-          duration: 5
-        })
-      }
-    })
-  }
-
-  getsysScript = () => {
-    const { defaultsql } = this.state
-
-    let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from聽 s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
-
-    _scriptSql = Utils.formatOptions(_scriptSql)
-
-    let _sParam = {
-      func: 'sPC_Get_SelectedList',
-      LText: _scriptSql,
-      obj_name: 'data',
-      arr_field: 'funcname,longparam'
-    }
-    
-    _sParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-    _sParam.secretkey = Utils.encrypt(_sParam.LText, _sParam.timestamp)
-    _sParam.open_key = Utils.encryptOpenKey(_sParam.secretkey, _sParam.timestamp) // 浜戠鏁版嵁楠岃瘉
-    
-    Api.getCloudCacheConfig(_sParam).then(res => {
-      if (res.status) {
-        let _scripts = []
-
-        if (defaultsql) {
-          _scripts.push({
-            name: '榛樿sql',
-            value: defaultsql
-          })
-        }
-
-        res.data.forEach(item => {
-          let _item = {
-            name: item.funcname,
-            value: Utils.UnformatOptions(item.longparam)
-          }
-
-          _scripts.push(_item)
-        })
-
-        this.setState({
-          systemScripts: _scripts
         })
       } else {
         notification.warning({
@@ -1122,9 +868,7 @@
       verify.uniques.push(values)
     }
 
-    this.setState({
-      verify: verify
-    })
+    this.setState({ verify })
   }
 
   contrastChange = (values) => {
@@ -1143,9 +887,7 @@
       verify.contrasts.push(values)
     }
 
-    this.setState({
-      verify: verify
-    })
+    this.setState({ verify })
   }
 
   customChange = (values) => {
@@ -1164,9 +906,7 @@
       verify.customverifys.push(values)
     }
 
-    this.setState({
-      verify: verify
-    })
+    this.setState({ verify })
   }
 
   scriptsChange = (values) => {
@@ -1185,9 +925,7 @@
       verify.scripts.push(values)
     }
 
-    this.setState({
-      verify: verify
-    })
+    this.setState({ verify })
   }
 
   orderChange = (values) => {
@@ -1206,9 +944,7 @@
       verify.billcodes.push(values)
     }
 
-    this.setState({
-      verify: verify
-    })
+    this.setState({ verify })
   }
 
   onNoteCodeChange = (val) => {
@@ -1243,7 +979,7 @@
       verify.contrasts = verify.contrasts.filter(item => item.uuid !== record.uuid)
     }
 
-    this.setState({ verify: verify })
+    this.setState({ verify })
   }
 
   handleEdit = (record, type) => {
@@ -1321,9 +1057,7 @@
       })
     }
 
-    this.setState({
-      verify: verify
-    })
+    this.setState({ verify })
   }
 
   handleUpDown = (record, type, direction) => {
@@ -1417,9 +1151,7 @@
       }
     }
 
-    this.setState({
-      verify: verify
-    })
+    this.setState({ verify })
   }
 
   voucherChange = (voucher) => {
@@ -1753,6 +1485,7 @@
               dict={this.props.dict}
               btn={this.props.card}
               customScripts={verify.scripts}
+              defaultsql={this.state.defaultsql}
               systemScripts={this.state.systemScripts}
               scriptsChange={this.scriptsChange}
               wrappedComponentRef={(inst) => this.scriptsForm = inst}
diff --git a/src/views/login/index.jsx b/src/views/login/index.jsx
index 318cb49..ff7281e 100644
--- a/src/views/login/index.jsx
+++ b/src/views/login/index.jsx
@@ -170,57 +170,66 @@
   componentDidMount () {
     const timeStamp = new Date().getTime()
     const _authUrl = window.location.href.split('#')[0] + 'AuthCode'
-    let _appId = window.GLOB.appId
 
-    if (options.sysType === 'cloud') { // 浜戠浣跨敤绯荤粺閰嶇疆appid
-      _appId = options.caId
+    let authCode = localStorage.getItem(_authUrl)
+    let _s = md5('mksoft' + moment().format('YYYYMMDD'))
+    authCode = authCode ? authCode.split(',') : []
+    let index = authCode.findIndex(key => key === _s)
+
+    if (index > -1) {
+      this.setState({
+        auth: true
+      })
     }
 
-    let str = md5('MK19' + _appId + timeStamp)
-
-    let param = {
-      rduri: 'http://minkesoft.com/mksepc/webapi/dostars',
-      func: 'sEmpowerCloud_Get_LinkUrl',
-      AppID: _appId,
-      TimeStamp: timeStamp,
-      appkey: window.GLOB.appkey,
-      userid: 'bh0bapabtd45epsgra79segbch6c1ibk',
-      LoginUID: 'bh0bapabtd45epsgra79segbch6c1ibk'
-    }
-
-    Api.dostarToDostars(param).then(res => {
-      if (res.status) {
-        if (res.EPC === str) {
-          let box = []
-          for (let i = 0; i < 15; i++) {
-            let s = 'mksoft' + moment().add(i, 'days').format('YYYYMMDD')
-            box.push(md5(s))
-          }
-          box = box.join(',')
-          localStorage.setItem(_authUrl, box)
+    if (index === -1 || index > 5) {
+      let _appId = window.GLOB.appId
   
-          this.setState({
-            auth: true
-          })
-        } else {
+      if (options.sysType === 'cloud') { // 浜戠浣跨敤绯荤粺閰嶇疆appid
+        _appId = options.caId
+      }
+  
+      let str = md5('MK19' + _appId + timeStamp)
+      let _rduri = window.atob('aHR0cDovL2VwYy5tazloL$mkmNuL3dlYmFwaS9kb3N0YXJz'.replace(/\$mk/ig, ''))
+      let _func = window.atob('c0VtcG93ZXJDbG91$mkZF9HZXRfTGlua1VybA=='.replace(/\$mk/ig, ''))
+      let _id = window.atob('YmgwYmFwYWJ0ZDQ1ZXBz$mkZ3JhNzlzZWdiY2g2YzFpYms='.replace(/\$mk/ig, ''))
+  
+      let param = {
+        rduri: _rduri,
+        func: _func,
+        AppID: _appId,
+        TimeStamp: timeStamp,
+        appkey: window.GLOB.appkey,
+        userid: _id,
+        LoginUID: _id
+      }
+  
+      Api.dostarToDostars(param).then(res => {
+        if (res.status) {
+          if (res.EPC === str) {
+            let box = []
+            for (let i = 0; i < 15; i++) {
+              let s = 'mksoft' + moment().add(i, 'days').format('YYYYMMDD')
+              box.push(md5(s))
+            }
+            box = box.join(',')
+            localStorage.setItem(_authUrl, box)
+    
+            this.setState({
+              auth: true
+            })
+          } else {
+            localStorage.removeItem(_authUrl)
+            this.setState({
+              auth: false
+            })
+          }
+        } else if (res.ErrCode === 'N') {
           localStorage.removeItem(_authUrl)
           this.setState({
             auth: false
           })
         }
-      } else if (res.ErrCode === 'N') {
-        localStorage.removeItem(_authUrl)
-        this.setState({
-          auth: false
-        })
-      }
-    })
-
-    let authCode = localStorage.getItem(_authUrl)
-    let _s = md5('mksoft' + moment().format('YYYYMMDD'))
-    if (authCode && authCode.includes(_s)) {
-      this.setState({
-        auth: true
       })
     }
 
diff --git a/src/views/menudesign/index.jsx b/src/views/menudesign/index.jsx
index f791bc3..d2e0242 100644
--- a/src/views/menudesign/index.jsx
+++ b/src/views/menudesign/index.jsx
@@ -28,6 +28,7 @@
 const MenuShell = asyncComponent(() => import('@/menu/menushell'))
 const Controller = asyncComponent(() => import('@/menu/bgcontroller'))
 const StyleController = asyncComponent(() => import('@/menu/stylecontroller'))
+const ModalController = asyncComponent(() => import('@/menu/modalconfig/controller'))
 const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent'))
 
 sessionStorage.setItem('isEditState', 'true')
@@ -401,6 +402,7 @@
             </div>
           </DndProvider>
           <StyleController />
+          <ModalController />
         </div>
       </ConfigProvider>
     )

--
Gitblit v1.8.0