king
2020-10-23 407c0f1765c7d085218a91ad8842784977383d05
2020-10-23
27个文件已修改
9个文件已添加
3221 ■■■■■ 已修改文件
package-lock.json 229 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/mobimg/nightingale.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/mobimg/pie.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/mobimg/ring.png 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/index.jsx 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/index.jsx 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/index.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-pie/chartcompile/index.jsx 258 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-pie/chartcompile/index.scss 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-pie/index.jsx 433 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-pie/index.scss 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabcomponents/card.jsx 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabcomponents/index.jsx 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/card.jsx 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/index.jsx 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modalconfig/controller.jsx 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modalconfig/index.jsx 604 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modalconfig/index.scss 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modelsource/option.jsx 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/formtab/actionList/index.jsx 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/formtab/index.jsx 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/formtabconfig/actionform/index.jsx 64 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/formtabconfig/dragelement/card.jsx 121 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/formtabconfig/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/formtabconfig/index.scss 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/formtabconfig/source.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/index.scss 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/customscript/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/index.jsx 637 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/index.jsx 93 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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",
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",
src/assets/mobimg/nightingale.png
src/assets/mobimg/pie.png
src/assets/mobimg/ring.png
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}
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}
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
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: '隐藏' }
      ]
    },
    {
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>
src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx
New file
@@ -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: '白色'
      }]
    }
  ]
}
src/menu/components/chart/antv-pie/chartcompile/index.jsx
New file
@@ -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)
src/menu/components/chart/antv-pie/chartcompile/index.scss
New file
@@ -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;
      }
    }
  }
}
src/menu/components/chart/antv-pie/index.jsx
New file
@@ -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)
src/menu/components/chart/antv-pie/index.scss
New file
@@ -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;
}
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') {
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}
        />
      ))}
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') {
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>
src/menu/modalconfig/controller.jsx
New file
@@ -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
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、number、datetime、date
    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
  }
}
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;
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 },
]
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) // 数据源
        
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 => {
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
          }
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
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,
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 {
src/templates/formtabconfig/source.jsx
@@ -63,7 +63,7 @@
        btnType: 'confirm',
        uuid: Utils.getuuid(),
        label: '确定',
        intertype: 'inner',
        intertype: 'system',
        innerFunc: '',
        interface: '',
        outerFunc: '',
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;
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}
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>
                )}
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) { // 表单中增加BID
        _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: '表单未添加或解析错误,请检查表单设置!',
              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) { // 子表表单中增加BID
            _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) { // 子表表单中增加BID
        _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}
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
      })
    }
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>
    )