king
2021-04-14 30b6c01972cc74152b733a94edcc0c2a614a2268
2021-04-14
28个文件已修改
8个文件已添加
2034 ■■■■■ 已修改文件
package-lock.json 241 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/mobimg/dashboard.png 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-dashboard/chartcompile/formconfig.jsx 145 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-dashboard/chartcompile/index.jsx 355 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-dashboard/chartcompile/index.scss 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-dashboard/index.jsx 391 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-dashboard/index.scss 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-pie/index.jsx 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/group/groupcomponents/card.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/group/groupcomponents/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/columns/index.jsx 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/columns/index.scss 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/wrapsetting/settingform/index.jsx 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabcomponents/card.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabcomponents/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/card.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modulesource/option.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/mobshell/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/modulesource/option.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/menushell/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/modulesource/option.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-dashboard/index.jsx 467 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-dashboard/index.scss 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/group/normal-group/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/normalTable/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/normalTable/index.scss 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/tabtransfer/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/normal-table/index.jsx 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.jsx 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/billprint/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobdesign/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pcdesign/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json
@@ -60,47 +60,74 @@
      }
    },
    "@antv/color-util": {
      "version": "2.0.5",
      "resolved": "https://registry.npmjs.org/@antv/color-util/-/color-util-2.0.5.tgz",
      "integrity": "sha512-eQktA9YDnWCj03rfjpg0ajvCfRkHXzBzsZa9z94pY6Jb7e3XtPUp7vDpB8KhaKm9GjPtGzQDneh+gnqkEK8mtQ==",
      "version": "2.0.6",
      "resolved": "https://registry.npmjs.org/@antv/color-util/-/color-util-2.0.6.tgz",
      "integrity": "sha512-KnPEaAH+XNJMjax9U35W67nzPI+QQ2x27pYlzmSIWrbj4/k8PGrARXfzDTjwoozHJY8qG62Z+Ww6Alhu2FctXQ==",
      "requires": {
        "@antv/util": "^2.0.9",
        "tslib": "^1.10.0"
        "tslib": "^2.0.3"
      },
      "dependencies": {
        "@antv/util": {
          "version": "2.0.9",
          "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.9.tgz",
          "integrity": "sha512-JblWzne7msAPDdxkUhEk8zAz0Wd6igKwqymGbvIeyOydGrhBhGjA3nEayFj4IlG+XixCvGFKsCB4yuFS4glRIA==",
          "version": "2.0.13",
          "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.13.tgz",
          "integrity": "sha512-mfYL7K8XJIeDmal33K+6abr8Yb526YXKg5XQlddNo+X1Doll+gun6HxnbdySoLv21vW4bLkcbVPjqxWl7ZJAFA==",
          "requires": {
            "tslib": "^1.10.0"
            "tslib": "^2.0.3"
          }
        },
        "tslib": {
          "version": "2.2.0",
          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
        }
      }
    },
    "@antv/component": {
      "version": "0.8.2",
      "resolved": "https://registry.npmjs.org/@antv/component/-/component-0.8.2.tgz",
      "integrity": "sha512-aU65T9jD85H+3WhhmgPz8kiuqxJGPuHFgRiBYmR+vQUnAA2nOW2bCafiNx/bSEAqmVgsr+8e+9IDQZ6PowIgtQ==",
      "version": "0.8.11",
      "resolved": "https://registry.npmjs.org/@antv/component/-/component-0.8.11.tgz",
      "integrity": "sha512-7hl7IPPF/QmE25lrZhppEW8BYJzU3SE6IGq4/NhrvcDk79Xhm1L4KOcAAcZ0zYBRaOwQL3yMcraIL+/Z1UhLjw==",
      "requires": {
        "@antv/dom-util": "~2.0.1",
        "@antv/g-base": "~0.5.0",
        "@antv/g-base": "0.5.6",
        "@antv/matrix-util": "^3.1.0-beta.1",
        "@antv/path-util": "~2.0.7",
        "@antv/scale": "~0.3.1",
        "@antv/util": "~2.0.0",
        "fecha": "~4.2.0",
        "tslib": "^1.10.0"
        "tslib": "^2.0.3"
      },
      "dependencies": {
        "tslib": {
          "version": "2.2.0",
          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
        }
      }
    },
    "@antv/coord": {
      "version": "0.3.0",
      "resolved": "https://registry.npmjs.org/@antv/coord/-/coord-0.3.0.tgz",
      "integrity": "sha512-lm5Ct+r62mFVqhziKoDFN3PQjnkNBMOoOG+kBsPq3M3GqlQt5Jc7euOHMFcYSZM9HJmsKkGcih6EWDVVliMEZg==",
      "version": "0.3.1",
      "resolved": "https://registry.npmjs.org/@antv/coord/-/coord-0.3.1.tgz",
      "integrity": "sha512-rFE94C8Xzbx4xmZnHh2AnlB3Qm1n5x0VT3OROy257IH6Rm4cuzv1+tZaUBATviwZd99S+rOY9telw/+6C9GbRw==",
      "requires": {
        "@antv/matrix-util": "^3.1.0-beta.2",
        "@antv/util": "~2.0.3",
        "tslib": "^1.10.0"
        "@antv/util": "~2.0.12",
        "tslib": "^2.1.0"
      },
      "dependencies": {
        "@antv/util": {
          "version": "2.0.13",
          "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.13.tgz",
          "integrity": "sha512-mfYL7K8XJIeDmal33K+6abr8Yb526YXKg5XQlddNo+X1Doll+gun6HxnbdySoLv21vW4bLkcbVPjqxWl7ZJAFA==",
          "requires": {
            "tslib": "^2.0.3"
          }
        },
        "tslib": {
          "version": "2.2.0",
          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
        }
      }
    },
    "@antv/data-set": {
@@ -127,11 +154,18 @@
      }
    },
    "@antv/dom-util": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/@antv/dom-util/-/dom-util-2.0.2.tgz",
      "integrity": "sha512-i/rh385casRd6OA4rbpbA2jyiwY/w7PtkA+74mH43PiBzOcLpDg1jEWR9dMO0tIqUzHQWWqKNNjmXVubl4GS6g==",
      "version": "2.0.3",
      "resolved": "https://registry.npmjs.org/@antv/dom-util/-/dom-util-2.0.3.tgz",
      "integrity": "sha512-dUHsUT4U9X1T1/Y9bH3jRMe0MzvWJk2jSQm1vm3w9NX+Ra0ftq5VUBiGTNbthm3nFwG0fFFjip904rYjl50g4A==",
      "requires": {
        "tslib": "^1.10.0"
        "tslib": "^2.0.3"
      },
      "dependencies": {
        "tslib": {
          "version": "2.2.0",
          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
        }
      }
    },
    "@antv/event-emitter": {
@@ -140,81 +174,105 @@
      "integrity": "sha512-6C6NJOdoNVptCr5y9BVOhKkCgW7LFs/SpcRyAExUeSjAm0zJqcqNkSIRGsXYhj4PJI+CZICHzGwwiSnIsE68Ug=="
    },
    "@antv/g-base": {
      "version": "0.5.1",
      "resolved": "https://registry.npmjs.org/@antv/g-base/-/g-base-0.5.1.tgz",
      "integrity": "sha512-gbv+uz/SvzM4/p3PLjAiEZUp6kdzKkCbVWTCdBXB1cvNMttlEzWEB8MOFbEkcIAy7TtjQJJRv8ThI/ngFzU+fg==",
      "version": "0.5.6",
      "resolved": "https://registry.npmjs.org/@antv/g-base/-/g-base-0.5.6.tgz",
      "integrity": "sha512-szxqFQ/xdCnfaeSEEC2kVjXdKxJnvKKJNT0MvaOG3UXOfsjPDLgb3IKLr+bU3sLvTAQfPhsbtYh7mWb03+mGjA==",
      "requires": {
        "@antv/event-emitter": "^0.1.1",
        "@antv/g-math": "^0.1.5",
        "@antv/g-math": "^0.1.6",
        "@antv/matrix-util": "^3.1.0-beta.1",
        "@antv/path-util": "~2.0.5",
        "@antv/util": "~2.0.0",
        "@types/d3-timer": "^1.0.9",
        "@types/d3-timer": "^2.0.0",
        "d3-ease": "^1.0.5",
        "d3-interpolate": "^1.3.2",
        "d3-timer": "^1.0.9",
        "detect-browser": "^5.1.0"
        "detect-browser": "^5.1.0",
        "tslib": "^2.0.3"
      },
      "dependencies": {
        "tslib": {
          "version": "2.2.0",
          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
        }
      }
    },
    "@antv/g-canvas": {
      "version": "0.5.3",
      "resolved": "https://registry.npmjs.org/@antv/g-canvas/-/g-canvas-0.5.3.tgz",
      "integrity": "sha512-80k1BbiY05heHKUm4o6IL6KVRZS+uAgzdIF2OaC9grQc6KxrJoK2dCxKpmna3NBHTU9Sm+/rsiGcL7lp7S+ecQ==",
      "version": "0.5.6",
      "resolved": "https://registry.npmjs.org/@antv/g-canvas/-/g-canvas-0.5.6.tgz",
      "integrity": "sha512-r6f6KqYuNZWunf2Vnf1ACopn8aic6TBFhaN3XuckenhQNqR+/PI/4Mft7z14zo7WH58X2Xs2Npq9awJXBEUzaw==",
      "requires": {
        "@antv/g-base": "^0.5.1",
        "@antv/g-math": "^0.1.5",
        "@antv/g-base": "^0.5.3",
        "@antv/g-math": "^0.1.6",
        "@antv/matrix-util": "^3.1.0-beta.1",
        "@antv/path-util": "~2.0.5",
        "@antv/util": "~2.0.0",
        "gl-matrix": "^3.0.0"
        "gl-matrix": "^3.0.0",
        "tslib": "^2.0.3"
      },
      "dependencies": {
        "tslib": {
          "version": "2.2.0",
          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
        }
      }
    },
    "@antv/g-math": {
      "version": "0.1.5",
      "resolved": "https://registry.npmjs.org/@antv/g-math/-/g-math-0.1.5.tgz",
      "integrity": "sha512-29B3p33jzUPIyx1xYfNCexbp7jvahD6bD8FKKyWqfYZHQbvrFfV8ZNUu66RJLfDrl0KaKT6C5whfKs/WrVaflQ==",
      "version": "0.1.7",
      "resolved": "https://registry.npmjs.org/@antv/g-math/-/g-math-0.1.7.tgz",
      "integrity": "sha512-xGyXaloD1ynfp7gS4VuV+MjSptZIwHvLHr8ekXJSFAeWPYLu84yOW2wOZHDdp1bzDAIuRv6xDBW58YGHrWsFcA==",
      "requires": {
        "@antv/util": "~2.0.0",
        "gl-matrix": "^3.0.0"
      }
    },
    "@antv/g-svg": {
      "version": "0.5.2",
      "resolved": "https://registry.npmjs.org/@antv/g-svg/-/g-svg-0.5.2.tgz",
      "integrity": "sha512-T0PYjIM+WX6zv3yUgSkyRcHFq4hlio0MeRGoJR60P5U5MNSdkZnblcu79cpU2i42Z7wBr404Kv1dplCGxC38PA==",
      "version": "0.5.6",
      "resolved": "https://registry.npmjs.org/@antv/g-svg/-/g-svg-0.5.6.tgz",
      "integrity": "sha512-Xve1EUGk4HMbl2nq4ozR4QLh6GyoZ8Xw/+9kHYI4B5P2lIUQU95MuRsaLFfW5NNpZDx85ZeH97tqEmC9L96E7A==",
      "requires": {
        "@antv/g-base": "^0.5.1",
        "@antv/g-math": "^0.1.5",
        "@antv/g-base": "^0.5.3",
        "@antv/g-math": "^0.1.6",
        "@antv/util": "~2.0.0",
        "detect-browser": "^5.0.0"
        "detect-browser": "^5.0.0",
        "tslib": "^2.0.3"
      },
      "dependencies": {
        "tslib": {
          "version": "2.2.0",
          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
        }
      }
    },
    "@antv/g2": {
      "version": "4.1.0-beta.18",
      "resolved": "https://registry.npmjs.org/@antv/g2/-/g2-4.1.0-beta.18.tgz",
      "integrity": "sha512-RW3e95V2aUtys36guS7PNHbfgyYZgigu18OLSYPkgyRLF0pPABcSrIot+xnVGQ4Cx0ZDmhJVTvpXjU4QMa96kw==",
      "version": "4.1.14",
      "resolved": "https://registry.npmjs.org/@antv/g2/-/g2-4.1.14.tgz",
      "integrity": "sha512-JdU+0suxkDqjTZNyG915zQ7eM+bdT2fHV48VGc1LvCroUHzCncCnbx5HZ19aZhvuij2hM6eh52vb8mwIXIzMBw==",
      "requires": {
        "@antv/adjust": "^0.2.1",
        "@antv/attr": "^0.3.1",
        "@antv/color-util": "^2.0.2",
        "@antv/component": "^0.8.0",
        "@antv/component": "^0.8.7",
        "@antv/coord": "^0.3.0",
        "@antv/dom-util": "^2.0.2",
        "@antv/event-emitter": "~0.1.0",
        "@antv/g-base": "^0.5.0",
        "@antv/g-canvas": "^0.5.0",
        "@antv/g-svg": "^0.5.0",
        "@antv/g-base": "0.5.6",
        "@antv/g-canvas": "0.5.6",
        "@antv/g-svg": "0.5.6",
        "@antv/matrix-util": "^3.1.0-beta.1",
        "@antv/path-util": "^2.0.3",
        "@antv/scale": "^0.3.1",
        "@antv/scale": "^0.3.7",
        "@antv/util": "~2.0.5",
        "tslib": "^2.0.0"
      },
      "dependencies": {
        "tslib": {
          "version": "2.0.3",
          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
          "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
          "version": "2.2.0",
          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
        }
      }
    },
@@ -237,38 +295,50 @@
      },
      "dependencies": {
        "@antv/util": {
          "version": "2.0.9",
          "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.9.tgz",
          "integrity": "sha512-JblWzne7msAPDdxkUhEk8zAz0Wd6igKwqymGbvIeyOydGrhBhGjA3nEayFj4IlG+XixCvGFKsCB4yuFS4glRIA==",
          "version": "2.0.13",
          "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.13.tgz",
          "integrity": "sha512-mfYL7K8XJIeDmal33K+6abr8Yb526YXKg5XQlddNo+X1Doll+gun6HxnbdySoLv21vW4bLkcbVPjqxWl7ZJAFA==",
          "requires": {
            "tslib": "^1.10.0"
            "tslib": "^2.0.3"
          },
          "dependencies": {
            "tslib": {
              "version": "2.2.0",
              "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
              "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
            }
          }
        }
      }
    },
    "@antv/path-util": {
      "version": "2.0.8",
      "resolved": "https://registry.npmjs.org/@antv/path-util/-/path-util-2.0.8.tgz",
      "integrity": "sha512-g5gt12MY1oEzh/j5XfLNRCfJU7E+Us+2yM5Hqc0y8xeWhb5l013XG5BPV37KmOf6WAys9KNxklNniHCZ6SqCKw==",
      "version": "2.0.9",
      "resolved": "https://registry.npmjs.org/@antv/path-util/-/path-util-2.0.9.tgz",
      "integrity": "sha512-kunEz4dNheQMVn4rVFsoBDx+n9Knfi3uRLvDk9SojZAqpninsjFhdoiYtbExwJGz1FYGtiV10Y6N1tp73kZFcg==",
      "requires": {
        "@antv/util": "^2.0.9",
        "tslib": "^1.10.0"
        "tslib": "^2.0.3"
      },
      "dependencies": {
        "@antv/util": {
          "version": "2.0.9",
          "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.9.tgz",
          "integrity": "sha512-JblWzne7msAPDdxkUhEk8zAz0Wd6igKwqymGbvIeyOydGrhBhGjA3nEayFj4IlG+XixCvGFKsCB4yuFS4glRIA==",
          "version": "2.0.13",
          "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.13.tgz",
          "integrity": "sha512-mfYL7K8XJIeDmal33K+6abr8Yb526YXKg5XQlddNo+X1Doll+gun6HxnbdySoLv21vW4bLkcbVPjqxWl7ZJAFA==",
          "requires": {
            "tslib": "^1.10.0"
            "tslib": "^2.0.3"
          }
        },
        "tslib": {
          "version": "2.2.0",
          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
        }
      }
    },
    "@antv/scale": {
      "version": "0.3.4",
      "resolved": "https://registry.npmjs.org/@antv/scale/-/scale-0.3.4.tgz",
      "integrity": "sha512-mZaf3MtMoQJtd+KAgTANVbvKpaXVpzLAFbKO/wSKaLFpnWO0bwMVDYzrs+5DZhfEfMbZpP/A7qUZ2/DLh0T3Tg==",
      "version": "0.3.9",
      "resolved": "https://registry.npmjs.org/@antv/scale/-/scale-0.3.9.tgz",
      "integrity": "sha512-m56Rs4Zta7XnuF+aNbJXMsgBqATO1M4kvu+dEmhzLYsPK5D3dHpJTOGh/Zy55eirekb9F7jiu29SJqPNnhxq+g==",
      "requires": {
        "@antv/util": "~2.0.3",
        "fecha": "~4.2.0",
@@ -276,18 +346,25 @@
      },
      "dependencies": {
        "tslib": {
          "version": "2.0.3",
          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
          "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
          "version": "2.2.0",
          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
        }
      }
    },
    "@antv/util": {
      "version": "2.0.8",
      "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.8.tgz",
      "integrity": "sha512-G9QRygQJ8UNGMi8L1dfMIa4SofbEO+jkXwvRY4ek/MLd04Q01UN0U28JeMFzw6FCKJdxiFu+2uwT/zjoFr3QoQ==",
      "version": "2.0.13",
      "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.13.tgz",
      "integrity": "sha512-mfYL7K8XJIeDmal33K+6abr8Yb526YXKg5XQlddNo+X1Doll+gun6HxnbdySoLv21vW4bLkcbVPjqxWl7ZJAFA==",
      "requires": {
        "tslib": "^1.10.0"
        "tslib": "^2.0.3"
      },
      "dependencies": {
        "tslib": {
          "version": "2.2.0",
          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
          "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
        }
      }
    },
    "@babel/code-frame": {
@@ -2376,9 +2453,9 @@
      "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
    },
    "@types/d3-timer": {
      "version": "1.0.10",
      "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-1.0.10.tgz",
      "integrity": "sha512-ZnAbquVqy+4ZjdW0cY6URp+qF/AzTVNda2jYyOzpR2cPT35FTXl78s15Bomph9+ckOiI1TtkljnWkwbIGAb6rg=="
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-2.0.0.tgz",
      "integrity": "sha512-l6stHr1VD1BWlW6u3pxrjLtJfpPZq9I3XmKIQtq7zHM/s6fwEtI1Yn6Sr5/jQTrUDCC5jkS6gWqlFGCDArDqNg=="
    },
    "@types/eslint-visitor-keys": {
      "version": "1.0.0",
@@ -8435,9 +8512,9 @@
      }
    },
    "fecha": {
      "version": "4.2.0",
      "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz",
      "integrity": "sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg=="
      "version": "4.2.1",
      "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz",
      "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q=="
    },
    "figgy-pudding": {
      "version": "3.5.1",
package.json
@@ -4,7 +4,8 @@
  "private": true,
  "dependencies": {
    "@antv/data-set": "^0.11.4",
    "@antv/g2": "^4.1.0-beta.18",
    "@antv/g2": "^4.1.14",
    "@antv/util": "^2.0.13",
    "@babel/core": "7.5.5",
    "@svgr/webpack": "4.3.2",
    "@typescript-eslint/eslint-plugin": "1.13.0",
src/assets/mobimg/dashboard.png
src/menu/components/chart/antv-dashboard/chartcompile/formconfig.jsx
New file
@@ -0,0 +1,145 @@
// import zhCN from '@/locales/zh-CN/model.js'
// import enUS from '@/locales/en-US/model.js'
// const Formdict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
/**
 * @description 获取图表视图配置表单
 * @param {object} card       // 图表对象
 */
export function getBaseForm (card) {
  let roleList = sessionStorage.getItem('sysRoles')
  if (roleList) {
    try {
      roleList = JSON.parse(roleList)
    } catch {
      roleList = []
    }
  } else {
    roleList = []
  }
  return [
    {
      type: 'text',
      key: 'title',
      label: '标题',
      initVal: card.title,
      required: false
    },
    {
      type: 'text',
      key: 'name',
      label: '组件名称',
      initVal: card.name,
      tooltip: '用于组件间的区分。',
      required: true
    },
    {
      type: 'number',
      key: 'width',
      label: '宽度',
      initVal: card.width,
      tooltip: '栅格布局,每行等分为24列。',
      min: 1,
      max: 24,
      decimal: 0,
      required: true
    },
    {
      type: 'number',
      key: 'height',
      label: '高度',
      initVal: card.height,
      min: 100,
      max: 1000,
      decimal: 0,
      required: true
    },
    {
      type: 'select',
      key: 'blacklist',
      label: '黑名单',
      initVal: card.blacklist || [],
      multi: true,
      required: false,
      options: roleList
    }
  ]
}
/**
 * @description 获取图表视图配置表单
 * @param {object} card       // 图表对象
 * @param {Array}  columns    // 显示列
 */
export function getOptionForm (card, columns) {
  let yfields = columns.filter(item => /^(Int|Decimal)/ig.test(item.datatype))
  return [
    {
      type: 'text',
      key: 'label',
      label: '指标名称',
      initVal: card.label || '',
      required: false
    },
    {
      type: 'select',
      key: 'valueField',
      label: '显示值',
      initVal: card.valueField || '',
      required: true,
      options: yfields
    },
    {
      type: 'number',
      key: 'maxValue',
      label: '最大值',
      initVal: card.maxValue || 100,
      tooltip: '仪表盘最大刻度值',
      min: 0,
      max: 999999,
      decimal: 1,
      required: true
    },
    {
      type: 'number',
      key: 'tickInterval',
      label: '间隔',
      initVal: card.tickInterval || 10,
      tooltip: '仪表盘刻度间隔值。',
      min: 0,
      max: 999999,
      decimal: 1,
      required: true
    },
    {
      type: 'radio',
      key: 'percent',
      label: '百分率',
      initVal: card.percent || 'true',
      required: false,
      options: [{
        value: 'true',
        text: '使用'
      }, {
        value: 'false',
        text: '不使用'
      }]
    },
    {
      type: 'color',
      key: 'tickColor',
      label: '刻度线',
      initVal: card.tickColor || '#CBCBCB',
      required: false
    },
    {
      type: 'color',
      key: 'labelColor',
      label: '指标颜色',
      initVal: card.labelColor || '#545454',
      required: false
    }
  ]
}
src/menu/components/chart/antv-dashboard/chartcompile/index.jsx
New file
@@ -0,0 +1,355 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Modal, Form, Row, Col, Select, Icon, Radio, Tooltip, Input, InputNumber, Tabs, Button } from 'antd'
import Utils from '@/utils/utils.js'
import { getBaseForm, getOptionForm } from './formconfig'
import asyncComponent from '@/utils/asyncComponent'
import ColorSketch from '@/mob/colorsketch'
import './index.scss'
const { TabPane } = Tabs
const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
const NormalForm = asyncComponent(() => import('@/menu/components/share/normalform'))
class LineChartDrawerForm extends Component {
  static propTpyes = {
    dict: PropTypes.object,
    plot: PropTypes.object,
    config: PropTypes.object,
    plotchange: PropTypes.func
  }
  state = {
    visible: false,
    plot: null,
    formlist: null,
    baseFormlist: null,
    view: 'normal',
    colorColumns: [
      {
        title: '指标',
        dataIndex: 'tick',
        inputType: 'number',
        editable: true,
        width: '40%'
      },
      {
        title: '颜色',
        dataIndex: 'color',
        inputType: 'color',
        editable: true,
        width: '40%',
        render: (text, record) => {
          return (<div style={{width: '80px', height: '23px', background: text}}></div>)
        }
      },
    ]
  }
  showDrawer = () => {
    const { config } = this.props
    this.setState({
      visible: true,
      view: 'normal',
      plot: fromJS(config.plot).toJS(),
      baseFormlist: getBaseForm(config.plot),
      formlist: getOptionForm(config.plot, config.columns)
    })
  }
  radioChange = (e, key) => {
    const { formlist } = this.state
    let val = e.target.value
    if (key === 'shape') {
      this.setState({
        formlist: formlist.map(item => {
          if (item.key === 'innerRadius') {
            item.hidden = val === 'pie'
          }
          return item
        })
      }, () => {
        if (val === 'ring') {
          this.props.form.setFieldsValue({innerRadius: 50})
        } else if (val === 'nightingale') {
          this.props.form.setFieldsValue({innerRadius: 0})
        }
      })
    }
  }
  getFields() {
    const { formlist } = this.state
    const { getFieldDecorator } = this.props.form
    const fields = []
    if (!formlist) {
      return fields
    }
    formlist.forEach((item, index) => {
      if (item.hidden || item.forbid) return
      if (item.type === 'text') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  }
                ]
              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.onSubmit}/>)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'number') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  }
                ]
              })(<InputNumber min={item.min} max={item.max} precision={item.decimal} onPressEnter={this.onSubmit}/>)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'select') { // 下拉
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <Select mode={item.multi ? 'multiple' : ''}>
                  {item.options.map((option, index) =>
                    <Select.Option key={index} value={option.field}>
                      {option.label}
                    </Select.Option>
                  )}
                </Select>
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'radio') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <Radio.Group disabled={item.readonly} onChange={(e) => this.radioChange(e, item.key)}>
                  {item.options.map(option => {
                    return (
                      <Radio key={option.value} value={option.value}>{option.text}</Radio>
                    )
                  })}
                </Radio.Group>
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'color') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal
              })(
                <ColorSketch />
              )}
            </Form.Item>
          </Col>
        )
      }
    })
    return fields
  }
  onSubmit = () => {
    const { config } = this.props
    const { plot, view } = this.state
    if (view === 'normal') {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          let _plot = {...plot, ...values}
          this.setState({
            plot: _plot,
            visible: false
          })
          this.props.plotchange({...config, plot: _plot})
        }
      })
    } else if (view === 'base') {
      this.baseRef.handleConfirm().then(res => {
        let _plot = {...plot, ...res}
        this.setState({
          plot: _plot,
          visible: false
        })
        this.props.plotchange({...config, plot: _plot})
      })
    } else {
      this.setState({
        visible: false
      })
      this.props.plotchange({...config, plot: plot})
    }
  }
  changeTab = (tab) => {
    const { plot, view } = this.state
    if (view === 'normal') {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          let _plot = {...plot, ...values}
          this.setState({
            plot: _plot,
            view: tab
          })
        }
      })
    } else if (view === 'base') {
      this.baseRef.handleConfirm().then(res => {
        let _plot = {...plot, ...res}
        this.setState({
          plot: _plot,
          view: tab
        })
      })
    } else {
      this.setState({
        view: tab
      })
    }
  }
  addColor = () => {
    let plot = fromJS(this.state.plot).toJS()
    plot.colors = plot.colors || []
    plot.colors.push({
      uuid: Utils.getuuid(),
      tick: plot.maxValue || 1,
      color: '#1890ff'
    })
    this.setState({plot})
  }
  changeColor = (colors) => {
    const { plot } = this.state
    this.setState({plot: {...plot, colors}})
  }
  render() {
    const { visible, plot, colorColumns, view, baseFormlist } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 6 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 18 }
      }
    }
    return (
      <div className="line-chart-drawer-form">
        <Icon type="edit" title="编辑" onClick={this.showDrawer} />
        <Modal
          wrapClassName="popview-modal menu-chart-edit-modal"
          title="图表编辑"
          visible={visible}
          width={850}
          maskClosable={false}
          onOk={this.onSubmit}
          onCancel={() => { this.setState({ visible: false }) }}
          destroyOnClose
        >
          <Tabs activeKey={view} className="menu-chart-edit-box" onChange={this.changeTab}>
            <TabPane tab="组件设置" key="base">
              <NormalForm dict={this.props.dict} formlist={baseFormlist} inputSubmit={this.onSubmit} wrappedComponentRef={(inst) => this.baseRef = inst}/>
            </TabPane>
            <TabPane tab="图表设置" key="normal">
              <Form {...formItemLayout}>
                <Row gutter={16}>{this.getFields()}</Row>
              </Form>
            </TabPane>
            {plot ? <TabPane tab="颜色设置" key="color">
              <div>
                <Button className="color-add mk-green" onClick={this.addColor}>{this.props.dict['model.add']}</Button>
                <EditTable actions={['edit', 'move', 'del']} data={plot.colors || []} columns={colorColumns} onChange={this.changeColor}/>
              </div>
            </TabPane> : null}
          </Tabs>
        </Modal>
      </div>
    );
  }
}
export default Form.create()(LineChartDrawerForm)
src/menu/components/chart/antv-dashboard/chartcompile/index.scss
New file
@@ -0,0 +1,39 @@
.line-chart-drawer-form {
  display: inline-block;
  > .anticon-edit {
    color: #1890ff;
  }
}
.menu-chart-edit-modal {
  .ant-modal {
    top: 50px;
    .ant-modal-body {
      min-height: 50vh;
      max-height: calc(100vh - 190px);
      padding-top: 10px;
      .anticon-question-circle {
        color: #c49f47;
        position: relative;
        left: -3px;
      }
      .ant-input-number {
        width: 100%;
      }
      .ant-tabs-nav-wrap {
        text-align: center;
      }
      .color-sketch-block {
        position: relative;
        top: 5px;
        width: 240px;
      }
      .color-add {
        float: right;
        margin-bottom: 10px;
        position: relative;
        z-index: 1;
      }
    }
  }
}
src/menu/components/chart/antv-dashboard/index.jsx
New file
@@ -0,0 +1,391 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Icon, Popover } from 'antd'
import { Chart, registerShape } from '@antv/g2'
import MKEmitter from '@/utils/events.js'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { resetStyle } from '@/utils/utils-custom.js'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import './index.scss'
const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
const ChartCompileForm = asyncIconComponent(() => import('./chartcompile'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
registerShape('point', 'pointer', {
  draw(cfg, container) {
    const group = container.addGroup({});
    // 获取极坐标系下画布中心点
    const center = this.parsePoint({ x: 0, y: 0 });
    // 绘制指针
    group.addShape('line', {
      attrs: {
        x1: center.x,
        y1: center.y,
        x2: cfg.x,
        y2: cfg.y,
        stroke: cfg.color,
        lineWidth: 5,
        lineCap: 'round',
      },
    });
    group.addShape('circle', {
      attrs: {
        x: center.x,
        y: center.y,
        r: 9.75,
        stroke: cfg.color,
        lineWidth: 4.5,
        fill: '#fff',
      },
    });
    return group;
  },
})
class antvDashboardChart extends Component {
  static propTpyes = {
    card: PropTypes.object,
    updateConfig: PropTypes.func,
    deletecomponent: PropTypes.func,
  }
  state = {
    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    card: null,
    ismob: sessionStorage.getItem('appType') === 'mob',
    eventListener: null
  }
  UNSAFE_componentWillMount () {
    const { card, ismob } = this.props
    if (card.isNew) {
      let _plot = {
        width: card.width || 12,
        height: 400,
        label: '',
        valueField: '',
        name: card.name,
        maxValue: 100,
        tickInterval: 10,
        labelColor: '#545454',
        tickColor: '#CBCBCB',
        percent: 'true'
      }
      if (ismob) {
        _plot.width = 24
      }
      let _card = {
        uuid: card.uuid,
        type: card.type,
        floor: card.floor,
        tabId: card.tabId || '',
        parentId: card.parentId || '',
        format: 'object',   // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: _plot.width,
        name: _plot.name,
        subtype: card.subtype,
        setting: { interType: 'system' },
        style: {
          borderWidth: '1px', borderColor: 'rgb(217, 217, 217)',
          marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px'
        },
        headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
        columns: [],
        scripts: [],
        search: [],
        action: [],
        plot: _plot,
        btnlog: [],
      }
      if (card.config) {
        let config = fromJS(card.config).toJS()
        _card.plot = config.plot
        _card.plot.name = card.name
        _card.style = config.style
        _card.headerStyle = config.headerStyle
      }
      this.props.updateConfig(_card)
      this.setState({
        card: _card
      })
    } else {
      this.setState({
        card: fromJS(card).toJS()
      })
    }
  }
  componentDidMount () {
    this.dashboardrender()
    MKEmitter.addListener('tabsChange', this.handleTabsChange)
    MKEmitter.addListener('submitStyle', this.getStyle)
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  /**
   * @description 组件销毁,清除state更新,清除快捷键设置
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('tabsChange', this.handleTabsChange)
    MKEmitter.removeListener('submitStyle', this.getStyle)
  }
  handleTabsChange = (parentId) => {
    const { card } = this.state
    if (parentId === card.parentId) {
      let _element = document.getElementById(card.uuid + 'canvas')
      if (_element) {
        _element.innerHTML = ''
      }
      setTimeout(this.dashboardrender, 100)
    }
  }
  getdata = () => {
    const { card } = this.state
    const data = [];
    const val = (Math.random() * card.plot.maxValue).toFixed(1);
    data.push({ value: +val });
    return data;
  }
  dashboardrender = () => {
    const { card } = this.state
    const plot = card.plot
    const data = this.getdata()
    const chart = new Chart({
      container: card.uuid + 'dashboard',
      autoFit: true,
      height: plot.height ? (plot.height - 80) : 320,
      padding: [0, 0, 0, 0],
    })
    chart.data(data);
    chart.scale('value', {
      min: 0,
      max: plot.maxValue,
      tickInterval: plot.tickInterval,
    });
    chart.coordinate('polar', {
      startAngle: (-9 / 8) * Math.PI,
      endAngle: (1 / 8) * Math.PI,
      radius: 0.75,
    });
    chart.axis('1', false);
    chart.axis('value', {
      line: null,
      label: {
        offset: -36,
        style: {
          fontSize: 18,
          fill: plot.tickColor,
          textAlign: 'center',
          textBaseline: 'middle',
        },
      },
      tickLine: {
        length: -24,
        style: {
          stroke: plot.tickColor
        }
      },
      grid: null,
    });
    chart.legend(false);
    chart.tooltip(false);
    chart
      .point()
      .position('value*1')
      .shape('pointer')
      .color('value', (val) => {
        let _color = '#1890FF'
        if (plot.colors && plot.colors.length > 0) {
          _color = plot.colors[plot.colors.length - 1].color || '#1890FF'
          plot.colors.some(item => {
            if (item.tick > val) {
              _color = item.color
              return true
            }
            return false
          })
        }
        return _color
      })
      .animate({
        appear: {
          animation: 'fade-in'
        }
      });
    // 绘制仪表盘背景
    chart.annotation().arc({
      top: false,
      start: [0, 1],
      end: [plot.maxValue, 1],
      style: {
        stroke: '#CBCBCB',
        lineWidth: 18,
        lineDash: null,
      },
    })
    if (!plot.colors || plot.colors.length === 0) {
      chart.annotation().arc({
        start: [0, 1],
        end: [plot.maxValue, 1],
        style: {
          stroke: '#1890FF',
          lineWidth: 18,
          lineDash: null,
        },
      });
    } else {
      let start = 0
      plot.colors.forEach(item => {
        chart.annotation().arc({
          start: [start, 1],
          end: [item.tick, 1],
          style: {
            stroke: item.color,
            lineWidth: 18,
            lineDash: null,
          },
        })
        start = item.tick
      })
    }
    if (plot.label) {
      chart.annotation().text({
        position: ['50%', '85%'],
        content: plot.label,
        style: {
          fontSize: 20,
          fill: plot.labelColor,
          textAlign: 'center',
        },
      })
    }
    let val = data[0].value
    if (plot.percent !== 'false' && plot.maxValue) {
      val = +(val / plot.maxValue * 100).toFixed(2) + ' %'
    }
    chart.annotation().text({
      position: ['50%', '90%'],
      content: val,
      style: {
        fontSize: 36,
        fill: plot.labelColor,
        textAlign: 'center',
      },
      offsetY: 15,
    });
    chart.render()
  }
  updateComponent = (component) => {
    const card = fromJS(this.state.card).toJS()
    let refresh = false
    if (!is(fromJS(component.plot), fromJS(card.plot)) || !is(fromJS(component.style), fromJS(card.style))) {
      let _element = document.getElementById(card.uuid + 'dashboard')
      if (_element) {
        _element.innerHTML = ''
      }
      refresh = true
    }
    component.width = component.plot.width
    component.name = component.plot.name
    this.setState({
      card: component
    }, () => {
      if (refresh) {
        setTimeout(() => {
          this.dashboardrender()
        }, 100)
      }
    })
    this.props.updateConfig(component)
  }
  changeStyle = () => {
    const { card } = this.state
    MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style)
  }
  getStyle = (comIds, style) => {
    const { card } = this.state
    if (comIds[0] !== card.uuid || comIds.length > 1) return
    let _card = {...card, style}
    this.updateComponent(_card)
  }
  clickComponent = (e) => {
    if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
      e.stopPropagation()
      MKEmitter.emit('clickComponent', this.state.card)
    }
  }
  render() {
    const { card } = this.state
    let _style = resetStyle(card.style)
    return (
      <div className="menu-dashboard-edit-box" style={{..._style, height: card.plot.height || 400}} onClick={this.clickComponent} id={card.uuid}>
        <NormalHeader config={card} updateComponent={this.updateComponent}/>
        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
          <div className="mk-popover-control">
            <ChartCompileForm config={card} dict={this.state.dict} plotchange={this.updateComponent}/>
            <CopyComponent type="dashboard" card={card}/>
            <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" />
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
            <UserComponent config={card}/>
            <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
            <SettingComponent config={card} updateConfig={this.updateComponent}/>
          </div>
        } trigger="hover">
          <Icon type="tool" />
        </Popover>
        <div className="canvas" id={card.uuid + 'dashboard'}></div>
      </div>
    )
  }
}
export default antvDashboardChart
src/menu/components/chart/antv-dashboard/index.scss
New file
@@ -0,0 +1,45 @@
.menu-dashboard-edit-box {
  position: relative;
  box-sizing: border-box;
  background: #ffffff;
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  .canvas {
    margin: 0px;
    letter-spacing: 0px;
  }
  >.anticon-tool {
    position: absolute;
    right: 1px;
    top: 1px;
    z-index: 2;
    font-size: 16px;
    padding: 5px;
    cursor: pointer;
    color: rgba(0, 0, 0, 0.85);
    background: rgba(255, 255, 255, 0.55);
  }
  .model-menu-action-list {
    position: absolute;
    right: 0px;
    z-index: 4;
    padding-top: 10px;
    font-size: 16px;
    .ant-row .anticon-plus {
      float: right;
    }
    .page-card {
      float: right;
    }
  }
}
.menu-dashboard-edit-box:hover {
  z-index: 1;
  box-shadow: 0px 0px 4px #1890ff;
}
src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx
@@ -274,14 +274,7 @@
      label: '色系',
      initVal: card.color || 'rgba(0, 0, 0, 0.85)',
      tooltip: '坐标轴及示例等提示文字使用的颜色。',
      required: false,
      options: [{
        value: 'black',
        text: '黑色'
      }, {
        value: 'white',
        text: '白色'
      }]
      required: false
    }
  ]
}
src/menu/components/chart/antv-pie/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Icon, Popover, notification } from 'antd'
import { Icon, Popover } from 'antd'
import { Chart } from '@antv/g2'
import DataSet from '@antv/data-set'
@@ -18,7 +18,6 @@
const ChartCompileForm = asyncIconComponent(() => import('./chartcompile'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
@@ -38,7 +37,7 @@
  }
  UNSAFE_componentWillMount () {
    const { card } = this.props
    const { card, ismob } = this.props
    if (card.isNew) {
      let _plot = {
@@ -47,6 +46,10 @@
        height: 400,
        label: 'outer',
        name: card.name
      }
      if (ismob) {
        _plot.width = 24
      }
      if (card.subtype === 'ring') {
@@ -167,7 +170,7 @@
  pierender = () => {
    const { card } = this.state
    let plot = {...card.plot, height: card.plot.height - 80}
    const plot = card.plot
    let color = plot.color || 'rgba(0, 0, 0, 0.85)'
    let X_axis = plot.Xaxis || 'x'
@@ -181,7 +184,7 @@
    const chart = new Chart({
      container: card.uuid + 'canvas',
      autoFit: true,
      height: plot.height || 400
      height: card.plot.height ? (card.plot.height - 80) : 320
    })
    if (plot.shape !== 'nightingale' && plot.show !== 'value') {
@@ -411,32 +414,6 @@
    this.updateComponent(_card)
  }
  handleLog = (type, logs, item) => {
    let card = fromJS(this.state.card).toJS()
    if (type === 'revert') {
      card.action = card.action ? [...card.action, item] : [item]
      card.btnlog = logs
      this.setState({ card })
      this.props.updateConfig(card)
      notification.success({
        top: 92,
        message: '恢复成功!',
        duration: 2
      })
    } else {
      card.btnlog = logs
      this.setState({ card })
      this.props.updateConfig(card)
      notification.success({
        top: 92,
        message: '清除成功!',
        duration: 2
      })
    }
  }
  clickComponent = (e) => {
    if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
      e.stopPropagation()
@@ -458,7 +435,6 @@
            <CopyComponent type="pie" card={card}/>
            <PasteComponent config={card} options={['search', 'form']} updateConfig={this.updateComponent} />
            <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" />
            <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} />
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
            <UserComponent config={card}/>
            <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
src/menu/components/group/groupcomponents/card.jsx
@@ -11,6 +11,7 @@
const TableCard = asyncComponent(() => import('@/menu/components/card/table-card'))
const NormalTable = asyncComponent(() => import('@/menu/components/table/normal-table'))
const BraftEditor = asyncComponent(() => import('@/menu/components/editor/braft-editor'))
const AntvDashboard = asyncComponent(() => import('@/menu/components/chart/antv-dashboard'))
const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => {
  const originalIndex = findCard(id).index
@@ -50,6 +51,8 @@
      return (<AntvBar card={card} updateConfig={updateConfig} deletecomponent={delCard} />)
    } else if (card.type === 'pie') {
      return (<AntvPie card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'dashboard') {
      return (<AntvDashboard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'card' && card.subtype === 'datacard') {
      return (<DataCard card={card} updateConfig={updateConfig} deletecomponent={delCard} />)
    } else if (card.type === 'card' && card.subtype === 'propcard') {
src/menu/components/group/groupcomponents/index.jsx
@@ -104,6 +104,7 @@
        pie: '饼图',
        table: '表格',
        editor: '富文本',
        dashboard: '仪表盘',
        card: '卡片'
      }
      let i = 1
src/menu/components/table/normal-table/columns/index.jsx
@@ -496,8 +496,16 @@
    const columns = this.handlecolumns(this.state.columns, fields, config)
    let style = {}
    if (config.wrap.color) {
      style.color = config.wrap.color
    }
    if (config.wrap.fontSize) {
      style.fontSize = config.wrap.fontSize
    }
    return (
      <div className={`normal-table-columns ${config.setting.laypage} ${config.wrap.tableType}`} id={tableId}>
      <div className={`normal-table-columns ${config.setting.laypage} ${config.wrap.tableType} ${config.wrap.mode || ''}`} id={tableId}>
        <div className="col-control">
          <Icon title="复制" type="copy" onClick={this.copycolumn} />
          <MarkColumn columns={fields} type="line" marks={lineMarks} onSubmit={this.updateLineMarks} />
@@ -508,6 +516,7 @@
            rowKey="uuid"
            size={config.wrap.size || 'middle'}
            rowClassName="editable-row"
            style={style}
            bordered={config.wrap.bordered !== 'false'}
            components={components}
            dataSource={this.state.data}
src/menu/components/table/normal-table/columns/index.scss
@@ -1,5 +1,9 @@
.normal-table-columns {
  position: relative;
  .ant-table {
    color: inherit;
    font-size: inherit;
  }
  .ant-table-body {
    overflow-x: auto;
    tr {
@@ -89,3 +93,29 @@
    border-radius: 0;
  }
}
.normal-table-columns.ghost {
  .ant-table-thead > tr {
    > th {
      color: inherit;
      background: transparent;
      .ant-table-column-sorter .ant-table-column-sorter-inner {
        color: inherit;
      }
    }
    > th:hover {
      background: transparent;
    }
  }
  .ant-table-body {
    overflow-x: auto;
    tr {
      td {
        background: transparent;
      }
    }
    tr:hover td {
      background: transparent!important;
    }
  }
}
src/menu/components/table/normal-table/wrapsetting/settingform/index.jsx
@@ -163,6 +163,39 @@
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label="模式">
                {getFieldDecorator('mode', {
                  initialValue: wrap.mode || 'default'
                })(
                  <Radio.Group>
                    <Radio key="default" value="default"> 常规 </Radio>
                    <Radio key="ghost" value="ghost"> 透明 </Radio>
                  </Radio.Group>
                )}
              </Form.Item>
            </Col>
            <Col span={12} style={{height: '64px'}}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="默认值 rgba(0, 0, 0, 0.65)。">
                  <Icon type="question-circle" />
                  字体颜色
                </Tooltip>
              }>
                {getFieldDecorator('color', {
                  initialValue: wrap.color || 'rgba(0, 0, 0, 0.65)'
                })(
                  <ColorSketch />
                )}
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label="字体大小">
                {getFieldDecorator('fontSize', {
                  initialValue: wrap.fontSize || 14
                })(<InputNumber min={14} max={30} precision={0} />)}
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="栅格布局,每行等分为24列。">
                  <Icon type="question-circle" />
src/menu/components/tabs/tabcomponents/card.jsx
@@ -7,6 +7,7 @@
const AntvBar = asyncComponent(() => import('@/menu/components/chart/antv-bar'))
const MainSearch = asyncComponent(() => import('@/menu/components/search/main-search'))
const AntvPie = asyncComponent(() => import('@/menu/components/chart/antv-pie'))
const AntvDashboard = asyncComponent(() => import('@/menu/components/chart/antv-dashboard'))
const AntvTabs = asyncComponent(() => import('@/menu/components/tabs/antv-tabs'))
const DataCard = asyncComponent(() => import('@/menu/components/card/data-card'))
const PropCard = asyncComponent(() => import('@/menu/components/card/prop-card'))
@@ -57,6 +58,8 @@
      return (<MainSearch card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'pie') {
      return (<AntvPie card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'dashboard') {
      return (<AntvDashboard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'tabs') {
      return (<AntvTabs tabs={card} updateConfig={updateConfig} deletecomponent={delCard} />)
    } else if (card.type === 'card' && card.subtype === 'datacard') {
src/menu/components/tabs/tabcomponents/index.jsx
@@ -98,6 +98,7 @@
        group: '分组',
        editor: '富文本',
        carousel: '轮播',
        dashboard: '仪表盘',
        card: '卡片'
      }
      let i = 1
src/menu/menushell/card.jsx
@@ -7,6 +7,7 @@
const AntvBar = asyncComponent(() => import('@/menu/components/chart/antv-bar'))
const MainSearch = asyncComponent(() => import('@/menu/components/search/main-search'))
const AntvPie = asyncComponent(() => import('@/menu/components/chart/antv-pie'))
const AntvDashboard = asyncComponent(() => import('@/menu/components/chart/antv-dashboard'))
const AntvTabs = asyncComponent(() => import('@/menu/components/tabs/antv-tabs'))
const DataCard = asyncComponent(() => import('@/menu/components/card/data-card'))
const PropCard = asyncComponent(() => import('@/menu/components/card/prop-card'))
@@ -59,6 +60,8 @@
      return (<MainSearch card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'pie') {
      return (<AntvPie card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'dashboard') {
      return (<AntvDashboard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'form') {
      return (<NormalForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'tabs') {
src/menu/menushell/index.jsx
@@ -19,6 +19,10 @@
    handleList({...menu, components: _cards})
    setCards(_cards)
  }
  if (menu.components.length > cards.length) {
    setCards(menu.components)
  }
  
  const findCard = id => {
    const card = cards.filter(c => `${c.uuid}` === id)[0]
@@ -93,6 +97,7 @@
        code: '自定义',
        carousel: '轮播',
        form: '表单',
        dashboard: '仪表盘',
        card: '卡片'
      }
      let i = 1
src/menu/modulesource/option.jsx
@@ -17,6 +17,7 @@
import Carousel from '@/assets/mobimg/carousel.png'
import Carousel1 from '@/assets/mobimg/carousel1.png'
import form from '@/assets/mobimg/form.png'
import dashboard from '@/assets/mobimg/dashboard.png'
// 组件配置信息
export const menuOptions = [
@@ -35,8 +36,9 @@
  { type: 'menu', url: bar1, component: 'bar', subtype: 'bar1', title: '条形图', width: 24 },
  { type: 'menu', url: Pie, component: 'pie', subtype: 'pie', title: '饼图', width: 12 },
  { type: 'menu', url: Pie1, component: 'pie', subtype: 'ring', title: '环图', width: 12 },
  { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '南丁格尔图', width: 12 },
  { type: 'menu', url: dashboard, component: 'dashboard', subtype: 'dashboard', title: '仪表盘', width: 12 },
  { type: 'menu', url: Editor, component: 'editor', subtype: 'brafteditor', title: '富文本', width: 24 },
  { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '自定义', width: 24 },
  { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '南丁格尔图', width: 12 },
  { type: 'menu', url: group, component: 'group', subtype: 'normalgroup', title: '分组', width: 24, forbid: ['billPrint'] },
]
src/mob/mobshell/index.jsx
@@ -19,6 +19,10 @@
    handleList({...menu, components: _cards})
    setCards(_cards)
  }
  if (menu.components.length > cards.length) {
    setCards(menu.components)
  }
  
  const findCard = id => {
    const card = cards.filter(c => `${c.uuid}` === id)[0]
@@ -92,6 +96,7 @@
        editor: '富文本',
        code: '自定义',
        carousel: '轮播',
        dashboard: '仪表盘',
        form: '表单',
        card: '卡片',
        login: '登录'
src/mob/modulesource/option.jsx
@@ -18,6 +18,7 @@
import Carousel1 from '@/assets/mobimg/carousel1.png'
import form from '@/assets/mobimg/form.png'
import Login from '@/assets/mobimg/login.png'
import dashboard from '@/assets/mobimg/dashboard.png'
// 组件配置信息
export const menuOptions = [
@@ -37,8 +38,9 @@
  { type: 'menu', url: bar1, component: 'bar', subtype: 'bar1', title: '条形图', width: 24 },
  { type: 'menu', url: Pie, component: 'pie', subtype: 'pie', title: '饼图', width: 24 },
  { type: 'menu', url: Pie1, component: 'pie', subtype: 'ring', title: '环图', width: 24 },
  { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '自定义', width: 24 },
  { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '南丁格尔图', width: 24 },
  { type: 'menu', url: dashboard, component: 'dashboard', subtype: 'dashboard', title: '仪表盘', width: 12 },
  { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '自定义', width: 24 },
  { type: 'menu', url: group, component: 'group', subtype: 'normalgroup', title: '分组', width: 24 },
  { type: 'menu', url: Login, component: 'login', subtype: 'normallogin', title: '登录', width: 24 },
]
src/pc/menushell/index.jsx
@@ -19,6 +19,10 @@
    handleList({...menu, components: _cards})
    setCards(_cards)
  }
  if (menu.components.length > cards.length) {
    setCards(menu.components)
  }
  
  const findCard = id => {
    const card = cards.filter(c => `${c.uuid}` === id)[0]
@@ -102,6 +106,7 @@
        code: '自定义',
        navbar: '导航栏',
        carousel: '轮播',
        dashboard: '仪表盘',
        card: '卡片',
        login: '登录'
      }
src/pc/modulesource/option.jsx
@@ -19,6 +19,7 @@
import Carousel1 from '@/assets/mobimg/carousel1.png'
import form from '@/assets/mobimg/form.png'
import Login from '@/assets/mobimg/login.png'
import dashboard from '@/assets/mobimg/dashboard.png'
// 组件配置信息
export const menuOptions = [
@@ -38,9 +39,10 @@
  { type: 'menu', url: bar1, component: 'bar', subtype: 'bar1', title: '条形图', width: 24 },
  { type: 'menu', url: Pie, component: 'pie', subtype: 'pie', title: '饼图', width: 12 },
  { type: 'menu', url: Pie1, component: 'pie', subtype: 'ring', title: '环图', width: 12 },
  { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '南丁格尔图', width: 12 },
  { type: 'menu', url: dashboard, component: 'dashboard', subtype: 'dashboard', title: '仪表盘', width: 12 },
  { type: 'menu', url: Editor, component: 'editor', subtype: 'brafteditor', title: '富文本', width: 24 },
  { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '自定义', width: 24 },
  { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '南丁格尔图', width: 12 },
  { type: 'menu', url: group, component: 'group', subtype: 'normalgroup', title: '分组', width: 24 },
  { type: 'menu', url: Login, component: 'login', subtype: 'normallogin', title: '登录', width: 24 },
]
src/tabviews/custom/components/chart/antv-dashboard/index.jsx
New file
@@ -0,0 +1,467 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Chart, registerShape } from '@antv/g2'
import { Spin, notification } from 'antd'
import moment from 'moment'
import Api from '@/api'
import Utils from '@/utils/utils.js'
import asyncComponent from '@/utils/asyncComponent'
import UtilsDM from '@/utils/utils-datamanage.js'
import MKEmitter from '@/utils/events.js'
import './index.scss'
const NormalHeader = asyncComponent(() => import('@/tabviews/custom/components/share/normalheader'))
registerShape('point', 'pointer', {
  draw(cfg, container) {
    const group = container.addGroup({});
    // 获取极坐标系下画布中心点
    const center = this.parsePoint({ x: 0, y: 0 });
    // 绘制指针
    group.addShape('line', {
      attrs: {
        x1: center.x,
        y1: center.y,
        x2: cfg.x,
        y2: cfg.y,
        stroke: cfg.color,
        lineWidth: 5,
        lineCap: 'round',
      },
    });
    group.addShape('circle', {
      attrs: {
        x: center.x,
        y: center.y,
        r: 9.75,
        stroke: cfg.color,
        lineWidth: 4.5,
        fill: '#fff',
      },
    });
    return group;
  },
})
class DashboardChart extends Component {
  static propTpyes = {
    BID: PropTypes.any,              // 父级Id
    data: PropTypes.array,           // 统一查询数据
    config: PropTypes.object,        // 组件配置信息
    mainSearch: PropTypes.any,       // 外层搜索条件
    menuType: PropTypes.any,         // 菜单类型
  }
  state = {
    BID: '',                   // 上级ID
    config: null,              // 图表配置信息
    loading: false,            // 数据加载状态
    chartId: Utils.getuuid(),  // 图表Id
    title: '',                 // 组件标题
    sync: false,               // 是否统一请求数据
    plot: null,                // 图表设置
    data: null,                // 数据
  }
  UNSAFE_componentWillMount () {
    const { config, data, initdata, BID } = this.props
    let _config = fromJS(config).toJS()
    let _data = {}
    let _sync = _config.setting.sync === 'true'
    if (_sync && data) {
      _data = data[_config.dataName] || {}
      if (_data && Array.isArray(_data)) {
        _data = _data[0] || {}
      }
      _sync = false
    } else if (_sync && initdata) {
      _data = initdata || {}
      if (_data && Array.isArray(_data)) {
        _data = _data[0] || {}
      }
      _sync = false
    }
    if (_config.style) {
      _config.style = {..._config.style, minHeight: (config.plot.height || 400)}
    } else {
      _config.style = {minHeight: (config.plot.height || 400)}
    }
    this.setState({
      config: _config,
      data: _data,
      BID: BID || '',
      arr_field: _config.columns.map(col => col.field).join(','),
      plot: _config.plot,
      sync: _sync,
      title: config.plot.title
    }, () => {
      if (config.setting.sync !== 'true' && config.setting.onload === 'true') {
        this.loadData()
      } else if (config.setting.sync === 'true' && _data) {
        this.handleData()
      }
    })
  }
  /**
   * @description 图表数据更新,刷新内容
   */
  UNSAFE_componentWillReceiveProps (nextProps) {
    const { sync, config } = this.state
    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
      let _data = {}
      if (nextProps.data && nextProps.data[config.dataName]) {
        _data = nextProps.data[config.dataName] || {}
      }
      if (_data.hasOwnProperty(config.plot.valueField)) {
        _data.value = _data[config.plot.valueField]
      }
      this.setState({sync: false, data: _data}, () => {
        this.handleData()
      })
    } else if (nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
      if (config.setting.syncRefresh === 'true') {
        this.setState({}, () => {
          this.loadData()
        })
      }
    }
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  componentDidMount () {
    MKEmitter.addListener('reloadData', this.reloadData)
    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
    this.handleTimer()
  }
  /**
   * @description 组件销毁,清除state更新,清除快捷键设置
   */
  componentWillUnmount () {
    clearTimeout(this.timer)
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('reloadData', this.reloadData)
    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
  }
  handleTimer = () => {
    const { config } = this.state
    if (!config.timer) return
    const _change = {
      '15s': 15000,
      '30s': 30000,
      '1min': 60000,
      '5min': 300000,
      '10min': 600000,
      '15min': 900000,
      '30min': 1800000,
      '1hour': 3600000
    }
    let timer = _change[config.timer]
    if (!timer) return
    let _param = {
      func: 's_get_timers_role',
      LText: `select '${window.GLOB.appkey || ''}','${config.uuid}'`,
      timer_type: config.timer,
      component_id: config.uuid
    }
    _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')          // 时间戳
    _param.LText = Utils.formatOptions(_param.LText)                   // 关键字符替换,base64加密
    _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)   // md5密钥
    Api.getSystemConfig(_param).then(result => {
      if (!result.status) {
        notification.warning({
          top: 92,
          message: result.message,
          duration: 5
        })
        return
      } else if (result.run_type) {
        this.setState({timer})
        this.timer = setTimeout(() => {
          this.timerTask()
        }, timer)
      }
    })
  }
  timerTask = () => {
    const { timer } = this.state
    if (!timer) return
    this.loadData(true)
    this.timer = setTimeout(() => {
      this.timerTask()
    }, timer)
  }
  reloadData = (menuId) => {
    const { config } = this.state
    if (config.uuid !== menuId) return
    this.loadData()
  }
  resetParentParam = (MenuID, id) => {
    const { config } = this.state
    if (!config.setting.supModule || config.setting.supModule !== MenuID) return
    if (id !== this.state.BID) {
      this.setState({ BID: id }, () => {
        this.loadData()
      })
    }
  }
  handleData = () => {
    let _element = document.getElementById(this.state.chartId)
    if (_element) {
      _element.innerHTML = ''
    }
    this.dashboardrender()
  }
  async loadData (hastimer) {
    const { mainSearch, menuType } = this.props
    const { config, arr_field, BID } = this.state
    if (config.setting.supModule && !BID) { // BID 不存在时,不做查询
      this.setState({
        data: {}
      }, () => {
        this.handleData()
      })
      return
    }
    let searches = []
    if (mainSearch && mainSearch.length > 0) { // 主表搜索条件
      let keys = []
      mainSearch.forEach(item => {
        if (!keys.includes(item.key)) {
          searches.push(item)
        }
      })
    }
    if (!hastimer) {
      this.setState({
        loading: true
      })
    }
    let _orderBy = config.setting.order || ''
    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, '', '', BID, menuType)
    let result = await Api.genericInterface(param)
    if (result.status) {
      let data = {}
      if (result.data && result.data[0] && result.data[0].hasOwnProperty(config.plot.valueField)) {
        data.value = result.data[0][config.plot.valueField]
      }
      this.setState({
        data,
        loading: false
      }, () => {
        this.handleData()
      })
    } else {
      this.setState({
        loading: false,
        timer: null
      })
      notification.error({
        top: 92,
        message: result.message,
        duration: 10
      })
    }
  }
  /**
   * @description 饼图渲染
   */
  dashboardrender = () => {
    const { plot, chartId, data } = this.state
    const chart = new Chart({
      container: chartId,
      autoFit: true,
      height: plot.height ? (plot.height - 80) : 320,
      padding: [0, 0, 0, 0],
    })
    chart.data([data]);
    chart.scale('value', {
      min: 0,
      max: plot.maxValue,
      tickInterval: plot.tickInterval,
    });
    chart.coordinate('polar', {
      startAngle: (-9 / 8) * Math.PI,
      endAngle: (1 / 8) * Math.PI,
      radius: 0.75,
    });
    chart.axis('1', false);
    chart.axis('value', {
      line: null,
      label: {
        offset: -36,
        style: {
          fontSize: 18,
          fill: plot.tickColor,
          textAlign: 'center',
          textBaseline: 'middle',
        },
      },
      tickLine: {
        length: -24,
        style: {
          stroke: plot.tickColor
        }
      },
      grid: null,
    });
    chart.legend(false);
    chart.tooltip(false);
    chart
      .point()
      .position('value*1')
      .shape('pointer')
      .color('value', (val) => {
        if (!val && val !== 0) return 'transparent'
        let _color = '#1890FF'
        if (plot.colors && plot.colors.length > 0) {
          _color = plot.colors[plot.colors.length - 1].color || '#1890FF'
          plot.colors.some(item => {
            if (item.tick > val) {
              _color = item.color
              return true
            }
            return false
          })
        }
        return _color
      })
      .animate({
        appear: {
          animation: 'fade-in'
        }
      });
    // 绘制仪表盘背景
    chart.annotation().arc({
      top: false,
      start: [0, 1],
      end: [plot.maxValue, 1],
      style: {
        stroke: '#CBCBCB',
        lineWidth: 18,
        lineDash: null,
      },
    })
    if (!plot.colors || plot.colors.length === 0) {
      chart.annotation().arc({
        start: [0, 1],
        end: [plot.maxValue, 1],
        style: {
          stroke: '#1890FF',
          lineWidth: 18,
          lineDash: null,
        },
      });
    } else {
      let start = 0
      plot.colors.forEach(item => {
        chart.annotation().arc({
          start: [start, 1],
          end: [item.tick, 1],
          style: {
            stroke: item.color,
            lineWidth: 18,
            lineDash: null,
          },
        })
        start = item.tick
      })
    }
    if (plot.label) {
      chart.annotation().text({
        position: ['50%', '85%'],
        content: plot.label,
        style: {
          fontSize: 20,
          fill: plot.labelColor,
          textAlign: 'center',
        },
      })
    }
    if (data.hasOwnProperty('value')) {
      let val = data.value
      if (plot.percent !== 'false' && plot.maxValue) {
        val = +(val / plot.maxValue * 100).toFixed(2) + ' %'
      }
      chart.annotation().text({
        position: ['50%', '90%'],
        content: val,
        style: {
          fontSize: 36,
          fill: plot.labelColor,
          textAlign: 'center',
        },
        offsetY: 15,
      });
    }
    chart.render()
  }
  render() {
    const { config, loading, empty } = this.state
    return (
      <div className="custom-dashboard-plot-box" style={config.style}>
        {loading ?
          <div className="loading-mask">
            <div className="ant-spin-blur"></div>
            <Spin />
          </div> : null
        }
        <NormalHeader config={config} />
        <div className="canvas-wrap">
          <div className={'canvas' + (empty ? ' empty' : '')} id={this.state.chartId}></div>
        </div>
      </div>
    )
  }
}
export default DashboardChart
src/tabviews/custom/components/chart/antv-dashboard/index.scss
New file
@@ -0,0 +1,105 @@
.custom-dashboard-plot-box {
  position: relative;
  background: #ffffff;
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  min-height: 100px;
  .canvas-wrap {
    margin: 0 0px;
    position: relative;
    .chart-action {
      position: absolute;
      top: 2px;
      right: 5px;
      z-index: 1;
    }
    .chart-action.with-title {
      top: 35px;
    }
  }
  .canvas {
    margin: 0;
    padding: 15px;
    letter-spacing: 0px;
  }
  .canvas.empty {
    div {
      opacity: 0;
    }
  }
  .ant-empty {
    position: absolute;
    top: calc(50% - 34px);
    left: calc(50% - 92px);
    .ant-empty-image {
      height: 60px;
    }
  }
  .loading-mask {
    position: absolute;
    left: 0px;
    top: 0;
    right: 0px;
    bottom: 0px;
    z-index: 1;
    .ant-spin-blur {
      position: absolute;
      width: 100%;
      height: 100%;
      opacity: 0.5;
      background: #ffffff;
    }
  }
  > .ant-select {
    width: 150px;
    float: right;
    position: relative;
    z-index: 1;
    .ant-select-selection {
      min-height: 24px;
      height: 28px;
      li {
        background: unset;
        border: 0;
        width: 99%;
        padding: 0;
        margin-right: 0;
        cursor: pointer;
        .type-label {
          overflow: hidden;
          word-break: break-word;
          white-space: nowrap;
          text-overflow: ellipsis;
        }
      }
      li + li {
        margin-top: 0;
        width: 1%;
        opacity: 0;
      }
    }
  }
  > .ant-select.ant-select-focused {
    .ant-select-selection {
      li {
        width: 50%;
      }
      li + li {
        width: 49%;
        opacity: 1;
      }
    }
  }
  .g2-tooltip-list{
    display: none;
  }
  .g2-tooltip-title + .g2-tooltip-list{
    display: block;
  }
}
src/tabviews/custom/components/group/normal-group/index.jsx
@@ -15,6 +15,7 @@
// 通用组件
const AntvBarAndLine = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-bar-line'))
const AntvPie = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-pie'))
const AntvDashboard = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-dashboard'))
const DataCard = asyncComponent(() => import('@/tabviews/custom/components/card/data-card'))
const TableCard = asyncComponent(() => import('@/tabviews/custom/components/card/table-card'))
const NormalTable = asyncComponent(() => import('@/tabviews/custom/components/table/normal-table'))
@@ -253,6 +254,12 @@
            <AntvPie data={data} config={item} BID={_bid} mainSearch={mainSearch} menuType={menuType} />
          </Col>
        )
      } else if (item.type === 'dashboard') {
        return (
          <Col span={item.width} key={item.uuid}>
            <AntvDashboard config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} />
          </Col>
        )
      } else if (item.type === 'card' && item.subtype === 'datacard') {
        return (
          <Col span={item.width} key={item.uuid}>
src/tabviews/custom/components/share/normalTable/index.jsx
@@ -803,12 +803,13 @@
    }
    return (
      <div className={'normal-custom-table ' + setting.tableHeader} id={tableId}>
      <div className={`normal-custom-table ${setting.tableHeader || ''} ${setting.mode || ''}`} id={tableId}>
        {(setting.tableType === 'radio' || setting.tableType === 'checkbox') && data && data.length > 0 ?
          <Switch title="收起" className="main-pickup" checkedChildren="开" unCheckedChildren="关" checked={pickup} onChange={this.pickupChange} /> : null
        }
        <Table
          components={components}
          style={setting.style}
          size={setting.size || 'middle'}
          bordered={setting.bordered !== 'false'}
          rowSelection={rowSelection}
src/tabviews/custom/components/share/normalTable/index.scss
@@ -14,6 +14,10 @@
    position: relative;
    z-index: 1;
  }
  .ant-table {
    color: inherit;
    font-size: inherit;
  }
  table {
    max-width: 100%;
@@ -163,6 +167,34 @@
    display: none;
  }
}
.normal-custom-table.ghost {
  .main-pickup {
    display: none;
  }
  .ant-table-thead > tr {
    > th {
      color: inherit;
      background: transparent;
      .ant-table-column-sorter .ant-table-column-sorter-inner {
        color: inherit;
      }
    }
    > th:hover {
      background: transparent;
    }
  }
  .ant-table-body {
    overflow-x: auto;
    tr {
      td {
        background: transparent!important;
      }
    }
    tr:hover td {
      background: transparent!important;
    }
  }
}
.image-scale-modal {
  width: 70vw;
  min-height: 80vh;
src/tabviews/custom/components/share/tabtransfer/index.jsx
@@ -16,6 +16,7 @@
const AntvBarAndLine = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-bar-line'))
const MainSearch = asyncComponent(() => import('@/tabviews/zshare/topSearch'))
const AntvPie = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-pie'))
const AntvDashboard = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-dashboard'))
const AntvTabs = asyncComponent(() => import('@/tabviews/custom/components/tabs/antv-tabs'))
const DataCard = asyncComponent(() => import('@/tabviews/custom/components/card/data-card'))
const TableCard = asyncComponent(() => import('@/tabviews/custom/components/card/table-card'))
@@ -272,6 +273,12 @@
            <AntvPie data={data} config={item} BID={BID} mainSearch={mainSearch} menuType={menuType} />
          </Col>
        )
      } else if (item.type === 'dashboard') {
        return (
          <Col span={item.width} key={item.uuid}>
            <AntvDashboard config={item} data={data} BID={BID} mainSearch={mainSearch} menuType={menuType} />
          </Col>
        )
      } else if (item.type === 'search') {
        return (
          <Col span={item.width} key={item.uuid}>
src/tabviews/custom/components/table/normal-table/index.jsx
@@ -95,13 +95,21 @@
      }
    })
    let setting = {..._config.setting, ..._config.wrap, style: {}}
    if (setting.color) {
      setting.style.color = setting.color
    }
    if (setting.fontSize) {
      setting.style.fontSize = setting.fontSize
    }
    this.setState({
      BID: BID || '',
      title: _config.wrap.title,
      sync: _sync,
      data: _data,
      config: _config,
      setting: {..._config.setting, ..._config.wrap},
      setting: setting,
      searchlist: _config.search,
      actions: _config.action,
      columns: _config.cols,
src/tabviews/custom/index.jsx
@@ -21,6 +21,7 @@
const AntvBarAndLine = asyncComponent(() => import('./components/chart/antv-bar-line'))
const AntvPie = asyncComponent(() => import('./components/chart/antv-pie'))
const AntvTabs = asyncComponent(() => import('./components/tabs/antv-tabs'))
const AntvDashboard = asyncComponent(() => import('./components/chart/antv-dashboard'))
const DataCard = asyncComponent(() => import('./components/card/data-card'))
const PropCard = asyncComponent(() => import('./components/card/prop-card'))
const NormalForm = asyncComponent(() => import('./components/form/normal-form'))
@@ -477,14 +478,14 @@
        }
        item.components = this.filterComponent(item.components, roleId, permAction, permMenus)
      } else if (item.type === 'pie' || item.type === 'bar' || item.type === 'line') {
      } else if (item.type === 'pie' || item.type === 'bar' || item.type === 'line' || item.type === 'dashboard') {
        if (
          item.plot.blacklist && item.plot.blacklist.length > 0 &&
          item.plot.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0
        ) {
          return false
        }
      } else {
      } else if (item.wrap) {
        if (
          item.wrap.blacklist && item.wrap.blacklist.length > 0 &&
          item.wrap.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0
@@ -1005,6 +1006,12 @@
            <AntvPie config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} />
          </Col>
        )
      } else if (item.type === 'dashboard') {
        return (
          <Col span={item.width} key={item.uuid}>
            <AntvDashboard config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} />
          </Col>
        )
      } else if (item.type === 'form') {
        return (
          <Col span={item.width} key={item.uuid}>
src/views/billprint/index.scss
@@ -32,17 +32,23 @@
}
.print-page {
  color: rgba(0,0,0,1);
  table {
    color: rgba(0,0,0,1);
    border-radius: 0!important;
    .ant-table-column-sorter {
      display: none!important;
    }
  }
  .ant-table-thead > tr > th {
    color: rgba(0,0,0,1);
    background: transparent!important;
    border-radius: 0!important;
  }
}
.print-page:last-child {
  height: auto!important;
}
.normal-custom-table .main-pickup {
  display: none!important;
src/views/menudesign/index.jsx
@@ -857,6 +857,8 @@
          if (!item.plot.Xaxis) {
            error = `组件《${item.name}》图表字段尚未设置!`
          }
        } else if (item.type === 'dashboard' && !item.plot.valueField) {
          error = `组件《${item.name}》显示值尚未设置!`
        }
      })
    }
src/views/mobdesign/index.jsx
@@ -1300,6 +1300,8 @@
          if (!item.plot.Xaxis) {
            error = `组件《${item.name}》图表字段尚未设置!`
          }
        } else if (item.type === 'dashboard' && !item.plot.valueField) {
          error = `组件《${item.name}》显示值尚未设置!`
        }
      })
    }
src/views/pcdesign/index.jsx
@@ -1345,6 +1345,8 @@
          if (!item.plot.Xaxis) {
            error = `组件《${item.name}》图表字段尚未设置!`
          }
        } else if (item.type === 'dashboard' && !item.plot.valueField) {
          error = `组件《${item.name}》显示值尚未设置!`
        }
      })
    }