7 文件已重命名
299个文件已修改
14 文件已复制
157个文件已添加
11个文件已删除
| | |
| | | 'use strict'; |
| | | // 'use strict'; |
| | | |
| | | const fs = require('fs'); |
| | | const path = require('path'); |
| | |
| | | 'use strict'; |
| | | // 'use strict'; |
| | | |
| | | const fs = require('fs'); |
| | | const path = require('path'); |
| | |
| | | 'use strict'; |
| | | // 'use strict'; |
| | | |
| | | const path = require('path'); |
| | | const fs = require('fs'); |
| | |
| | | 'use strict'; |
| | | // 'use strict'; |
| | | |
| | | const { resolveModuleName } = require('ts-pnp'); |
| | | |
| | |
| | | pathinfo: isEnvDevelopment, |
| | | // There will be one main bundle, and one file per asynchronous chunk. |
| | | // In development, it does not produce real files. |
| | | // contenthash => hash |
| | | filename: isEnvProduction |
| | | ? 'static/js/[name].[contenthash:8].js' |
| | | ? 'static/js/[name].[hash:8].js' |
| | | : isEnvDevelopment && 'static/js/bundle.js', |
| | | // TODO: remove this when upgrading to webpack 5 |
| | | futureEmitAssets: true, |
| | | // There are also additional JS chunk files if you use code splitting. |
| | | // contenthash => hash |
| | | chunkFilename: isEnvProduction |
| | | ? 'static/js/[name].[contenthash:8].chunk.js' |
| | | ? 'static/js/[name].[hash:8].chunk.js' |
| | | : isEnvDevelopment && 'static/js/[name].chunk.js', |
| | | // We inferred the "public path" (such as / or /my-project) from homepage. |
| | | // We use "/" in development. |
| | |
| | | new MiniCssExtractPlugin({ |
| | | // Options similar to the same options in webpackOptions.output |
| | | // both options are optional |
| | | filename: 'static/css/[name].[contenthash:8].css', |
| | | chunkFilename: 'static/css/[name].[contenthash:8].chunk.css', |
| | | // contenthash => hash |
| | | filename: 'static/css/[name].[hash:8].css', |
| | | chunkFilename: 'static/css/[name].[hash:8].chunk.css', |
| | | }), |
| | | // Generate a manifest file which contains a mapping of all asset filenames |
| | | // to their corresponding output file so that tools can pick it up without |
| | |
| | | 'use strict'; |
| | | // 'use strict'; |
| | | |
| | | const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware'); |
| | | const evalSourceMapMiddleware = require('react-dev-utils/evalSourceMapMiddleware'); |
| | |
| | | } |
| | | }, |
| | | "@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": { |
| | |
| | | } |
| | | }, |
| | | "@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": { |
| | |
| | | "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==" |
| | | } |
| | | } |
| | | }, |
| | |
| | | }, |
| | | "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", |
| | |
| | | }, |
| | | "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": { |
| | |
| | | "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-9.0.1.tgz", |
| | | "integrity": "sha512-6It2EVfGskxZCQhuykrfnALg7oVeiI6KclWSmGDqB0AiInVrTGB9Jp9i4/Ad21u9Jde/voVQz6eFX/eSg/UsPA==" |
| | | }, |
| | | "@fast-csv/format": { |
| | | "version": "4.3.5", |
| | | "resolved": "https://registry.npmjs.org/@fast-csv/format/-/format-4.3.5.tgz", |
| | | "integrity": "sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A==", |
| | | "requires": { |
| | | "@types/node": "^14.0.1", |
| | | "lodash.escaperegexp": "^4.1.2", |
| | | "lodash.isboolean": "^3.0.3", |
| | | "lodash.isequal": "^4.5.0", |
| | | "lodash.isfunction": "^3.0.9", |
| | | "lodash.isnil": "^4.0.0" |
| | | } |
| | | }, |
| | | "@fast-csv/parse": { |
| | | "version": "4.3.6", |
| | | "resolved": "https://registry.npmjs.org/@fast-csv/parse/-/parse-4.3.6.tgz", |
| | | "integrity": "sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA==", |
| | | "requires": { |
| | | "@types/node": "^14.0.1", |
| | | "lodash.escaperegexp": "^4.1.2", |
| | | "lodash.groupby": "^4.6.0", |
| | | "lodash.isfunction": "^3.0.9", |
| | | "lodash.isnil": "^4.0.0", |
| | | "lodash.isundefined": "^3.0.1", |
| | | "lodash.uniq": "^4.5.0" |
| | | } |
| | | }, |
| | | "@hapi/address": { |
| | | "version": "2.1.1", |
| | | "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.1.tgz", |
| | |
| | | "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", |
| | |
| | | "version": "7.0.3", |
| | | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz", |
| | | "integrity": "sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==" |
| | | }, |
| | | "@types/node": { |
| | | "version": "14.14.44", |
| | | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.44.tgz", |
| | | "integrity": "sha512-+gaugz6Oce6ZInfI/tK4Pq5wIIkJMEJUu92RB3Eu93mtj4wjjjz9EB5mLp5s1pSsLXdC/CPut/xF20ZzAQJbTA==" |
| | | }, |
| | | "@types/prop-types": { |
| | | "version": "15.7.2", |
| | |
| | | "version": "1.2.0", |
| | | "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", |
| | | "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" |
| | | }, |
| | | "archiver": { |
| | | "version": "5.3.0", |
| | | "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.0.tgz", |
| | | "integrity": "sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg==", |
| | | "requires": { |
| | | "archiver-utils": "^2.1.0", |
| | | "async": "^3.2.0", |
| | | "buffer-crc32": "^0.2.1", |
| | | "readable-stream": "^3.6.0", |
| | | "readdir-glob": "^1.0.0", |
| | | "tar-stream": "^2.2.0", |
| | | "zip-stream": "^4.1.0" |
| | | }, |
| | | "dependencies": { |
| | | "async": { |
| | | "version": "3.2.0", |
| | | "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", |
| | | "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" |
| | | }, |
| | | "readable-stream": { |
| | | "version": "3.6.0", |
| | | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", |
| | | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", |
| | | "requires": { |
| | | "inherits": "^2.0.3", |
| | | "string_decoder": "^1.1.1", |
| | | "util-deprecate": "^1.0.1" |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | "archiver-utils": { |
| | | "version": "2.1.0", |
| | | "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", |
| | | "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", |
| | | "requires": { |
| | | "glob": "^7.1.4", |
| | | "graceful-fs": "^4.2.0", |
| | | "lazystream": "^1.0.0", |
| | | "lodash.defaults": "^4.2.0", |
| | | "lodash.difference": "^4.5.0", |
| | | "lodash.flatten": "^4.4.0", |
| | | "lodash.isplainobject": "^4.0.6", |
| | | "lodash.union": "^4.6.0", |
| | | "normalize-path": "^3.0.0", |
| | | "readable-stream": "^2.0.0" |
| | | }, |
| | | "dependencies": { |
| | | "normalize-path": { |
| | | "version": "3.0.0", |
| | | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", |
| | | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" |
| | | } |
| | | } |
| | | }, |
| | | "are-we-there-yet": { |
| | | "version": "1.1.5", |
| | |
| | | "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", |
| | | "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" |
| | | }, |
| | | "binary": { |
| | | "version": "0.3.0", |
| | | "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", |
| | | "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", |
| | | "requires": { |
| | | "buffers": "~0.1.1", |
| | | "chainsaw": "~0.1.0" |
| | | } |
| | | }, |
| | | "binary-extensions": { |
| | | "version": "1.13.1", |
| | | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", |
| | | "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" |
| | | }, |
| | | "bl": { |
| | | "version": "4.1.0", |
| | | "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", |
| | | "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", |
| | | "requires": { |
| | | "buffer": "^5.5.0", |
| | | "inherits": "^2.0.4", |
| | | "readable-stream": "^3.4.0" |
| | | }, |
| | | "dependencies": { |
| | | "buffer": { |
| | | "version": "5.7.1", |
| | | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", |
| | | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", |
| | | "requires": { |
| | | "base64-js": "^1.3.1", |
| | | "ieee754": "^1.1.13" |
| | | } |
| | | }, |
| | | "readable-stream": { |
| | | "version": "3.6.0", |
| | | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", |
| | | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", |
| | | "requires": { |
| | | "inherits": "^2.0.3", |
| | | "string_decoder": "^1.1.1", |
| | | "util-deprecate": "^1.0.1" |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | "block-stream": { |
| | | "version": "0.0.9", |
| | |
| | | "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", |
| | | "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==" |
| | | }, |
| | | "buffer-indexof-polyfill": { |
| | | "version": "1.0.2", |
| | | "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", |
| | | "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==" |
| | | }, |
| | | "buffer-xor": { |
| | | "version": "1.0.3", |
| | | "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", |
| | | "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" |
| | | }, |
| | | "buffers": { |
| | | "version": "0.1.1", |
| | | "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", |
| | | "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=" |
| | | }, |
| | | "builtin-status-codes": { |
| | | "version": "3.0.0", |
| | |
| | | "commander": "^2.16.0", |
| | | "crc-32": "~1.2.0", |
| | | "printj": "~1.1.2" |
| | | } |
| | | }, |
| | | "chainsaw": { |
| | | "version": "0.1.0", |
| | | "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", |
| | | "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", |
| | | "requires": { |
| | | "traverse": ">=0.3.0 <0.4" |
| | | }, |
| | | "dependencies": { |
| | | "traverse": { |
| | | "version": "0.3.9", |
| | | "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", |
| | | "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=" |
| | | } |
| | | } |
| | | }, |
| | | "chalk": { |
| | |
| | | "arity-n": "^1.0.4" |
| | | } |
| | | }, |
| | | "compress-commons": { |
| | | "version": "4.1.0", |
| | | "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.0.tgz", |
| | | "integrity": "sha512-ofaaLqfraD1YRTkrRKPCrGJ1pFeDG/MVCkVVV2FNGeWquSlqw5wOrwOfPQ1xF2u+blpeWASie5EubHz+vsNIgA==", |
| | | "requires": { |
| | | "buffer-crc32": "^0.2.13", |
| | | "crc32-stream": "^4.0.1", |
| | | "normalize-path": "^3.0.0", |
| | | "readable-stream": "^3.6.0" |
| | | }, |
| | | "dependencies": { |
| | | "normalize-path": { |
| | | "version": "3.0.0", |
| | | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", |
| | | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" |
| | | }, |
| | | "readable-stream": { |
| | | "version": "3.6.0", |
| | | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", |
| | | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", |
| | | "requires": { |
| | | "inherits": "^2.0.3", |
| | | "string_decoder": "^1.1.1", |
| | | "util-deprecate": "^1.0.1" |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | "compressible": { |
| | | "version": "2.0.17", |
| | | "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz", |
| | |
| | | "requires": { |
| | | "exit-on-epipe": "~1.0.1", |
| | | "printj": "~1.1.0" |
| | | } |
| | | }, |
| | | "crc32-stream": { |
| | | "version": "4.0.2", |
| | | "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", |
| | | "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", |
| | | "requires": { |
| | | "crc-32": "^1.2.0", |
| | | "readable-stream": "^3.4.0" |
| | | }, |
| | | "dependencies": { |
| | | "readable-stream": { |
| | | "version": "3.6.0", |
| | | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", |
| | | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", |
| | | "requires": { |
| | | "inherits": "^2.0.3", |
| | | "string_decoder": "^1.1.1", |
| | | "util-deprecate": "^1.0.1" |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | "create-ecdh": { |
| | |
| | | "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", |
| | | "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" |
| | | }, |
| | | "duplexer2": { |
| | | "version": "0.1.4", |
| | | "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", |
| | | "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", |
| | | "requires": { |
| | | "readable-stream": "^2.0.2" |
| | | } |
| | | }, |
| | | "duplexify": { |
| | | "version": "3.7.1", |
| | | "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", |
| | |
| | | "safe-buffer": "^5.1.1" |
| | | } |
| | | }, |
| | | "exceljs": { |
| | | "version": "4.2.1", |
| | | "resolved": "https://registry.npmjs.org/exceljs/-/exceljs-4.2.1.tgz", |
| | | "integrity": "sha512-EogoTdXH1X1PxqD9sV8caYd1RIfXN3PVlCV+mA/87CgdO2h4X5xAEbr7CaiP8tffz7L4aBFwsdMbjfMXi29NjA==", |
| | | "requires": { |
| | | "archiver": "^5.0.0", |
| | | "dayjs": "^1.8.34", |
| | | "fast-csv": "^4.3.1", |
| | | "jszip": "^3.5.0", |
| | | "readable-stream": "^3.6.0", |
| | | "saxes": "^5.0.1", |
| | | "tmp": "^0.2.0", |
| | | "unzipper": "^0.10.11", |
| | | "uuid": "^8.3.0" |
| | | }, |
| | | "dependencies": { |
| | | "readable-stream": { |
| | | "version": "3.6.0", |
| | | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", |
| | | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", |
| | | "requires": { |
| | | "inherits": "^2.0.3", |
| | | "string_decoder": "^1.1.1", |
| | | "util-deprecate": "^1.0.1" |
| | | } |
| | | }, |
| | | "rimraf": { |
| | | "version": "3.0.2", |
| | | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", |
| | | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", |
| | | "requires": { |
| | | "glob": "^7.1.3" |
| | | } |
| | | }, |
| | | "saxes": { |
| | | "version": "5.0.1", |
| | | "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", |
| | | "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", |
| | | "requires": { |
| | | "xmlchars": "^2.2.0" |
| | | } |
| | | }, |
| | | "tmp": { |
| | | "version": "0.2.1", |
| | | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", |
| | | "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", |
| | | "requires": { |
| | | "rimraf": "^3.0.0" |
| | | } |
| | | }, |
| | | "uuid": { |
| | | "version": "8.3.2", |
| | | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", |
| | | "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" |
| | | } |
| | | } |
| | | }, |
| | | "exec-sh": { |
| | | "version": "0.3.2", |
| | | "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.2.tgz", |
| | |
| | | "time-stamp": "^1.0.0" |
| | | } |
| | | }, |
| | | "fast-csv": { |
| | | "version": "4.3.6", |
| | | "resolved": "https://registry.npmjs.org/fast-csv/-/fast-csv-4.3.6.tgz", |
| | | "integrity": "sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw==", |
| | | "requires": { |
| | | "@fast-csv/format": "4.3.5", |
| | | "@fast-csv/parse": "4.3.6" |
| | | } |
| | | }, |
| | | "fast-deep-equal": { |
| | | "version": "2.0.1", |
| | | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", |
| | |
| | | } |
| | | }, |
| | | "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", |
| | |
| | | "inherits": "^2.0.1", |
| | | "readable-stream": "^2.0.0" |
| | | } |
| | | }, |
| | | "fs-constants": { |
| | | "version": "1.0.0", |
| | | "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", |
| | | "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" |
| | | }, |
| | | "fs-extra": { |
| | | "version": "7.0.1", |
| | |
| | | "version": "0.6.3", |
| | | "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.6.3.tgz", |
| | | "integrity": "sha512-47xSUiQioGaB96nqtp5/q55m0aBQSQdyIloMOc/x+QVTDZLNmXE892IIDrJ0hM1A5vcNUDD5tDffkSP5lCaIIA==" |
| | | }, |
| | | "immediate": { |
| | | "version": "3.0.6", |
| | | "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", |
| | | "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" |
| | | }, |
| | | "immer": { |
| | | "version": "1.10.0", |
| | |
| | | "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", |
| | | "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==" |
| | | }, |
| | | "js-table2excel": { |
| | | "version": "1.0.3", |
| | | "resolved": "https://registry.npmjs.org/js-table2excel/-/js-table2excel-1.0.3.tgz", |
| | | "integrity": "sha512-ivzOdgYqOD3zqzJZfW0Nm35P9BWffxD0Unwr+2QBeEawV7hhRY9RHBVNcvO6A9PhGkMyqPVL/u4/NeufaTTTXw==" |
| | | }, |
| | | "js-tokens": { |
| | | "version": "4.0.0", |
| | | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", |
| | |
| | | "object.assign": "^4.1.0" |
| | | } |
| | | }, |
| | | "jszip": { |
| | | "version": "3.6.0", |
| | | "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.6.0.tgz", |
| | | "integrity": "sha512-jgnQoG9LKnWO3mnVNBnfhkh0QknICd1FGSrXcgrl67zioyJ4wgx25o9ZqwNtrROSflGBCGYnJfjrIyRIby1OoQ==", |
| | | "requires": { |
| | | "lie": "~3.3.0", |
| | | "pako": "~1.0.2", |
| | | "readable-stream": "~2.3.6", |
| | | "set-immediate-shim": "~1.0.1" |
| | | } |
| | | }, |
| | | "killable": { |
| | | "version": "1.0.1", |
| | | "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", |
| | |
| | | "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", |
| | | "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" |
| | | }, |
| | | "lazystream": { |
| | | "version": "1.0.0", |
| | | "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", |
| | | "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", |
| | | "requires": { |
| | | "readable-stream": "^2.0.5" |
| | | } |
| | | }, |
| | | "lcid": { |
| | | "version": "1.0.0", |
| | | "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", |
| | |
| | | "prelude-ls": "~1.1.2", |
| | | "type-check": "~0.3.2" |
| | | } |
| | | }, |
| | | "lie": { |
| | | "version": "3.3.0", |
| | | "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", |
| | | "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", |
| | | "requires": { |
| | | "immediate": "~3.0.5" |
| | | } |
| | | }, |
| | | "listenercount": { |
| | | "version": "1.0.1", |
| | | "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", |
| | | "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=" |
| | | }, |
| | | "load-json-file": { |
| | | "version": "1.1.0", |
| | |
| | | "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", |
| | | "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" |
| | | }, |
| | | "lodash.defaults": { |
| | | "version": "4.2.0", |
| | | "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", |
| | | "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" |
| | | }, |
| | | "lodash.difference": { |
| | | "version": "4.5.0", |
| | | "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", |
| | | "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=" |
| | | }, |
| | | "lodash.escaperegexp": { |
| | | "version": "4.1.2", |
| | | "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", |
| | | "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=" |
| | | }, |
| | | "lodash.flatten": { |
| | | "version": "4.4.0", |
| | | "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", |
| | | "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" |
| | | }, |
| | | "lodash.groupby": { |
| | | "version": "4.6.0", |
| | | "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz", |
| | | "integrity": "sha1-Cwih3PaDl8OXhVwyOXg4Mt90A9E=" |
| | | }, |
| | | "lodash.isarguments": { |
| | | "version": "3.1.0", |
| | | "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", |
| | |
| | | "version": "3.0.4", |
| | | "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", |
| | | "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" |
| | | }, |
| | | "lodash.isboolean": { |
| | | "version": "3.0.3", |
| | | "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", |
| | | "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" |
| | | }, |
| | | "lodash.isequal": { |
| | | "version": "4.5.0", |
| | | "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", |
| | | "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" |
| | | }, |
| | | "lodash.isfunction": { |
| | | "version": "3.0.9", |
| | | "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", |
| | | "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" |
| | | }, |
| | | "lodash.isnil": { |
| | | "version": "4.0.0", |
| | | "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", |
| | | "integrity": "sha1-SeKM1VkBNFjIFMVHnTxmOiG/qmw=" |
| | | }, |
| | | "lodash.isplainobject": { |
| | | "version": "4.0.6", |
| | | "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", |
| | | "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" |
| | | }, |
| | | "lodash.isundefined": { |
| | | "version": "3.0.1", |
| | | "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", |
| | | "integrity": "sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g=" |
| | | }, |
| | | "lodash.keys": { |
| | | "version": "3.1.2", |
| | |
| | | "version": "4.0.1", |
| | | "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", |
| | | "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=" |
| | | }, |
| | | "lodash.union": { |
| | | "version": "4.6.0", |
| | | "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", |
| | | "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=" |
| | | }, |
| | | "lodash.uniq": { |
| | | "version": "4.5.0", |
| | |
| | | } |
| | | } |
| | | }, |
| | | "readdir-glob": { |
| | | "version": "1.1.1", |
| | | "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.1.tgz", |
| | | "integrity": "sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA==", |
| | | "requires": { |
| | | "minimatch": "^3.0.4" |
| | | } |
| | | }, |
| | | "readdirp": { |
| | | "version": "2.2.1", |
| | | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", |
| | |
| | | "version": "2.0.0", |
| | | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", |
| | | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" |
| | | }, |
| | | "set-immediate-shim": { |
| | | "version": "1.0.1", |
| | | "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", |
| | | "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" |
| | | }, |
| | | "set-value": { |
| | | "version": "2.0.1", |
| | |
| | | "inherits": "2" |
| | | } |
| | | }, |
| | | "tar-stream": { |
| | | "version": "2.2.0", |
| | | "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", |
| | | "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", |
| | | "requires": { |
| | | "bl": "^4.0.3", |
| | | "end-of-stream": "^1.4.1", |
| | | "fs-constants": "^1.0.0", |
| | | "inherits": "^2.0.3", |
| | | "readable-stream": "^3.1.1" |
| | | }, |
| | | "dependencies": { |
| | | "readable-stream": { |
| | | "version": "3.6.0", |
| | | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", |
| | | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", |
| | | "requires": { |
| | | "inherits": "^2.0.3", |
| | | "string_decoder": "^1.1.1", |
| | | "util-deprecate": "^1.0.1" |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | "temp": { |
| | | "version": "0.8.3", |
| | | "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", |
| | |
| | | "version": "1.0.0", |
| | | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", |
| | | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" |
| | | } |
| | | } |
| | | }, |
| | | "unzipper": { |
| | | "version": "0.10.11", |
| | | "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", |
| | | "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", |
| | | "requires": { |
| | | "big-integer": "^1.6.17", |
| | | "binary": "~0.3.0", |
| | | "bluebird": "~3.4.1", |
| | | "buffer-indexof-polyfill": "~1.0.0", |
| | | "duplexer2": "~0.1.4", |
| | | "fstream": "^1.0.12", |
| | | "graceful-fs": "^4.2.2", |
| | | "listenercount": "~1.0.1", |
| | | "readable-stream": "~2.3.6", |
| | | "setimmediate": "~1.0.4" |
| | | }, |
| | | "dependencies": { |
| | | "bluebird": { |
| | | "version": "3.4.7", |
| | | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", |
| | | "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=" |
| | | } |
| | | } |
| | | }, |
| | |
| | | } |
| | | } |
| | | }, |
| | | "zip-stream": { |
| | | "version": "4.1.0", |
| | | "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", |
| | | "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", |
| | | "requires": { |
| | | "archiver-utils": "^2.1.0", |
| | | "compress-commons": "^4.1.0", |
| | | "readable-stream": "^3.6.0" |
| | | }, |
| | | "dependencies": { |
| | | "readable-stream": { |
| | | "version": "3.6.0", |
| | | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", |
| | | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", |
| | | "requires": { |
| | | "inherits": "^2.0.3", |
| | | "string_decoder": "^1.1.1", |
| | | "util-deprecate": "^1.0.1" |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | "zrender": { |
| | | "version": "4.1.2", |
| | | "resolved": "https://registry.npmjs.org/zrender/-/zrender-4.1.2.tgz", |
| | |
| | | "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", |
| | |
| | | "eslint-plugin-jsx-a11y": "6.2.3", |
| | | "eslint-plugin-react": "7.14.3", |
| | | "eslint-plugin-react-hooks": "^1.6.1", |
| | | "exceljs": "^4.2.1", |
| | | "file-loader": "3.0.1", |
| | | "fs-extra": "7.0.1", |
| | | "html-webpack-plugin": "4.0.0-beta.5", |
| | |
| | | "jest-environment-jsdom-fourteen": "0.1.0", |
| | | "jest-resolve": "24.8.0", |
| | | "jest-watch-typeahead": "0.3.1", |
| | | "js-table2excel": "^1.0.3", |
| | | "jsbarcode": "^3.11.3", |
| | | "jssha": "^3.2.0", |
| | | "md5": "^2.2.1", |
| | |
| | | ] |
| | | ] |
| | | }, |
| | | "homepage": "./build", |
| | | "homepage": ".", |
| | | "devDependencies": { |
| | | "typescript": "^4.0.2" |
| | | } |
| | |
| | | var appPort = 'admin/index.html' |
| | | if ((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) { |
| | | appPort = 'mob/index.html' |
| | | } else { |
| | | if (config.defaultApp) { |
| | | appPort = 'pc/' |
| | | } |
| | | } else if (config.defaultApp) { |
| | | appPort = 'pc/index.html' |
| | | } |
| | | window.location.replace(url + appPort) |
| | | } |
| | |
| | | { |
| | | "appId": "20201221213901540C6BC419CE41E47FABA62", |
| | | "appkey": "2020122121373692319E639E61B0E46A6BC2C", |
| | | "mainSystemApi": "http://cloud.positecgroup.com:8080/webapi/dostar", |
| | | "mainSystemApi": "https://cloud.positecgroup.com/webapi/dostars", |
| | | "systemType": "", |
| | | "externalDatabase": "false", |
| | | "externalDatabase": "mkdata_kress_test", |
| | | "lineColor": "", |
| | | "filter": "false", |
| | | "defaultApp": "", |
| | | "defaultLang": "zh-CN", |
| | | "host": "http://qingqiumarket.cn", |
| | | "service": "mkwms/" |
| | | "WXAppID": "", |
| | | "debugger": false, |
| | | "host": "http://bms-test.kresstools.cn", |
| | | "service": "oc/" |
| | | } |
| | |
| | | /** |
| | | * @description 打开websql |
| | | */ |
| | | static openWebSql () { |
| | | static openWebSql (sysType) { |
| | | let service = window.GLOB.service ? '-' + window.GLOB.service.replace('/', '') : '' |
| | | try { |
| | | window.GLOB.WebSql = openDatabase(`mkdb${service}`, '1', 'mk-pc-database', 50 * 1024 * 1024) |
| | |
| | | // eslint-disable-next-line |
| | | throw 'CREATE TABLE ERROR' |
| | | }) |
| | | |
| | | if (sysType === 'local' && window.GLOB.systemType === '') { |
| | | tx.executeSql('CREATE TABLE IF NOT EXISTS FUNCS (func_code varchar(50), key_sql text, CDefine1 varchar(50), CDefine2 varchar(50), CDefine3 varchar(50))', [], () => { |
| | | |
| | | }, () => { |
| | | // eslint-disable-next-line |
| | | throw 'CREATE TABLE ERROR' |
| | | }) |
| | | } |
| | | }) |
| | | // window.GLOB.WebSql.transaction(tx => { |
| | | // tx.executeSql('DROP TABLE VERSIONS') |
| | |
| | | } |
| | | return new Promise((resolve, reject) => { |
| | | window.GLOB.WebSql.transaction(tx => { |
| | | tx.executeSql('SELECT * FROM VERSIONS', [], (tx, results) => { |
| | | tx.executeSql("SELECT * FROM VERSIONS where CDefine1='LongParam'", [], (tx, results) => { |
| | | if (results.rows.length === 0) { |
| | | tx.executeSql('DELETE FROM CONFIGS') |
| | | resolve({version: '', createDate: ''}) |
| | | } else if (results.rows.length === 1) { |
| | | resolve(results.rows[0]) |
| | | } else if (results.rows.length > 1) { |
| | | tx.executeSql('DELETE FROM VERSIONS') |
| | | tx.executeSql('DELETE FROM CONFIGS') |
| | | resolve({version: '', createDate: ''}) |
| | | } else { |
| | | resolve(results.rows[0]) |
| | | } |
| | | }, (tx, results) => { |
| | | window.GLOB.WebSql = null |
| | |
| | | static updateWebSqlTime (curTime) { |
| | | if (!window.GLOB.WebSql || !curTime) return |
| | | window.GLOB.WebSql.transaction(tx => { |
| | | tx.executeSql(`UPDATE VERSIONS SET createDate='${curTime}'`, [], () => {}, () => { |
| | | tx.executeSql(`UPDATE VERSIONS SET createDate='${curTime}' where CDefine1='LongParam'`, [], () => {}, () => { |
| | | window.GLOB.WebSql = null |
| | | }) |
| | | }) |
| | |
| | | static updateWebSqlversion (version, curTime) { |
| | | if (!window.GLOB.WebSql || !curTime || !version) return |
| | | window.GLOB.WebSql.transaction(tx => { |
| | | tx.executeSql(`UPDATE VERSIONS SET version='${version}', createDate='${curTime}'`, [], () => {}, () => { |
| | | tx.executeSql(`UPDATE VERSIONS SET version='${version}', createDate='${curTime}' where CDefine1='LongParam'`, [], () => {}, () => { |
| | | window.GLOB.WebSql = null |
| | | }) |
| | | }) |
| | |
| | | static createWebSqlversion (version, curTime) { |
| | | if (!window.GLOB.WebSql || !curTime || !version) return |
| | | window.GLOB.WebSql.transaction(tx => { |
| | | tx.executeSql('INSERT INTO VERSIONS (version, createDate) VALUES (?, ?)', [version, curTime], () => {}, () => { |
| | | tx.executeSql('INSERT INTO VERSIONS (version, createDate, CDefine1) VALUES (?, ?, ?)', [version, curTime, 'LongParam'], () => {}, () => { |
| | | window.GLOB.WebSql = null |
| | | }) |
| | | }) |
| | |
| | | /** |
| | | * @description 打开IndexedDB |
| | | */ |
| | | static openIndexDB () { |
| | | static openIndexDB (sysType) { |
| | | let service = window.GLOB.service ? '-' + window.GLOB.service.replace('/', '') : '' |
| | | try { |
| | | let request = window.indexedDB.open(`mkdb${service}`, 1) |
| | |
| | | objectStore.createIndex('menuid', 'menuid', { unique: false }) |
| | | objectStore.createIndex('userid', 'userid', { unique: false }) |
| | | } |
| | | if (window.GLOB.systemType === '' && sysType === 'local' && !window.GLOB.IndexDB.objectStoreNames.contains('funcs')) { |
| | | window.GLOB.IndexDB.createObjectStore('funcs', { keyPath: 'id' }) |
| | | } |
| | | } |
| | | } catch (e) { |
| | | console.warn('IndexedDB 初始化失败!') |
| | |
| | | 1578479100252lfbp29v1kafk4s4q4ig,1577971621421tg4v0i1ur8873k7e0ob,1577929944419lgc5h3hepum765e2k7u,1588493493409k9guqp067d31lu7blsv` |
| | | |
| | | if (window.openDatabase) { |
| | | CacheUtils.openWebSql() |
| | | CacheUtils.openWebSql(options.sysType) |
| | | } else if (window.indexedDB) { |
| | | CacheUtils.openIndexDB() |
| | | CacheUtils.openIndexDB(options.sysType) |
| | | } |
| | | |
| | | axios.defaults.crossDomain = true |
| | |
| | | login_id_address: ipAddress |
| | | } |
| | | |
| | | param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') |
| | | |
| | | let sys_datetime = sessionStorage.getItem('sys_datetime') |
| | | let app_datetime = sessionStorage.getItem('app_datetime') |
| | | if (sys_datetime && app_datetime) { |
| | | let seconds = Math.floor((new Date().getTime() - app_datetime) / 1000) |
| | | param.timestamp = moment(sys_datetime, 'YYYY-MM-DD HH:mm:ss').add(seconds, 'seconds').format('YYYY-MM-DD HH:mm:ss') |
| | | } |
| | | |
| | | // Type: 'S' 时 |
| | | let shaObj = new jsSHA('SHA-1', 'TEXT') |
| | | param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') |
| | | shaObj.update(password) |
| | | param.Password = shaObj.getHash('HEX').toUpperCase() |
| | | param.Password = md5(username + param.Password + param.timestamp) |
| | | |
| | | // Type: 'mk_' 时 |
| | | // param.Type = '公钥' |
| | | // let shaObj = new jsSHA('SHA-1', 'TEXT') |
| | | // shaObj.update(password) |
| | | // param.Password = shaObj.getHash('HEX').toUpperCase() |
| | | // param.Password = md5('私钥' + username + param.Password + param.timestamp) |
| | | |
| | | // Type: 'X' 时 |
| | | // param.Password = Utils.formatOptions(password) |
| | | |
| | | param.appkey = window.GLOB.appkey || '' |
| | | let url = '/webapi/dologon' |
| | | |
| | |
| | | return Promise.reject() |
| | | } |
| | | |
| | | let curTime = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' |
| | | let sys_datetime = sessionStorage.getItem('sys_datetime') |
| | | let app_datetime = sessionStorage.getItem('app_datetime') |
| | | if (sys_datetime && app_datetime) { |
| | | let seconds = Math.floor((new Date().getTime() - app_datetime) / 1000) |
| | | curTime = moment(sys_datetime, 'YYYY-MM-DD HH:mm:ss').add(seconds, 'seconds').format('YYYY-MM-DD HH:mm:ss') + '.000' |
| | | } |
| | | |
| | | if (window.GLOB.WebSql) { |
| | | return new Promise((resolve, reject) => { |
| | | CacheUtils.getWebSqlVersion().then(msg => { |
| | | appVersion.oldVersion = msg.version || '' |
| | | let curTime = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' |
| | | let modifydate = msg.createDate || curTime |
| | | if (modifydate.indexOf('Invalid date') > -1) { |
| | | modifydate = curTime |
| | | } |
| | | |
| | | let param = { |
| | | func: 's_get_app_version', |
| | | modifydate: msg.createDate || curTime, |
| | | modifydate |
| | | } |
| | | |
| | | this.getSystemConfig(param).then(res => { |
| | |
| | | return new Promise((resolve, reject) => { |
| | | CacheUtils.getIndexDBVersion().then(msg => { |
| | | appVersion.oldVersion = msg.version || '' |
| | | let curTime = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' |
| | | let modifydate = msg.createDate || curTime |
| | | if (modifydate.indexOf('Invalid date') > -1) { |
| | | modifydate = curTime |
| | | } |
| | | let param = { |
| | | func: 's_get_app_version', |
| | | modifydate: msg.createDate || curTime, |
| | | modifydate |
| | | } |
| | | |
| | | this.getSystemConfig(param).then(res => { |
| | |
| | | |
| | | return axios({ |
| | | url, |
| | | method: 'post', |
| | | data: param |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 获取或修改系统配置,增加appkey |
| | | */ |
| | | getSystemFuncs (time) { |
| | | let param = { |
| | | func: 's_get_func_base_sso', |
| | | update_date: time, |
| | | userid: sessionStorage.getItem('UserID') || '', |
| | | lang: sessionStorage.getItem('lang') || '', |
| | | SessionUid: localStorage.getItem('SessionUid') || '', |
| | | LoginUID: sessionStorage.getItem('LoginUID') || '', |
| | | appkey: window.GLOB.appkey |
| | | } |
| | | |
| | | let url = window.GLOB.mainSystemApi |
| | | param = this.encryptParam(param) |
| | | |
| | | return axios({ |
| | | url: `${url}/${param.func}`, |
| | | method: 'post', |
| | | data: param |
| | | }) |
| | |
| | | |
| | | param = this.encryptParam(param) |
| | | |
| | | let url = '/webapi/SaveBase64Image' |
| | | if (param.rduri) { |
| | | let url = param.rduri.replace(/webapi(.*)$/, 'webapi/SaveBase64Image') |
| | | url = param.rduri.replace(/webapi(.*)$/, 'webapi/SaveBase64Image') |
| | | delete param.rduri |
| | | |
| | | return axios({ |
| | | url, |
| | | method: 'post', |
| | | data: param |
| | | }) |
| | | } else { |
| | | return axios({ |
| | | url: '/webapi/SaveBase64Image', |
| | | method: 'post', |
| | | data: param |
| | | }) |
| | | } |
| | | |
| | | return axios({ |
| | | url, |
| | | method: 'post', |
| | | data: param |
| | | }) |
| | | } |
| | | |
| | | /** |
| | |
| | | background: rgba(0, 0, 0, 0); |
| | | } |
| | | // 重置模态框滚动条 |
| | | .ant-modal-wrap::-webkit-scrollbar { |
| | | .ant-modal-wrap::-webkit-scrollbar, .ant-drawer-wrapper-body::-webkit-scrollbar { |
| | | width: 7px; |
| | | } |
| | | .ant-modal-wrap::-webkit-scrollbar-thumb { |
| | | .ant-modal-wrap::-webkit-scrollbar-thumb, .ant-drawer-wrapper-body::-webkit-scrollbar-thumb { |
| | | border-radius: 5px; |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13); |
| | | background: rgba(0, 0, 0, 0.13); |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.1); |
| | | background: rgba(0, 0, 0, 0.1); |
| | | } |
| | | .ant-modal-wrap::-webkit-scrollbar-track { |
| | | .ant-modal-wrap::-webkit-scrollbar-track, .ant-drawer-wrapper-body::-webkit-scrollbar-track { |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); |
| | | border-radius: 3px; |
| | | border: 1px solid rgba(0, 0, 0, 0.07); |
| | |
| | | padding: 5px 20px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .ant-input[disabled] { |
| | | background-color: #fafafa!important; |
| | | } |
| | | .ant-btn[disabled] { |
| | | background-color: transparent!important; |
| | | border-color: rgba(0, 0, 0, 0.35)!important; |
| | | color: rgba(0, 0, 0, 0.35)!important; |
| | | } |
| | | .ant-btn.ant-btn-link { |
| | | border-width: 0; |
| | | } |
| | | .button-list { |
| | | .ant-btn.ant-btn-link { |
| | | border-width: 1px; |
| | | } |
| | | } |
| | |
| | | button.vercode { |
| | | color: $color6; |
| | | } |
| | | .ant-tabs { |
| | | .ant-tabs-tab.ant-tabs-tab-active { |
| | | color: $color6; |
| | | } |
| | | .ant-tabs-tab:hover { |
| | | .login-way-wrap { |
| | | .login-way.active, .login-way:hover { |
| | | color: $color6; |
| | | } |
| | | } |
| | |
| | | .top-search { |
| | | >.ant-row { |
| | | .ant-col.search-button { |
| | | .ant-btn:not(.ant-btn-primary):active, .ant-btn:not(.ant-btn-primary).active, .ant-btn:not(.ant-btn-primary):hover, .ant-btn:not(.ant-btn-primary):focus { |
| | | .ant-btn:not(.ant-btn-primary):not(.ant-btn-link):active, .ant-btn:not(.ant-btn-primary):not(.ant-btn-link).active, .ant-btn:not(.ant-btn-primary):not(.ant-btn-link):hover, .ant-btn:not(.ant-btn-primary):not(.ant-btn-link):focus { |
| | | color: $color7; |
| | | border-color: $color7; |
| | | } |
| | |
| | | background-color: $color6; |
| | | border-color: $color6; |
| | | } |
| | | .ant-btn-link { |
| | | color: $color6; |
| | | } |
| | | } |
| | | } |
| | | .advanced-list { |
| | | .advance-value { |
| | | color: $color6; |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | class NormalEditor extends Component { |
| | | static propTpyes = { |
| | | Item: PropTypes.object, // 表单元素 |
| | | onChange: PropTypes.func, // 表单更新 |
| | | config: PropTypes.object, |
| | | onChange: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { config, defaultValue } = this.props |
| | | let initVal = null |
| | | let encryption = 'false' |
| | | |
| | | if (this.props['data-__meta']) { |
| | | initVal = this.props['data-__meta'].initialValue || null |
| | | } else if (this.props.defaultValue) { |
| | | initVal = this.props.defaultValue || null |
| | | if (config && config.initval) { |
| | | initVal = config.initval |
| | | } else if (defaultValue) { |
| | | initVal = defaultValue |
| | | } |
| | | |
| | | if (this.props.Item && this.props.Item.encryption === 'true') { |
| | | if (config && config.encryption === 'true') { |
| | | encryption = 'true' |
| | | if (initVal) { |
| | | try { |
| | |
| | | form.append('fileExt', params.file.fileType) |
| | | form.append('shardingCnt', _param.chunks) |
| | | form.append('shardingNo', _param.chunk) |
| | | form.append('LoginUID', sessionStorage.getItem('LoginUID') || '') |
| | | |
| | | Api.getLargeFileUpload(form).then(res => { |
| | | if (res.status) { |
| | |
| | | edition_type: 'A', |
| | | pro_sys: window.GLOB.systemType === 'production' ? 'Y' : '' |
| | | }).then(result => { |
| | | let _permAction = {} // 按钮权限 |
| | | let _permAction = {loaded: true} // 按钮权限 |
| | | |
| | | if (result && result.status) { |
| | | if (result.UserRoles_Menu) { |
| | |
| | | |
| | | this.props.modifyMenuTree(menulist) |
| | | this.props.modifyMainMenu(mainMenu) |
| | | this.props.initMenuPermission(thdMenuList) |
| | | this.props.initMenuPermission([...thdMenuList, {MenuID: 'home_page_id', EasyCode: '', MenuName: 'home', type: 'CustomPage'}]) |
| | | |
| | | resolve(_menu) |
| | | }) |
| | |
| | | // 修改编辑状态 |
| | | let UserID = sessionStorage.getItem('CloudUserID') |
| | | let LoginUID = sessionStorage.getItem('CloudLoginUID') |
| | | |
| | | |
| | | if (!UserID || !LoginUID) { |
| | | this.setState({ |
| | | loginVisible: true |
| | |
| | | sessionStorage.setItem('dataM', res.dataM ? 'true' : '') |
| | | sessionStorage.setItem('isEditState', 'true') |
| | | |
| | | this.setSystemFuncs() |
| | | |
| | | this.props.modifyMenuTree([]) |
| | | this.props.modifyMainMenu(null) |
| | | this.props.modifyTabview([]) |
| | | |
| | | this.props.history.replace('/design') |
| | | } else { |
| | | if (res.message.indexOf('密码错误') > -1) { |
| | | const input = document.getElementById('password') |
| | | input && input.select() |
| | | } |
| | | this.setState({ |
| | | loginLoading: false |
| | | }) |
| | |
| | | }) |
| | | } |
| | | |
| | | setSystemFuncs = () => { |
| | | if (!window.GLOB.WebSql && !window.GLOB.IndexDB) { |
| | | return |
| | | } |
| | | this.getfuncTime().then(res => { |
| | | Api.getSystemFuncs(res.createDate).then(result => { |
| | | if (!result.status) { |
| | | notification.error({ |
| | | top: 92, |
| | | message: result.message, |
| | | duration: 10 |
| | | }) |
| | | return |
| | | } else if (result.func_detail && result.func_detail.length > 0) { |
| | | this.writeFuncs(result.func_detail) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | writeFuncs = (funcs) => { |
| | | let timestamp = moment().format('YYYY-MM-DD HH:mm:ss') |
| | | |
| | | let sys_datetime = sessionStorage.getItem('sys_datetime') |
| | | let app_datetime = sessionStorage.getItem('app_datetime') |
| | | if (sys_datetime && app_datetime) { |
| | | let seconds = Math.floor((new Date().getTime() - app_datetime) / 1000) |
| | | timestamp = moment(sys_datetime, 'YYYY-MM-DD HH:mm:ss').add(seconds, 'seconds').format('YYYY-MM-DD HH:mm:ss') |
| | | } |
| | | |
| | | if (window.GLOB.WebSql) { |
| | | window.GLOB.WebSql.transaction(tx => { |
| | | tx.executeSql('DELETE FROM FUNCS') |
| | | |
| | | funcs.forEach(item => { |
| | | if (!item.key_sql) return |
| | | tx.executeSql('INSERT INTO FUNCS (func_code, key_sql) VALUES (?, ?)', [item.func_code, item.key_sql]) |
| | | }) |
| | | tx.executeSql(`UPDATE VERSIONS SET createDate='${timestamp}' where CDefine1='funcs'`) |
| | | }) |
| | | } else { |
| | | let objectStore = window.GLOB.IndexDB.transaction(['funcs'], 'readwrite').objectStore('funcs') |
| | | |
| | | objectStore.clear() |
| | | |
| | | funcs.forEach(item => { |
| | | if (!item.key_sql) return |
| | | item.id = item.func_code |
| | | objectStore.add(item) |
| | | }) |
| | | |
| | | let funcStore = window.GLOB.IndexDB.transaction(['version'], 'readwrite').objectStore('version') |
| | | funcStore.put({id: 'funcs', version: '1.0', createDate: timestamp}) |
| | | } |
| | | } |
| | | |
| | | getfuncTime = () => { |
| | | return new Promise((resolve, reject) => { |
| | | if (window.GLOB.WebSql) { |
| | | window.GLOB.WebSql.transaction(tx => { |
| | | tx.executeSql("SELECT * FROM VERSIONS where CDefine1='funcs'", [], (tx, results) => { |
| | | let rows = results.rows |
| | | if (rows.length === 0) { |
| | | tx.executeSql('DELETE FROM FUNCS') |
| | | tx.executeSql('INSERT INTO VERSIONS (version, createDate, CDefine1) VALUES (?, ?, ?)', ['1.0', '1970-01-01 14:59:09.000', 'funcs']) |
| | | resolve({createDate: '1970-01-01 14:59:09.000'}) |
| | | } else { |
| | | resolve(rows[0]) |
| | | } |
| | | }, (tx, results) => { |
| | | reject() |
| | | console.warn(results) |
| | | }) |
| | | }) |
| | | } else { |
| | | let objectStore = window.GLOB.IndexDB.transaction(['version'], 'readwrite').objectStore('version') |
| | | let request = objectStore.get('funcs') |
| | | |
| | | request.onerror = (event) => { |
| | | console.warn(event) |
| | | reject() |
| | | } |
| | | |
| | | request.onsuccess = () => { |
| | | if (request.result) { |
| | | resolve(request.result) |
| | | } else { |
| | | let add = objectStore.add({id: 'funcs', version: '1.0', createDate: '1970-01-01 14:59:09.000'}) |
| | | |
| | | add.onerror = () => { |
| | | reject() |
| | | } |
| | | add.onsuccess = () => { |
| | | resolve({id: 'funcs', version: '1.0', createDate: '1970-01-01 14:59:09.000'}) |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | |
| | | changeSystem = (system) => { |
| | | let url = system.LinkUrl1 |
| | | |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Modal, Icon, Row, Col, Button } from 'antd' |
| | | |
| | | import { minkeIconSystem } from '@/utils/option.js' |
| | | import './index.scss' |
| | | |
| | | class MkIcon extends Component { |
| | | static propTpyes = { |
| | | onChange: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | selectIcon: '', |
| | | allowClear: false, |
| | | icons: [...minkeIconSystem.direction, ...minkeIconSystem.edit, ...minkeIconSystem.normal, ...minkeIconSystem.trademark, ...minkeIconSystem.data, ...minkeIconSystem.hint], |
| | | visible: false |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | let val = '' |
| | | if (this.props['data-__meta']) { |
| | | val = this.props['data-__meta'].initialValue || '' |
| | | } |
| | | |
| | | this.setState({selectIcon: val, allowClear: this.props.allowClear === true}) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | checkIcon = (val) => { |
| | | this.setState({selectIcon: val, visible: false}) |
| | | this.props.onChange(val) |
| | | } |
| | | |
| | | render() { |
| | | const { selectIcon, visible, icons, allowClear } = this.state |
| | | |
| | | return ( |
| | | <div className="mk-icon-box"> |
| | | {selectIcon ? <Icon type={selectIcon}/> : <Icon style={{opacity: 0}} type="plus"/>} |
| | | <Icon className="trigger" onClick={() => this.setState({visible: true})} type="swap"/> |
| | | {allowClear ? <Icon className="close" onClick={() => this.checkIcon('')} type="close"/> : null} |
| | | <Modal |
| | | wrapClassName="popview-modal mk-icon-wrap" |
| | | title={'图标选择'} |
| | | visible={visible} |
| | | width={800} |
| | | maskClosable={false} |
| | | onCancel={() => { this.setState({ visible: false }) }} |
| | | footer={[ |
| | | <Button key="close" onClick={() => { this.setState({ visible: false }) }}>关闭</Button> |
| | | ]} |
| | | destroyOnClose |
| | | > |
| | | <Row> |
| | | {icons.map(icon => <Col className={icon === selectIcon ? 'active' : ''} key={icon} span={4}> |
| | | <Icon onClick={() => this.checkIcon(icon)} type={icon} /> |
| | | </Col>)} |
| | | </Row> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default MkIcon |
New file |
| | |
| | | .mk-icon-box { |
| | | display: block; |
| | | height: 32px; |
| | | border: 1px solid #d9d9d9; |
| | | border-radius: 4px; |
| | | line-height: 32px; |
| | | padding: 0px 0px 0px 10px; |
| | | |
| | | .anticon.trigger { |
| | | float: right; |
| | | line-height: 32px; |
| | | padding: 0 10px; |
| | | border-left: 1px solid #d9d9d9; |
| | | } |
| | | .close.anticon { |
| | | float: right; |
| | | margin-top: 6px; |
| | | margin-right: 5px; |
| | | background: #efefef; |
| | | border-radius: 50%; |
| | | color: #757575; |
| | | padding: 3px; |
| | | font-size: 10px; |
| | | opacity: 0; |
| | | transition: opacity 0.3s; |
| | | } |
| | | } |
| | | .mk-icon-box:hover { |
| | | border-color: #1890ff; |
| | | .close.anticon { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | .mk-icon-box::after { |
| | | content: ' '; |
| | | display: block; |
| | | clear: both; |
| | | } |
| | | .mk-icon-wrap { |
| | | .ant-col { |
| | | text-align: center; |
| | | line-height: 55px; |
| | | .anticon { |
| | | font-size: 30px; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | .active.ant-col { |
| | | .anticon { |
| | | color: #1890ff; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Icon, Modal, notification } from 'antd' |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import './index.scss' |
| | | |
| | | const PasteForm = asyncComponent(() => import('@/templates/zshare/pasteform')) |
| | | |
| | | class PasteController extends Component { |
| | | static propTpyes = { |
| | | options: PropTypes.array, |
| | | updateConfig: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | visible: false |
| | | } |
| | | |
| | | handleMenuClick = () => { |
| | | this.setState({visible: true}) |
| | | } |
| | | |
| | | pasteSubmit = () => { |
| | | const { options } = this.props |
| | | this.pasteFormRef.handleConfirm().then(res => { |
| | | if (!options.includes(res.copyType)) { |
| | | notification.warning({ top: 92, message: '配置信息格式错误!', duration: 5 }) |
| | | return |
| | | } |
| | | this.props.updateConfig(res, (result) => { |
| | | if (result.status) { |
| | | notification.success({ |
| | | top: 92, |
| | | message: '粘贴成功!', |
| | | duration: 2 |
| | | }) |
| | | this.setState({visible: false}) |
| | | } else { |
| | | notification.success({ |
| | | top: 92, |
| | | message: result.message, |
| | | duration: 2 |
| | | }) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const { visible } = this.state |
| | | |
| | | return ( |
| | | <div style={{display: 'inline-block'}}> |
| | | <Icon type="snippets" style={{color: 'purple'}} onClick={() => {this.setState({visible: true})}} /> |
| | | <Modal |
| | | title="粘贴" |
| | | visible={visible} |
| | | width={600} |
| | | maskClosable={false} |
| | | onOk={this.pasteSubmit} |
| | | onCancel={() => {this.setState({visible: false})}} |
| | | destroyOnClose |
| | | > |
| | | <PasteForm wrappedComponentRef={(inst) => this.pasteFormRef = inst} inputSubmit={this.pasteSubmit}/> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default PasteController |
copy from src/tabviews/zshare/mutilform/customSwitch/index.scss
copy to src/components/paste/index.scss
| | |
| | | return (<TabManage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID}/>) |
| | | } else if (view.type === 'RolePermission') { |
| | | return (<RoleManage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID}/>) |
| | | } else if (view.type === 'appRolePermission') { |
| | | return (<RoleManage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID}/>) |
| | | } else if (view.type === 'FormTab') { |
| | | return (<FormTab MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param}/>) |
| | | } else if (view.type === 'iframe') { |
| | |
| | | sessionStorage.setItem('role_id', sessionStorage.getItem('localRole_id') || '') |
| | | sessionStorage.setItem('dataM', sessionStorage.getItem('localDataM') || '') |
| | | |
| | | // 新系统文件置于admin中 ../options.json |
| | | // 新系统文件置于admin中 ../options.json , { cache: 'no-cache'} |
| | | |
| | | fetch('./options.json') |
| | | fetch('../options.json') |
| | | .then(response => response.json()) |
| | | .catch(() => { |
| | | document.getElementById('root').innerHTML = '<div style="text-align: center; font-size: 30px; margin-top: 40vh;">系统配置信息获取失败,请联系管理员!</div>' |
| | |
| | | 'model.form.link': '联动菜单', |
| | | 'model.form.linkform': '关联表单', |
| | | 'model.form.dateday': '日期(天)', |
| | | 'model.form.datetime': '日期(秒)', |
| | | 'model.form.datetime': '日期(分/秒)', |
| | | 'model.form.dateweek': '日期(周)', |
| | | 'model.form.datemonth': '日期(月)', |
| | | 'model.form.daterange': '日期(区间)', |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Form } from 'antd' |
| | | import { Form, Select } from 'antd' |
| | | |
| | | import zhCN from '@/locales/zh-CN/mob.js' |
| | | import enUS from '@/locales/en-US/mob.js' |
| | |
| | | |
| | | const ColorSketch = asyncComponent(() => import('@/mob/colorsketch')) |
| | | const SourceComponent = asyncComponent(() => import('@/menu/components/share/sourcecomponent')) |
| | | const { Option } = Select |
| | | |
| | | class MobController extends Component { |
| | | static propTpyes = { |
| | |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | backgroundColor: '', |
| | | backgroundImage: '', |
| | | backgroundSize: '', |
| | | backgroundRepeat: '', |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | |
| | | |
| | | this.setState({ |
| | | backgroundColor: config.style.backgroundColor, |
| | | backgroundImage: bgImg |
| | | backgroundImage: bgImg, |
| | | backgroundSize: config.style.backgroundSize || '100%', |
| | | backgroundRepeat: config.style.backgroundRepeat || 'repeat', |
| | | }) |
| | | } |
| | | |
| | |
| | | this.props.updateConfig(config) |
| | | } |
| | | |
| | | backgroundSizeChange = (val) => { |
| | | this.setState({ |
| | | backgroundSize: val |
| | | }) |
| | | |
| | | let config = fromJS(this.props.config).toJS() |
| | | config.style.backgroundSize = val |
| | | |
| | | this.props.updateConfig(config) |
| | | } |
| | | |
| | | backgroundRepeatChange = (val) => { |
| | | this.setState({ |
| | | backgroundRepeat: val |
| | | }) |
| | | |
| | | let config = fromJS(this.props.config).toJS() |
| | | config.style.backgroundRepeat = val |
| | | |
| | | this.props.updateConfig(config) |
| | | } |
| | | |
| | | render () { |
| | | const { backgroundColor, backgroundImage } = this.state |
| | | const { backgroundColor, backgroundImage, backgroundSize, backgroundRepeat } = this.state |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | |
| | | <Form.Item colon={false} label="图片"> |
| | | <SourceComponent value={backgroundImage} type="" placement="right" onChange={this.imgChange}/> |
| | | </Form.Item> |
| | | <Form.Item colon={false} label="比例"> |
| | | <Select defaultValue={backgroundSize} onChange={this.backgroundSizeChange}> |
| | | <Option value="100%">100%</Option> |
| | | <Option value="100% 100%">100% 100%</Option> |
| | | <Option value="auto 100%">auto 100%</Option> |
| | | <Option value="contain">contain</Option> |
| | | <Option value="cover">cover</Option> |
| | | </Select> |
| | | </Form.Item> |
| | | <Form.Item colon={false} label="重复"> |
| | | <Select defaultValue={backgroundRepeat} onChange={this.backgroundRepeatChange}> |
| | | <Option value="repeat">repeat</Option> |
| | | <Option value="no-repeat">no-repeat</Option> |
| | | <Option value="repeat-x">repeat-x</Option> |
| | | <Option value="repeat-y">repeat-y</Option> |
| | | </Select> |
| | | </Form.Item> |
| | | </Form> |
| | | </div> |
| | | ) |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Popover } from 'antd' |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | 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 WrapComponent = asyncIconComponent(() => import('./wrapsetting')) |
| | | const CardCellComponent = asyncComponent(() => import('../cardcellcomponent')) |
| | | const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) |
| | | const PasteComponent = asyncIconComponent(() => import('@/components/paste')) |
| | | const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent')) |
| | | const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent')) |
| | | |
| | | class BalconyEditComponent extends Component { |
| | | static propTpyes = { |
| | | card: PropTypes.object, |
| | | deletecomponent: PropTypes.func, |
| | | updateConfig: PropTypes.func, |
| | | } |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | card: null, |
| | | back: false |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { card } = this.props |
| | | |
| | | if (card.isNew) { |
| | | 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: card.width || 24, |
| | | name: card.name, |
| | | subtype: card.subtype, |
| | | setting: { interType: 'system' }, |
| | | wrap: { name: card.name, width: card.width || 24, linkType: 'static', position: 'relative', datatype: 'static' }, |
| | | style: { marginLeft: '0px', marginRight: '0px', marginTop: '0px', marginBottom: '0px' }, |
| | | columns: [], |
| | | scripts: [], |
| | | elements: [], |
| | | } |
| | | |
| | | if (card.config) { |
| | | let config = fromJS(card.config).toJS() |
| | | |
| | | _card.wrap = config.wrap |
| | | _card.wrap.name = card.name |
| | | _card.style = config.style |
| | | |
| | | _card.elements = _card.elements.map(elem => { |
| | | elem.uuid = Utils.getuuid() |
| | | return elem |
| | | }) |
| | | } |
| | | this.setState({ |
| | | card: _card |
| | | }) |
| | | this.props.updateConfig(_card) |
| | | } else { |
| | | this.setState({ |
| | | card: fromJS(card).toJS() |
| | | }) |
| | | } |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('submitStyle', this.getStyle) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新,清除快捷键设置 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('submitStyle', this.getStyle) |
| | | } |
| | | |
| | | /** |
| | | * @description 卡片行外层信息更新(数据源,样式等) |
| | | */ |
| | | updateComponent = (component) => { |
| | | this.setState({ |
| | | card: component |
| | | }) |
| | | |
| | | component.width = component.wrap.width |
| | | component.name = component.wrap.name |
| | | |
| | | this.props.updateConfig(component) |
| | | } |
| | | |
| | | updateCard = (elements) => { |
| | | const { card } = this.state |
| | | |
| | | let _card = {...card, elements: elements} |
| | | |
| | | this.setState({ |
| | | card: _card, |
| | | }) |
| | | |
| | | this.props.updateConfig(_card) |
| | | } |
| | | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['height', '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) |
| | | } |
| | | |
| | | addElement = () => { |
| | | const { card } = this.state |
| | | |
| | | let newcard = {} |
| | | newcard.uuid = Utils.getuuid() |
| | | newcard.focus = true |
| | | |
| | | newcard.eleType = 'text' |
| | | newcard.datatype = 'dynamic' |
| | | newcard.height = 1 |
| | | |
| | | // 注册事件-添加元素 |
| | | MKEmitter.emit('cardAddElement', [card.uuid, card.uuid], newcard) |
| | | } |
| | | |
| | | addButton = () => { |
| | | const { card } = this.state |
| | | |
| | | let newcard = {} |
| | | newcard.uuid = Utils.getuuid() |
| | | newcard.focus = true |
| | | |
| | | newcard.eleType = 'button' |
| | | newcard.label = 'button' |
| | | newcard.sqlType = '' |
| | | newcard.Ot = 'requiredSgl' |
| | | newcard.OpenType = 'prompt' |
| | | newcard.icon = '' |
| | | newcard.class = 'primary' |
| | | newcard.intertype = 'system' |
| | | newcard.execSuccess = 'grid' |
| | | newcard.execError = 'never' |
| | | newcard.popClose = 'never' |
| | | newcard.errorTime = 10 |
| | | newcard.verify = null |
| | | newcard.show = 'link' |
| | | |
| | | // 注册事件-添加元素 |
| | | MKEmitter.emit('cardAddElement', [card.uuid, card.uuid], newcard) |
| | | } |
| | | |
| | | pasteComponent = (res, resolve) => { |
| | | const { card } = this.state |
| | | |
| | | let type = res.copyType |
| | | delete res.copyType |
| | | |
| | | res.uuid = Utils.getuuid() |
| | | res.focus = true |
| | | |
| | | if (type === 'customCardElement') { |
| | | MKEmitter.emit('cardAddElement', [card.uuid, card.uuid], res) |
| | | } else { |
| | | res.eleType = 'button' |
| | | MKEmitter.emit('cardAddElement', [card.uuid, card.uuid], res) |
| | | } |
| | | resolve({status: true}) |
| | | } |
| | | |
| | | render() { |
| | | const { card } = this.state |
| | | |
| | | let _style = resetStyle(card.style) |
| | | |
| | | return ( |
| | | <div className="menu-balcony-edit-box" style={_style} id={card.uuid}> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <Icon className="plus" title="添加元素" onClick={this.addElement} type="plus" /> |
| | | <Icon className="plus" title="添加按钮" onClick={this.addButton} type="plus-square" /> |
| | | <WrapComponent config={card} updateConfig={this.updateComponent} /> |
| | | <CopyComponent type="balcony" card={card}/> |
| | | <PasteComponent options={['action', 'customCardElement']} updateConfig={this.pasteComponent} /> |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | | <ClockComponent config={card} updateConfig={this.updateComponent}/> |
| | | <UserComponent config={card}/> |
| | | <Icon className="close" title="删除组件" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> |
| | | {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null} |
| | | {card.wrap.datatype === 'static' ? <Icon style={{color: '#eeeeee', cursor: 'not-allowed'}} type="setting"/> : null} |
| | | </div> |
| | | } trigger="hover"> |
| | | <Icon type="tool" /> |
| | | </Popover> |
| | | <CardCellComponent cards={card} cardCell={card} elements={card.elements} updateElement={this.updateCard}/> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default BalconyEditComponent |
New file |
| | |
| | | .menu-balcony-edit-box { |
| | | position: relative; |
| | | box-sizing: border-box; |
| | | background: #ffffff; |
| | | background-position: center center; |
| | | background-repeat: no-repeat; |
| | | background-size: cover; |
| | | min-height: 30px; |
| | | |
| | | .card-control { |
| | | position: absolute; |
| | | top: 0px; |
| | | left: 0px; |
| | | .anticon-tool { |
| | | right: auto; |
| | | left: 1px; |
| | | padding: 1px; |
| | | } |
| | | } |
| | | .anticon-tool { |
| | | position: absolute; |
| | | z-index: 2; |
| | | font-size: 16px; |
| | | right: 1px; |
| | | top: 1px; |
| | | cursor: pointer; |
| | | padding: 5px; |
| | | background: rgba(255, 255, 255, 0.55); |
| | | } |
| | | |
| | | .card-item { |
| | | overflow: hidden; |
| | | position: relative; |
| | | background-color: #ffffff; |
| | | background-position: center center; |
| | | background-repeat: no-repeat; |
| | | background-size: cover; |
| | | min-height: 20px; |
| | | } |
| | | |
| | | .card-item:hover { |
| | | box-shadow: 0px 0px 2px #1890ff; |
| | | } |
| | | |
| | | .model-menu-card-cell-list .card-detail-row > .anticon-plus { |
| | | position: absolute; |
| | | right: -30px; |
| | | font-size: 16px; |
| | | } |
| | | .model-menu-action-list { |
| | | line-height: 40px; |
| | | .ant-row > .anticon-plus { |
| | | position: absolute; |
| | | right: -30px; |
| | | font-size: 16px; |
| | | } |
| | | } |
| | | .card-add-button { |
| | | text-align: right; |
| | | clear: left; |
| | | .anticon-plus { |
| | | font-size: 20px; |
| | | color: #26C281; |
| | | padding: 5px; |
| | | margin-right: 10px; |
| | | } |
| | | } |
| | | } |
| | | .menu-balcony-edit-box::after { |
| | | display: block; |
| | | content: ' '; |
| | | clear: both; |
| | | } |
| | | .menu-balcony-edit-box:hover { |
| | | z-index: 1; |
| | | box-shadow: 0px 0px 4px #1890ff; |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Modal } from 'antd' |
| | | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import SettingForm from './settingform' |
| | | import './index.scss' |
| | | |
| | | class BalconyWrapSetting extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.any, |
| | | updateConfig: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | visible: false, |
| | | wrap: null |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { config } = this.props |
| | | |
| | | this.setState({wrap: fromJS(config.wrap).toJS()}) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | editDataSource = () => { |
| | | this.setState({ |
| | | visible: true |
| | | }) |
| | | } |
| | | |
| | | verifySubmit = () => { |
| | | const { config } = this.props |
| | | |
| | | this.verifyRef.handleConfirm().then(res => { |
| | | |
| | | this.setState({ |
| | | wrap: res, |
| | | visible: false |
| | | }) |
| | | this.props.updateConfig({...config, wrap: res}) |
| | | }) |
| | | } |
| | | |
| | | render () { |
| | | const { config } = this.props |
| | | const { visible, dict, wrap } = this.state |
| | | |
| | | return ( |
| | | <div className="model-menu-setting-wrap"> |
| | | <Icon type="edit" title="编辑" onClick={() => this.editDataSource()} /> |
| | | <Modal |
| | | wrapClassName="popview-modal" |
| | | title="卡片设置" |
| | | visible={visible} |
| | | width={800} |
| | | maskClosable={false} |
| | | okText={dict['model.submit']} |
| | | onOk={this.verifySubmit} |
| | | onCancel={() => { this.setState({ visible: false }) }} |
| | | destroyOnClose |
| | | > |
| | | <SettingForm |
| | | dict={dict} |
| | | wrap={wrap} |
| | | config={config} |
| | | inputSubmit={this.verifySubmit} |
| | | wrappedComponentRef={(inst) => this.verifyRef = inst} |
| | | /> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default BalconyWrapSetting |
New file |
| | |
| | | .model-menu-setting-wrap { |
| | | display: inline-block; |
| | | |
| | | >.anticon-edit { |
| | | color: #1890ff; |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { fromJS } from 'immutable' |
| | | import { Form, Row, Col, Input, Radio, Tooltip, Icon, InputNumber, Select, Cascader } from 'antd' |
| | | |
| | | import MenuUtils from '@/utils/utils-custom.js' |
| | | import StyleInput from '@/menu/components/share/styleInput' |
| | | import './index.scss' |
| | | |
| | | class SettingForm extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, |
| | | config: PropTypes.object, |
| | | wrap: PropTypes.object, |
| | | inputSubmit: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | roleList: [], |
| | | modules: [], |
| | | supmodules: [], |
| | | appType: sessionStorage.getItem('appType'), |
| | | linkType: this.props.wrap.linkType, |
| | | position: this.props.wrap.position, |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | let roleList = sessionStorage.getItem('sysRoles') |
| | | if (roleList) { |
| | | try { |
| | | roleList = JSON.parse(roleList) |
| | | } catch { |
| | | roleList = [] |
| | | } |
| | | } else { |
| | | roleList = [] |
| | | } |
| | | |
| | | let menu = fromJS(window.GLOB.customMenu).toJS() |
| | | |
| | | let modules = MenuUtils.getLinkModules(menu.components) |
| | | if (!modules) { |
| | | modules = [] |
| | | } |
| | | |
| | | let _menu = fromJS(window.GLOB.customMenu).toJS() |
| | | |
| | | let supmodules = MenuUtils.getSupModules(_menu.components, '') |
| | | if (!supmodules) { |
| | | supmodules = [] |
| | | } |
| | | |
| | | this.setState({roleList, modules, supmodules}) |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | | return new Promise((resolve, reject) => { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | resolve(values) |
| | | } else { |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | handleSubmit = (e) => { |
| | | e.preventDefault() |
| | | |
| | | if (this.props.inputSubmit) { |
| | | this.props.inputSubmit() |
| | | } |
| | | } |
| | | |
| | | chose = (val) => { |
| | | let values = {} |
| | | if (val === 'top') { |
| | | values = { |
| | | top: '0px', |
| | | left: '50%', |
| | | right: '', |
| | | bottom: '', |
| | | transform: 'translateX(-50%)' |
| | | } |
| | | } else if (val === 'top-left') { |
| | | values = { |
| | | top: '0px', |
| | | left: '0px', |
| | | right: '', |
| | | bottom: '', |
| | | transform: '' |
| | | } |
| | | } else if (val === 'top-right') { |
| | | values = { |
| | | top: '0px', |
| | | left: '', |
| | | right: '0px', |
| | | bottom: '', |
| | | transform: '' |
| | | } |
| | | } else if (val === 'left-middle') { |
| | | values = { |
| | | top: '50%', |
| | | left: '0px', |
| | | right: '', |
| | | bottom: '', |
| | | transform: 'translateY(-50%)' |
| | | } |
| | | } else if (val === 'right-middle') { |
| | | values = { |
| | | top: '50%', |
| | | left: '', |
| | | right: '0px', |
| | | bottom: '', |
| | | transform: 'translateY(-50%)' |
| | | } |
| | | } else if (val === 'bottom-left') { |
| | | values = { |
| | | top: '', |
| | | left: '0px', |
| | | right: '', |
| | | bottom: '0px', |
| | | transform: '' |
| | | } |
| | | } else if (val === 'bottom-right') { |
| | | values = { |
| | | top: '', |
| | | left: '', |
| | | right: '0px', |
| | | bottom: '0px', |
| | | transform: '' |
| | | } |
| | | } else if (val === 'bottom') { |
| | | values = { |
| | | top: '', |
| | | left: '50%', |
| | | right: '', |
| | | bottom: '0px', |
| | | transform: 'translateX(-50%)' |
| | | } |
| | | } else if (val === 'middle') { |
| | | values = { |
| | | top: '50%', |
| | | left: '50%', |
| | | right: '', |
| | | bottom: '', |
| | | transform: 'translate(-50%, -50%)' |
| | | } |
| | | } |
| | | this.props.form.setFieldsValue(values) |
| | | } |
| | | |
| | | render() { |
| | | const { wrap } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { roleList, modules, supmodules, linkType, position } = this.state |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 8 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 16 } |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <div className="model-menu-setting-form"> |
| | | <Form {...formItemLayout}> |
| | | <Row gutter={24}> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="用于组件间的区分。"> |
| | | <Icon type="question-circle" /> |
| | | 组件名称 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('name', { |
| | | initialValue: wrap.name, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '组件名称!' |
| | | } |
| | | ] |
| | | })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="栅格布局,每行等分为24列。"> |
| | | <Icon type="question-circle" /> |
| | | 宽度 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('width', { |
| | | initialValue: wrap.width || 24, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '宽度!' |
| | | } |
| | | ] |
| | | })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="选择静态值,无需配置数据源。"> |
| | | <Icon type="question-circle" /> |
| | | 数据来源 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('datatype', { |
| | | initialValue: wrap.datatype |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="dynamic">动态</Radio> |
| | | <Radio value="static">静态</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="组件与其他组件之间的控制类型,独立表示与其他没有关联。"> |
| | | <Icon type="question-circle" /> |
| | | 受控类型 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('linkType', { |
| | | initialValue: wrap.linkType || 'static' |
| | | })( |
| | | <Radio.Group onChange={(e) => this.setState({linkType: e.target.value})}> |
| | | <Radio value="static">独立</Radio> |
| | | <Radio value="sync">同步</Radio> |
| | | <Radio value="sup">上级</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {linkType === 'sup' ? <Col span={12}> |
| | | <Form.Item label="上级组件"> |
| | | {getFieldDecorator('supModule', { |
| | | initialValue: wrap.supModule, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '上级组件!' |
| | | } |
| | | ] |
| | | })( |
| | | <Cascader options={supmodules} expandTrigger="hover" placeholder="" /> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {linkType === 'sup' ? <Col span={12}> |
| | | <Form.Item label="显示控制"> |
| | | {getFieldDecorator('supControl', { |
| | | initialValue: wrap.supControl || 'show' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio key="hidden" value="hidden"> 选行显示 </Radio> |
| | | <Radio key="show" value="show"> 始终显示 </Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {linkType === 'sync' ? <Col span={12}> |
| | | <Form.Item label="同步组件"> |
| | | {getFieldDecorator('syncModule', { |
| | | initialValue: wrap.syncModule, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '同步组件!' |
| | | } |
| | | ] |
| | | })( |
| | | <Cascader options={modules} expandTrigger="hover" placeholder="" /> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {linkType === 'sync' ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="当同步组件可多选时,设置全选有效。"> |
| | | <Icon type="question-circle" /> |
| | | 全选 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('checkAll', { |
| | | initialValue: wrap.checkAll || 'hidden' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio key="hidden" value="hidden"> 隐藏 </Radio> |
| | | <Radio key="show" value="show"> 显示 </Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="使用固定定位时,请在测试环境中查看定位效果。"> |
| | | <Icon type="question-circle" /> |
| | | 位置 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('position', { |
| | | initialValue: wrap.position || 'relative' |
| | | })( |
| | | <Radio.Group onChange={(e) => this.setState({position: e.target.value})}> |
| | | <Radio value="relative">相对定位</Radio> |
| | | <Radio value="fixed">固定定位</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {position === 'fixed' ? <Col span={12}> |
| | | <Form.Item label="快捷选择"> |
| | | <Select onSelect={this.chose}> |
| | | <Select.Option key='1' value={'top'}>上</Select.Option> |
| | | <Select.Option key='2' value={'top-left'}>左上</Select.Option> |
| | | <Select.Option key='3' value={'top-right'}>右上</Select.Option> |
| | | <Select.Option key='4' value={'left-middle'}>左中</Select.Option> |
| | | <Select.Option key='5' value={'right-middle'}>右中</Select.Option> |
| | | <Select.Option key='6' value={'bottom-left'}>左下</Select.Option> |
| | | <Select.Option key='7' value={'bottom-right'}>右下</Select.Option> |
| | | <Select.Option key='8' value={'bottom'}>下</Select.Option> |
| | | <Select.Option key='9' value={'middle'}>中间</Select.Option> |
| | | </Select> |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {position === 'fixed' ? <Col span={12}> |
| | | <Form.Item label="距上"> |
| | | {getFieldDecorator('top', { |
| | | initialValue: wrap.top || '' |
| | | })(<StyleInput options={['px', 'vh', 'vw', '%']} />)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {position === 'fixed' ? <Col span={12}> |
| | | <Form.Item label="距右"> |
| | | {getFieldDecorator('right', { |
| | | initialValue: wrap.right || '' |
| | | })(<StyleInput options={['px', 'vh', 'vw', '%']} />)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {position === 'fixed' ? <Col span={12}> |
| | | <Form.Item label="距下"> |
| | | {getFieldDecorator('bottom', { |
| | | initialValue: wrap.bottom || '' |
| | | })(<StyleInput options={['px', 'vh', 'vw', '%']} />)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {position === 'fixed' ? <Col span={12}> |
| | | <Form.Item label="距左"> |
| | | {getFieldDecorator('left', { |
| | | initialValue: wrap.left || '' |
| | | })(<StyleInput options={['px', 'vh', 'vw', '%']} />)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {position === 'fixed' ? <Col span={12}> |
| | | <Form.Item label="实际宽度"> |
| | | {getFieldDecorator('realwidth', { |
| | | initialValue: wrap.realwidth || '' |
| | | })(<StyleInput options={['px', 'vh', 'vw', '%']} />)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {position === 'fixed' ? <Col span={12}> |
| | | <Form.Item label="变换"> |
| | | {getFieldDecorator('transform', { |
| | | initialValue: wrap.transform || '' |
| | | })( |
| | | <Select> |
| | | <Select.Option key='1' value={''}>无</Select.Option> |
| | | <Select.Option key='2' value={'translateY(-50%)'}>上移50%</Select.Option> |
| | | <Select.Option key='3' value={'translateY(50%)'}>下移50%</Select.Option> |
| | | <Select.Option key='4' value={'translateX(-50%)'}>左移50%</Select.Option> |
| | | <Select.Option key='5' value={'translateX(50%)'}>右移50%</Select.Option> |
| | | <Select.Option key='6' value={'translate(-50%, -50%)'}>左上移50%</Select.Option> |
| | | <Select.Option key='7' value={'translate(-50%, 50%)'}>左下移50%</Select.Option> |
| | | <Select.Option key='8' value={'translate(50%, -50%)'}>右上移50%</Select.Option> |
| | | <Select.Option key='9' value={'translate(50%, 50%)'}>右下移50%</Select.Option> |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={12}> |
| | | <Form.Item label="黑名单"> |
| | | {getFieldDecorator('blacklist', { |
| | | initialValue: wrap.blacklist || [] |
| | | })( |
| | | <Select |
| | | showSearch |
| | | mode="multiple" |
| | | filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} |
| | | > |
| | | {roleList.map(option => |
| | | <Select.Option key={option.uuid} value={option.value}>{option.text}</Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(SettingForm) |
New file |
| | |
| | | .model-menu-setting-form { |
| | | position: relative; |
| | | |
| | | .anticon-question-circle { |
| | | color: #c49f47; |
| | | margin-right: 3px; |
| | | } |
| | | .ant-input-number { |
| | | width: 100%; |
| | | } |
| | | .css { |
| | | padding-top: 10px; |
| | | .css-class { |
| | | position: absolute; |
| | | right: 13px; |
| | | top: -15px; |
| | | z-index: 1; |
| | | button { |
| | | height: 25px; |
| | | } |
| | | } |
| | | .ant-form-item { |
| | | margin-bottom: 0; |
| | | } |
| | | .ant-form-item-label { |
| | | width: 16%; |
| | | } |
| | | .ant-form-item-control-wrapper { |
| | | width: 84%; |
| | | .code-mirror-wrap .code-mirror-area .CodeMirror { |
| | | height: 100px; |
| | | min-height: 100px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | import React from 'react' |
| | | import { useDrag, useDrop } from 'react-dnd' |
| | | import { Icon, Popover, Button } from 'antd' |
| | | |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import './index.scss' |
| | | |
| | | const Card = ({ id, card, moveCard, findCard, editCard, delCard, profileCard, changeStyle, doubleClickCard }) => { |
| | | const Card = ({ id, card, moveCard, findCard, editCard, copyCard, delCard, profileCard, changeStyle, doubleClickCard }) => { |
| | | const originalIndex = findCard(id).index |
| | | const [{ isDragging }, drag] = useDrag({ |
| | | item: { type: 'action', id, originalIndex }, |
| | |
| | | }, |
| | | }) |
| | | |
| | | let _style = {opacity: isDragging ? 0 : 1} |
| | | |
| | | if (card.style) { |
| | | _style = {...card.style, opacity: isDragging ? 0 : 1} |
| | | } |
| | | |
| | | let hasProfile = false |
| | | if (['pop', 'prompt', 'exec'].includes(card.OpenType)) { |
| | | hasProfile = true |
| | |
| | | } |
| | | |
| | | let btnElement = null |
| | | let _style = resetStyle(card.style) |
| | | if (card.show === 'icon') { |
| | | btnElement = (<Button style={card.btnstyle} type="link"><Icon type={card.icon}/></Button>) |
| | | btnElement = (<Button style={_style} type="link"><Icon type={card.icon}/></Button>) |
| | | } else if (card.show === 'link') { |
| | | btnElement = (<Button style={card.btnstyle} type="link">{card.label}{card.icon ? <Icon type={card.icon}/> : null}</Button>) |
| | | btnElement = (<Button style={_style} type="link">{card.icon ? <Icon type={card.icon}/> : null}{card.label}</Button>) |
| | | } else { |
| | | btnElement = (<Button icon={card.icon} style={card.btnstyle}> {card.label} </Button>) |
| | | btnElement = (<Button style={_style}> {card.label}{card.icon ? <Icon type={card.icon}/> : null} </Button>) |
| | | } |
| | | |
| | | return ( |
| | | <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={() => editCard(id)} /> |
| | | <Icon className="copy" title="复制" type="copy" onClick={() => copyCard(id)} /> |
| | | <Icon className="close" title="删除" type="close" onClick={() => delCard(id)} /> |
| | | <Icon className="style" title="调整样式" onClick={() => changeStyle(id)} type="font-colors" /> |
| | | {hasProfile ? <Icon className="profile" title="setting" type="profile" onClick={() => profileCard(id)} /> : null} |
| | | </div> |
| | | } trigger="hover"> |
| | | <div ref={node => drag(drop(node))} className={'ant-col card-button-cell ant-col-' + card.width} onDoubleClick={() => doubleClickCard(id)}> |
| | | <div style={_style}> |
| | | <div ref={node => drag(drop(node))} className={'ant-col card-button-cell ant-col-' + card.width} onDoubleClick={(e) => {e.stopPropagation(); doubleClickCard(id)}}> |
| | | <div style={{opacity: isDragging ? 0 : 1}}> |
| | | {btnElement} |
| | | </div> |
| | | </div> |
| | |
| | | import MKEmitter from '@/utils/events.js' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import './index.scss' |
| | | |
| | | const BarCode = asyncComponent(() => import('@/components/barcode')) |
| | | const QrCode = asyncComponent(() => import('@/components/qrcode')) |
| | | const Video = asyncComponent(() => import('@/components/video')) |
| | | const MarkColumn = asyncIconComponent(() => import('@/menu/components/share/markcomponent')) |
| | | const PicRadio = { |
| | | '4:3': '75%', '3:2': '66.67%', '16:9': '56.25%', '2:1': '50%', '3:1': '33.33%', '4:1': '25%', |
| | | '5:1': '20%', '6:1': '16.67%', '7:1': '14.29%', '8:1': '12.5%', '9:1': '11.11%', |
| | | '10:1': '10%', '3:4': '133.33%', '2:3': '150%', '9:16': '177.78%' |
| | | } |
| | | |
| | | const Card = ({ id, parent, fields, card, moveCard, findCard, editCard, delCard, copyCard, changeStyle, updateMarks, doubleClickCard }) => { |
| | | const originalIndex = findCard(id).index |
| | |
| | | |
| | | if (card.style) { |
| | | _style = {...card.style, opacity: isDragging ? 0 : 1} |
| | | _style = resetStyle(_style) |
| | | } |
| | | if (card.eleType === 'picture' && card.maxWidth) { |
| | | _style.maxWidth = card.maxWidth |
| | | let left = _style.marginLeft && _style.marginLeft !== '0px' ? _style.marginLeft : 'auto' |
| | | let right = _style.marginRight && _style.marginRight !== '0px' ? _style.marginRight : 'auto' |
| | | _style.margin = (_style.marginTop || 0) + ' ' + right + ' ' + (_style.marginBottom || 0) + ' ' + left |
| | | delete _style.marginLeft |
| | | delete _style.marginRight |
| | | delete _style.marginTop |
| | | delete _style.marginBottom |
| | | } |
| | | |
| | | const getContent = () => { |
| | |
| | | _imagestyle.borderRadius = card.style.borderRadius |
| | | } |
| | | |
| | | if (card.lenWidRadio === '16:9') { |
| | | _imagestyle.paddingTop = '56.25%' |
| | | } else if (card.lenWidRadio === '3:2') { |
| | | _imagestyle.paddingTop = '66.67%' |
| | | } else if (card.lenWidRadio === '4:3') { |
| | | _imagestyle.paddingTop = '75%' |
| | | if (PicRadio[card.lenWidRadio]) { |
| | | _imagestyle.paddingTop = PicRadio[card.lenWidRadio] |
| | | } else { |
| | | _imagestyle.paddingTop = '100%' |
| | | } |
| | |
| | | <Icon className="copy" title="复制" type="copy" onClick={() => copyCard(id)} /> |
| | | <Icon className="close" title="删除" type="close" onClick={() => delCard(id)} /> |
| | | <Icon className="style" title="调整样式" onClick={() => changeStyle(id)} type="font-colors" /> |
| | | {['text', 'number', 'slider'].includes(card.eleType) ? <MarkColumn columns={fields} type={card.eleType} marks={card.marks} onSubmit={(vals) => updateMarks({...card, marks: vals})} /> : null } |
| | | {['text', 'number', 'slider', 'sequence'].includes(card.eleType) ? <MarkColumn columns={fields} type={card.eleType} marks={card.marks} onSubmit={(vals) => updateMarks({...card, marks: vals})} /> : null } |
| | | </div> |
| | | } trigger="hover"> |
| | | <div ref={node => drag(drop(node))} className={'ant-col card-cell ant-col-' + card.width}> |
| | |
| | | let copycard = fromJS(card).toJS() |
| | | let _cards = fromJS(cards).toJS() |
| | | |
| | | copycard.copyType = 'customCardElement' |
| | | if (card.eleType === 'button') { |
| | | copycard.copyType = 'action' |
| | | } else { |
| | | copycard.copyType = 'customCardElement' |
| | | } |
| | | copycard.focus = true |
| | | |
| | | let _val = fromJS(copycard).toJS() |
| | |
| | | key={card.uuid} |
| | | card={card} |
| | | parent={parent} |
| | | copyCard={copyCard} |
| | | moveCard={moveCard} |
| | | editCard={editCard} |
| | | changeStyle={changeStyle} |
| | |
| | | sequence: ['eleType', 'width'], |
| | | text: ['eleType', 'datatype', 'format', 'width', 'height', 'prefix', 'postfix', 'link'], |
| | | number: ['eleType', 'datatype', 'format', 'width', 'height', 'prefix', 'postfix'], |
| | | picture: ['eleType', 'datatype', 'width', 'lenWidRadio', 'link'], |
| | | picture: ['eleType', 'datatype', 'width', 'lenWidRadio', 'maxWidth', 'link'], |
| | | video: ['eleType', 'datatype', 'width', 'aspectRatio', 'autoPlay', 'loop'], |
| | | icon: ['eleType', 'icon', 'datatype', 'width'], |
| | | slider: ['eleType', 'datatype', 'width', 'color', 'maxValue'], |
| | |
| | | const Formdict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS |
| | | |
| | | /** |
| | | * @description 获取按钮表单配置信息 |
| | | * @param {*} card 编辑按钮 |
| | | * @param {*} type 按钮类型,用于区分可选的打开方式 |
| | | * @description 获取元素配置信息 |
| | | * @param {*} card |
| | | * @param {*} type |
| | | */ |
| | | export function getCardCellForm (card, type) { |
| | | export function getCardCellForm (card, type, subtype, cardCell) { |
| | | let _options = [ |
| | | { value: 'text', text: '文本'}, |
| | | { value: 'number', text: '数值'}, |
| | |
| | | { value: 'currentDate', text: '当前时间'}, |
| | | ] |
| | | |
| | | if (type === 'table') { |
| | | if (type === 'table' || (type === 'card' && subtype === 'datacard')) { |
| | | _options.push({value: 'sequence', text: '序号'}) |
| | | } |
| | | let appMenus = [] |
| | |
| | | } else { |
| | | appMenus = [] |
| | | } |
| | | } |
| | | |
| | | let dataTypes = [ |
| | | { value: 'dynamic', text: '动态' }, |
| | | { value: 'static', text: '静态' } |
| | | ] |
| | | if (cardCell.$cardType === 'extendCard') { |
| | | card.datatype = 'static' |
| | | dataTypes = [ |
| | | { value: 'static', text: '静态' } |
| | | ] |
| | | } |
| | | |
| | | let forms = [ |
| | |
| | | label: '数据类型', |
| | | initVal: card.datatype || 'static', |
| | | required: true, |
| | | options: [ |
| | | { value: 'dynamic', text: '动态' }, |
| | | { value: 'static', text: '静态' } |
| | | ] |
| | | options: dataTypes |
| | | }, |
| | | { |
| | | type: 'select', |
| | |
| | | required: true, |
| | | options: [ |
| | | { value: '1:1', text: '1:1' }, |
| | | { value: '3:2', text: '3:2' }, |
| | | { value: '4:3', text: '4:3' }, |
| | | { value: '16:9', text: '16:9' } |
| | | { value: '3:2', text: '3:2' }, |
| | | { value: '16:9', text: '16:9' }, |
| | | { value: '2:1', text: '2:1' }, |
| | | { value: '3:1', text: '3:1' }, |
| | | { value: '4:1', text: '4:1' }, |
| | | { value: '5:1', text: '5:1' }, |
| | | { value: '6:1', text: '6:1' }, |
| | | { value: '7:1', text: '7:1' }, |
| | | { value: '8:1', text: '8:1' }, |
| | | { value: '9:1', text: '9:1' }, |
| | | { value: '10:1', text: '10:1' }, |
| | | { value: '3:4', text: '3:4' }, |
| | | { value: '2:3', text: '2:3' }, |
| | | { value: '9:16', text: '9:16' }, |
| | | ] |
| | | }, |
| | | { |
| | | type: 'number', |
| | | key: 'maxWidth', |
| | | min: 10, |
| | | max: 2000, |
| | | label: '最大宽度', |
| | | initVal: card.maxWidth || '', |
| | | tooltip: '图片宽度的最大值。', |
| | | required: false, |
| | | }, |
| | | { |
| | | type: 'select', |
| | |
| | | forbid: !isApp, |
| | | options: [ |
| | | { value: '', text: '无' }, |
| | | { value: 'page', text: '菜单' }, |
| | | // { value: 'page', text: '菜单' }, |
| | | { value: 'linkpage', text: '关联菜单' }, |
| | | { value: 'custom', text: '链接' } |
| | | ] |
| | |
| | | { value: 'self', text: '当前页面' } |
| | | ] |
| | | }, |
| | | { |
| | | type: 'select', |
| | | key: 'copyMenuId', |
| | | label: '复制菜单', |
| | | initVal: card.copyMenuId || '', |
| | | required: false, |
| | | forbid: !isApp, |
| | | options: appMenus |
| | | }, |
| | | // { |
| | | // type: 'select', |
| | | // key: 'copyMenuId', |
| | | // label: '复制菜单', |
| | | // initVal: card.copyMenuId || '', |
| | | // required: false, |
| | | // forbid: !isApp, |
| | | // options: appMenus |
| | | // }, |
| | | { |
| | | type: 'radio', |
| | | key: 'joint', |
| | |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | appType: sessionStorage.getItem('appType'), |
| | | card: null, // 编辑中元素 |
| | | formlist: null, // 表单信息 |
| | | elements: null, // 按钮组 |
| | |
| | | */ |
| | | UNSAFE_componentWillMount () { |
| | | const { elements } = this.props |
| | | let _elements = fromJS(elements).toJS() |
| | | |
| | | this.setState({ |
| | | elements: fromJS(elements).toJS() |
| | | elements: _elements.map(item => { |
| | | if (item.btnstyle) { // 兼容 |
| | | item.style = item.style || {} |
| | | item.style = {...item.style, ...item.btnstyle} |
| | | delete item.btnstyle |
| | | } |
| | | |
| | | return item |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('cardAddElement', this.cardAddElement) |
| | | MKEmitter.addListener('submitStyle', this.getStyle) |
| | | MKEmitter.addListener('submitModal', this.handleSave) |
| | | MKEmitter.addListener('cardAddElement', this.cardAddElement) |
| | | MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle) |
| | | } |
| | | |
| | |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('cardAddElement', this.cardAddElement) |
| | | MKEmitter.removeListener('submitStyle', this.getStyle) |
| | | MKEmitter.removeListener('submitModal', this.handleSave) |
| | | MKEmitter.removeListener('cardAddElement', this.cardAddElement) |
| | | MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle) |
| | | } |
| | | |
| | |
| | | const { cards, cardCell } = this.props |
| | | |
| | | let _style = element.style ? fromJS(element.style).toJS() : {} |
| | | let options = ['font', 'border', 'padding', 'margin', 'backgroundColor'] |
| | | let options = ['font', 'border', 'padding', 'margin', 'background'] |
| | | |
| | | if (element.eleType === 'button') { |
| | | if (element.btnstyle) { |
| | | _style = {..._style, ...element.btnstyle} |
| | | } |
| | | options.push('width', 'float') |
| | | } else if (element.eleType === 'picture') { |
| | | options = ['border', 'margin'] |
| | | } else if (element.eleType === 'slider') { |
| | |
| | | if (line) { |
| | | _card.innerHeight = fontSize * lineHeight * line |
| | | } |
| | | } else if (_card.eleType === 'sequence') { |
| | | _card.style = style |
| | | |
| | | let fontSize = 14 |
| | | let lineHeight = 1.5 |
| | | |
| | | if (_card.style.fontSize) { |
| | | fontSize = parseInt(_card.style.fontSize) |
| | | } |
| | | |
| | | _card.innerHeight = fontSize * lineHeight |
| | | } else if (_card.eleType === 'barcode') { |
| | | _card.style = style |
| | | |
| | |
| | | |
| | | _card.innerHeight = _card.barHeight + (_card.displayValue === 'true' ? fontSize + 2 : 0) |
| | | } else if (_card.eleType === 'button') { // 拆分style |
| | | let _style = fromJS(style).toJS() |
| | | _card.style = {} |
| | | |
| | | if (_style.marginTop) { |
| | | _card.style.marginTop = _style.marginTop |
| | | delete _style.marginTop |
| | | } |
| | | if (_style.marginBottom) { |
| | | _card.style.marginBottom = _style.marginBottom |
| | | delete _style.marginBottom |
| | | } |
| | | if (_style.marginLeft) { |
| | | _card.style.marginLeft = _style.marginLeft |
| | | delete _style.marginLeft |
| | | } |
| | | if (_style.marginRight) { |
| | | _card.style.marginRight = _style.marginRight |
| | | delete _style.marginRight |
| | | } |
| | | if (_style.paddingTop) { |
| | | _card.style.paddingTop = _style.paddingTop |
| | | delete _style.paddingTop |
| | | } |
| | | if (_style.paddingBottom) { |
| | | _card.style.paddingBottom = _style.paddingBottom |
| | | delete _style.paddingBottom |
| | | } |
| | | if (_style.paddingLeft) { |
| | | _card.style.paddingLeft = _style.paddingLeft |
| | | delete _style.paddingLeft |
| | | } |
| | | if (_style.paddingRight) { |
| | | _card.style.paddingRight = _style.paddingRight |
| | | delete _style.paddingRight |
| | | } |
| | | if (_style.textAlign) { |
| | | _card.style.textAlign = _style.textAlign |
| | | delete _style.textAlign |
| | | } |
| | | |
| | | _card.btnstyle = _style |
| | | _card.style = style |
| | | } else { |
| | | _card.style = style |
| | | } |
| | |
| | | * @description 元素编辑,获取元素表单信息 |
| | | */ |
| | | handleElement = (card) => { |
| | | const { cards } = this.props |
| | | const { cards, cardCell } = this.props |
| | | |
| | | if (card.eleType === 'button') { |
| | | this.handleAction(card) |
| | |
| | | this.setState({ |
| | | visible: true, |
| | | card: card, |
| | | formlist: getCardCellForm(card, cards.type) |
| | | formlist: getCardCellForm(card, cards.type, cards.subtype, cardCell) |
| | | }) |
| | | } |
| | | } |
| | |
| | | this.setState({ |
| | | actvisible: true, |
| | | card: card, |
| | | formlist: getActionForm(card, functip, cards.setting, usefulFields, 'card', menulist, modules) |
| | | formlist: getActionForm(card, functip, cards, usefulFields, 'card', menulist, modules) |
| | | }) |
| | | } |
| | | |
| | |
| | | if (cell.uuid === res.uuid) { |
| | | res = {...cell, ...res} |
| | | delete res.focus |
| | | let btnstyle = {} |
| | | let style = {} |
| | | |
| | | if (res.class !== cell.class || res.show !== cell.show || !res.btnstyle) { |
| | | if (res.class !== cell.class || res.show !== cell.show || !res.style) { |
| | | if (res.show === 'link' || res.show === 'icon') { |
| | | btnstyle.color = color[res.class] |
| | | btnstyle.backgroundColor = 'transparent' |
| | | style.color = color[res.class] |
| | | style.backgroundColor = 'transparent' |
| | | } else { |
| | | btnstyle.color = '#ffffff' |
| | | btnstyle.backgroundColor = color[res.class] |
| | | style.color = '#ffffff' |
| | | style.backgroundColor = color[res.class] |
| | | } |
| | | } |
| | | res.btnstyle = {...res.btnstyle, ...btnstyle} |
| | | res.style = {...res.style, ...style} |
| | | |
| | | return res |
| | | } |
| | |
| | | */ |
| | | deleteElement = (card) => { |
| | | const { cards, cardCell, side } = this.props |
| | | const { dict, elements } = this.state |
| | | const { dict, elements, appType } = this.state |
| | | let _this = this |
| | | |
| | | confirm({ |
| | | content: dict['model.confirm'] + dict['model.delete'] + '元素吗?', |
| | | onOk() { |
| | | let _elements = elements.filter(item => item.uuid !== card.uuid) |
| | | |
| | | if (card.eleType === 'button') { |
| | | MKEmitter.emit('delButtons', [card.uuid]) |
| | | } |
| | | |
| | | if (card.OpenType === 'popview' || card.verify || card.modal) { |
| | | card.$parentId = cardCell.uuid |
| | | card.$side = side || '' |
| | |
| | | }, () => { |
| | | _this.props.updateElement(_elements) |
| | | }) |
| | | |
| | | if (card.eleType !== 'button') return |
| | | if (appType === 'mob' || (appType === 'pc' && card.OpenType !== 'popview')) return |
| | | |
| | | MKEmitter.emit('delButtons', [card.uuid]) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | |
| | | |
| | | handleSubConfig = (item) => { |
| | | const { cards } = this.props |
| | | const { appType } = this.state |
| | | let btn = fromJS(item).toJS() |
| | | |
| | | if ((sessionStorage.getItem('style-control') && sessionStorage.getItem('style-control') !== 'false')) return |
| | | if ((sessionStorage.getItem('style-control') && sessionStorage.getItem('style-control') === 'true')) return |
| | | |
| | | if (btn.eleType === 'button') { |
| | | if (btn.OpenType === 'pop') { |
| | | if (!btn.modal) { |
| | | btn.modal = { |
| | | setting: { title: btn.label, width: 60, cols: '2', container: 'view', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' }, |
| | | setting: { title: btn.label, width: appType === 'mob' ? 100 : 60, cols: '2', container: 'view', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' }, |
| | | tables: [], |
| | | groups: [], |
| | | fields: [] |
| | |
| | | > |
| | | <ActionForm |
| | | dict={dict} |
| | | type="card" |
| | | type={cards.type === 'balcony' ? '' : 'card'} |
| | | card={card} |
| | | formlist={this.state.formlist} |
| | | inputSubmit={this.handleActionSubmit} |
| | |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .ant-btn { |
| | | padding: 0; |
| | | } |
| | | |
| | | .card-button-cell { |
| | | float: left; |
| | | button { |
| | | width: 100%; |
| | | background-size: cover; |
| | | background-position: center center; |
| | | height: auto; |
| | | min-height: 32px; |
| | | text-align: center; |
| | | span { |
| | | font-style: inherit; |
| | | text-decoration: inherit; |
| | | font-weight: inherit; |
| | | } |
| | | } |
| | | } |
| | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import SettingForm from './settingform' |
| | | |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import './index.scss' |
| | | |
| | | const CardCellComponent = asyncComponent(() => import('../cardcellcomponent')) |
| | | const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) |
| | | const PasteComponent = asyncIconComponent(() => import('./pastecomponent')) |
| | | |
| | | class CardBoxComponent extends Component { |
| | | static propTpyes = { |
| | |
| | | this.props.updateElement(_card) |
| | | } |
| | | |
| | | updateCard = (elements) => { |
| | | updateCard = (elements, type) => { |
| | | const { card, side } = this.state |
| | | |
| | | let _card = {} |
| | |
| | | _card = {...card, elements: elements} |
| | | } |
| | | |
| | | this.setState({ |
| | | card: _card |
| | | }) |
| | | if (type === 'paste') { |
| | | this.setState({ |
| | | card: _card, |
| | | elements: fromJS(elements).toJS() |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | card: _card |
| | | }) |
| | | } |
| | | |
| | | this.props.updateElement(_card) |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | doubleClickCard = () => { |
| | | const { card } = this.state |
| | | |
| | | if (card.setting.click === 'menu' && card.setting.menu) { |
| | | MKEmitter.emit('changeEditMenu', {MenuID: card.setting.menu}) |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { cards, offset } = this.props |
| | | const { card, elements, side, settingVisible, dict } = this.state |
| | |
| | | marginTop: card.style.marginTop |
| | | } |
| | | } |
| | | _style = resetStyle(_style) |
| | | |
| | | return ( |
| | | <Col span={card.setting.width || 6} offset={offset || 0}> |
| | | <div className="card-item" style={_style} onClick={this.clickComponent} id={card.uuid}> |
| | | <div className="card-item" style={_style} onClick={this.clickComponent} onDoubleClick={(e) => {e.stopPropagation(); this.doubleClickCard()}} id={card.uuid}> |
| | | <CardCellComponent cards={cards} cardCell={card} side={side} elements={elements} updateElement={this.updateCard}/> |
| | | <div className="card-control"> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | |
| | | <Icon className="plus" title="添加按钮" onClick={this.addButton} type="plus-square" /> |
| | | <Icon className="edit" title="编辑" type="edit" onClick={() => this.setState({settingVisible: true})} /> |
| | | <CopyComponent type="cardcell" card={card}/> |
| | | <PasteComponent elements={elements} options={['action', 'customCardElement']} updateConfig={(list) => this.updateCard(list, 'paste')} /> |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | | {cards.subtype === 'propcard' ? <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <Icon className="plus" title="左移" type="arrow-left" onClick={() => this.props.move(card, 'left')} /> |
| | | <Icon className="close" title="右移" type="arrow-right" onClick={() => this.props.move(card, 'right')} /> |
| | | <Icon className="plus" title="前移" type="arrow-left" onClick={() => this.props.move(card, 'left')} /> |
| | | <Icon className="close" title="后移" type="arrow-right" onClick={() => this.props.move(card, 'right')} /> |
| | | </div> |
| | | } trigger="hover" getPopupContainer={() => document.getElementById(card.uuid + 'swap')}> |
| | | <Icon type="swap" id={card.uuid + 'swap'}/> |
| | | </Popover> : null} |
| | | {cards.subtype === 'propcard' ? <Icon className="close" title="删除卡片" type="delete" onClick={() => this.props.deleteElement(card)} /> : null} |
| | | </Popover> |
| | | {cards.subtype === 'propcard' || card.$cardType === 'extendCard' ? <Icon className="close" title="删除卡片" type="delete" onClick={() => this.props.deleteElement(card)} /> : null} |
| | | {card.setting.type === 'multi' ? <Switch size="small" onClick={this.changeSide} defaultChecked /> : null} |
| | | </div> |
| | | } trigger="hover"> |
| | |
| | | wrapClassName="popview-modal" |
| | | title={'卡片设置'} |
| | | visible={settingVisible} |
| | | width={700} |
| | | width={800} |
| | | maskClosable={false} |
| | | okText={dict['model.submit']} |
| | | onOk={this.settingSubmit} |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { fromJS } from 'immutable' |
| | | import { Icon, Modal, notification } from 'antd' |
| | | |
| | | import Utils from '@/utils/utils.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import './index.scss' |
| | | |
| | | const PasteForm = asyncComponent(() => import('@/templates/zshare/pasteform')) |
| | | |
| | | class PasteController extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.object, // 组件配置 |
| | | updateConfig: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | visible: false |
| | | } |
| | | |
| | | handleMenuClick = () => { |
| | | this.setState({visible: true}) |
| | | } |
| | | |
| | | pasteSubmit = () => { |
| | | const { options, elements } = this.props |
| | | this.pasteFormRef.handleConfirm().then(res => { |
| | | if (!options.includes(res.copyType)) { |
| | | notification.warning({ top: 92, message: '配置信息格式错误!', duration: 5 }) |
| | | return |
| | | } |
| | | |
| | | let _uuid = Utils.getuuid() |
| | | if (res.copyType === 'action' && res.OpenType === 'popview') { |
| | | let _cell = fromJS(res).toJS() |
| | | _cell.$originUuid = res.uuid |
| | | _cell.uuid = _uuid |
| | | MKEmitter.emit('copyButtons', [_cell]) |
| | | } |
| | | res.uuid = _uuid |
| | | |
| | | this.props.updateConfig([...elements, res]) |
| | | this.setState({visible: false}) |
| | | |
| | | notification.success({ |
| | | top: 92, |
| | | message: '粘贴成功!', |
| | | duration: 2 |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const { visible } = this.state |
| | | |
| | | return ( |
| | | <div style={{display: 'inline-block'}}> |
| | | <Icon type="snippets" style={{color: 'purple'}} onClick={() => {this.setState({visible: true})}} /> |
| | | <Modal |
| | | title="粘贴" |
| | | visible={visible} |
| | | width={600} |
| | | maskClosable={false} |
| | | onOk={this.pasteSubmit} |
| | | onCancel={() => {this.setState({visible: false})}} |
| | | destroyOnClose |
| | | > |
| | | <PasteForm wrappedComponentRef={(inst) => this.pasteFormRef = inst} inputSubmit={this.pasteSubmit}/> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default PasteController |
copy from src/tabviews/zshare/mutilform/customSwitch/index.scss
copy to src/menu/components/card/cardcomponent/pastecomponent/index.scss
| | |
| | | state = { |
| | | type: this.props.setting.type || 'simple', |
| | | click: this.props.setting.click || '', |
| | | isApp: sessionStorage.getItem('appType') === 'pc', |
| | | appType: sessionStorage.getItem('appType'), |
| | | menulist: [] |
| | | } |
| | | |
| | | UNSAFE_componentWillMount() { |
| | | const { isApp } = this.state |
| | | const { appType } = this.state |
| | | let menulist = null |
| | | |
| | | if (isApp) { |
| | | if (appType) { |
| | | menulist = sessionStorage.getItem('appMenus') |
| | | } else { |
| | | menulist = sessionStorage.getItem('fstMenuList') |
| | |
| | | render() { |
| | | const { setting, cards } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { menulist, click, isApp } = this.state |
| | | const { menulist, click, appType } = this.state |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | |
| | | } |
| | | |
| | | return ( |
| | | <div className="model-menu-setting-form"> |
| | | <div className="model-menu-card-setting-form"> |
| | | <Form {...formItemLayout}> |
| | | <Row gutter={24}> |
| | | <Col span={12}> |
| | |
| | | })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit}/>)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | {appType !== 'mob' ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="选择复式卡时,可配置鼠标悬浮时的显示信息。"> |
| | | <Icon type="question-circle" /> |
| | |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | </Col> : null} |
| | | {this.state.type === 'multi' ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="复式卡片鼠标悬浮信息的动画效果。"> |
| | |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={12}> |
| | | <Form.Item label="点击事件"> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="当选择触发按钮时,只有当卡片中只存在一个按钮时有效。"> |
| | | <Icon type="question-circle" /> |
| | | 点击事件 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('click', { |
| | | initialValue: click |
| | | })( |
| | | <Radio.Group onChange={(e) => this.setState({click: e.target.value})}> |
| | | <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => this.setState({click: e.target.value})}> |
| | | <Radio value="">无</Radio> |
| | | <Radio value="menu">菜单</Radio> |
| | | <Radio value="link">链接</Radio> |
| | | <Radio value="button">按钮</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {!isApp && click === 'menu' ? <Col span={12}> |
| | | {!appType && click === 'menu' ? <Col span={12}> |
| | | <Form.Item label="菜单"> |
| | | {getFieldDecorator('menu', { |
| | | initialValue: setting.menu || [], |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {isApp && click === 'menu' ? <Col span={12}> |
| | | {appType && click === 'menu' ? <Col span={12}> |
| | | <Form.Item label="关联菜单"> |
| | | {getFieldDecorator('menu', { |
| | | initialValue: setting.menu || '', |
| | |
| | | })( <TextArea rows={2}/> )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {isApp ? <Col span={12}> |
| | | {appType === 'pc' && click !== '' && click !== 'button' ? <Col span={12}> |
| | | <Form.Item label="打开方式"> |
| | | {getFieldDecorator('open', { |
| | | initialValue: setting.open || 'blank' |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {click !== '' ? <Col span={12}> |
| | | {click !== '' && click !== 'button' ? <Col span={12}> |
| | | <Form.Item label="参数拼接"> |
| | | {getFieldDecorator('joint', { |
| | | initialValue: setting.joint || 'true' |
| | |
| | | .model-menu-setting-form { |
| | | .model-menu-card-setting-form { |
| | | position: relative; |
| | | |
| | | .anticon-question-circle { |
| | |
| | | width: 84%; |
| | | } |
| | | } |
| | | .ant-radio-wrapper { |
| | | margin-right: 3px; |
| | | } |
| | | } |
| | |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | |
| | | const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) |
| | | const WrapComponent = asyncIconComponent(() => import('./wrapsetting')) |
| | | const CardComponent = asyncComponent(() => import('../cardcomponent')) |
| | | const MobPagination = asyncIconComponent(() => import('@/menu/components/share/mobPagination')) |
| | | const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent')) |
| | | const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) |
| | | const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent')) |
| | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | card: null, |
| | | appType: sessionStorage.getItem('appType'), |
| | | back: false |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { card } = this.props |
| | | const { appType } = this.state |
| | | |
| | | if (card.isNew) { |
| | | let ismob = sessionStorage.getItem('appType') === 'mob' |
| | | let _card = { |
| | | uuid: card.uuid, |
| | | type: card.type, |
| | |
| | | name: card.name, |
| | | subtype: card.subtype, |
| | | setting: { interType: 'system' }, |
| | | wrap: { name: card.name, width: card.width || 24, title: '', pagestyle: 'page', switch: 'false' }, |
| | | wrap: { name: card.name, width: card.width || 24, title: '', pagestyle: 'page', switch: 'false', cardType: '' }, |
| | | style: { marginLeft: '0px', marginRight: '0px', marginTop: '8px', marginBottom: '8px' }, |
| | | headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' }, |
| | | columns: [], |
| | |
| | | btnlog: [], |
| | | subcards: [{ |
| | | uuid: Utils.getuuid(), |
| | | setting: { width: ismob ? 24 : 6, type: 'simple'}, |
| | | setting: { width: appType === 'mob' ? 24 : 6, type: 'simple'}, |
| | | style: { |
| | | borderWidth: '1px', borderColor: '#e8e8e8', |
| | | paddingTop: '15px', paddingBottom: '15px', paddingLeft: '15px', paddingRight: '15px', |
| | |
| | | * @description 单个卡片信息更新 |
| | | */ |
| | | deleteCard = (cell) => { |
| | | const { appType } = this.state |
| | | let card = fromJS(this.state.card).toJS() |
| | | let _this = this |
| | | |
| | |
| | | onOk() { |
| | | card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid) |
| | | |
| | | let uuids = [] |
| | | cell.elements && cell.elements.forEach(c => { |
| | | if (c.eleType === 'button') { |
| | | uuids.push(c.uuid) |
| | | } |
| | | }) |
| | | cell.backElements && cell.backElements.forEach(c => { |
| | | if (c.eleType === 'button') { |
| | | uuids.push(c.uuid) |
| | | } |
| | | }) |
| | | MKEmitter.emit('delButtons', uuids) |
| | | |
| | | if (card.btnlog) { |
| | | card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid) |
| | | } |
| | | |
| | | _this.setState({card}) |
| | | _this.props.updateConfig(card) |
| | | |
| | | if (appType === 'mob') return |
| | | |
| | | let uuids = [] |
| | | |
| | | cell.elements && cell.elements.forEach(c => { |
| | | if (c.eleType !== 'button' || (appType === 'pc' && c.OpenType !== 'popview')) return |
| | | |
| | | uuids.push(c.uuid) |
| | | }) |
| | | cell.backElements && cell.backElements.forEach(c => { |
| | | if (c.eleType !== 'button' || (appType === 'pc' && c.OpenType !== 'popview')) return |
| | | |
| | | uuids.push(c.uuid) |
| | | }) |
| | | |
| | | if (uuids.length === 0) return |
| | | |
| | | MKEmitter.emit('delButtons', uuids) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | |
| | | newcard.execError = 'never' |
| | | newcard.verify = null |
| | | newcard.show = 'button' |
| | | newcard.btnstyle = {marginRight: '15px'} |
| | | newcard.style = {marginRight: '15px'} |
| | | |
| | | // 注册事件-添加按钮 |
| | | MKEmitter.emit('addButton', card.uuid, newcard) |
| | | } |
| | | |
| | | setSubConfig = (item) => { |
| | | const { card } = this.state |
| | | const { card, appType } = this.state |
| | | let btn = fromJS(item).toJS() |
| | | |
| | | if (btn.OpenType === 'pop' || btn.execMode === 'pop') { |
| | | if (!btn.modal) { |
| | | btn.modal = { |
| | | setting: { title: btn.label, width: 60, cols: '2', container: 'view', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' }, |
| | | setting: { title: btn.label, width: appType === 'mob' ? 100 : 60, cols: '2', container: 'view', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' }, |
| | | tables: [], |
| | | groups: [], |
| | | fields: [] |
| | | } |
| | | } |
| | | MKEmitter.emit('changeModal', card, btn) |
| | | } else if (btn.OpenType === 'popview') { |
| | | } else if (btn.OpenType === 'popview' && appType !== 'mob') { |
| | | MKEmitter.emit('changePopview', card, btn) |
| | | } |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | addCard = () => { |
| | | let card = fromJS(this.state.card).toJS() |
| | | let height = card.subcards[0].style.height |
| | | if (height === 'auto') { |
| | | height = '100px' |
| | | } |
| | | |
| | | let newcard = { |
| | | uuid: Utils.getuuid(), |
| | | $cardType: 'extendCard', |
| | | setting: { width: 6, type: 'simple', click: 'button'}, |
| | | style: { |
| | | height, |
| | | borderWidth: '1px', borderColor: '#e8e8e8', |
| | | paddingTop: '15px', paddingBottom: '15px', paddingLeft: '15px', paddingRight: '15px', |
| | | marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' |
| | | }, |
| | | backStyle: {}, |
| | | elements: [], |
| | | backElements: [] |
| | | } |
| | | |
| | | card.subcards.push(newcard) |
| | | |
| | | this.setState({card}) |
| | | this.props.updateConfig(card) |
| | | } |
| | | |
| | | move = (item, direction) => { |
| | | let card = fromJS(this.state.card).toJS() |
| | | |
| | | let dragIndex = card.subcards.findIndex(c => c.uuid === item.uuid) |
| | | let hoverIndex = null |
| | | |
| | | if (direction === 'left') { |
| | | hoverIndex = dragIndex - 1 |
| | | } else { |
| | | hoverIndex = dragIndex + 1 |
| | | } |
| | | |
| | | if (hoverIndex === -1 || hoverIndex === card.subcards.length) return |
| | | |
| | | card.subcards.splice(hoverIndex, 0, ...card.subcards.splice(dragIndex, 1)) |
| | | |
| | | this.setState({card}) |
| | | this.props.updateConfig(card) |
| | | } |
| | | |
| | | clickComponent = (e) => { |
| | | if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { |
| | | e.stopPropagation() |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { card } = this.state |
| | | const { card, appType } = this.state |
| | | |
| | | let offset = 0 |
| | | if (card.wrap.cardFloat && card.wrap.cardFloat !== 'left') { |
| | |
| | | offset = Math.floor(offset / 2) |
| | | } |
| | | } |
| | | let _style = resetStyle(card.style) |
| | | |
| | | return ( |
| | | <div className="menu-data-card-edit-box" style={{...card.style}} onClick={this.clickComponent} id={card.uuid}> |
| | | <div className={'menu-data-card-edit-box ' + appType} style={_style} onClick={this.clickComponent} id={card.uuid}> |
| | | <NormalHeader defaultshow="hidden" config={card} updateComponent={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" /> |
| | | {appType !== 'mob' ? <Icon className="plus" title="添加卡片" onClick={this.addCard} type="plus" /> : null} |
| | | {appType !== 'mob' ? <Icon className="plus" title="添加搜索" onClick={this.addSearch} type="plus-circle" /> : null} |
| | | <Icon className="plus" title="添加按钮" onClick={this.addButton} type="plus-square" /> |
| | | <WrapComponent config={card} updateConfig={this.updateComponent} /> |
| | | <CopyComponent type="datacard" card={card}/> |
| | | <PasteComponent config={card} options={['action', 'search', 'form']} updateConfig={this.updateComponent} /> |
| | | <PasteComponent config={card} options={['action', 'search', 'form', 'cardcell']} updateConfig={this.updateComponent} /> |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | | <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> |
| | | <UserComponent config={card}/> |
| | |
| | | } trigger="hover"> |
| | | <Icon type="tool" /> |
| | | </Popover> |
| | | <ActionComponent config={card} setSubConfig={this.setSubConfig} updateaction={this.updateComponent}/> |
| | | {card.subcards.map((subcard, index) => (<CardComponent key={subcard.uuid} offset={!index ? offset : 0} cards={card} card={subcard} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))} |
| | | <ActionComponent config={card} type="datacard" setSubConfig={this.setSubConfig} updateaction={this.updateComponent}/> |
| | | {card.subcards.map((subcard, index) => (<CardComponent key={subcard.uuid} offset={!index ? offset : 0} cards={card} card={subcard} move={this.move} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))} |
| | | <div style={{clear: 'both'}}></div> |
| | | {card.wrap.pagestyle !== 'switch' && card.setting.laypage === 'true' ? <Pagination total={85} size="small" showTotal={total => `共 ${total} 条`} pageSize={20} defaultCurrent={1}/> : null} |
| | | {card.wrap.pagestyle === 'page' && card.setting.laypage === 'true' && appType !== 'mob' ? <Pagination total={85} size="small" showTotal={total => `共 ${total} 条`} pageSize={20} defaultCurrent={1}/> : null} |
| | | {card.wrap.pagestyle === 'page' && card.setting.laypage === 'true' && appType === 'mob' ? <MobPagination /> : null} |
| | | </div> |
| | | ) |
| | | } |
| | |
| | | line-height: 55px; |
| | | } |
| | | } |
| | | .normal-pagination { |
| | | .am-button::before { |
| | | display: none; |
| | | } |
| | | .am-button { |
| | | border: none; |
| | | font-size: 16px; |
| | | } |
| | | } |
| | | } |
| | | .menu-data-card-edit-box::after { |
| | | display: block; |
| | | content: ' '; |
| | | clear: both; |
| | | } |
| | | .menu-data-card-edit-box.mob { |
| | | .model-menu-action-list { |
| | | position: absolute; |
| | | top: 5px; |
| | | right: 0px; |
| | | .page-card { |
| | | line-height: 40px; |
| | | } |
| | | } |
| | | } |
| | | .menu-data-card-edit-box:hover { |
| | | z-index: 1; |
| | | box-shadow: 0px 0px 4px #1890ff; |
| | |
| | | import SettingForm from './settingform' |
| | | import './index.scss' |
| | | |
| | | class DataSource extends Component { |
| | | class CardWrapSetting extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.any, |
| | | updateConfig: PropTypes.func |
| | |
| | | } |
| | | } |
| | | |
| | | export default DataSource |
| | | export default CardWrapSetting |
| | |
| | | |
| | | class SettingForm extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, // 字典项 |
| | | config: PropTypes.object, // 卡片行信息 |
| | | wrap: PropTypes.object, // 数据源配置 |
| | | inputSubmit: PropTypes.func // 回车事件 |
| | | dict: PropTypes.object, |
| | | config: PropTypes.object, |
| | | wrap: PropTypes.object, |
| | | inputSubmit: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | roleList: [] |
| | | roleList: [], |
| | | appType: sessionStorage.getItem('appType'), |
| | | cardType: this.props.wrap.cardType, |
| | | MenuType: '' |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | |
| | | roleList = [] |
| | | } |
| | | |
| | | this.setState({roleList}) |
| | | let MenuType = '' |
| | | |
| | | if (window.GLOB.customMenu && window.GLOB.customMenu.parentId === 'BillPrintTemp') { |
| | | MenuType = 'billPrint' |
| | | } |
| | | |
| | | this.setState({roleList, MenuType}) |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | |
| | | render() { |
| | | const { wrap, config } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { roleList } = this.state |
| | | const { roleList, MenuType, appType, cardType } = this.state |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {config.subtype === 'datacard' ? <Col span={12}> |
| | | {config.subtype === 'datacard' || (config.subtype === 'tablecard' && appType === 'mob') ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="数据源中选择分页时有效。"> |
| | | <Icon type="question-circle" /> |
| | |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="page">页码</Radio> |
| | | <Radio value="switch">左右切换</Radio> |
| | | {appType !== 'mob' ? <Radio value="switch">左右切换</Radio> : null} |
| | | {appType === 'mob' ? <Radio value="slide">滑动加载</Radio> : null} |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | |
| | | {getFieldDecorator('cardType', { |
| | | initialValue: wrap.cardType || '' |
| | | })( |
| | | <Radio.Group style={{whiteSpace: 'nowrap'}}> |
| | | <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => this.setState({cardType: e.target.value})}> |
| | | <Radio key="" value=""> 不可选 </Radio> |
| | | <Radio key="radio" value={'radio'}> 单选 </Radio> |
| | | {config.subtype !== 'propcard' ? <Radio key="checkbox" value={'checkbox'}> 多选 </Radio> : null} |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {config.subtype === 'datacard' && appType === 'mob' && cardType === 'checkbox' ? <Col span={12}> |
| | | <Form.Item label="全选"> |
| | | {getFieldDecorator('checkAll', { |
| | | initialValue: wrap.checkAll || 'hidden' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio key="hidden" value="hidden"> 隐藏 </Radio> |
| | | <Radio key="show" value="show"> 显示 </Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {config.subtype !== 'tablecard' ? <Col span={12}> |
| | | {config.subtype !== 'tablecard' && appType !== 'mob' ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="鼠标悬浮于卡片上方时,卡片放大1.05倍。"> |
| | | <Icon type="question-circle" /> |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {config.subtype === 'tablecard' ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="表格高度,超出时滚动,高度为空时根据内容自适应。"> |
| | | <Icon type="question-circle" /> |
| | | 高度 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('height', { |
| | | initialValue: wrap.height |
| | | })(<InputNumber min={100} max={2000} precision={0} onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {config.subtype === 'propcard' ? <Col span={12}> |
| | | {config.subtype === 'propcard' && MenuType === 'billPrint' ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="选择类型为《页眉/页脚》时,打印的每页里都会带有该组件。"> |
| | | <Icon type="question-circle" /> |
| | |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | appType: sessionStorage.getItem('appType'), |
| | | card: null, |
| | | back: false |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { card } = this.props |
| | | const { appType } = this.state |
| | | |
| | | if (card.isNew) { |
| | | let ismob = sessionStorage.getItem('appType') === 'mob' |
| | | let _card = { |
| | | uuid: card.uuid, |
| | | type: card.type, |
| | |
| | | scripts: [], |
| | | subcards: [{ |
| | | uuid: Utils.getuuid(), |
| | | setting: { width: ismob ? 24 : 6, type: 'simple'}, |
| | | setting: { width: appType === 'mob' ? 24 : 6, type: 'simple'}, |
| | | style: { |
| | | borderWidth: '1px', borderColor: '#e8e8e8', |
| | | paddingTop: '15px', paddingBottom: '15px', paddingLeft: '15px', paddingRight: '15px', |
| | |
| | | * @description 单个卡片信息更新 |
| | | */ |
| | | deleteCard = (cell) => { |
| | | const { appType } = this.state |
| | | let card = fromJS(this.state.card).toJS() |
| | | let _this = this |
| | | |
| | |
| | | content: '确定删除卡片吗?', |
| | | onOk() { |
| | | card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid) |
| | | |
| | | let uuids = [] |
| | | cell.elements && cell.elements.forEach(c => { |
| | | if (c.eleType === 'button') { |
| | | uuids.push(c.uuid) |
| | | } |
| | | }) |
| | | cell.backElements && cell.backElements.forEach(c => { |
| | | if (c.eleType === 'button') { |
| | | uuids.push(c.uuid) |
| | | } |
| | | }) |
| | | MKEmitter.emit('delButtons', uuids) |
| | | |
| | | if (card.btnlog) { |
| | | card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid) |
| | |
| | | |
| | | _this.setState({card}) |
| | | _this.props.updateConfig(card) |
| | | |
| | | if (appType === 'mob') return |
| | | |
| | | let uuids = [] |
| | | |
| | | cell.elements && cell.elements.forEach(c => { |
| | | if (c.eleType !== 'button' || (appType === 'pc' && c.OpenType !== 'popview')) return |
| | | |
| | | uuids.push(c.uuid) |
| | | }) |
| | | cell.backElements && cell.backElements.forEach(c => { |
| | | if (c.eleType !== 'button' || (appType === 'pc' && c.OpenType !== 'popview')) return |
| | | |
| | | uuids.push(c.uuid) |
| | | }) |
| | | |
| | | if (uuids.length === 0) return |
| | | |
| | | MKEmitter.emit('delButtons', uuids) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | |
| | | } |
| | | } |
| | | |
| | | let _style = resetStyle(card.style) |
| | | |
| | | return ( |
| | | <div className="menu-prop-card-edit-box" style={{...card.style}} onClick={this.clickComponent} id={card.uuid}> |
| | | <div className="menu-prop-card-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> |
| | | <NormalHeader defaultshow="hidden" config={card} updateComponent={this.updateComponent}/> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import SettingForm from './settingform' |
| | | |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import './index.scss' |
| | |
| | | render() { |
| | | const { cards } = this.props |
| | | const { card, elements, settingVisible, dict } = this.state |
| | | let _style = resetStyle(card.style) |
| | | |
| | | return ( |
| | | <div className="ant-col ant-col-24"> |
| | | <div className="card-item" style={card.style}> |
| | | <div className="card-item" style={_style}> |
| | | <CardCellComponent cards={cards} cardCell={card} elements={elements} updateElement={this.updateCard}/> |
| | | <div className="card-control"> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | |
| | | <Icon className="edit" title="编辑" type="edit" onClick={() => this.setState({settingVisible: true})} /> |
| | | <CopyComponent type="cardcell" card={card}/> |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <Icon className="plus" title="前移" type="arrow-left" onClick={() => this.props.move(card, 'left')} /> |
| | | <Icon className="close" title="后移" type="arrow-right" onClick={() => this.props.move(card, 'right')} /> |
| | | </div> |
| | | } trigger="hover" getPopupContainer={() => document.getElementById(card.uuid + 'swap')}> |
| | | <Icon type="swap" id={card.uuid + 'swap'}/> |
| | | </Popover> |
| | | <Icon className="close" title="删除卡片" type="delete" onClick={() => this.props.deleteElement(card)} /> |
| | | </div> |
| | | } trigger="hover"> |
| | |
| | | {option.label} |
| | | </Select.Option> |
| | | )} |
| | | <Select.Option key={'index'} value={'$Index'}>序号(前端)</Select.Option> |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | |
| | | const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) |
| | | const WrapComponent = asyncIconComponent(() => import('../data-card/wrapsetting')) |
| | | const CardComponent = asyncComponent(() => import('./cardcomponent')) |
| | | const MobPagination = asyncIconComponent(() => import('@/menu/components/share/mobPagination')) |
| | | const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) |
| | | const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent')) |
| | | const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent')) |
| | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | card: null, |
| | | appType: sessionStorage.getItem('appType'), |
| | | back: false |
| | | } |
| | | |
| | |
| | | * @description 单个卡片信息更新 |
| | | */ |
| | | deleteCard = (cell) => { |
| | | const { appType } = this.state |
| | | let card = fromJS(this.state.card).toJS() |
| | | let _this = this |
| | | |
| | |
| | | content: '确定删除卡片吗?', |
| | | onOk() { |
| | | card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid) |
| | | |
| | | let uuids = [] |
| | | cell.elements && cell.elements.forEach(c => { |
| | | if (c.eleType === 'button') { |
| | | uuids.push(c.uuid) |
| | | } |
| | | }) |
| | | |
| | | MKEmitter.emit('delButtons', uuids) |
| | | |
| | | if (card.btnlog) { |
| | | card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid) |
| | |
| | | |
| | | _this.setState({card}) |
| | | _this.props.updateConfig(card) |
| | | |
| | | if (appType === 'mob') return |
| | | |
| | | let uuids = [] |
| | | |
| | | cell.elements && cell.elements.forEach(c => { |
| | | if (c.eleType !== 'button' || (appType === 'pc' && c.OpenType !== 'popview')) return |
| | | |
| | | uuids.push(c.uuid) |
| | | }) |
| | | |
| | | if (uuids.length === 0) return |
| | | |
| | | MKEmitter.emit('delButtons', uuids) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['height', 'background', 'border', 'padding', 'margin'], card.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | |
| | | } |
| | | } |
| | | |
| | | move = (item, direction) => { |
| | | let card = fromJS(this.state.card).toJS() |
| | | |
| | | let dragIndex = card.subcards.findIndex(c => c.uuid === item.uuid) |
| | | let hoverIndex = null |
| | | |
| | | if (direction === 'left') { |
| | | hoverIndex = dragIndex - 1 |
| | | } else { |
| | | hoverIndex = dragIndex + 1 |
| | | } |
| | | |
| | | if (hoverIndex === -1 || hoverIndex === card.subcards.length) return |
| | | |
| | | card.subcards.splice(hoverIndex, 0, ...card.subcards.splice(dragIndex, 1)) |
| | | |
| | | this.setState({card}) |
| | | this.props.updateConfig(card) |
| | | } |
| | | |
| | | clickComponent = (e) => { |
| | | if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { |
| | | e.stopPropagation() |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { card } = this.state |
| | | const { card, appType } = this.state |
| | | let _style = resetStyle(card.style) |
| | | |
| | | return ( |
| | | <div className="menu-table-card-edit-box" style={{...card.style, height: card.wrap.height}} onClick={this.clickComponent} id={card.uuid}> |
| | | <div className="menu-table-card-edit-box" style={_style} 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"> |
| | | <Icon className="plus" title="添加卡片" onClick={this.addCard} type="plus" /> |
| | | <Icon className="plus" title="添加搜索" onClick={this.addSearch} type="plus-circle" /> |
| | | {appType !== 'mob' ? <Icon className="plus" title="添加搜索" onClick={this.addSearch} type="plus-circle" /> : null} |
| | | <WrapComponent config={card} updateConfig={this.updateComponent} /> |
| | | <CopyComponent type="tablecard" card={card}/> |
| | | <PasteComponent config={card} options={['cardcell', 'search', 'form']} updateConfig={this.updateComponent} /> |
| | |
| | | } trigger="hover"> |
| | | <Icon type="tool" /> |
| | | </Popover> |
| | | <div style={{minHeight: card.wrap.height - 90}}> |
| | | {card.subcards.map(subcard => (<CardComponent key={subcard.uuid} cards={card} card={subcard} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))} |
| | | <div style={{minHeight: 'calc(100% - 90px)'}}> |
| | | {card.subcards.map(subcard => (<CardComponent key={subcard.uuid} cards={card} card={subcard} updateElement={this.updateCard} move={this.move} deleteElement={this.deleteCard}/>))} |
| | | </div> |
| | | {card.setting.laypage === 'true' ? <Pagination size="small" total={50} /> : null} |
| | | {card.setting.laypage === 'true' && card.wrap.pagestyle !== 'slide' && appType !== 'mob' ? <Pagination size="small" total={50} /> : null} |
| | | {card.setting.laypage === 'true' && card.wrap.pagestyle !== 'slide' && appType === 'mob' ? <MobPagination /> : null} |
| | | </div> |
| | | ) |
| | | } |
| | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import SettingForm from './settingform' |
| | | |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import './index.scss' |
| | |
| | | _style.boxShadow = '0 0 4px ' + _style.shadow |
| | | } |
| | | _style.height = cards.style.height |
| | | _style = resetStyle(_style) |
| | | |
| | | return ( |
| | | <div className="card-item" style={_style} onClick={this.clickComponent} id={card.uuid}> |
| | |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | appType: sessionStorage.getItem('appType'), |
| | | card: null, |
| | | back: false |
| | | } |
| | |
| | | * @description 单个卡片信息更新 |
| | | */ |
| | | deleteCard = (cell) => { |
| | | const { appType } = this.state |
| | | let card = fromJS(this.state.card).toJS() |
| | | let _this = this |
| | | |
| | |
| | | onOk() { |
| | | card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid) |
| | | |
| | | let uuids = [] |
| | | cell.elements && cell.elements.forEach(c => { |
| | | if (c.eleType === 'button') { |
| | | uuids.push(c.uuid) |
| | | } |
| | | }) |
| | | MKEmitter.emit('delButtons', uuids) |
| | | |
| | | if (card.btnlog) { |
| | | card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid) |
| | | } |
| | | |
| | | _this.setState({card}) |
| | | _this.props.updateConfig(card) |
| | | |
| | | if (appType === 'mob') return |
| | | |
| | | let uuids = [] |
| | | |
| | | cell.elements && cell.elements.forEach(c => { |
| | | if (c.eleType !== 'button' || (appType === 'pc' && c.OpenType !== 'popview')) return |
| | | |
| | | uuids.push(c.uuid) |
| | | }) |
| | | |
| | | if (uuids.length === 0) return |
| | | |
| | | MKEmitter.emit('delButtons', uuids) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | |
| | | |
| | | render() { |
| | | const { card } = this.state |
| | | let _style = resetStyle(card.style) |
| | | |
| | | return ( |
| | | <div className="menu-data-carousel-edit-box" style={{...card.style}} onClick={this.clickComponent} id={card.uuid}> |
| | | <div className="menu-data-carousel-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <WrapComponent config={card} updateConfig={this.updateComponent}/> |
| | |
| | | } |
| | | |
| | | state = { |
| | | appType: sessionStorage.getItem('appType'), |
| | | roleList: [] |
| | | } |
| | | |
| | |
| | | render() { |
| | | const { wrap, config } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { roleList } = this.state |
| | | const { roleList, appType } = this.state |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | {appType === 'mob' ? <Col span={12}> |
| | | <Form.Item label="垂直显示"> |
| | | {getFieldDecorator('vertical', { |
| | | initialValue: wrap.vertical || 'false' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="true">是</Radio> |
| | | <Radio value="false">否</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {appType !== 'mob' ? <Col span={12}> |
| | | <Form.Item label="指示点位置"> |
| | | {getFieldDecorator('dotPosition', { |
| | | initialValue: wrap.dotPosition || 'bottom' |
| | |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | </Col> : null} |
| | | {appType !== 'mob' ? <Col span={12}> |
| | | <Form.Item label="动画效果"> |
| | | {getFieldDecorator('effect', { |
| | | initialValue: wrap.effect || 'scrollx' |
| | |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | </Col> : null} |
| | | <Col span={12}> |
| | | <Form.Item label="黑名单"> |
| | | {getFieldDecorator('blacklist', { |
| | |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | appType: sessionStorage.getItem('appType'), |
| | | card: null, |
| | | back: false |
| | | } |
| | |
| | | * @description 单个卡片信息更新 |
| | | */ |
| | | deleteCard = (cell) => { |
| | | const { appType } = this.state |
| | | let card = fromJS(this.state.card).toJS() |
| | | let _this = this |
| | | |
| | |
| | | content: '确定删除卡片吗?', |
| | | onOk() { |
| | | card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid) |
| | | |
| | | let uuids = [] |
| | | cell.elements && cell.elements.forEach(c => { |
| | | if (c.eleType === 'button') { |
| | | uuids.push(c.uuid) |
| | | } |
| | | }) |
| | | MKEmitter.emit('delButtons', uuids) |
| | | |
| | | if (card.btnlog) { |
| | | card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid) |
| | |
| | | |
| | | _this.setState({card}) |
| | | _this.props.updateConfig(card) |
| | | |
| | | if (appType === 'mob') return |
| | | |
| | | let uuids = [] |
| | | |
| | | cell.elements && cell.elements.forEach(c => { |
| | | if (c.eleType !== 'button' || (appType === 'pc' && c.OpenType !== 'popview')) return |
| | | |
| | | uuids.push(c.uuid) |
| | | }) |
| | | |
| | | if (uuids.length === 0) return |
| | | |
| | | MKEmitter.emit('delButtons', uuids) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | |
| | | |
| | | render() { |
| | | const { card } = this.state |
| | | let _style = resetStyle(card.style) |
| | | |
| | | return ( |
| | | <div className="menu-prop-carousel-edit-box" style={{...card.style}} onClick={this.clickComponent} id={card.uuid}> |
| | | <div className="menu-prop-carousel-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <Icon className="plus" title="添加卡片" onClick={this.addCard} type="plus" /> |
| | |
| | | * @param {object} card // 图表对象 |
| | | */ |
| | | export function getBaseForm (card) { |
| | | let isApp = sessionStorage.getItem('appType') === 'pc' |
| | | let menulist = null |
| | | // let appType = sessionStorage.getItem('appType') |
| | | // let menulist = null |
| | | |
| | | if (isApp) { |
| | | menulist = sessionStorage.getItem('appMenus') |
| | | } else { |
| | | menulist = sessionStorage.getItem('fstMenuList') |
| | | } |
| | | // if (appType === 'pc') { |
| | | // menulist = sessionStorage.getItem('appMenus') |
| | | // if (Array.isArray(card.linkmenu)) { |
| | | // card.linkmenu = '' |
| | | // } |
| | | // } else { |
| | | // menulist = sessionStorage.getItem('fstMenuList') |
| | | // } |
| | | |
| | | if (menulist) { |
| | | try { |
| | | menulist = JSON.parse(menulist) |
| | | if (isApp) { |
| | | menulist = menulist.map(item => { |
| | | item.value = item.MenuID |
| | | item.text = item.MenuName |
| | | return item |
| | | }) |
| | | } |
| | | } catch { |
| | | menulist = [] |
| | | } |
| | | } else { |
| | | menulist = [] |
| | | } |
| | | // if (menulist) { |
| | | // try { |
| | | // menulist = JSON.parse(menulist) |
| | | // if (appType === 'pc') { |
| | | // menulist = menulist.map(item => { |
| | | // item.value = item.MenuID |
| | | // item.text = item.MenuName |
| | | // return item |
| | | // }) |
| | | // } |
| | | // } catch { |
| | | // menulist = [] |
| | | // } |
| | | // } else { |
| | | // menulist = [] |
| | | // } |
| | | |
| | | let roleList = sessionStorage.getItem('sysRoles') |
| | | if (roleList) { |
| | |
| | | required: false, |
| | | options: roleList |
| | | }, |
| | | { |
| | | type: 'cascader', |
| | | key: 'linkmenu', |
| | | label: '关联菜单', |
| | | initVal: card.linkmenu || [], |
| | | tooltip: '在使用柱形图且未启用自定义设置时有效。', |
| | | required: false, |
| | | forbid: isApp, |
| | | options: menulist |
| | | }, |
| | | { |
| | | type: 'select', |
| | | key: 'linkmenu', |
| | | label: '关联菜单', |
| | | initVal: card.linkmenu || '', |
| | | tooltip: '双击饼图,会打开关联的菜单。', |
| | | required: false, |
| | | forbid: !isApp, |
| | | options: menulist |
| | | }, |
| | | { |
| | | type: 'radio', |
| | | key: 'open', |
| | | label: '打开方式', |
| | | initVal: card.open || 'blank', |
| | | required: false, |
| | | forbid: !isApp, |
| | | options: [ |
| | | { value: 'blank', text: '新窗口' }, |
| | | { value: 'self', text: '当前窗口' } |
| | | ] |
| | | } |
| | | // { |
| | | // type: 'cascader', |
| | | // key: 'linkmenu', |
| | | // label: '关联菜单', |
| | | // initVal: card.linkmenu || [], |
| | | // tooltip: '在使用柱形图且未启用自定义设置时有效。', |
| | | // required: false, |
| | | // forbid: appType === 'pc' || appType === 'mob', |
| | | // options: menulist |
| | | // }, |
| | | // { |
| | | // type: 'select', |
| | | // key: 'linkmenu', |
| | | // label: '关联菜单', |
| | | // initVal: card.linkmenu || '', |
| | | // tooltip: '双击柱状图,会打开关联的菜单。', |
| | | // required: false, |
| | | // forbid: appType !== 'pc', |
| | | // options: menulist |
| | | // }, |
| | | // { |
| | | // type: 'radio', |
| | | // key: 'open', |
| | | // label: '打开方式', |
| | | // initVal: card.open || 'blank', |
| | | // required: false, |
| | | // forbid: appType !== 'pc', |
| | | // options: [ |
| | | // { value: 'blank', text: '新窗口' }, |
| | | // { value: 'self', text: '当前窗口' } |
| | | // ] |
| | | // } |
| | | ] |
| | | } |
| | | |
| | |
| | | * @param {Array} columns // 显示列 |
| | | */ |
| | | export function getOptionForm (card, columns) { |
| | | let appType = sessionStorage.getItem('appType') |
| | | let shapes = [] |
| | | |
| | | if (card.chartType === 'line') { |
| | |
| | | let xfields = columns.filter(item => /^Nvarchar/ig.test(item.datatype)) |
| | | let yfields = columns.filter(item => /^(Int|Decimal)/ig.test(item.datatype)) |
| | | |
| | | let labelOptions = [{ |
| | | value: 'false', |
| | | text: '隐藏' |
| | | }, { |
| | | value: 'true', |
| | | text: '显示' |
| | | }] |
| | | |
| | | if (card.chartType === 'bar') { |
| | | labelOptions[1].text = '外部' |
| | | labelOptions.push(...[{ |
| | | value: 'top', |
| | | text: '顶部' |
| | | }, { |
| | | value: 'middle', |
| | | text: '中间' |
| | | }, { |
| | | value: 'bottom', |
| | | text: '底部' |
| | | }]) |
| | | } |
| | | |
| | | return [ |
| | | { |
| | | type: 'radio', |
| | | key: 'datatype', |
| | | label: '数据类型', |
| | | initVal: card.datatype || 'query', |
| | | tooltip: '统计图表适用于表格不分页,且数据需要转换', |
| | | tooltip: '统计图表适用于展示数据类型为动态值。', |
| | | required: false, |
| | | options: [ |
| | | { value: 'query', text: Formdict['header.form.query'] }, |
| | | { value: 'statistics', text: Formdict['header.form.statistics'] } |
| | | ] |
| | | }, |
| | | { |
| | | }, { |
| | | type: 'select', |
| | | key: 'Xaxis', |
| | | label: 'X-轴', |
| | | initVal: card.Xaxis || '', |
| | | required: true, |
| | | options: xfields |
| | | }, |
| | | { |
| | | }, { |
| | | type: 'select', |
| | | key: 'InfoType', |
| | | label: '类型', |
| | |
| | | hidden: card.datatype !== 'statistics', |
| | | required: true, |
| | | options: xfields |
| | | }, |
| | | { |
| | | }, { |
| | | type: 'select', |
| | | key: 'InfoValue', |
| | | label: '值', |
| | |
| | | hidden: card.datatype !== 'statistics', |
| | | required: true, |
| | | options: yfields |
| | | }, |
| | | { |
| | | }, { |
| | | type: 'select', |
| | | key: 'legend', |
| | | label: '图例位置', |
| | |
| | | { field: 'left-bottom', label: '左下' }, |
| | | { field: 'hidden', label: '隐藏' } |
| | | ] |
| | | }, |
| | | { |
| | | }, { |
| | | type: 'select', |
| | | key: 'Yaxis', |
| | | label: 'Y-轴', |
| | |
| | | hidden: card.datatype === 'statistics', |
| | | required: true, |
| | | options: yfields |
| | | }, |
| | | { |
| | | }, { |
| | | type: 'select', |
| | | key: 'shape', |
| | | label: '形状', |
| | | initVal: card.shape || (shapes[0] && shapes[0].field), |
| | | required: false, |
| | | options: shapes |
| | | }, |
| | | { |
| | | }, { |
| | | type: 'radio', |
| | | key: 'tooltip', |
| | | label: '悬浮提示', |
| | |
| | | value: 'false', |
| | | text: '隐藏' |
| | | }] |
| | | }, |
| | | { |
| | | }, { |
| | | type: 'radio', |
| | | key: 'point', |
| | | label: '点图', |
| | |
| | | value: 'false', |
| | | text: '隐藏' |
| | | }] |
| | | }, |
| | | { |
| | | }, { |
| | | type: 'radio', |
| | | key: 'transpose', |
| | | label: '变换', |
| | |
| | | value: 'false', |
| | | text: Formdict['model.false'] |
| | | }] |
| | | }, |
| | | { |
| | | }, { |
| | | type: 'radio', |
| | | key: 'show', |
| | | label: '格式化', |
| | |
| | | value: 'percent', |
| | | text: '百分比' |
| | | }] |
| | | }, |
| | | { |
| | | type: 'radio', |
| | | }, { |
| | | type: labelOptions.length > 20 ? 'select' : 'radio', |
| | | key: 'label', |
| | | label: '标注值', |
| | | label: '标签', |
| | | initVal: card.label || 'false', |
| | | required: false, |
| | | options: labelOptions |
| | | }, { |
| | | type: 'radio', |
| | | key: 'labelColor', |
| | | label: '标签颜色', |
| | | initVal: card.labelColor || 'system', |
| | | tooltip: '使用系统色时,使用色系选项设置的系统颜色,使用自定义为颜色设置中定义的图形颜色。', |
| | | required: false, |
| | | options: [{ |
| | | value: 'true', |
| | | text: '显示' |
| | | value: 'system', |
| | | text: '系统' |
| | | }, { |
| | | value: 'false', |
| | | text: '隐藏' |
| | | value: 'custom', |
| | | text: '自定义' |
| | | }] |
| | | // }, { |
| | | // type: 'radio', |
| | | // key: 'offset', |
| | | // label: '标注位置', |
| | | // initVal: card.offset || 'outer', |
| | | // required: false, |
| | | // options: [{ |
| | | // value: 'outer', |
| | | // text: '外部' |
| | | // }, { |
| | | // value: 'inner', |
| | | // text: '内部' |
| | | // }], |
| | | // forbid: card.chartType !== 'bar' |
| | | }, { |
| | | type: 'radio', |
| | | key: 'adjust', |
| | |
| | | }, { |
| | | value: 'stack', |
| | | text: '堆叠' |
| | | }] |
| | | }, { |
| | | type: 'radio', |
| | | key: 'area', |
| | | label: '面积图', |
| | | initVal: card.area || 'false', |
| | | // tooltip: '仅在形状为smooth时有效。', |
| | | required: false, |
| | | forbid: ['bar'].includes(card.chartType), |
| | | options: [{ |
| | | value: 'true', |
| | | text: '显示' |
| | | }, { |
| | | value: 'false', |
| | | text: '不显示' |
| | | }] |
| | | }, { |
| | | type: 'radio', |
| | |
| | | text: '极坐标' |
| | | }] |
| | | }, { |
| | | type: 'number', |
| | | key: 'InfoDefNumber', |
| | | label: '展示数', |
| | | tooltip: '默认显示类型数量', |
| | | min: 1, |
| | | max: 50, |
| | | decimal: 0, |
| | | initVal: card.InfoDefNumber || 5, |
| | | hidden: card.datatype !== 'statistics', |
| | | required: true |
| | | type: 'radio', |
| | | key: 'grid', |
| | | label: '网格线', |
| | | initVal: card.grid || 'show', |
| | | required: false, |
| | | options: [{ |
| | | value: 'show', |
| | | text: '显示' |
| | | }, { |
| | | value: 'hidden', |
| | | text: '隐藏' |
| | | }] |
| | | }, { |
| | | type: 'radio', |
| | | key: 'y_line', |
| | | label: 'y轴边线', |
| | | initVal: card.y_line || 'hidden', |
| | | tooltip: '图形左侧或右侧的边线。', |
| | | required: false, |
| | | options: [{ |
| | | value: 'show', |
| | | text: '显示' |
| | | }, { |
| | | value: 'hidden', |
| | | text: '隐藏' |
| | | }] |
| | | }, { |
| | | type: 'number', |
| | | key: 'barSize', |
| | |
| | | forbid: !['bar'].includes(card.chartType), |
| | | required: false |
| | | }, { |
| | | type: 'number', |
| | | key: 'barRadius', |
| | | label: '柱形圆角', |
| | | tooltip: '柱形图上端圆角。', |
| | | min: 0, |
| | | max: 200, |
| | | decimal: 0, |
| | | initVal: card.barRadius || 0, |
| | | forbid: !['bar'].includes(card.chartType), |
| | | required: false |
| | | }, { |
| | | type: 'number', |
| | | key: 'min', |
| | | label: '最小值', |
| | | tooltip: 'y轴最小值,为空时自适应。', |
| | | initVal: card.min, |
| | | required: false |
| | | }, { |
| | | type: 'number', |
| | | key: 'max', |
| | | label: '最大值', |
| | | tooltip: 'y轴最大值,为空时自适应。', |
| | | initVal: card.max, |
| | | required: false |
| | | }, { |
| | | type: 'color', |
| | | key: 'color', |
| | | label: '色系', |
| | | initVal: card.color || 'rgba(0, 0, 0, 0.85)', |
| | | tooltip: '坐标轴及示例等提示文字使用的颜色。', |
| | | initVal: card.color || 'rgba(0, 0, 0, 0.65)', |
| | | tooltip: '坐标轴提示文字及示例的颜色。', |
| | | required: false |
| | | }, { |
| | | type: 'color', |
| | | key: 'lineColor', |
| | | label: '轴线颜色', |
| | | initVal: card.lineColor, |
| | | tooltip: '坐标轴线的颜色,包括x轴、y轴及网格线。', |
| | | allowClear: true, |
| | | required: false |
| | | }, { |
| | | type: 'color', |
| | | key: 'selectColor', |
| | | label: '选中颜色', |
| | | initVal: card.selectColor || '', |
| | | tooltip: '选中柱形图的颜色,在交互效果《元素选中(多选)》和《元素选中(单选)》中有效,自定义设置中无效。', |
| | | forbid: !['bar'].includes(card.chartType), |
| | | allowClear: true, |
| | | required: false |
| | | }, { |
| | | type: 'number', |
| | | key: 'rotate', |
| | | label: '旋转', |
| | | tooltip: '坐标轴标注文本的旋转角度。', |
| | | min: 0, |
| | | max: 360, |
| | | decimal: 0, |
| | | initVal: card.rotate, |
| | | forbid: appType !== 'mob', |
| | | required: false |
| | | }, { |
| | | type: 'select', |
| | | key: 'interaction', |
| | | label: '交互效果', |
| | | initVal: card.interaction || [], |
| | | multi: true, |
| | | required: false, |
| | | options: [{ |
| | | value: 'black', |
| | | text: '黑色' |
| | | }, { |
| | | value: 'white', |
| | | text: '白色' |
| | | }] |
| | | forbid: appType === 'mob', |
| | | options: [ |
| | | { value: 'element-active', label: '元素聚焦' }, |
| | | { value: 'element-selected', label: '元素选中(多选)' }, |
| | | { value: 'element-single-selected', label: '元素选中(单选)' }, |
| | | { value: 'active-region', label: '背景框' }, |
| | | { value: 'view-zoom', label: '视图缩放' }, |
| | | { value: 'element-highlight', label: '元素高亮' }, |
| | | { value: 'element-highlight-by-color', label: '同色元素高亮' }, |
| | | { value: 'element-highlight-by-x', label: '同X轴元素高亮' }, |
| | | { value: 'legend-filter', label: '图例过滤' }, |
| | | { value: 'legend-active', label: '图例聚焦' }, |
| | | { value: 'legend-highlight', label: '图例高亮' }, |
| | | { value: 'brush', label: '选框过滤' }, |
| | | ] |
| | | } |
| | | ] |
| | | } |
| | |
| | | |
| | | state = { |
| | | view: 'normal', |
| | | ramp: 'false', |
| | | visible: false, |
| | | datatype: '', |
| | | plot: null, |
| | |
| | | } |
| | | }, |
| | | ], |
| | | rampColorColumns: [ |
| | | { |
| | | title: '指标', |
| | | dataIndex: 'label', |
| | | editable: false, |
| | | width: '20%' |
| | | }, |
| | | { |
| | | title: '颜色1', |
| | | dataIndex: 'color', |
| | | inputType: 'color', |
| | | editable: true, |
| | | width: '30%', |
| | | render: (text, record) => { |
| | | return (<div style={{width: '80px', height: '23px', background: text}}></div>) |
| | | } |
| | | }, |
| | | { |
| | | title: '颜色2', |
| | | dataIndex: 'color1', |
| | | inputType: 'color', |
| | | editable: true, |
| | | width: '30%', |
| | | render: (text, record) => { |
| | | return (<div style={{width: '80px', height: '23px', background: text}}></div>) |
| | | } |
| | | }, |
| | | ], |
| | | statColorColumns: [ |
| | | { |
| | | title: '指标', |
| | |
| | | } |
| | | }, |
| | | ], |
| | | rampStatColorColumns: [ |
| | | { |
| | | title: '指标', |
| | | dataIndex: 'type', |
| | | inputType: 'input', |
| | | editable: true, |
| | | width: '20%' |
| | | }, |
| | | { |
| | | title: '颜色1', |
| | | dataIndex: 'color', |
| | | inputType: 'color', |
| | | editable: true, |
| | | width: '30%', |
| | | render: (text, record) => { |
| | | return (<div style={{width: '80px', height: '23px', background: text}}></div>) |
| | | } |
| | | }, |
| | | { |
| | | title: '颜色2', |
| | | dataIndex: 'color1', |
| | | inputType: 'color', |
| | | editable: true, |
| | | width: '30%', |
| | | render: (text, record) => { |
| | | return (<div style={{width: '80px', height: '23px', background: text}}></div>) |
| | | } |
| | | }, |
| | | ], |
| | | cusColumns: [ |
| | | { |
| | | title: '指标', |
| | | dataIndex: 'name', |
| | | editable: false, |
| | | width: '20%' |
| | | width: '14%' |
| | | }, |
| | | { |
| | | title: '形状', |
| | | dataIndex: 'shape', |
| | | inputType: 'cascader', |
| | | editable: true, |
| | | width: '20%', |
| | | width: '12%', |
| | | render: (text, record) => { |
| | | return text.join(' / ').replace('line', '折线').replace('bar', '柱形') |
| | | }, |
| | |
| | | dataIndex: 'axis', |
| | | inputType: 'select', |
| | | editable: true, |
| | | width: '20%', |
| | | width: '12%', |
| | | options: [ |
| | | { value: 'true', text: '显示'}, |
| | | { value: 'false', text: '隐藏'} |
| | |
| | | dataIndex: 'label', |
| | | inputType: 'select', |
| | | editable: true, |
| | | width: '20%', |
| | | width: '12%', |
| | | options: [ |
| | | { value: 'true', text: '显示'}, |
| | | { value: 'false', text: '隐藏'} |
| | |
| | | let trans = {'true': '显示', 'false': '隐藏'} |
| | | return trans[text] || '隐藏' |
| | | } |
| | | }, |
| | | { |
| | | title: '标题', |
| | | dataIndex: 'title', |
| | | inputType: 'select', |
| | | editable: true, |
| | | width: '12%', |
| | | options: [ |
| | | { value: 'true', text: '显示'}, |
| | | { value: 'false', text: '隐藏'} |
| | | ], |
| | | render: (text, record) => { |
| | | let trans = {'true': '显示', 'false': '隐藏'} |
| | | return trans[text] || '显示' |
| | | } |
| | | }, |
| | | { |
| | | title: '最小值', |
| | | dataIndex: 'min', |
| | | inputType: 'number', |
| | | editable: true, |
| | | required: false, |
| | | width: '12%' |
| | | }, |
| | | { |
| | | title: '最大值', |
| | | dataIndex: 'max', |
| | | inputType: 'number', |
| | | editable: true, |
| | | required: false, |
| | | width: '12%' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | this.setState({ |
| | | visible: true, |
| | | view: 'normal', |
| | | ramp: config.plot.ramp || 'false', |
| | | datatype: config.plot.datatype || 'query', |
| | | fieldName: fieldName, |
| | | plot: fromJS(config.plot).toJS(), |
| | |
| | | formlist: formlist.map(item => { |
| | | if (['Yaxis'].includes(item.key)) { |
| | | item.hidden = val === 'statistics' |
| | | } else if (['InfoType', 'InfoValue', 'InfoDefNumber'].includes(item.key)) { |
| | | } else if (['InfoType', 'InfoValue'].includes(item.key)) { |
| | | item.hidden = val !== 'statistics' |
| | | } |
| | | return item |
| | |
| | | } |
| | | ] |
| | | })( |
| | | <Radio.Group disabled={item.readonly} onChange={(e) => this.radioChange(e, item.key)}> |
| | | <Radio.Group style={{whiteSpace: 'nowrap'}} 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> |
| | |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal |
| | | })( |
| | | <ColorSketch /> |
| | | <ColorSketch allowClear={item.allowClear} /> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | |
| | | let val = e.target.value |
| | | |
| | | this.setState({plot: {...plot, enabled: val}}) |
| | | } |
| | | |
| | | mutilBarChange = (e) => { |
| | | const { plot } = this.state |
| | | let val = e.target.value |
| | | |
| | | this.setState({plot: {...plot, mutilBar: val}}) |
| | | } |
| | | |
| | | rampChange = (e) => { |
| | | const { plot } = this.state |
| | | let val = e.target.value |
| | | let colors = plot.colors || [] |
| | | |
| | | if (val === 'true') { |
| | | colors = colors.map(item => { |
| | | item.color1 = item.color1 || item.color |
| | | return item |
| | | }) |
| | | } |
| | | |
| | | this.setState({plot: {...plot, colors, ramp: val}, ramp: val}) |
| | | } |
| | | |
| | | rampDirectionChange = (e) => { |
| | | const { plot } = this.state |
| | | let val = e.target.value |
| | | |
| | | this.setState({plot: {...plot, rampDirection: val}}) |
| | | } |
| | | |
| | | onSubmit = () => { |
| | |
| | | name: labels[item] || item, |
| | | axis: i === 0 ? 'true' : 'false', |
| | | label: 'false', |
| | | title: 'true', |
| | | shape: _plot.chartType === 'bar' && i === 0 ? ['bar', 'rect'] : ['line', 'smooth'] |
| | | } |
| | | }) |
| | |
| | | uuid: Utils.getuuid(), |
| | | type: item, |
| | | label: labels[item] || item, |
| | | color: chartColors[i % limit] |
| | | color: chartColors[i % limit], |
| | | color1: chartColors[i % limit] |
| | | } |
| | | }) |
| | | } |
| | |
| | | plot.colors.push({ |
| | | uuid: Utils.getuuid(), |
| | | type: `指标${plot.colors.length}`, |
| | | color: 'rgb(91, 143, 249)' |
| | | color: 'rgb(91, 143, 249)', |
| | | color1: 'rgb(91, 143, 249)' |
| | | }) |
| | | |
| | | this.setState({plot}) |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { view, visible, datatype, plot, colorColumns, statColorColumns, cusColumns, baseFormlist } = this.state |
| | | const { view, visible, datatype, plot, ramp, colorColumns, rampColorColumns, statColorColumns, rampStatColorColumns, cusColumns, baseFormlist } = this.state |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | |
| | | wrapClassName="popview-modal menu-chart-edit-modal" |
| | | title="图表编辑" |
| | | visible={visible} |
| | | width={850} |
| | | width={950} |
| | | maskClosable={false} |
| | | onOk={this.onSubmit} |
| | | onCancel={() => { this.setState({ visible: false }) }} |
| | |
| | | </TabPane> |
| | | {plot ? <TabPane tab="颜色设置" key="color"> |
| | | <div> |
| | | <Col span={8} style={{height: '40px', top: '-5px', zIndex: 1}}> |
| | | <Form {...formItemLayout}> |
| | | <Form.Item label="渐变色" style={{marginBottom: 10}}> |
| | | <Radio.Group value={plot.ramp || 'false'} onChange={this.rampChange}> |
| | | <Radio value="false">不使用</Radio> |
| | | <Radio value="true">使用</Radio> |
| | | </Radio.Group> |
| | | </Form.Item> |
| | | </Form> |
| | | </Col> |
| | | {plot.chartType === 'line' ? <Col span={8} style={{height: '40px', top: '-5px', zIndex: 1}}> |
| | | <Form {...formItemLayout}> |
| | | <Form.Item label="渐变方向" style={{marginBottom: 10}}> |
| | | <Radio.Group value={plot.rampDirection || 'horizontal'} onChange={this.rampDirectionChange}> |
| | | <Radio value="horizontal">水平</Radio> |
| | | <Radio value="vertical">垂直</Radio> |
| | | </Radio.Group> |
| | | </Form.Item> |
| | | </Form> |
| | | </Col> : null} |
| | | {datatype === 'statistics' ? <Button className="color-add mk-green" onClick={this.addColor}>{this.props.dict['model.add']}</Button> : null} |
| | | {datatype === 'statistics' ? <EditTable actions={['edit', 'move', 'del']} data={plot.colors || []} columns={statColorColumns} onChange={this.changeColor}/> : null} |
| | | {datatype !== 'statistics' ? <EditTable actions={['edit']} data={plot.colors || []} columns={colorColumns} onChange={this.changeColor}/> : null} |
| | | {datatype === 'statistics' ? <EditTable actions={['edit', 'move', 'del']} data={plot.colors || []} columns={ramp ==='true' ? rampStatColorColumns : statColorColumns} onChange={this.changeColor}/> : null} |
| | | {datatype !== 'statistics' ? <EditTable actions={['edit']} data={plot.colors || []} columns={ramp ==='true' ? rampColorColumns : colorColumns} onChange={this.changeColor}/> : null} |
| | | </div> |
| | | </TabPane> : null} |
| | | {plot ? <TabPane tab="自定义设置" disabled={datatype === 'statistics'} key="custom"> |
| | |
| | | </Form.Item> |
| | | </Form> |
| | | </Col> |
| | | <Col style={{fontSize: '12px', color: '#757575', paddingLeft: '10px'}} span={24}>注:使用自定义设置时,显示的坐标轴第一个在左侧,第二个在右侧,多余的不生效;柱形图只可以添加一个(设置多个时,第一个生效)。</Col> |
| | | <Col span={12}> |
| | | <Form {...formItemLayout}> |
| | | <Form.Item label="多柱排列" style={{marginBottom: 10}}> |
| | | <Radio.Group value={plot.mutilBar || 'dodge'} onChange={this.mutilBarChange}> |
| | | <Radio value="dodge">分组</Radio> |
| | | <Radio value="stack">堆叠</Radio> |
| | | <Radio value="overlap">重叠</Radio> |
| | | </Radio.Group> |
| | | </Form.Item> |
| | | </Form> |
| | | </Col> |
| | | <Col style={{fontSize: '12px', color: '#757575', paddingLeft: '10px'}} span={24}>注:使用自定义设置时,显示的坐标轴第一个在左侧,第二个在右侧,多余的不生效。</Col> |
| | | <EditTable actions={['edit', 'move']} data={plot.customs || []} columns={cusColumns} onChange={this.changeCustom}/> |
| | | </TabPane> : null} |
| | | </Tabs> |
| | |
| | | .ant-input-number { |
| | | width: 100%; |
| | | } |
| | | .ant-radio-wrapper { |
| | | margin-right: 5px; |
| | | } |
| | | .ant-tabs-nav-wrap { |
| | | text-align: center; |
| | | } |
| | |
| | | import MKEmitter from '@/utils/events.js' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import { chartColors } from '@/utils/option.js' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | card: null, |
| | | appType: sessionStorage.getItem('appType'), |
| | | eventListener: null |
| | | } |
| | | |
| | |
| | | width: card.width || 24, |
| | | height: 400, |
| | | barSize: 35, |
| | | color: 'rgba(0, 0, 0, 0.65)', |
| | | name: card.name |
| | | } |
| | | |
| | |
| | | parentId: card.parentId || '', |
| | | format: 'array', // 组件属性 - 数据格式 |
| | | pageable: false, // 组件属性 - 是否可分页 |
| | | switchable: false, // 组件属性 - 数据是否可切换 |
| | | switchable: card.type === 'bar' ? true : false, // 组件属性 - 数据是否可切换 |
| | | dataName: card.dataName || '', |
| | | width: _plot.width, |
| | | name: _plot.name, |
| | |
| | | } |
| | | |
| | | componentDidMount () { |
| | | this.viewrender() |
| | | MKEmitter.addListener('submitStyle', this.getStyle) |
| | | MKEmitter.addListener('tabsChange', this.handleTabsChange) |
| | | setTimeout(() => { |
| | | this.viewrender() |
| | | }, 1000) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | |
| | | _element.innerHTML = '' |
| | | } |
| | | |
| | | setTimeout(this.viewrender, 100) |
| | | this.$timer && clearTimeout(this.$timer) |
| | | this.$timer = setTimeout(this.viewrender, 100) |
| | | } |
| | | } |
| | | |
| | |
| | | */ |
| | | linerender = () => { |
| | | const { card } = this.state |
| | | let plot = {...card.plot, height: card.plot.height - 80} // 去除title所占空间 |
| | | let color = plot.color || 'rgba(0, 0, 0, 0.85)' |
| | | let plot = {...card.plot} // 去除title所占空间 |
| | | let color = plot.color || 'rgba(0, 0, 0, 0.65)' |
| | | let X_axis = plot.Xaxis || 'x' |
| | | let Y_axis = plot.Yaxis || ['y'] |
| | | |
| | | if (card.plot.title || card.search.length > 0) { |
| | | plot.height = card.plot.height - 70 |
| | | } |
| | | |
| | | let data = this.getdata(X_axis, Y_axis) |
| | | |
| | |
| | | |
| | | chart.data(dv.rows) |
| | | |
| | | chart.axis(X_axis, { label: { style: { fill: color } }, line: { style: { fill: color } } }) |
| | | chart.axis('value', { grid: { style: { fill: color } }, label: { style: { fill: color } } }) |
| | | // chart.axis(X_axis, { label: { style: { fill: color } }, tickLine: {style: { stroke: color }}, line: { style: { stroke: color } } }) |
| | | // chart.axis('value', { grid: { line: { style: { stroke: color } }}, label: { style: { fill: color } } }) |
| | | |
| | | let xc = {label: { style: { fill: color } }} |
| | | let yc = {label: { style: { fill: color } }} |
| | | if (plot.grid === 'hidden') { |
| | | yc.grid = null |
| | | } |
| | | if (plot.y_line === 'show') { |
| | | yc.line = {style: { stroke: '#D1D2CE' }} |
| | | } |
| | | if (plot.lineColor) { |
| | | xc.tickLine = {style: { stroke: plot.lineColor }} |
| | | xc.line = { style: { stroke: plot.lineColor } } |
| | | if (yc.grid !== null) { |
| | | yc.grid = { line: { style: { stroke: plot.lineColor } }} |
| | | } |
| | | if (yc.line) { |
| | | yc.line = { style: { stroke: plot.lineColor } } |
| | | } |
| | | } |
| | | chart.axis(X_axis, xc) |
| | | chart.axis('value', yc) |
| | | |
| | | if (plot.coordinate !== 'polar') { |
| | | chart.scale(X_axis, { |
| | |
| | | } |
| | | chart.scale('value', { |
| | | nice: true, |
| | | range: [0, 0.93] |
| | | range: [0, 0.9] |
| | | }) |
| | | |
| | | if (!plot.legend || plot.legend === 'hidden') { |
| | |
| | | let colorIndex = 0 |
| | | |
| | | if (plot.colors && plot.colors.length > 0) { |
| | | plot.colors.forEach(item => { |
| | | if (!colors.has(transfield[item.type])) { |
| | | colors.set(transfield[item.type], item.color) |
| | | if (plot.ramp === 'true') { |
| | | let _s = 'l(0) ' |
| | | if (plot.rampDirection === 'vertical') { |
| | | _s = 'l(90) ' |
| | | } |
| | | }) |
| | | plot.colors.forEach(item => { |
| | | if (!colors.has(transfield[item.type])) { |
| | | colors.set(transfield[item.type], `${_s}0:${item.color} 1:${item.color1}` ) |
| | | } |
| | | }) |
| | | } else { |
| | | plot.colors.forEach(item => { |
| | | if (!colors.has(transfield[item.type])) { |
| | | colors.set(transfield[item.type], item.color) |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | |
| | | let _chart = chart |
| | |
| | | if (plot.colors && plot.colors.length > 0) { |
| | | let limit = chartColors.length |
| | | _chart.color('key', (key) => { |
| | | if (colors.get(key)) { |
| | | if (colors.has(key)) { |
| | | if (plot.area === 'true' && plot.rampDirection === 'vertical') { |
| | | return colors.get(key).replace(/l\(9?0\) 0:|\s1:.*/ig, '') |
| | | } |
| | | return colors.get(key) |
| | | } else { |
| | | colors.set(key, chartColors[colorIndex % limit]) |
| | | colorIndex++ |
| | | return chartColors[(colorIndex - 1) % limit] |
| | | } |
| | | }) |
| | | } else { |
| | | _chart.color('key') |
| | | } |
| | | if (plot.label === 'true') { |
| | | _chart.label('value', (value) => { |
| | | if (plot.label !== 'false') { |
| | | _chart.label('value*key', (value, key) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | } |
| | | let _color = color |
| | | |
| | | if (plot.labelColor === 'custom' && colors.has(key)) { |
| | | _color = colors.get(key) |
| | | } |
| | | return { |
| | | content: value, |
| | | style: { |
| | | fill: color |
| | | fill: _color |
| | | } |
| | | } |
| | | }) |
| | |
| | | .size(3) |
| | | .shape('circle') |
| | | } |
| | | |
| | | if (plot.area === 'true') { |
| | | let area = chart.area().position(`${X_axis}*value`).tooltip(false) |
| | | if (plot.shape === 'smooth') { |
| | | area.shape('smooth') |
| | | } |
| | | if (plot.colors && plot.colors.length > 0) { |
| | | let limit = chartColors.length |
| | | area.color('key', (key) => { |
| | | if (colors.has(key)) { |
| | | return colors.get(key) |
| | | } else { |
| | | colorIndex++ |
| | | return chartColors[(colorIndex - 1) % limit] |
| | | } |
| | | }) |
| | | } else { |
| | | area.color('key') |
| | | } |
| | | } |
| | | |
| | | if (plot.interaction && plot.interaction.length) { |
| | | plot.interaction.forEach(t => { |
| | | chart.interaction(t) |
| | | }) |
| | | } |
| | | chart.render() |
| | | } else { |
| | | this.customrender(data) |
| | |
| | | */ |
| | | customrender = (data) => { |
| | | let card = fromJS(this.state.card).toJS() |
| | | let plot = {...card.plot, height: card.plot.height - 80} // 去除title所占空间 |
| | | let color = plot.color || 'rgba(0, 0, 0, 0.85)' |
| | | let plot = {...card.plot} // 去除title所占空间 |
| | | let color = plot.color || 'rgba(0, 0, 0, 0.65)' |
| | | let fields = [] |
| | | let legends = [] |
| | | let transfield = {} |
| | | let Bar_axis = [] |
| | | |
| | | if (card.plot.title || card.search.length > 0) { |
| | | plot.height = card.plot.height - 70 |
| | | } |
| | | |
| | | card.columns.forEach(col => { |
| | | if (col.field) { |
| | |
| | | let limit = chartColors.length |
| | | |
| | | if (plot.colors && plot.colors.length > 0) { |
| | | plot.colors.forEach(item => { |
| | | if (!colors.has(item.type)) { |
| | | colors.set(item.type, item.color) |
| | | } |
| | | }) |
| | | if (plot.ramp === 'true') { |
| | | let bars = {} |
| | | plot.customs.forEach(item => { |
| | | if (!item.shape || !item.shape[0] || item.shape[0] === 'bar') { |
| | | bars[item.type] = true |
| | | } |
| | | }) |
| | | plot.colors.forEach(item => { |
| | | if (!colors.has(transfield[item.type])) { |
| | | if (bars[item.type]) { |
| | | colors.set(transfield[item.type], `l(90) 0:${item.color} 1:${item.color1}` ) |
| | | } else { |
| | | colors.set(transfield[item.type], `l(0) 0:${item.color} 1:${item.color1}` ) |
| | | } |
| | | } |
| | | }) |
| | | } else { |
| | | plot.colors.forEach(item => { |
| | | if (!colors.has(transfield[item.type])) { |
| | | colors.set(transfield[item.type], item.color) |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | |
| | | let axisIndex = 0 |
| | | let hasBar = false |
| | | |
| | | plot.$paddingLeft = 30 |
| | | plot.$paddingRight = 30 |
| | | |
| | | plot.customs.forEach(item => { |
| | | item.name = transfield[item.type] || item.type |
| | | item.chartType = item.shape ? (item.shape[0] || 'bar') : 'bar' |
| | | item.shape = item.shape ? (item.shape[1] || '') : '' |
| | | |
| | | if (colors.get(item.type)) { |
| | | item.color = colors.get(item.type) |
| | | if (colors.has(item.name)) { |
| | | item.color = colors.get(item.name) |
| | | } else { |
| | | item.color = chartColors[colorIndex % limit] |
| | | colorIndex++ |
| | | } |
| | | |
| | | if (item.chartType === 'bar' && !hasBar) { |
| | | if (item.chartType === 'bar') { |
| | | Bar_axis.push(item.type) |
| | | hasBar = true |
| | | } else if (item.chartType === 'bar') { |
| | | item.chartType = 'line' |
| | | item.shape = 'smooth' |
| | | } |
| | | |
| | | if (item.axis === 'true' && axisIndex < 2) { |
| | | if (axisIndex === 0) { |
| | | item.axis = { grid: {style: { fill: color }}, title: { style: { fill: color } }, label: {style: { fill: color }} } |
| | | // item.axis = { grid: {line: { style: { stroke: color } }}, title: { style: { fill: color } }, label: {style: { fill: color }} } |
| | | item.axis = { label: {style: { fill: color }} } |
| | | if (item.title !== 'false') { |
| | | item.axis.title = { style: { fill: color } } |
| | | plot.$paddingLeft = 50 |
| | | } |
| | | if (plot.grid === 'hidden') { |
| | | item.axis.grid = null |
| | | } |
| | | if (plot.y_line === 'show') { |
| | | item.axis.line = {style: { stroke: '#D1D2CE' }} |
| | | } |
| | | if (plot.lineColor) { |
| | | if (item.axis.grid !== null) { |
| | | item.axis.grid = { line: { style: { stroke: plot.lineColor } }} |
| | | } |
| | | if (item.axis.line) { |
| | | item.axis.line = { style: { stroke: plot.lineColor } } |
| | | } |
| | | } |
| | | |
| | | fields.unshift(item) |
| | | } else { |
| | | item.axis = { grid: null, title: {style: { fill: color }}, label: {style: { fill: color }} } |
| | | item.axis = { grid: null, label: {style: { fill: color }} } |
| | | if (item.title !== 'false') { |
| | | item.axis.title = { style: { fill: color } } |
| | | plot.$paddingRight = 60 |
| | | } |
| | | if (plot.y_line === 'show') { |
| | | item.axis.line = {style: { stroke: '#D1D2CE' }} |
| | | } |
| | | if (plot.lineColor && item.axis.line) { |
| | | item.axis.line = { style: { stroke: plot.lineColor } } |
| | | } |
| | | fields.splice(1, 0, item) |
| | | } |
| | | axisIndex++ |
| | |
| | | } |
| | | }) |
| | | |
| | | let padding = [10, 30, 30, 30] |
| | | if (plot.mutilBar === 'overlap') { |
| | | Bar_axis = [] |
| | | } |
| | | |
| | | if (!Bar_axis.length) { |
| | | padding = [10, plot.$paddingRight, 30, plot.$paddingLeft] |
| | | } |
| | | |
| | | const chart = new Chart({ |
| | | container: card.uuid + 'canvas', |
| | | autoFit: true, |
| | | height: plot.height || 400 |
| | | height: plot.height || 400, |
| | | }) |
| | | |
| | | chart.data(dv.rows) |
| | | // chart.axis(plot.Xaxis, { label: { style: { fill: color } }, tickLine: {style: { stroke: color }}, line: { style: { stroke: color } } }) |
| | | |
| | | chart.axis(plot.Xaxis, { label: { style: { fill: color } }, line: { style: { fill: color } } }) |
| | | let xc = {label: { style: { fill: color } }} |
| | | if (plot.lineColor) { |
| | | xc.tickLine = {style: { stroke: plot.lineColor }} |
| | | xc.line = { style: { stroke: plot.lineColor } } |
| | | } |
| | | chart.axis(plot.Xaxis, xc) |
| | | |
| | | if (!hasBar) { |
| | | chart.scale(plot.Xaxis, { |
| | |
| | | nice: true |
| | | }) |
| | | |
| | | fields.forEach(item => { |
| | | chart.axis(item.name, item.axis) |
| | | |
| | | chart.scale(item.name, { |
| | | nice: true, |
| | | range: [0, 0.93] |
| | | let lablecfg = { |
| | | position: 'top', |
| | | offset: 2, |
| | | style: { |
| | | fill: '#fff' |
| | | } |
| | | } |
| | | |
| | | if (plot.label === 'top') { |
| | | lablecfg.offset = -5 |
| | | lablecfg.style.textBaseline = 'top' |
| | | } else if (plot.label === 'middle') { |
| | | lablecfg.position = 'middle' |
| | | lablecfg.offset = 0 |
| | | } else if (plot.label === 'bottom') { |
| | | lablecfg.position = 'bottom' |
| | | lablecfg.offset = 0 |
| | | } else if (plot.label === 'true') { |
| | | lablecfg.style.fill = color |
| | | } |
| | | |
| | | if (Bar_axis.length) { |
| | | const view1 = chart.createView({ |
| | | region: { |
| | | start: { x: 0, y: 0 }, |
| | | end: { x: 1, y: 1 } |
| | | }, |
| | | padding |
| | | }) |
| | | const dst = new DataSet() |
| | | const dvt = dst.createView().source(data) |
| | | |
| | | dvt.transform({ |
| | | type: 'fold', |
| | | fields: [...Bar_axis], |
| | | key: 'key', |
| | | value: 'value' |
| | | }) |
| | | |
| | | dvt.transform({ |
| | | type: 'map', |
| | | callback(row) { |
| | | row.key = transfield[row.key] || row.key |
| | | return row |
| | | }, |
| | | }) |
| | | |
| | | if (item.chartType === 'bar') { |
| | | let _chart = chart |
| | | view1.data(dvt.rows) |
| | | view1.scale('value', { |
| | | nice: true, |
| | | range: [0, 0.9] |
| | | }) |
| | | |
| | | let yc = {label: { style: { fill: color } }} |
| | | if (plot.grid === 'hidden') { |
| | | yc.grid = null |
| | | } |
| | | if (plot.y_line === 'show') { |
| | | yc.line = {style: { stroke: '#D1D2CE' }} |
| | | } |
| | | if (plot.lineColor) { |
| | | if (yc.grid !== null) { |
| | | yc.grid = { line: { style: { stroke: plot.lineColor } }} |
| | | } |
| | | if (yc.line) { |
| | | yc.line = { style: { stroke: plot.lineColor } } |
| | | } |
| | | } |
| | | view1.axis('value', yc) |
| | | |
| | | view1.legend(false) |
| | | |
| | | if (plot.mutilBar !== 'stack') { |
| | | let _chart = view1 |
| | | .interval() |
| | | .position(`${plot.Xaxis}*value`) |
| | | .adjust([ |
| | | { |
| | | type: 'dodge', |
| | | marginRatio: 0 |
| | | } |
| | | ]) |
| | | .shape(plot.shape || 'rect') |
| | | .tooltip(`${plot.Xaxis}*value*key`, (name, value, key) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | } |
| | | return { |
| | | name: key, |
| | | value: value |
| | | } |
| | | }) |
| | | |
| | | if (plot.colors && plot.colors.length > 0) { |
| | | let limit = chartColors.length |
| | | _chart.color('key', (key) => { |
| | | if (colors.has(key)) { |
| | | return colors.get(key) |
| | | } else { |
| | | colorIndex++ |
| | | return chartColors[(colorIndex - 1) % limit] |
| | | } |
| | | }) |
| | | } else { |
| | | _chart.color('key') |
| | | } |
| | | if (plot.label !== 'false') { |
| | | _chart.label('value*key', (value, key) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | } |
| | | |
| | | if (plot.label === 'true' && plot.labelColor === 'custom' && colors.has(key)) { |
| | | lablecfg.style.fill = colors.get(key) |
| | | } |
| | | return { |
| | | content: value, |
| | | ...lablecfg |
| | | } |
| | | }) |
| | | } |
| | | |
| | | if (plot.barSize || plot.correction) { |
| | | _chart.size(plot.barSize || 35) |
| | | } |
| | | if (plot.barRadius) { |
| | | _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) |
| | | } |
| | | } else if (plot.mutilBar === 'stack') { |
| | | let _chart = view1 |
| | | .interval() |
| | | .position(`${plot.Xaxis}*value`) |
| | | .adjust('stack') |
| | | .shape(plot.shape || 'rect') |
| | | .tooltip(`${plot.Xaxis}*value*key`, (name, value, type) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | } |
| | | return { |
| | | name: type, |
| | | value: value |
| | | } |
| | | }) |
| | | |
| | | if (plot.colors && plot.colors.length > 0) { |
| | | let limit = chartColors.length |
| | | _chart.color('key', (key) => { |
| | | if (colors.has(key)) { |
| | | return colors.get(key) |
| | | } else { |
| | | colorIndex++ |
| | | return chartColors[(colorIndex - 1) % limit] |
| | | } |
| | | }) |
| | | } else { |
| | | _chart.color('key') |
| | | } |
| | | if (plot.label !== 'false') { |
| | | _chart.label('value*key', (value, key) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | } |
| | | |
| | | if (plot.label === 'true' && plot.labelColor === 'custom' && colors.has(key)) { |
| | | lablecfg.style.fill = colors.get(key) |
| | | } |
| | | |
| | | return { |
| | | content: value, |
| | | ...lablecfg |
| | | } |
| | | }) |
| | | } |
| | | |
| | | if (plot.barSize || plot.correction) { |
| | | _chart.size(plot.barSize || 35) |
| | | } |
| | | if (plot.barRadius) { |
| | | _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) |
| | | } |
| | | } |
| | | } |
| | | |
| | | const view2 = chart.createView({ |
| | | region: { |
| | | start: { x: 0, y: 0 }, |
| | | end: { x: 1, y: 1 } |
| | | }, |
| | | padding |
| | | }) |
| | | |
| | | view2.data(dv.rows) |
| | | |
| | | view2.legend(false) |
| | | |
| | | fields.forEach(item => { |
| | | if (item.chartType === 'bar' && !Bar_axis.length) { |
| | | view2.axis(item.name, item.axis) |
| | | |
| | | view2.scale(item.name, { |
| | | nice: true, |
| | | range: [0, 0.9] |
| | | }) |
| | | |
| | | let _chart = view2 |
| | | .interval() |
| | | .position(`${plot.Xaxis}*${item.name}`) |
| | | .color(item.color) |
| | |
| | | if (plot.barSize) { |
| | | _chart.size(plot.barSize || 35) |
| | | } |
| | | if (item.label === 'true') { |
| | | if (item.label !== 'false') { |
| | | _chart.label(item.name, (value) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | } |
| | | |
| | | if (plot.label === 'true' && plot.labelColor === 'custom') { |
| | | lablecfg.style.fill = item.color |
| | | } |
| | | return { |
| | | content: value, |
| | | style: { |
| | | fill: color |
| | | } |
| | | ...lablecfg |
| | | } |
| | | }) |
| | | } |
| | | if (plot.barRadius) { |
| | | _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) |
| | | } |
| | | } else if (item.chartType === 'line') { |
| | | let _chart = chart |
| | | if (!Bar_axis.length) { |
| | | view2.axis(item.name, item.axis) |
| | | } else { |
| | | view2.axis(item.name, { grid: null, title: null, label: null }) |
| | | } |
| | | view2.scale(item.name, { |
| | | nice: true, |
| | | range: [0, 0.9] |
| | | }) |
| | | let _chart = view2 |
| | | .line() |
| | | .position(`${plot.Xaxis}*${item.name}`) |
| | | .color(item.color) |
| | |
| | | } |
| | | }) |
| | | |
| | | if (item.label === 'true') { |
| | | if (item.label !== 'false') { |
| | | _chart.label(item.name, (value) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | } |
| | | let _color = color |
| | | |
| | | if (plot.labelColor === 'custom') { |
| | | _color = item.color |
| | | } |
| | | return { |
| | | content: value, |
| | | style: { |
| | | fill: color |
| | | fill: _color |
| | | } |
| | | } |
| | | }) |
| | |
| | | } |
| | | }) |
| | | |
| | | if (plot.interaction && plot.interaction.length) { |
| | | plot.interaction.forEach(t => { |
| | | if (t === 'element-active' || t === 'element-highlight') { |
| | | chart.interaction(t) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | chart.render() |
| | | } |
| | | |
| | |
| | | */ |
| | | barrender = () => { |
| | | const { card } = this.state |
| | | let plot = {...card.plot, height: card.plot.height - 80} |
| | | let color = plot.color || 'rgba(0, 0, 0, 0.85)' |
| | | let plot = {...card.plot} |
| | | let color = plot.color || 'rgba(0, 0, 0, 0.65)' |
| | | let X_axis = plot.Xaxis || 'x' |
| | | let Y_axis = plot.Yaxis || ['y'] |
| | | |
| | | if (card.plot.title || card.search.length > 0) { |
| | | plot.height = card.plot.height - 70 |
| | | } |
| | | |
| | | let data = this.getdata(X_axis, Y_axis) |
| | | |
| | |
| | | autoFit: true, |
| | | height: plot.height || 400 |
| | | }) |
| | | |
| | | |
| | | chart.data(dv.rows) |
| | | |
| | | chart.axis(X_axis, { label: { style: { fill: color } }, line: { style: { fill: color } } }) |
| | | chart.axis('value', { grid: { style: { fill: color } }, label: { style: { fill: color } } }) |
| | | // chart.axis(X_axis, { label: { style: { fill: color } }, tickLine: {style: { stroke: color }}, line: { style: { stroke: color } } }) |
| | | // chart.axis('value', { grid: { line: { style: { stroke: color } }}, label: { style: { fill: color } } }) |
| | | |
| | | let xc = {label: { style: { fill: color } }} |
| | | let yc = {label: { style: { fill: color } }} |
| | | if (plot.grid === 'hidden') { |
| | | yc.grid = null |
| | | } |
| | | if (plot.y_line === 'show') { |
| | | yc.line = {style: { stroke: '#D1D2CE' }} |
| | | } |
| | | if (plot.lineColor) { |
| | | xc.tickLine = {style: { stroke: plot.lineColor }} |
| | | xc.line = { style: { stroke: plot.lineColor } } |
| | | if (yc.grid !== null) { |
| | | yc.grid = { line: { style: { stroke: plot.lineColor } }} |
| | | } |
| | | if (yc.line) { |
| | | yc.line = { style: { stroke: plot.lineColor } } |
| | | } |
| | | } |
| | | chart.axis(X_axis, xc) |
| | | chart.axis('value', yc) |
| | | |
| | | chart.scale('value', { |
| | | nice: true, |
| | | range: [0, 0.93] |
| | | range: [0, 0.9] |
| | | }) |
| | | |
| | | if (!plot.legend || plot.legend === 'hidden') { |
| | |
| | | }) |
| | | } |
| | | |
| | | if (plot.transpose === 'true') { |
| | | chart.coordinate().transpose() |
| | | } |
| | | |
| | | if (plot.coordinate === 'polar') { |
| | | chart.coordinate('polar', { |
| | | innerRadius: 0.1, |
| | |
| | | |
| | | let colors = new Map() |
| | | let colorIndex = 0 |
| | | let lablecfg = { |
| | | position: 'top', |
| | | offset: 2, |
| | | style: { |
| | | fill: '#fff' |
| | | } |
| | | } |
| | | |
| | | if (plot.label === 'top') { |
| | | lablecfg.offset = -5 |
| | | lablecfg.style.textBaseline = 'top' |
| | | } else if (plot.label === 'middle') { |
| | | lablecfg.position = 'middle' |
| | | lablecfg.offset = 0 |
| | | } else if (plot.label === 'bottom') { |
| | | lablecfg.position = 'bottom' |
| | | lablecfg.offset = 0 |
| | | } else if (plot.label === 'true') { |
| | | lablecfg.style.fill = color |
| | | } |
| | | |
| | | if (plot.transpose === 'true') { |
| | | chart.coordinate().transpose() |
| | | if (plot.label === 'top') { |
| | | delete lablecfg.style.textBaseline |
| | | lablecfg.position = 'right' |
| | | lablecfg.offset = -3 |
| | | lablecfg.style.textAlign = 'end' |
| | | } else if (plot.label === 'middle') { |
| | | lablecfg.position = 'middle' |
| | | lablecfg.offset = 0 |
| | | } else if (plot.label === 'bottom') { |
| | | lablecfg.position = 'left' |
| | | lablecfg.offset = 2 |
| | | } else if (plot.label === 'true') { |
| | | lablecfg.position = 'right' |
| | | lablecfg.offset = 2 |
| | | } |
| | | } |
| | | |
| | | if (plot.colors && plot.colors.length > 0) { |
| | | plot.colors.forEach(item => { |
| | | if (!colors.has(transfield[item.type])) { |
| | | colors.set(transfield[item.type], item.color) |
| | | } |
| | | }) |
| | | if (plot.ramp === 'true') { |
| | | plot.colors.forEach(item => { |
| | | if (!colors.has(transfield[item.type])) { |
| | | colors.set(transfield[item.type], `l(90) 0:${item.color} 1:${item.color1}` ) |
| | | } |
| | | }) |
| | | } else { |
| | | plot.colors.forEach(item => { |
| | | if (!colors.has(transfield[item.type])) { |
| | | colors.set(transfield[item.type], item.color) |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | |
| | | if (plot.adjust !== 'stack') { |
| | |
| | | if (plot.colors && plot.colors.length > 0) { |
| | | let limit = chartColors.length |
| | | _chart.color('key', (key) => { |
| | | if (colors.get(key)) { |
| | | if (colors.has(key)) { |
| | | return colors.get(key) |
| | | } else { |
| | | colors.set(key, chartColors[colorIndex % limit]) |
| | | colorIndex++ |
| | | return chartColors[(colorIndex - 1) % limit] |
| | | } |
| | | }) |
| | | } else { |
| | | _chart.color('key') |
| | | } |
| | | if (plot.label === 'true') { |
| | | _chart.label('value', (value) => { |
| | | if (plot.label !== 'false') { |
| | | _chart.label('value*key', (value, key) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | } |
| | | |
| | | if (plot.label === 'true' && plot.labelColor === 'custom' && colors.has(key)) { |
| | | lablecfg.style.fill = colors.get(key) |
| | | } |
| | | |
| | | return { |
| | | content: value, |
| | | style: { |
| | | fill: color |
| | | } |
| | | ...lablecfg |
| | | } |
| | | }) |
| | | } |
| | | |
| | | if (plot.barSize || plot.correction) { |
| | | _chart.size(plot.barSize || 35) |
| | | } |
| | | if (plot.selectColor) { |
| | | _chart.state({ |
| | | selected: { |
| | | style: { |
| | | fill: plot.selectColor, |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | if (plot.barRadius) { |
| | | _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) |
| | | } |
| | | } else if (plot.adjust === 'stack') { |
| | | let _chart = chart |
| | |
| | | if (plot.colors && plot.colors.length > 0) { |
| | | let limit = chartColors.length |
| | | _chart.color('key', (key) => { |
| | | if (colors.get(key)) { |
| | | if (colors.has(key)) { |
| | | return colors.get(key) |
| | | } else { |
| | | colors.set(key, chartColors[colorIndex % limit]) |
| | | colorIndex++ |
| | | return chartColors[(colorIndex - 1) % limit] |
| | | } |
| | | }) |
| | | } else { |
| | | _chart.color('key') |
| | | } |
| | | if (plot.label === 'true') { |
| | | _chart.label('value', (value) => { |
| | | if (plot.label !== 'false') { |
| | | _chart.label('value*key', (value, key) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | } |
| | | |
| | | if (plot.label === 'true' && plot.labelColor === 'custom' && colors.has(key)) { |
| | | lablecfg.style.fill = colors.get(key) |
| | | } |
| | | return { |
| | | content: value, |
| | | style: { |
| | | fill: color |
| | | } |
| | | ...lablecfg |
| | | } |
| | | }) |
| | | } |
| | |
| | | if (plot.barSize || plot.correction) { |
| | | _chart.size(plot.barSize || 35) |
| | | } |
| | | if (plot.selectColor) { |
| | | _chart.state({ |
| | | selected: { |
| | | style: { |
| | | fill: plot.selectColor, |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | if (plot.barRadius) { |
| | | _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) |
| | | } |
| | | } |
| | | |
| | | if (plot.interaction && plot.interaction.length) { |
| | | plot.interaction.forEach(t => { |
| | | chart.interaction(t) |
| | | }) |
| | | } |
| | | |
| | | 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 + 'canvas') |
| | | if (_element) { |
| | | _element.innerHTML = '' |
| | | } |
| | | refresh = true |
| | | this.$timer && clearTimeout(this.$timer) |
| | | this.$timer = setTimeout(() => { |
| | | this.viewrender() |
| | | }, 150) |
| | | } |
| | | |
| | | component.width = component.plot.width |
| | |
| | | |
| | | this.setState({ |
| | | card: component |
| | | }, () => { |
| | | if (refresh) { |
| | | setTimeout(() => { |
| | | this.viewrender() |
| | | }, 100) |
| | | } |
| | | }) |
| | | this.props.updateConfig(component) |
| | | } |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { card } = this.state |
| | | const { card, appType } = this.state |
| | | let _style = resetStyle(card.style) |
| | | |
| | | return ( |
| | | <div className="menu-line-chart-edit-box" style={{...card.style, height: card.plot.height || 400}} onClick={this.clickComponent} id={card.uuid}> |
| | | <NormalHeader config={card} updateComponent={this.updateComponent}/> |
| | | <div className="menu-line-chart-edit-box" style={{..._style, height: card.plot.height || 400}} onClick={this.clickComponent} id={card.uuid}> |
| | | <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" /> |
| | | <Icon className="plus" title="添加按钮" onClick={this.addButton} type="plus-square" /> |
| | | {appType !== 'mob' ? <Icon className="plus" title="添加搜索" onClick={this.addSearch} type="plus-circle" /> : null} |
| | | {appType !== 'mob' ? <Icon className="plus" title="添加按钮" onClick={this.addButton} type="plus-square" /> : null} |
| | | <ChartCompileForm config={card} dict={this.state.dict} plotchange={this.updateComponent}/> |
| | | <CopyComponent type="line" card={card}/> |
| | | <PasteComponent config={card} options={['action', 'search', 'form']} updateConfig={this.updateComponent} /> |
| | |
| | | } trigger="hover"> |
| | | <Icon type="tool" /> |
| | | </Popover> |
| | | <ActionComponent |
| | | {card.plot.title || card.search.length > 0 ? <NormalHeader config={card} updateComponent={this.updateComponent}/> : null} |
| | | <div className="canvas" id={card.uuid + 'canvas'}></div> |
| | | {appType !== 'mob' ? <ActionComponent |
| | | type="chart" |
| | | config={card} |
| | | updateaction={this.updateComponent} |
| | | /> |
| | | <div className="canvas" id={card.uuid + 'canvas'}></div> |
| | | /> : null} |
| | | </div> |
| | | ) |
| | | } |
| | |
| | | |
| | | .canvas { |
| | | margin: 0px; |
| | | // padding: 20px 15px 15px; |
| | | padding: 15px; |
| | | padding: 15px 10px 10px; |
| | | letter-spacing: 0px; |
| | | height: 100%; |
| | | } |
| | | .normal-header + .canvas { |
| | | height: calc(100% - 45px); |
| | | } |
| | | |
| | | .chart-header { |
| | |
| | | .model-menu-action-list { |
| | | position: absolute; |
| | | right: 0px; |
| | | top: 30px; |
| | | z-index: 4; |
| | | font-size: 16px; |
| | | |
| | |
| | | float: right; |
| | | } |
| | | } |
| | | .normal-header + .canvas + .model-menu-action-list { |
| | | top: 45px; |
| | | } |
| | | } |
| | | .menu-line-chart-edit-box:hover { |
| | | z-index: 1; |
New file |
| | |
| | | // 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 |
| | | } |
| | | ] |
| | | } |
| | | |
| | | /** |
| | | * @description 获取图表视图配置表单 |
| | | * @param {object} card // 图表对象 |
| | | * @param {Array} columns // 显示列 |
| | | */ |
| | | export function getRadioOptionForm (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: 'select', |
| | | key: 'labelField', |
| | | label: '指标', |
| | | initVal: card.labelField || '', |
| | | required: true, |
| | | options: xfields |
| | | }, |
| | | { |
| | | type: 'select', |
| | | key: 'valueField', |
| | | label: '值', |
| | | initVal: card.valueField || '', |
| | | required: true, |
| | | options: yfields |
| | | }, |
| | | { |
| | | type: 'number', |
| | | key: 'maxValue', |
| | | label: '最大值', |
| | | initVal: card.maxValue || 100, |
| | | min: 0, |
| | | max: 999999, |
| | | decimal: 1, |
| | | required: true |
| | | }, |
| | | { |
| | | type: 'number', |
| | | key: 'radius', |
| | | label: '外环', |
| | | initVal: card.radius || 75, |
| | | tooltip: '图形所占区域的百分率。', |
| | | min: 30, |
| | | max: 100, |
| | | decimal: 0, |
| | | required: true |
| | | }, |
| | | { |
| | | type: 'number', |
| | | key: 'fontSize', |
| | | label: '字体大小', |
| | | initVal: card.fontSize || 28, |
| | | min: 12, |
| | | max: 200, |
| | | decimal: 0, |
| | | required: true |
| | | }, |
| | | { |
| | | type: 'radio', |
| | | key: 'percent', |
| | | label: '百分率', |
| | | initVal: card.percent || 'true', |
| | | required: false, |
| | | options: [{ |
| | | value: 'true', |
| | | text: '使用' |
| | | }, { |
| | | value: 'false', |
| | | text: '不使用' |
| | | }] |
| | | }, |
| | | { |
| | | type: 'color', |
| | | key: 'backColor', |
| | | label: '背景色', |
| | | initVal: card.backColor || '#ebedf0', |
| | | required: false |
| | | }, |
| | | { |
| | | type: 'color', |
| | | key: 'labelColor', |
| | | label: '字体颜色', |
| | | initVal: card.labelColor || '#8c8c8c', |
| | | required: false |
| | | } |
| | | ] |
| | | } |
New file |
| | |
| | | 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, getRadioOptionForm } 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: this.props.config.subtype === 'ratioboard' ? 'text' : '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: config.subtype === 'ratioboard' ? getRadioOptionForm(config.plot, config.columns) : getOptionForm(config.plot, config.columns) |
| | | }) |
| | | } |
| | | |
| | | 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}> |
| | | {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} className="color-col"> |
| | | <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) |
New file |
| | |
| | | .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; |
| | | } |
| | | .color-col { |
| | | .ant-form-item-control { |
| | | height: 40px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
New file |
| | |
| | | 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; |
| | | }, |
| | | }) |
| | | |
| | | registerShape('point', 'hidden', { |
| | | draw(cfg, container) { |
| | | return container.addGroup({}) |
| | | } |
| | | }) |
| | | |
| | | 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 = null |
| | | if (card.subtype === 'ratioboard') { |
| | | _plot = { |
| | | width: card.width || 12, |
| | | height: 400, |
| | | labelField: '', |
| | | valueField: '', |
| | | name: card.name, |
| | | maxValue: 100, |
| | | radius: 75, |
| | | fontSize: 28, |
| | | percent: 'true', |
| | | backColor: '#ebedf0', |
| | | labelColor: '#8c8c8c' |
| | | } |
| | | } else { |
| | | _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: card.subtype === 'ratioboard' ? 'array' : '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 () { |
| | | MKEmitter.addListener('tabsChange', this.handleTabsChange) |
| | | MKEmitter.addListener('submitStyle', this.getStyle) |
| | | |
| | | setTimeout(() => { |
| | | this.viewrender() |
| | | }, 1000) |
| | | } |
| | | |
| | | 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 = '' |
| | | } |
| | | |
| | | this.$timer && clearTimeout(this.$timer) |
| | | this.$timer = setTimeout(this.viewrender, 100) |
| | | } |
| | | } |
| | | |
| | | viewrender = () => { |
| | | const { card } = this.state |
| | | if (card.subtype === 'ratioboard') { |
| | | this.ratioboardrender() |
| | | } else { |
| | | this.dashboardrender() |
| | | } |
| | | } |
| | | |
| | | getratiodata = () => { |
| | | const { card } = this.state |
| | | |
| | | let val = (Math.random() * card.plot.maxValue).toFixed(1) |
| | | let data = [ |
| | | { type: '新用户', value: val, $percent: val / card.plot.maxValue, $color: '#1890ff' }, |
| | | ] |
| | | if (card.plot.colors && card.plot.colors.length > 0) { |
| | | data = [] |
| | | card.plot.colors.forEach(item => { |
| | | let _val = (Math.random() * card.plot.maxValue).toFixed(1) |
| | | data.push({ |
| | | type: item.tick, |
| | | value: _val, |
| | | $percent: _val / card.plot.maxValue, |
| | | $color: item.color |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | return data |
| | | } |
| | | |
| | | ratioboardrender = () => { |
| | | const { card } = this.state |
| | | const plot = card.plot |
| | | |
| | | const data = this.getratiodata() |
| | | |
| | | const chart = new Chart({ |
| | | container: card.uuid + 'dashboard', |
| | | autoFit: true, |
| | | height: plot.title ? plot.height - 45 : plot.height, |
| | | }) |
| | | |
| | | chart.data(data) |
| | | chart.coordinate('polar', { |
| | | startAngle: -Math.PI / 2, |
| | | endAngle: 3 * Math.PI / 2, |
| | | radius: (plot.radius || 75) / 100 |
| | | }) |
| | | chart.scale('$percent', { |
| | | min: 0, |
| | | max: 1, |
| | | tickInterval: 1, |
| | | }) |
| | | chart.axis(false) |
| | | chart.facet('rect', { |
| | | fields: ['type'], |
| | | showTitle: false, |
| | | eachView: function eachView(view, facet) { |
| | | const data = facet.data[0] |
| | | |
| | | view.point().position('').shape('hidden') |
| | | |
| | | view.annotation().arc({ |
| | | top: false, |
| | | start: [0, 1], |
| | | end: [0.9999, 1], |
| | | style: { |
| | | stroke: plot.backColor, |
| | | lineWidth: 10 |
| | | } |
| | | }) |
| | | |
| | | let _tick = data.$percent |
| | | if (_tick >= 1) { |
| | | _tick = 0.9999 |
| | | } |
| | | |
| | | view.annotation().arc({ |
| | | start: [0, 1], |
| | | end: [_tick, 1], |
| | | style: { |
| | | stroke: data.$color, |
| | | lineWidth: 10, |
| | | } |
| | | }) |
| | | // 仪表盘信息 |
| | | let text = '' |
| | | if (plot.percent === 'true') { |
| | | text = +(data.$percent * 100).toFixed(2) + '%' |
| | | } else { |
| | | text = data.value |
| | | } |
| | | |
| | | view.annotation().text({ |
| | | position: ['50%', '45%'], |
| | | content: data.type, |
| | | style: { |
| | | fontSize: plot.fontSize * 0.8, |
| | | fill: plot.labelColor, |
| | | fontWeight: 300, |
| | | textAlign: 'center' |
| | | }, |
| | | offsetX: 0 |
| | | }) |
| | | view.annotation().text({ |
| | | position: ['50%', '55%'], |
| | | content: text, |
| | | style: { |
| | | fontSize: plot.fontSize, |
| | | fill: plot.labelColor, |
| | | fontWeight: 500, |
| | | textAlign: 'center' |
| | | }, |
| | | offsetX: 0, |
| | | offsetY: 10 |
| | | }) |
| | | } |
| | | }) |
| | | chart.render() |
| | | } |
| | | |
| | | 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.title ? plot.height - 45 : plot.height, |
| | | 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: '#ebedf0', |
| | | 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() |
| | | |
| | | 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 = '' |
| | | } |
| | | this.$timer && clearTimeout(this.$timer) |
| | | this.$timer = setTimeout(() => { |
| | | this.viewrender() |
| | | }, 150) |
| | | } |
| | | |
| | | component.width = component.plot.width |
| | | component.name = component.plot.name |
| | | |
| | | this.setState({ |
| | | card: component |
| | | }) |
| | | 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}> |
| | | <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> |
| | | {card.plot.title ? <NormalHeader config={card} updateComponent={this.updateComponent}/> : null} |
| | | <div className="canvas" id={card.uuid + 'dashboard'}></div> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default antvDashboardChart |
New file |
| | |
| | | .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; |
| | | padding: 15px; |
| | | letter-spacing: 0px; |
| | | height: 100%; |
| | | } |
| | | .normal-header + .canvas { |
| | | height: calc(100% - 45px); |
| | | } |
| | | |
| | | >.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; |
| | | } |
| | |
| | | * @param {object} card // 图表对象 |
| | | */ |
| | | export function getBaseForm (card) { |
| | | let isApp = sessionStorage.getItem('appType') === 'pc' |
| | | let appType = sessionStorage.getItem('appType') |
| | | let isApp = appType === 'pc' || appType === 'mob' |
| | | let menulist = null |
| | | |
| | | if (isApp) { |
| | |
| | | * @param {Array} columns // 显示列 |
| | | */ |
| | | export function getOptionForm (card, columns) { |
| | | let appType = sessionStorage.getItem('appType') |
| | | let xfields = columns.filter(item => /^Nvarchar/ig.test(item.datatype)) |
| | | let yfields = columns.filter(item => /^(Int|Decimal)/ig.test(item.datatype)) |
| | | |
| | |
| | | options: [ |
| | | { value: 'pie', text: '饼图' }, |
| | | { value: 'ring', text: '环图' }, |
| | | { value: 'nest', text: '嵌套' }, |
| | | { value: 'nightingale', text: '南丁格尔图' } |
| | | ] |
| | | }, |
| | | { |
| | | type: 'select', |
| | | key: 'Xaxis', |
| | | label: 'X-轴', |
| | | label: '名称', |
| | | initVal: card.Xaxis || '', |
| | | required: true, |
| | | options: xfields |
| | |
| | | { |
| | | type: 'select', |
| | | key: 'Yaxis', |
| | | label: 'Y-轴', |
| | | label: '值', |
| | | initVal: card.Yaxis || '', |
| | | required: true, |
| | | options: yfields |
| | | }, |
| | | { |
| | | type: 'select', |
| | | key: 'type', |
| | | label: '类型', |
| | | initVal: card.type || '', |
| | | tooltip: '内环的分类字段。', |
| | | required: true, |
| | | options: xfields, |
| | | hidden: card.shape !== 'nest', |
| | | }, |
| | | { |
| | | type: 'select', |
| | |
| | | { field: 'left-top', label: '左上' }, |
| | | { field: 'left-bottom', label: '左下' }, |
| | | { field: 'hidden', label: '隐藏' } |
| | | ] |
| | | ], |
| | | hidden: card.shape === 'nest', |
| | | }, |
| | | { |
| | | type: 'number', |
| | |
| | | { |
| | | type: 'radio', |
| | | key: 'label', |
| | | label: '标注值', |
| | | label: '标签', |
| | | initVal: card.label || 'false', |
| | | required: false, |
| | | options: [{ |
| | |
| | | text: '内侧' |
| | | }, { |
| | | value: 'outer', |
| | | text: '外侧' |
| | | }] |
| | | text: '蜘蛛' |
| | | }, { |
| | | value: 'normal', |
| | | text: '常规' |
| | | }], |
| | | }, { |
| | | type: 'radio', |
| | | key: 'repeat', |
| | |
| | | text: '累加' |
| | | }] |
| | | }, { |
| | | type: 'number', |
| | | key: 'splitLine', |
| | | label: '分隔线', |
| | | initVal: card.splitLine || '', |
| | | tooltip: '分隔线的宽度。', |
| | | min: 0, |
| | | max: 20, |
| | | decimal: 0, |
| | | required: false |
| | | }, { |
| | | type: 'color', |
| | | key: 'splitColor', |
| | | label: '分隔色', |
| | | initVal: card.splitColor || '#ffffff', |
| | | tooltip: '分隔线的颜色,存在分隔线时有效。', |
| | | required: false |
| | | }, { |
| | | type: 'color', |
| | | key: 'color', |
| | | label: '色系', |
| | | initVal: card.color || 'rgba(0, 0, 0, 0.85)', |
| | | tooltip: '坐标轴及示例等提示文字使用的颜色。', |
| | | required: false |
| | | }, { |
| | | type: 'select', |
| | | key: 'interaction', |
| | | label: '交互效果', |
| | | initVal: card.interaction || [], |
| | | multi: true, |
| | | required: false, |
| | | options: [{ |
| | | value: 'black', |
| | | text: '黑色' |
| | | }, { |
| | | value: 'white', |
| | | text: '白色' |
| | | }] |
| | | forbid: appType === 'mob', |
| | | options: [ |
| | | { value: 'element-active', label: '元素聚焦' }, |
| | | { value: 'element-selected', label: '元素选中(多选)' }, |
| | | { value: 'element-single-selected', label: '元素选中(单选)' }, |
| | | // { value: 'active-region', label: '背景框' }, |
| | | // { value: 'view-zoom', label: '视图缩放' }, |
| | | { value: 'element-highlight', label: '元素高亮' }, |
| | | // { value: 'element-highlight-by-color', label: '同色元素高亮' }, |
| | | // { value: 'element-highlight-by-x', label: '同X轴元素高亮' }, |
| | | { value: 'legend-filter', label: '图例过滤' }, |
| | | { value: 'legend-active', label: '图例聚焦' }, |
| | | { value: 'legend-highlight', label: '图例高亮' }, |
| | | // { value: 'brush', label: '选框过滤' }, |
| | | ] |
| | | } |
| | | ] |
| | | } |
| | |
| | | formlist: formlist.map(item => { |
| | | if (item.key === 'innerRadius') { |
| | | item.hidden = val === 'pie' |
| | | } else if (item.key === 'type') { |
| | | item.hidden = val !== 'nest' |
| | | } else if (item.key === 'legend') { |
| | | item.hidden = val === 'nest' |
| | | } |
| | | return item |
| | | }) |
| | |
| | | })( |
| | | <Select mode={item.multi ? 'multiple' : ''}> |
| | | {item.options.map((option, index) => |
| | | <Select.Option key={index} value={option.field}> |
| | | <Select.Option key={index} value={option.field || option.value}> |
| | | {option.label} |
| | | </Select.Option> |
| | | )} |
| | |
| | | } |
| | | ] |
| | | })( |
| | | <Radio.Group disabled={item.readonly} onChange={(e) => this.radioChange(e, item.key)}> |
| | | <Radio.Group style={{whiteSpace: 'nowrap'}} 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> |
| | |
| | | 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' |
| | | import DataSet, { DataView } from '@antv/data-set' |
| | | |
| | | import MKEmitter from '@/utils/events.js' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | |
| | | 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')) |
| | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | card: null, |
| | | ismob: sessionStorage.getItem('appType') === 'mob', |
| | | eventListener: null |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { card } = this.props |
| | | const { card, ismob } = this.props |
| | | |
| | | if (card.isNew) { |
| | | let _plot = { |
| | |
| | | name: card.name |
| | | } |
| | | |
| | | if (ismob) { |
| | | _plot.width = 24 |
| | | } |
| | | |
| | | if (card.subtype === 'ring') { |
| | | _plot.innerRadius = 50 |
| | | } else if (card.subtype === 'nest') { |
| | | _plot.innerRadius = 30 |
| | | _plot.radius = 80 |
| | | } |
| | | |
| | | let _card = { |
| | |
| | | } |
| | | |
| | | componentDidMount () { |
| | | this.pierender() |
| | | MKEmitter.addListener('tabsChange', this.handleTabsChange) |
| | | MKEmitter.addListener('submitStyle', this.getStyle) |
| | | |
| | | setTimeout(() => { |
| | | this.viewrender() |
| | | }, 1000) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | |
| | | _element.innerHTML = '' |
| | | } |
| | | |
| | | setTimeout(this.pierender, 100) |
| | | this.$timer && clearTimeout(this.$timer) |
| | | this.$timer = setTimeout(this.viewrender, 100) |
| | | } |
| | | } |
| | | |
| | | viewrender = () => { |
| | | const { card } = this.state |
| | | |
| | | if (card.plot.shape === 'nest') { |
| | | this.nestrender() |
| | | } else { |
| | | this.pierender() |
| | | } |
| | | } |
| | | |
| | |
| | | { 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 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)' |
| | | getnestdata = (X_axis, Y_axis, type) => { |
| | | const xdata = [ |
| | | { name: '狮子', type: '火象', value: 11 }, |
| | | { name: '白羊', type: '火象', value: 10 }, |
| | | { name: '水瓶', type: '风向', value: 14 }, |
| | | { name: '射手', type: '火象', value: 10 }, |
| | | { name: '双子', type: '风向', value: 7 }, |
| | | { name: '天平', type: '风向', value: 7 }, |
| | | { name: '摩羯', type: '土象', value: 14 }, |
| | | { name: '金牛', type: '土象', value: 3 }, |
| | | { name: '处女', type: '土象', value: 3 }, |
| | | { name: '天蝎', type: '水象', value: 11 }, |
| | | { name: '巨蟹', type: '水象', value: 5 }, |
| | | { name: '双鱼', type: '水象', value: 5 }, |
| | | ] |
| | | |
| | | let map = new Map() |
| | | let sort = 1 |
| | | let data = xdata.map(item => { |
| | | let _sort = sort |
| | | if (map.has(item.type)) { |
| | | _sort = map.get(item.type) |
| | | } else { |
| | | map.set(item.type, _sort) |
| | | sort++ |
| | | } |
| | | return { |
| | | [X_axis]: item.name, |
| | | [Y_axis]: item.value, |
| | | [type]: item.type, |
| | | $sort: _sort |
| | | } |
| | | }) |
| | | |
| | | return data |
| | | } |
| | | |
| | | nestrender = () => { |
| | | const { card } = this.state |
| | | const plot = card.plot |
| | | |
| | | let color = plot.color || 'rgba(0, 0, 0, 0.85)' |
| | | let X_axis = plot.Xaxis || 'x' |
| | | let Y_axis = plot.Yaxis || 'y' |
| | | let type = plot.type || 'type' |
| | | let height = plot.height || 400 |
| | | if (card.plot.title || card.search.length > 0) { |
| | | height = height - 45 |
| | | } |
| | | |
| | | const _data = this.getnestdata(X_axis, Y_axis, type) |
| | | const dvx = new DataView().source(_data) |
| | | |
| | | dvx.transform({ |
| | | type: 'sort-by', |
| | | fields: ['$sort'] |
| | | }) |
| | | |
| | | let data = dvx.rows |
| | | |
| | | // 通过 DataSet 计算百分比 |
| | | const dv = new DataView() |
| | | dv.source(data).transform({ |
| | | type: 'percent', |
| | | field: Y_axis, |
| | | dimension: type, |
| | | as: '$percent' |
| | | }) |
| | | |
| | | const dv1 = new DataView() |
| | | dv1.source(data).transform({ |
| | | type: 'percent', |
| | | field: Y_axis, |
| | | dimension: X_axis, |
| | | as: '$percent', |
| | | }) |
| | | |
| | | const chart = new Chart({ |
| | | container: card.uuid + 'canvas', |
| | | autoFit: true, |
| | | height: height, |
| | | padding: 0, |
| | | }) |
| | | |
| | | chart.data(dv.rows) |
| | | |
| | | if (plot.show !== 'value') { |
| | | chart.scale('percent', { |
| | | formatter: (val) => { |
| | | val = val * 100 + '%' |
| | | return val |
| | | } |
| | | }) |
| | | |
| | | Y_axis = '$percent' |
| | | } |
| | | let radius = plot.radius / 100 |
| | | let innerRadius = plot.innerRadius / 100 |
| | | |
| | | chart.coordinate('theta', { |
| | | innerRadius: innerRadius, |
| | | radius: innerRadius + (radius - innerRadius) / 2, |
| | | }) |
| | | |
| | | if (plot.tooltip !== 'true') { |
| | | chart.tooltip(false) |
| | | } else { |
| | | chart.tooltip({ |
| | | showTitle: false, |
| | | showMarkers: false |
| | | }) |
| | | } |
| | | |
| | | chart.legend(false) |
| | | let chart1 = chart |
| | | .interval() |
| | | .adjust('stack') |
| | | .position(Y_axis) |
| | | .color(type) |
| | | .tooltip(`${type}*${Y_axis}`, (type, percent) => { |
| | | if (plot.show !== 'value') { |
| | | percent = (percent * 100).toFixed(2) + '%' |
| | | } |
| | | return { |
| | | name: type, |
| | | value: percent, |
| | | } |
| | | }) |
| | | |
| | | if (plot.splitLine) { |
| | | chart1.style({ |
| | | lineWidth: plot.splitLine, |
| | | stroke: plot.splitColor, |
| | | }) |
| | | } |
| | | if (plot.label !== 'false') { |
| | | chart1.label(type, { |
| | | offset: -10, |
| | | }) |
| | | } |
| | | |
| | | const outterView = chart.createView() |
| | | |
| | | outterView.data(dv1.rows) |
| | | |
| | | if (plot.show !== 'value') { |
| | | outterView.scale('percent', { |
| | | formatter: (val) => { |
| | | val = val * 100 + '%' |
| | | return val |
| | | } |
| | | }) |
| | | } |
| | | outterView.coordinate('theta', { |
| | | innerRadius: (innerRadius + (radius - innerRadius) / 2) / radius, |
| | | radius: radius |
| | | }) |
| | | let chart2 = outterView |
| | | .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.splitLine) { |
| | | chart2.style({ |
| | | lineWidth: plot.splitLine, |
| | | stroke: plot.splitColor, |
| | | }) |
| | | } |
| | | |
| | | if (plot.label !== 'false') { |
| | | if (plot.label === 'inner') { |
| | | chart2.label(Y_axis, { |
| | | offset: -30, |
| | | content: (data) => { |
| | | let _val = '' |
| | | if (plot.show !== 'value') { |
| | | _val = `${(data[Y_axis] * 100).toFixed(2)}%` |
| | | } else { |
| | | _val = `${data[Y_axis]}` |
| | | } |
| | | return _val |
| | | }, |
| | | style: { |
| | | textAlign: 'center', |
| | | fontSize: 16, |
| | | shadowBlur: 2, |
| | | shadowColor: 'rgba(0, 0, 0, .45)', |
| | | fill: '#fff', |
| | | } |
| | | }) |
| | | } else { |
| | | chart2.label(Y_axis, { |
| | | layout: { type: plot.label === 'outer' ? 'pie-spider' : 'fixed-overlap' }, |
| | | labelHeight: 20, |
| | | content: (data) => { |
| | | let _val = '' |
| | | if (plot.show !== 'value') { |
| | | _val = `${(data[Y_axis] * 100).toFixed(2)}%` |
| | | } else { |
| | | _val = `${data[Y_axis]}` |
| | | } |
| | | |
| | | return `${data[X_axis]}: ${_val}` |
| | | }, |
| | | labelLine: { |
| | | style: { |
| | | lineWidth: 0.5, |
| | | }, |
| | | }, |
| | | style: { |
| | | fill: color |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | |
| | | if (plot.interaction && plot.interaction.length) { |
| | | plot.interaction.forEach(t => { |
| | | chart.interaction(t) |
| | | }) |
| | | } |
| | | |
| | | chart.render() |
| | | } |
| | | |
| | | pierender = () => { |
| | | const { card } = this.state |
| | | const plot = card.plot |
| | | |
| | | let color = plot.color || 'rgba(0, 0, 0, 0.85)' |
| | | let X_axis = plot.Xaxis || 'x' |
| | | let Y_axis = plot.Yaxis || 'y' |
| | | let height = plot.height || 400 |
| | | if (card.plot.title || card.search.length > 0) { |
| | | height = height - 45 |
| | | } |
| | | |
| | | let data = this.getdata(X_axis, Y_axis) |
| | | |
| | |
| | | const chart = new Chart({ |
| | | container: card.uuid + 'canvas', |
| | | autoFit: true, |
| | | height: plot.height || 400 |
| | | height: height |
| | | }) |
| | | |
| | | if (plot.shape !== 'nightingale' && plot.show !== 'value') { |
| | |
| | | }) |
| | | } |
| | | |
| | | // 饼图或环图 |
| | | if (plot.shape !== 'nightingale') { |
| | | let _chart = chart |
| | | .interval() |
| | |
| | | value: value |
| | | } |
| | | }) |
| | | |
| | | if (plot.splitLine) { |
| | | _chart.style({ |
| | | lineWidth: plot.splitLine, |
| | | stroke: plot.splitColor, |
| | | }) |
| | | } |
| | | |
| | | 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 |
| | | return _val |
| | | }, |
| | | style: { |
| | | textAlign: 'center', |
| | |
| | | }) |
| | | } else { |
| | | _chart.label(Y_axis, { |
| | | layout: { type: 'pie-spider' }, |
| | | layout: { type: plot.label === 'outer' ? 'pie-spider' : 'fixed-overlap' }, |
| | | 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 |
| | | |
| | | return `${data[X_axis]}: ${_val}` |
| | | }, |
| | | labelLine: { |
| | | style: { |
| | |
| | | }) |
| | | } |
| | | } |
| | | chart.interaction('element-active') |
| | | } else { |
| | | chart.axis(false) |
| | | chart.interaction('element-highlight') |
| | | let _chart = chart |
| | | .interval() |
| | | .position(`${X_axis}*${Y_axis}`) |
| | |
| | | } |
| | | |
| | | _chart.label(X_axis, _label) |
| | | .style({ |
| | | lineWidth: 1, |
| | | stroke: '#fff', |
| | | } |
| | | if (plot.splitLine) { |
| | | _chart.style({ |
| | | lineWidth: plot.splitLine, |
| | | stroke: plot.splitColor, |
| | | }) |
| | | } |
| | | } |
| | | |
| | | if (plot.interaction && plot.interaction.length) { |
| | | plot.interaction.forEach(t => { |
| | | chart.interaction(t) |
| | | }) |
| | | } |
| | | |
| | | 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 + 'canvas') |
| | | if (_element) { |
| | | _element.innerHTML = '' |
| | | } |
| | | refresh = true |
| | | this.$timer && clearTimeout(this.$timer) |
| | | this.$timer = setTimeout(() => { |
| | | this.viewrender() |
| | | }, 150) |
| | | } |
| | | |
| | | component.width = component.plot.width |
| | |
| | | |
| | | this.setState({ |
| | | card: component |
| | | }, () => { |
| | | if (refresh) { |
| | | setTimeout(() => { |
| | | this.pierender() |
| | | }, 100) |
| | | } |
| | | }) |
| | | this.props.updateConfig(component) |
| | | } |
| | |
| | | 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() |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { card } = this.state |
| | | const { card, ismob } = this.state |
| | | let _style = resetStyle(card.style) |
| | | |
| | | return ( |
| | | <div className="menu-pie-chart-edit-box" style={{...card.style, height: card.plot.height || 400}} onClick={this.clickComponent} id={card.uuid}> |
| | | <NormalHeader config={card} updateComponent={this.updateComponent}/> |
| | | <div className="menu-pie-chart-edit-box" style={{..._style, height: card.plot.height || 400}} onClick={this.clickComponent} id={card.uuid}> |
| | | <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" /> |
| | | {!ismob ? <Icon className="plus" title="添加搜索" onClick={this.addSearch} type="plus-circle" /> : null} |
| | | <ChartCompileForm config={card} dict={this.state.dict} plotchange={this.updateComponent}/> |
| | | <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)} /> |
| | |
| | | } trigger="hover"> |
| | | <Icon type="tool" /> |
| | | </Popover> |
| | | {card.plot.title || card.search.length > 0 ? <NormalHeader config={card} updateComponent={this.updateComponent}/> : null} |
| | | <div className="canvas" id={card.uuid + 'canvas'}></div> |
| | | </div> |
| | | ) |
| | |
| | | margin: 0px; |
| | | padding: 15px; |
| | | letter-spacing: 0px; |
| | | height: 100%; |
| | | } |
| | | .normal-header + .canvas { |
| | | height: calc(100% - 45px); |
| | | } |
| | | |
| | | >.anticon-tool { |
New file |
| | |
| | | /** |
| | | * @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 appType = sessionStorage.getItem('appType') |
| | | let xfields = columns.filter(item => /^Nvarchar/ig.test(item.datatype)) |
| | | let yfields = columns.filter(item => /^(Int|Decimal)/ig.test(item.datatype)) |
| | | |
| | | return [ |
| | | { |
| | | type: 'select', |
| | | key: 'gender', |
| | | label: '类型', |
| | | initVal: card.gender || '', |
| | | required: true, |
| | | options: xfields |
| | | }, |
| | | { |
| | | type: 'select', |
| | | key: 'Xaxis', |
| | | label: 'X-轴', |
| | | initVal: card.Xaxis || '', |
| | | required: true, |
| | | options: columns |
| | | }, |
| | | { |
| | | type: 'select', |
| | | key: 'Yaxis', |
| | | label: 'Y-轴', |
| | | initVal: card.Yaxis || '', |
| | | required: true, |
| | | options: yfields |
| | | }, |
| | | { |
| | | type: 'radio', |
| | | key: 'shape', |
| | | label: '形状', |
| | | initVal: card.shape || 'circle', |
| | | required: false, |
| | | options: [{ |
| | | value: 'circle', |
| | | text: 'circle' |
| | | }, { |
| | | value: 'square', |
| | | text: 'square' |
| | | }] |
| | | }, |
| | | { |
| | | type: 'radio', |
| | | key: 'tooltip', |
| | | label: '悬浮提示', |
| | | initVal: card.tooltip || 'true', |
| | | required: false, |
| | | options: [{ |
| | | value: 'true', |
| | | text: '显示' |
| | | }, { |
| | | value: 'false', |
| | | text: '隐藏' |
| | | }] |
| | | }, |
| | | { |
| | | type: 'text', |
| | | key: 'Xunit', |
| | | label: 'X轴单位', |
| | | initVal: card.Xunit || '', |
| | | required: false |
| | | }, |
| | | { |
| | | type: 'text', |
| | | key: 'Yunit', |
| | | label: 'Y轴单位', |
| | | initVal: card.Yunit || '', |
| | | required: false |
| | | }, |
| | | { |
| | | type: 'color', |
| | | key: 'color', |
| | | label: '色系', |
| | | initVal: card.color || 'rgba(0, 0, 0, 0.65)', |
| | | tooltip: '坐标轴提示文字及示例的颜色。', |
| | | required: false |
| | | }, { |
| | | type: 'select', |
| | | key: 'interaction', |
| | | label: '交互效果', |
| | | initVal: card.interaction || [], |
| | | multi: true, |
| | | required: false, |
| | | forbid: appType === 'mob', |
| | | options: [ |
| | | { value: 'element-active', label: '元素聚焦' }, |
| | | { value: 'element-selected', label: '元素选中(多选)' }, |
| | | { value: 'element-single-selected', label: '元素选中(单选)' }, |
| | | // { value: 'active-region', label: '背景框' }, |
| | | { value: 'view-zoom', label: '视图缩放' }, |
| | | { value: 'element-highlight', label: '元素高亮' }, |
| | | { value: 'element-highlight-by-color', label: '同色元素高亮' }, |
| | | { value: 'element-highlight-by-x', label: '同X轴元素高亮' }, |
| | | { value: 'legend-filter', label: '图例过滤' }, |
| | | { value: 'legend-active', label: '图例聚焦' }, |
| | | { value: 'legend-highlight', label: '图例高亮' }, |
| | | { value: 'brush', label: '选框过滤' }, |
| | | ] |
| | | } |
| | | ] |
| | | } |
New file |
| | |
| | | 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 } from 'antd' |
| | | |
| | | import { getBaseForm, getOptionForm } from './formconfig' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import ColorSketch from '@/mob/colorsketch' |
| | | import './index.scss' |
| | | |
| | | const { TabPane } = Tabs |
| | | 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 = { |
| | | view: 'normal', |
| | | visible: false, |
| | | plot: null, |
| | | formlist: null, |
| | | baseFormlist: null |
| | | } |
| | | |
| | | 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) |
| | | }) |
| | | } |
| | | |
| | | 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.value}> |
| | | {option.label || option.text} |
| | | </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}> |
| | | {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}) |
| | | }) |
| | | } |
| | | } |
| | | |
| | | changeTab = (tab) => { |
| | | const { plot, view } = this.state |
| | | |
| | | if (view === 'normal') { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | this.setState({ |
| | | plot: {...plot, ...values}, |
| | | view: tab |
| | | }) |
| | | } |
| | | }) |
| | | } else if (view === 'base') { |
| | | this.baseRef.handleConfirm().then(res => { |
| | | this.setState({ |
| | | plot: {...plot, ...res}, |
| | | view: tab |
| | | }) |
| | | }) |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { view, visible, 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> |
| | | </Tabs> |
| | | </Modal> |
| | | </div> |
| | | ); |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(LineChartDrawerForm) |
New file |
| | |
| | | .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); |
| | | min-height: 50vh; |
| | | padding-top: 10px; |
| | | .menu-chart-edit-box { |
| | | .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; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Popover, notification } from 'antd' |
| | | import { Chart } 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 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 ChartCompileForm = asyncIconComponent(() => import('./chartcompile')) |
| | | const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent')) |
| | | const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) |
| | | const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent')) |
| | | const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader')) |
| | | const ActionComponent = asyncComponent(() => import('@/menu/components/share/actioncomponent')) |
| | | const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent')) |
| | | const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent')) |
| | | |
| | | class antvScatterChart extends Component { |
| | | static propTpyes = { |
| | | card: PropTypes.object, |
| | | updateConfig: PropTypes.func, |
| | | deletecomponent: PropTypes.func, |
| | | } |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | card: null, |
| | | appType: sessionStorage.getItem('appType'), |
| | | eventListener: null |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { card } = this.props |
| | | |
| | | if (card.isNew) { |
| | | let _plot = { |
| | | width: card.width || 24, |
| | | height: 400, |
| | | gender: '', |
| | | Xaxis: '', |
| | | Xunit: '', |
| | | Yaxis: '', |
| | | Yunit: '', |
| | | shape: 'circle', |
| | | color: 'rgba(0, 0, 0, 0.65)', |
| | | name: card.name |
| | | } |
| | | |
| | | let _card = { |
| | | uuid: card.uuid, |
| | | type: card.type, |
| | | floor: card.floor, |
| | | tabId: card.tabId || '', |
| | | parentId: card.parentId || '', |
| | | format: 'array', // 组件属性 - 数据格式 |
| | | 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 |
| | | |
| | | _card.action = config.action.map(col => { |
| | | col.uuid = Utils.getuuid() |
| | | return col |
| | | }) |
| | | _card.search = config.search.map(col => { |
| | | col.uuid = Utils.getuuid() |
| | | return col |
| | | }) |
| | | } |
| | | this.setState({ |
| | | card: _card |
| | | }) |
| | | this.props.updateConfig(_card) |
| | | } else { |
| | | this.setState({ |
| | | card: fromJS(card).toJS() |
| | | }) |
| | | } |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('submitStyle', this.getStyle) |
| | | MKEmitter.addListener('tabsChange', this.handleTabsChange) |
| | | setTimeout(() => { |
| | | this.ponitrender() |
| | | }, 1000) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新,清除快捷键设置 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('submitStyle', this.getStyle) |
| | | MKEmitter.removeListener('tabsChange', this.handleTabsChange) |
| | | } |
| | | |
| | | handleTabsChange = (parentId) => { |
| | | const { card } = this.state |
| | | |
| | | if (parentId === card.parentId) { |
| | | let _element = document.getElementById(card.uuid + 'canvas') |
| | | if (_element) { |
| | | _element.innerHTML = '' |
| | | } |
| | | |
| | | this.$timer && clearTimeout(this.$timer) |
| | | this.$timer = setTimeout(this.ponitrender, 100) |
| | | } |
| | | } |
| | | |
| | | getdata = () => { |
| | | let data = [] |
| | | |
| | | for (let i = 0; i < 500; i++) { |
| | | let item = {} |
| | | let n = Math.random() |
| | | let m = Math.random() |
| | | if (n > 0.7) { |
| | | n = n * n |
| | | } else if (n < 0.3) { |
| | | n = Math.sqrt(n) |
| | | } |
| | | if (m > 0.7) { |
| | | m = m * m |
| | | } else if (m < 0.3) { |
| | | m = Math.sqrt(m) |
| | | } |
| | | |
| | | if (i % 2 === 0) { |
| | | item.gender = 'male' |
| | | item.height = 160 + Math.floor(n * 35 * 10) / 10 |
| | | item.weight = 50 + Math.floor(m * 55 * 10) / 10 |
| | | } else { |
| | | item.gender = 'female' |
| | | item.height = 140 + Math.floor(n * 40 * 10) / 10 |
| | | item.weight = 41 + Math.floor(m * 45 * 10) / 10 |
| | | } |
| | | |
| | | data.push(item) |
| | | } |
| | | |
| | | return data |
| | | } |
| | | |
| | | /** |
| | | * @description 散点图 |
| | | */ |
| | | ponitrender = () => { |
| | | const { card } = this.state |
| | | const plot = card.plot |
| | | const data = this.getdata() |
| | | let height = plot.height - 25 |
| | | |
| | | if (card.plot.title || card.search.length > 0) { |
| | | height = plot.height - 70 |
| | | } |
| | | |
| | | const chart = new Chart({ |
| | | container: card.uuid + 'canvas', |
| | | autoFit: true, |
| | | height: height |
| | | }) |
| | | |
| | | chart.data(data); |
| | | chart.scale({ |
| | | height: { nice: true }, |
| | | weight: { nice: true }, |
| | | }) |
| | | |
| | | // chart.axis('height', { label: { style: { fill: plot.color } }, tickLine: {style: { stroke: plot.color }}, line: { style: { stroke: plot.color } } }) |
| | | // chart.axis('weight', { grid: { line: { style: { stroke: plot.color } }}, label: { style: { fill: plot.color } } }) |
| | | chart.axis('height', { label: { style: { fill: plot.color } } }) |
| | | chart.axis('weight', { label: { style: { fill: plot.color } } }) |
| | | chart.legend({ |
| | | position: plot.legend || 'bottom', |
| | | itemName: { style: { fill: plot.color } } |
| | | }) |
| | | |
| | | if (plot.tooltip !== 'true') { |
| | | chart.tooltip(false) |
| | | } else { |
| | | chart.tooltip({ |
| | | showTitle: false, |
| | | showCrosshairs: true, |
| | | crosshairs: { |
| | | type: 'xy', |
| | | } |
| | | }) |
| | | } |
| | | |
| | | chart |
| | | .point() |
| | | .position('height*weight') |
| | | .color('gender') |
| | | .shape(plot.shape) |
| | | .tooltip('gender*height*weight', (gender, height, weight) => { |
| | | return { |
| | | name: gender, |
| | | value: height + (plot.Xunit ? `(${plot.Xunit}), ` : ', ') + weight + (plot.Yunit ? `(${plot.Yunit})` : '') |
| | | }; |
| | | }) |
| | | .style({ |
| | | fillOpacity: 0.85 |
| | | }) |
| | | if (plot.interaction && plot.interaction.length) { |
| | | plot.interaction.forEach(t => { |
| | | chart.interaction(t) |
| | | }) |
| | | } |
| | | chart.render() |
| | | } |
| | | |
| | | updateComponent = (component) => { |
| | | const card = fromJS(this.state.card).toJS() |
| | | |
| | | if (!is(fromJS(component.plot), fromJS(card.plot)) || !is(fromJS(component.style), fromJS(card.style))) { |
| | | let _element = document.getElementById(card.uuid + 'canvas') |
| | | if (_element) { |
| | | _element.innerHTML = '' |
| | | } |
| | | this.$timer && clearTimeout(this.$timer) |
| | | this.$timer = setTimeout(() => { |
| | | this.ponitrender() |
| | | }, 150) |
| | | } |
| | | |
| | | component.width = component.plot.width |
| | | component.name = component.plot.name |
| | | |
| | | this.setState({ |
| | | card: component |
| | | }) |
| | | 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) |
| | | } |
| | | |
| | | addButton = () => { |
| | | const { card } = this.state |
| | | |
| | | let newcard = {} |
| | | newcard.uuid = Utils.getuuid() |
| | | newcard.focus = true |
| | | |
| | | newcard.label = '导出Excel' |
| | | newcard.sqlType = '' |
| | | newcard.Ot = 'requiredSgl' |
| | | newcard.OpenType = 'excelOut' |
| | | newcard.icon = 'download' |
| | | newcard.class = 'dgreen' |
| | | newcard.intertype = card.setting.interType |
| | | newcard.innerFunc = card.setting.innerFunc || '' |
| | | newcard.sysInterface = card.setting.sysInterface || '' |
| | | newcard.outerFunc = card.setting.outerFunc || '' |
| | | newcard.interface = card.setting.interface || '' |
| | | newcard.execSuccess = 'grid' |
| | | newcard.execError = 'never' |
| | | newcard.popClose = 'never' |
| | | newcard.errorTime = 10 |
| | | newcard.verify = null |
| | | newcard.show = 'icon' |
| | | |
| | | // 注册事件-添加按钮 |
| | | MKEmitter.emit('addButton', card.uuid, newcard) |
| | | } |
| | | |
| | | 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) |
| | | } |
| | | |
| | | 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() |
| | | MKEmitter.emit('clickComponent', this.state.card) |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { card, appType } = this.state |
| | | let _style = resetStyle(card.style) |
| | | |
| | | return ( |
| | | <div className="menu-scatter-chart-edit-box" style={{..._style, height: card.plot.height || 400}} onClick={this.clickComponent} id={card.uuid}> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | {appType !== 'mob' ? <Icon className="plus" title="添加搜索" onClick={this.addSearch} type="plus-circle"/> : null} |
| | | {appType !== 'mob' ? <Icon className="plus" title="添加按钮" onClick={this.addButton} type="plus-square" /> : null} |
| | | <ChartCompileForm config={card} dict={this.state.dict} plotchange={this.updateComponent}/> |
| | | <CopyComponent type="line" card={card}/> |
| | | <PasteComponent config={card} options={['action', '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)}/> |
| | | <SettingComponent config={card} updateConfig={this.updateComponent}/> |
| | | </div> |
| | | } trigger="hover"> |
| | | <Icon type="tool" /> |
| | | </Popover> |
| | | {card.plot.title || card.search.length > 0 ? <NormalHeader config={card} updateComponent={this.updateComponent}/> : null} |
| | | <div className="canvas" id={card.uuid + 'canvas'}></div> |
| | | {appType !== 'mob' ? <ActionComponent type="chart" config={card} updateaction={this.updateComponent}/> : null} |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default antvScatterChart |
New file |
| | |
| | | .menu-scatter-chart-edit-box { |
| | | position: relative; |
| | | box-sizing: border-box; |
| | | background: #ffffff; |
| | | background-position: center center; |
| | | background-repeat: no-repeat; |
| | | background-size: cover; |
| | | |
| | | .canvas { |
| | | margin: 0px; |
| | | padding: 15px 10px 10px; |
| | | letter-spacing: 0px; |
| | | height: 100%; |
| | | } |
| | | .normal-header + .canvas { |
| | | height: calc(100% - 45px); |
| | | } |
| | | |
| | | .chart-header { |
| | | position: relative; |
| | | height: 45px; |
| | | border-bottom: 1px solid #e8e8e8; |
| | | overflow: hidden; |
| | | padding-right: 35px; |
| | | |
| | | .chart-title { |
| | | text-decoration: inherit; |
| | | font-weight: inherit; |
| | | font-style: inherit; |
| | | float: left; |
| | | line-height: 45px; |
| | | margin-left: 10px; |
| | | position: relative; |
| | | z-index: 1; |
| | | } |
| | | } |
| | | |
| | | >.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; |
| | | top: 30px; |
| | | z-index: 4; |
| | | font-size: 16px; |
| | | |
| | | .ant-row .anticon-plus { |
| | | float: right; |
| | | } |
| | | |
| | | .page-card { |
| | | float: right; |
| | | } |
| | | } |
| | | .normal-header + .canvas + .model-menu-action-list { |
| | | top: 45px; |
| | | } |
| | | } |
| | | .menu-scatter-chart-edit-box:hover { |
| | | z-index: 1; |
| | | box-shadow: 0px 0px 4px #1890ff; |
| | | } |
| | |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | |
| | | |
| | | render() { |
| | | const { card } = this.state |
| | | let _style = resetStyle(card.style) |
| | | |
| | | return ( |
| | | <div className="menu-editor-sand-box" style={{...card.style}} onClick={this.clickComponent} id={card.uuid}> |
| | | <div className="menu-editor-sand-box" style={_style} onClick={this.clickComponent} id={card.uuid}> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <WrapComponent config={card} updateConfig={this.updateComponent} /> |
| | |
| | | const { card } = this.props |
| | | |
| | | if (card.type === 'prev') { |
| | | return ['type', 'label'] |
| | | return ['type', 'label', 'enable'] |
| | | } else if (card.type === 'next') { |
| | | return ['type', 'label', 'enable'] |
| | | } |
| | | let _options = ['type', 'label', 'intertype', 'syncComponent', 'linkmenu', 'open'] // 选项列表 |
| | | let _options = ['type', 'label', 'intertype', 'syncComponent', 'linkmenu', 'open', 'enable'] // 选项列表 |
| | | |
| | | if (_intertype === 'custom') { |
| | | _options.push('procMode', 'interface', 'callbackType', 'cbTable', 'proInterface', 'method', 'cross') |
| | |
| | | */ |
| | | |
| | | export function getActionForm (card, functip, tableName, usefulFields, modules) { |
| | | const isApp = sessionStorage.getItem('appType') === 'pc' |
| | | const appType = sessionStorage.getItem('appType') |
| | | let _type = '提交' |
| | | if (card.type === 'prev') { |
| | | _type = '上一步' |
| | |
| | | } |
| | | |
| | | let menulist = [] |
| | | if (isApp) { |
| | | if (appType === 'pc' || appType === 'mob') { |
| | | menulist = sessionStorage.getItem('appMenus') |
| | | if (menulist) { |
| | | try { |
| | |
| | | readonly: false |
| | | }, |
| | | { |
| | | type: isApp ? 'select' : 'cascader', |
| | | type: (appType === 'pc' || appType === 'mob') ? 'select' : 'cascader', |
| | | key: 'linkmenu', |
| | | label: '打开菜单', |
| | | tooltip: '执行成功后需要打开的菜单。', |
| | |
| | | label: '打开方式', |
| | | initVal: card.open || 'blank', |
| | | required: false, |
| | | forbid: !isApp, |
| | | forbid: appType !== 'pc', |
| | | options: [{ |
| | | value: 'blank', |
| | | text: '新窗口' |
| | |
| | | type: 'radio', |
| | | key: 'enable', |
| | | label: '是否显示', |
| | | initVal: card.enable || 'false', |
| | | initVal: card.enable || 'true', |
| | | required: false, |
| | | options: [{ |
| | | value: 'true', |
| | |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import { getActionForm } from './formconfig' |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | |
| | | import MKEmitter from '@/utils/events.js' |
| | | import MenuUtils from '@/utils/utils-custom.js' |
| | |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | appType: sessionStorage.getItem('appType'), |
| | | card: null, // 编辑中元素 |
| | | formlist: null, // 表单信息 |
| | | visible: false, // 模态框控制 |
| | |
| | | }) |
| | | } |
| | | |
| | | changeMenu = () => { |
| | | const { appType } = this.state |
| | | const { group } = this.props |
| | | |
| | | if (appType !== 'pc' && appType !== 'mob') return |
| | | if (!group.subButton.linkmenu) return |
| | | |
| | | MKEmitter.emit('changeEditMenu', { |
| | | MenuID: group.subButton.linkmenu, |
| | | copyMenuId: '', |
| | | MenuNo: '', |
| | | MenuName: '', |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const { group, config } = this.props |
| | | const { visible, profVisible, card, dict } = this.state |
| | |
| | | <Icon className="style" title="调整样式" onClick={() => this.handleStyle(group.prevButton)} type="font-colors" /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <Button type="link" className="prev" style={group.prevButton.style}>{group.prevButton.label}</Button> |
| | | <Button type="link" className={'prev ' + group.prevButton.enable} style={resetStyle(group.prevButton.style)}>{group.prevButton.label}</Button> |
| | | </Popover> : null} |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | |
| | | <Icon className="profile" title="setting" type="profile" onClick={() => this.profileAction()} /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <Button type="link" className="submit mk-primary" style={group.subButton.style}>{group.subButton.label}</Button> |
| | | <Button type="link" className="submit mk-primary" onDoubleClick={this.changeMenu} style={resetStyle(group.subButton.style)}>{group.subButton.label}</Button> |
| | | </Popover> |
| | | {group.sort !== config.subcards.length ? <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | |
| | | <Icon className="style" title="调整样式" onClick={() => this.handleStyle(group.nextButton)} type="font-colors" /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <Button type="link" className={'skip ' + group.nextButton.enable} style={group.nextButton.style}>{group.nextButton.label}</Button> |
| | | <Button type="link" className={'skip ' + group.nextButton.enable} style={resetStyle(group.nextButton.style)}>{group.nextButton.label}</Button> |
| | | </Popover> : null} |
| | | {/* 编辑按钮:复制、编辑 */} |
| | | <Modal |
| | |
| | | .prev { |
| | | margin-right: 15px; |
| | | } |
| | | .prev.false { |
| | | span { |
| | | text-decoration: line-through; |
| | | } |
| | | } |
| | | .submit { |
| | | border: none; |
| | | } |
| | |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { group } = this.props |
| | | const { appType } = this.state |
| | | let fields = [] |
| | | |
| | | group.fields.forEach(f => { |
| | | if (f.field && ['select', 'link', 'text', 'number'].includes(f.type) && f.hidden !== 'true' && f.readonly !== 'true') { |
| | | fields.push(f) |
| | | } |
| | | }) |
| | | if (appType === 'mob') { |
| | | group.fields.forEach(f => { |
| | | if (f.field && ['text', 'number'].includes(f.type) && f.hidden !== 'true' && f.readonly !== 'true') { |
| | | fields.push(f) |
| | | } |
| | | }) |
| | | } else { |
| | | group.fields.forEach(f => { |
| | | if (f.field && ['select', 'link', 'text', 'number'].includes(f.type) && f.hidden !== 'true' && f.readonly !== 'true') { |
| | | fields.push(f) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | this.setState({ |
| | | fields: fields |
| | |
| | | render() { |
| | | const { group, dict } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { fields } = this.state |
| | | const { fields, appType } = this.state |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | {appType !== 'mob' ? <Col span={12}> |
| | | <Form.Item label="表单排列"> |
| | | {getFieldDecorator('align', { |
| | | initialValue: group.setting.align || 'left_right' |
| | |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | </Col> : null} |
| | | </Row> |
| | | </Form> |
| | | ) |
| | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | import { getModalForm } from '@/templates/zshare/formconfig' |
| | | import ModalForm from '@/templates/zshare/modalform' |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | 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 ModalForm = asyncComponent(() => import('@/templates/zshare/modalform')) |
| | | const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) |
| | | const WrapComponent = asyncIconComponent(() => import('@/menu/components/form/wrapsetting')) |
| | | const CardComponent = asyncComponent(() => import('@/templates/modalconfig/dragelement')) |
| | | const MobCardComponent = asyncComponent(() => import('@/mob/components/formdragelement')) |
| | | const FormTitle = asyncComponent(() => import('../dragtitle')) |
| | | const GroupForm = asyncComponent(() => import('./groupform')) |
| | | const FormAction = asyncComponent(() => import('../formaction')) |
| | |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | appType: sessionStorage.getItem('appType'), |
| | | card: null, |
| | | back: false, |
| | | group: null, |
| | |
| | | name: card.name, |
| | | subtype: card.subtype, |
| | | setting: { }, |
| | | wrap: { name: card.name, width: card.width || 24, datatype: 'static', color: '#1890ff' }, |
| | | wrap: { name: card.name, width: card.width || 24, datatype: 'static', groupLabel: 'show', color: '#1890ff' }, |
| | | style: { marginLeft: '0px', marginRight: '0px', marginTop: '8px', marginBottom: '8px' }, |
| | | columns: [], |
| | | scripts: [], |
| | |
| | | sort: 1, |
| | | style: {}, |
| | | fields: [], |
| | | prevButton: {label: '上一步', type: 'prev'}, |
| | | subButton: {label: '提交', type: 'submit', style: {backgroundColor: '#1890ff', color: '#ffffff', paddingLeft: '25px', paddingRight: '25px'}}, |
| | | prevButton: {label: '上一步', type: 'prev', enable: 'true'}, |
| | | subButton: {label: '提交', type: 'submit', enable: 'true', style: {backgroundColor: '#1890ff', color: '#ffffff', paddingLeft: '25px', paddingRight: '25px'}}, |
| | | nextButton: {label: '跳过', type: 'next', enable: 'false'} |
| | | }] |
| | | } |
| | |
| | | this.props.updateConfig(card) |
| | | } |
| | | |
| | | /** |
| | | * @description 单个卡片信息更新 |
| | | */ |
| | | deleteCard = (cell) => { |
| | | let card = fromJS(this.state.card).toJS() |
| | | let _this = this |
| | | |
| | | confirm({ |
| | | content: '确定删除表单吗?', |
| | | onOk() { |
| | | card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid) |
| | | |
| | | let uuids = [] |
| | | cell.elements && cell.elements.forEach(c => { |
| | | if (c.eleType === 'button') { |
| | | uuids.push(c.uuid) |
| | | } |
| | | }) |
| | | MKEmitter.emit('delButtons', uuids) |
| | | |
| | | _this.setState({card}) |
| | | _this.props.updateConfig(card) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } |
| | | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | |
| | | sort: card.subcards.length + 1, |
| | | style: {}, |
| | | fields: [], |
| | | prevButton: {label: '上一步', type: 'prev'}, |
| | | subButton: {label: '提交', type: 'submit', style: {backgroundColor: '#1890ff', color: '#ffffff', paddingLeft: '25px', paddingRight: '25px'}}, |
| | | prevButton: {label: '上一步', type: 'prev', enable: 'true'}, |
| | | subButton: {label: '提交', type: 'submit', enable: 'true', style: {backgroundColor: '#1890ff', color: '#ffffff', paddingLeft: '25px', paddingRight: '25px'}}, |
| | | nextButton: {label: '跳过', type: 'next', enable: 'false'} |
| | | } |
| | | |
| | |
| | | }) |
| | | } |
| | | |
| | | handleList = (list) => { |
| | | handleList = (list, newcard) => { |
| | | let group = fromJS(this.state.group).toJS() |
| | | let card = fromJS(this.state.card).toJS() |
| | | |
| | |
| | | return item |
| | | }) |
| | | |
| | | this.setState({card, group}) |
| | | this.setState({card, group}, () => { |
| | | if (newcard) { |
| | | this.handleForm(newcard) |
| | | } |
| | | }) |
| | | this.props.updateConfig(card) |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | addForm = () => { |
| | | const { appType } = this.state |
| | | let group = fromJS(this.state.group).toJS() |
| | | let lastItem = group.fields[group.fields.length - 1] |
| | | let span = lastItem ? lastItem.span : 12 |
| | | let span = appType === 'mob' ? 24 : 12 |
| | | if (lastItem && lastItem.span) { |
| | | span = lastItem.span |
| | | } |
| | | |
| | | let newcard = { |
| | | uuid: Utils.getuuid(), |
| | |
| | | group.fields = group.fields.filter(item => !item.focus) |
| | | |
| | | this.setState({group, visible: false, editform: null}) |
| | | this.updateGroup(group) |
| | | } |
| | | |
| | | /** |
| | | * @description 表单编辑 |
| | | */ |
| | | handleForm = (_item) => { |
| | | const { card, group } = this.state |
| | | const { card, group, appType } = this.state |
| | | let _form = fromJS(_item).toJS() |
| | | let _inputfields = [] |
| | | let _tabfields = [] |
| | |
| | | let standardform = null |
| | | |
| | | _inputfields = group.fields.filter(item => item.type === 'text' || item.type === 'number' || item.type === 'textarea' || item.type === 'color') |
| | | _tabfields = group.fields.filter(item => _form.field !== item.field && item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) |
| | | if (appType === 'mob') { |
| | | _tabfields = group.fields.filter(item => _form.field !== item.field && item.hidden !== 'true' && ['text', 'number'].includes(item.type)) |
| | | } else { |
| | | _tabfields = group.fields.filter(item => _form.field !== item.field && item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) |
| | | } |
| | | _tabfields.unshift({field: '', text: '原表单'}) |
| | | |
| | | let uniq = new Map() |
| | |
| | | if (_form.uuid === item.uuid) { |
| | | index = i |
| | | } |
| | | if (item.type !== 'select' && item.type !== 'link' && item.type !== 'radio') return |
| | | |
| | | if (!['select', 'link', 'radio', 'checkcard'].includes(item.type)) return |
| | | if (item.field && !uniq.has(item.field)) { |
| | | uniq.set(item.field, true) |
| | | |
| | |
| | | _form.linkSubField = _form.linkSubField.filter(item => fields.includes(item)) |
| | | } |
| | | |
| | | if (!_form.span && standardform && standardform.span) { |
| | | if (appType !== 'mob' && !_form.span && standardform && standardform.span) { |
| | | _form.span = standardform.span |
| | | _form.labelwidth = standardform.labelwidth |
| | | } |
| | |
| | | return |
| | | } |
| | | |
| | | if ((res.type === 'select' || res.type === 'multiselect' || res.type === 'link') && res.resourceType === '1' && /\s/.test(res.dataSource)) { |
| | | if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) { |
| | | this.setState({ |
| | | sqlVerifing: true |
| | | }) |
| | |
| | | }) |
| | | } |
| | | |
| | | pasteForm = (res) => { |
| | | let _config = fromJS(this.state.group).toJS() |
| | | let fieldrepet = false // 字段重复 |
| | | let labelrepet = false // 提示文字重复 |
| | | |
| | | _config.fields.forEach(item => { |
| | | if (res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) { |
| | | fieldrepet = true |
| | | } else if (res.label && item.label === res.label) { |
| | | labelrepet = true |
| | | } |
| | | }) |
| | | |
| | | if (fieldrepet) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '字段已存在!', |
| | | duration: 10 |
| | | }) |
| | | return |
| | | } else if (labelrepet) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '名称已存在!', |
| | | duration: 10 |
| | | }) |
| | | return |
| | | } |
| | | _config.fields.push(res) |
| | | |
| | | this.updateGroup(_config) |
| | | |
| | | this.handleForm(res) |
| | | |
| | | notification.success({ |
| | | top: 92, |
| | | message: '粘贴成功!', |
| | | duration: 2 |
| | | }) |
| | | } |
| | | |
| | | clickComponent = (e) => { |
| | | if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { |
| | | e.stopPropagation() |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { card, dict, group } = this.state |
| | | const { card, dict, group, appType } = this.state |
| | | |
| | | return ( |
| | | <div className="menu-normal-form-edit-box" style={{...card.style}} onClick={this.clickComponent} id={card.uuid}> |
| | | <div className="menu-normal-form-edit-box" style={resetStyle(card.style)} onClick={this.clickComponent} id={card.uuid}> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <Icon className="plus" title="添加分组" onClick={this.addCard} type="plus" /> |
| | | <WrapComponent config={card} updateConfig={this.updateComponent} /> |
| | | <CopyComponent type="propcard" card={card}/> |
| | | <PasteComponent config={card} options={['cardcell']} updateConfig={this.updateComponent} /> |
| | | <PasteComponent config={card} options={['form']} updateConfig={this.pasteForm} /> |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | | <UserComponent config={card}/> |
| | | <Icon className="close" title="删除组件" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> |
| | |
| | | <Icon className="plus" title="添加表单" onClick={this.addForm} type="plus" /> |
| | | <FieldsComponent config={group} type="form" updatefield={this.updateGroup} /> |
| | | <Switch checkedChildren={dict['model.switch.open']} unCheckedChildren={dict['model.switch.close']} defaultChecked={this.state.showField} onChange={(val) => this.setState({showField: val})} /> |
| | | <Button className="mk-cols-change" onClick={() => this.changecols(1)}>1列</Button> |
| | | <Button className="mk-cols-change" onClick={() => this.changecols(2)}>2列</Button> |
| | | <Button className="mk-cols-change" onClick={() => this.changecols(3)}>3列</Button> |
| | | <Button className="mk-cols-change" onClick={() => this.changecols(4)}>4列</Button> |
| | | {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(1)}>1列</Button> : null} |
| | | {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(2)}>2列</Button> : null} |
| | | {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(3)}>3列</Button> : null} |
| | | {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(4)}>4列</Button> : null} |
| | | <div style={{clear: 'both'}}></div> |
| | | <CardComponent |
| | | {appType !== 'mob' ? <CardComponent |
| | | list={group.fields} |
| | | setting={group.setting} |
| | | showField={this.state.showField} |
| | |
| | | handleList={this.handleList} |
| | | handleForm={this.handleForm} |
| | | closeForm={this.closeForm} |
| | | /> |
| | | /> : <MobCardComponent |
| | | list={group.fields} |
| | | setting={group.setting} |
| | | showField={this.state.showField} |
| | | handleList={this.handleList} |
| | | handleForm={this.handleForm} |
| | | closeForm={this.closeForm} |
| | | />} |
| | | <FormAction config={card} group={group} updateconfig={this.updateGroup}/> |
| | | </div> : null} |
| | | <Modal |
| | |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="加载时是否显示分组名称。"> |
| | | <Icon type="question-circle" /> |
| | | 分组名称 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('groupLabel', { |
| | | initialValue: wrap.groupLabel || 'show' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="show">显示</Radio> |
| | | <Radio value="hidden">隐藏</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="完成后的颜色"> |
| | | <Icon type="question-circle" /> |
| | | 颜色控制 |
| | |
| | | width: 100%; |
| | | } |
| | | .color-sketch-block { |
| | | margin-top: 6px; |
| | | position: relative; |
| | | top: 6px; |
| | | } |
| | | } |
| | |
| | | const DataCard = asyncComponent(() => import('@/menu/components/card/data-card')) |
| | | const PropCard = asyncComponent(() => import('@/menu/components/card/prop-card')) |
| | | const TableCard = asyncComponent(() => import('@/menu/components/card/table-card')) |
| | | const NormalTree = asyncComponent(() => import('@/menu/components/tree/antd-tree')) |
| | | const NormalTable = asyncComponent(() => import('@/menu/components/table/normal-table')) |
| | | const BraftEditor = asyncComponent(() => import('@/menu/components/editor/braft-editor')) |
| | | const AntvScatter = asyncComponent(() => import('@/menu/components/chart/antv-scatter')) |
| | | const NormalForm = asyncComponent(() => import('@/menu/components/form/normal-form')) |
| | | const AntvDashboard = asyncComponent(() => import('@/menu/components/chart/antv-dashboard')) |
| | | const CarouselDataCard = asyncComponent(() => import('@/menu/components/carousel/data-card')) |
| | | const CarouselPropCard = asyncComponent(() => import('@/menu/components/carousel/prop-card')) |
| | | const CodeSandbox = asyncComponent(() => import('@/menu/components/code/sandbox')) |
| | | |
| | | const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => { |
| | | const originalIndex = findCard(id).index |
| | |
| | | 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 === 'tree') { |
| | | return (<NormalTree card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'scatter') { |
| | | return (<AntvScatter card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'form') { |
| | | return (<NormalForm 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') { |
| | |
| | | return (<TableCard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'table' && card.subtype === 'normaltable') { |
| | | return (<NormalTable card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'carousel' && card.subtype === 'datacard') { |
| | | return (<CarouselDataCard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'carousel' && card.subtype === 'propcard') { |
| | | return (<CarouselPropCard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'editor') { |
| | | return (<BraftEditor card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'code') { |
| | | return (<CodeSandbox card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | import Utils from '@/utils/utils.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import MenuUtils from '@/utils/utils-custom.js' |
| | | import Card from './card' |
| | | import './index.scss' |
| | | |
| | |
| | | const deleteCard = (id) => { |
| | | const { card } = findCard(id) |
| | | |
| | | let uuids = [] |
| | | if (card.action && card.action.length) { |
| | | card.action.forEach(act => { |
| | | if (!act.origin) { |
| | | uuids.push(act.uuid) |
| | | } |
| | | }) |
| | | } |
| | | if (card.type === 'card') { |
| | | card.subcards.forEach(_card => { |
| | | _card.elements && _card.elements.forEach(cell => { |
| | | if (cell.eleType === 'button') { |
| | | uuids.push(cell.uuid) |
| | | } |
| | | }) |
| | | _card.backElements && _card.backElements.forEach(cell => { |
| | | if (cell.eleType === 'button') { |
| | | uuids.push(cell.uuid) |
| | | } |
| | | }) |
| | | }) |
| | | } else if (card.type === 'table' && card.subtype === 'tablecard') { |
| | | card.subcards.forEach(_card => { |
| | | _card.elements && _card.elements.forEach(cell => { |
| | | if (cell.eleType === 'button') { |
| | | uuids.push(cell.uuid) |
| | | } |
| | | }) |
| | | }) |
| | | } else if (card.type === 'table' && card.subtype === 'normaltable') { |
| | | card.cols && card.cols.forEach(col => { |
| | | if (col.type !== 'action') return |
| | | col.elements && col.elements.forEach(cell => { |
| | | uuids.push(cell.uuid) |
| | | }) |
| | | }) |
| | | } |
| | | let uuids = MenuUtils.getDelButtonIds(card) |
| | | |
| | | confirm({ |
| | | title: `确定删除《${card.name}》吗?`, |
| | | onOk() { |
| | | MKEmitter.emit('delButtons', uuids) |
| | | handleList({...config, components: cards.filter(item => item.uuid !== card.uuid)}) |
| | | |
| | | if (uuids.length === 0) return |
| | | |
| | | MKEmitter.emit('delButtons', uuids) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | |
| | | |
| | | let name = '' |
| | | let names = { |
| | | bar: '柱状图', |
| | | bbar: '柱状图', |
| | | line: '折线图', |
| | | tabs: '标签组', |
| | | pie: '饼图', |
| | | search: '搜索', |
| | | table: '表格', |
| | | group: '分组', |
| | | editor: '富文本', |
| | | code: '自定义', |
| | | carousel: '轮播', |
| | | form: '表单', |
| | | dashboard: '仪表盘', |
| | | scatter: '散点图', |
| | | tree: '树形列表', |
| | | card: '卡片' |
| | | } |
| | | let i = 1 |
| | |
| | | .group-shell-inner { |
| | | margin: -8px; |
| | | margin: 0px; |
| | | |
| | | >.ant-col { |
| | | padding: 8px; |
| | | } |
| | | .anticon { |
| | | cursor: unset; |
| | | } |
| | |
| | | |
| | | state = { |
| | | roleList: [], |
| | | appType: sessionStorage.getItem('appType'), |
| | | print: this.props.setting.print || 'false' |
| | | } |
| | | |
| | |
| | | render() { |
| | | const { setting, dict } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { roleList, print } = this.state |
| | | const { roleList, print, appType } = this.state |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | |
| | | })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit}/>)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | {appType !== 'mob' ? <Col span={12}> |
| | | <Form.Item label="打印按钮"> |
| | | {getFieldDecorator('print', { |
| | | initialValue: print |
| | |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {print === 'true' ? <Col span={12}> |
| | | </Col> : null} |
| | | {print === 'true' && appType !== 'mob' ? <Col span={12}> |
| | | <Form.Item label="打印尺寸"> |
| | | {getFieldDecorator('pageSize', { |
| | | initialValue: setting.pageSize || 'A4', |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {print === 'true' ? <Col span={12}> |
| | | {print === 'true' && appType !== 'mob' ? <Col span={12}> |
| | | <Form.Item label="打印布局"> |
| | | {getFieldDecorator('pageLayout', { |
| | | initialValue: setting.pageLayout || 'vertical', |
| | |
| | | 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' |
| | |
| | | |
| | | render() { |
| | | const { group } = this.state |
| | | let _style = resetStyle(group.style) |
| | | |
| | | let paddingTop = true |
| | | if (group.style.paddingTop && parseInt(group.style.paddingTop) >= 28) { |
| | | paddingTop = false |
| | | } |
| | | |
| | | return ( |
| | | <div className="menu-group-edit-box" style={group.style} onClick={this.clickComponent} id={group.uuid}> |
| | | <div className={'menu-group-edit-box' + (paddingTop ? ' padding' : '')} style={_style} onClick={this.clickComponent} id={group.uuid}> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <SettingComponent config={group} updateConfig={this.updateComponent} /> |
| | |
| | | color: #bcbcbc; |
| | | } |
| | | } |
| | | .menu-group-edit-box::before { |
| | | .menu-group-edit-box.padding:before { |
| | | content: ' '; |
| | | display: block; |
| | | float: right; |
| | |
| | | import { Icon, Select, DatePicker, Input, Popover, Form } from 'antd' |
| | | import moment from 'moment' |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import DateGroup from '../dategroup' |
| | | import './index.scss' |
| | | |
| | | const { MonthPicker, WeekPicker, RangePicker } = DatePicker |
| | | const { Search } = Input |
| | | const CheckCard = asyncComponent(() => import('@/templates/modalconfig/checkCard')) |
| | | const appType = sessionStorage.getItem('appType') |
| | | |
| | | const Card = ({ id, card, moveCard, copyCard, findCard, editCard, delCard }) => { |
| | | const Card = ({ id, card, showField, moveCard, copyCard, findCard, editCard, delCard }) => { |
| | | const originalIndex = findCard(id).index |
| | | const [{ isDragging }, drag] = useDrag({ |
| | | item: { type: 'search', id, originalIndex }, |
| | |
| | | } |
| | | } |
| | | |
| | | let formItem = null |
| | | if (card.type === 'text') { |
| | | if (card.inputType === 'search') { |
| | | formItem = (<Search style={{marginTop: '4px'}} placeholder={card.labelShow === 'false' ? card.label : ''} value={card.initval} enterButton />) |
| | | } else { |
| | | formItem = (<Input style={{marginTop: '4px'}} placeholder={card.labelShow === 'false' ? card.label : ''} value={card.initval} />) |
| | | } |
| | | } else if (card.type === 'multiselect' || card.type === 'select' || card.type === 'link') { |
| | | formItem = (<Select value={_defaultValue}></Select>) |
| | | } else if (card.type === 'date' && appType === 'mob') { |
| | | formItem = (<div className="mob-list-item">{card.initval ? moment().subtract(card.initval, 'days').format('YYYY-MM-DD') : '请选择'}<Icon type="right" /></div>) |
| | | } else if (card.type === 'datemonth' && appType === 'mob') { |
| | | formItem = (<div className="mob-list-item">{card.initval ? moment().subtract(card.initval, 'month').format('YYYY-MM') : '请选择'}<Icon type="right" /></div>) |
| | | } else if (card.type === 'date') { |
| | | formItem = (<Input style={{marginTop: '4px'}} placeholder={card.labelShow === 'false' ? card.label : ''} value={card.initval} />) |
| | | } else if (card.type === 'dateweek') { |
| | | formItem = (<WeekPicker value={card.initval ? moment().subtract(card.initval * 7, 'days') : null} />) |
| | | } else if (card.type === 'datemonth') { |
| | | formItem = (<MonthPicker value={card.initval ? moment().subtract(card.initval, 'month') : null} />) |
| | | } else if (card.type === 'daterange') { |
| | | formItem = (<RangePicker |
| | | className="data-range" |
| | | placeholder={['BeginTime', 'EndTime']} |
| | | renderExtraFooter={() => 'extra footer'} |
| | | value={_defaultValue} |
| | | />) |
| | | } else if (card.type === 'group') { |
| | | formItem = (<DateGroup card={card} />) |
| | | } else if (card.type === 'checkcard') { |
| | | formItem = <CheckCard config={card} /> |
| | | } |
| | | |
| | | return ( |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | |
| | | <Icon className="close" title="delete" type="close" onClick={() => delCard(id)} /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <div className={'page-card ' + card.labelShow} style={{ opacity: opacity}}> |
| | | <div className={'page-card ' + card.labelShow + ' ' + card.type} style={{ opacity: opacity}}> |
| | | <div ref={node => drag(drop(node))}> |
| | | <Form.Item |
| | | labelCol={{xs: { span: 24 }, sm: { span: 8 }}} |
| | | wrapperCol = {{xs: { span: 24 }, sm: { span: 16 }}} |
| | | label={card.labelShow !== 'false' ? card.label : ''} |
| | | required={card.required === 'true'} |
| | | help={showField ? card.field + (card.datefield ? ', ' + card.datefield : '') : ''} |
| | | > |
| | | {card.type === 'text' ? |
| | | <Input style={{marginTop: '4px'}} placeholder={card.labelShow === 'false' ? card.label : ''} value={card.initval} /> : null |
| | | } |
| | | {(card.type === 'multiselect' || card.type === 'select' || card.type === 'link') ? |
| | | <Select value={_defaultValue}></Select> : null |
| | | } |
| | | {card.type === 'date' ? |
| | | <DatePicker value={card.initval ? moment().subtract(card.initval, 'days') : null} /> : null |
| | | } |
| | | {card.type === 'dateweek' ? |
| | | <WeekPicker value={card.initval ? moment().subtract(card.initval * 7, 'days') : null} /> : null |
| | | } |
| | | {card.type === 'datemonth' ? |
| | | <MonthPicker value={card.initval ? moment().subtract(card.initval, 'month') : null} /> : null |
| | | } |
| | | {card.type === 'daterange' ? |
| | | <RangePicker |
| | | className="data-range" |
| | | placeholder={['BeginTime', 'EndTime']} |
| | | renderExtraFooter={() => 'extra footer'} |
| | | value={_defaultValue} |
| | | /> : null |
| | | } |
| | | {card.type === 'group' ? <DateGroup card={card} /> : null } |
| | | {formItem} |
| | | </Form.Item> |
| | | </div> |
| | | </div> |
| | |
| | | import Card from './card' |
| | | import './index.scss' |
| | | |
| | | const Container = ({list, placeholder, handleList, handleMenu, deleteMenu }) => { |
| | | const Container = ({list, showField, placeholder, handleList, handleMenu, deleteMenu }) => { |
| | | const [cards, setCards] = useState(list) |
| | | const moveCard = (id, atIndex) => { |
| | | const { card, index } = findCard(id) |
| | |
| | | drop() {} |
| | | }) |
| | | |
| | | const appType = sessionStorage.getItem('appType') |
| | | |
| | | return ( |
| | | <div ref={drop} className="ant-row"> |
| | | {cards.length > 0 ? <Col key="preaction" className="action pre-action" span={6}> |
| | | <div className="ant-row ant-form-item" style={{lineHeight: '40px', height: '55px', marginBottom: 0}}> |
| | | <div className="ant-col ant-form-item-label ant-col-xs-24 ant-col-sm-8"> |
| | | </div> |
| | | <div className="ant-col ant-form-item-control-wrapper ant-col-xs-24 ant-col-sm-16"> |
| | | <Button type="primary">搜索</Button> |
| | | {appType !== 'mob' ? <Button style={{ marginLeft: 8 }}>重置</Button> : null} |
| | | <div style={{position: 'absolute', top: 0, bottom: 0, left: 0, right: 0}}></div> |
| | | </div> |
| | | </div> |
| | | </Col> : null} |
| | | {cards.map(card => ( |
| | | <Col key={card.uuid} span={card.ratio || 6}> |
| | | <Card |
| | | id={`${card.uuid}`} |
| | | card={card} |
| | | showField={showField} |
| | | moveCard={moveCard} |
| | | copyCard={copyCard} |
| | | editCard={editCard} |
| | |
| | | /> |
| | | </Col> |
| | | ))} |
| | | {cards.length > 0 ? <Col key="action" className="action" span={6}> |
| | | {cards.length > 0 ? <Col key="nextaction" className="action next-action" span={6}> |
| | | <div className="ant-row ant-form-item" style={{lineHeight: '40px', height: '55px', marginBottom: 0}}> |
| | | <div className="ant-col ant-form-item-label ant-col-xs-24 ant-col-sm-8"> |
| | | </div> |
| | | <div className="ant-col ant-form-item-control-wrapper ant-col-xs-24 ant-col-sm-16"> |
| | | <Button type="primary">搜索</Button> |
| | | <Button style={{ marginLeft: 8 }}>重置</Button> |
| | | {appType !== 'mob' ? <Button style={{ marginLeft: 8 }}>重置</Button> : null} |
| | | <div style={{position: 'absolute', top: 0, bottom: 0, left: 0, right: 0}}></div> |
| | | </div> |
| | | </div> |
| | |
| | | import React, { Component } from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Modal, notification, Popover, Icon } from 'antd' |
| | | import { Modal, notification, Popover, Icon, Switch } from 'antd' |
| | | import moment from 'moment' |
| | | |
| | | import Api from '@/api' |
| | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import { getSearchForm } from '@/templates/zshare/formconfig' |
| | | |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | import SearchForm from '@/templates/sharecomponent/searchcomponent/searchform' |
| | | import DragElement from './dragsearch' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import './index.scss' |
| | |
| | | const { confirm } = Modal |
| | | |
| | | const WrapComponent = asyncIconComponent(() => import('./wrapsetting')) |
| | | const SearchForm = asyncIconComponent(() => import('@/templates/sharecomponent/searchcomponent/searchform')) |
| | | const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) |
| | | const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent')) |
| | | |
| | |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | appType: sessionStorage.getItem('appType'), |
| | | searchlist: null, // 搜索条件集 |
| | | sqlVerifing: false, // sql验证中 |
| | | visible: false, // 模态框控制 |
| | | showField: false, |
| | | editcard: null // 编辑中元素 |
| | | } |
| | | |
| | |
| | | width: 24, |
| | | name: card.name, |
| | | subtype: card.subtype, |
| | | wrap: { name: card.name, width: 24, show: 'true', float: 'left' }, |
| | | wrap: { name: card.name, width: 24, show: this.state.appType === 'mob' ? 'false' : 'true', float: 'left' }, |
| | | style: { |
| | | marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' |
| | | }, |
| | |
| | | component.name = component.wrap.name |
| | | |
| | | this.props.updateConfig(component) |
| | | } |
| | | |
| | | checkComponent = (component) => { |
| | | this.updateComponent(component) |
| | | |
| | | let _item = null |
| | | component.search.forEach(item => { |
| | | if (!_item && item.focus) { |
| | | _item = item |
| | | } |
| | | }) |
| | | if (_item) { |
| | | this.handleSearch(_item) |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | return |
| | | } |
| | | |
| | | if (['select', 'multiselect', 'link'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) { |
| | | if (['select', 'multiselect', 'link', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) { |
| | | this.setState({ |
| | | sqlVerifing: true |
| | | }) |
| | |
| | | }) |
| | | } |
| | | |
| | | onFieldChange = () => { |
| | | const { showField } = this.state |
| | | |
| | | this.setState({ |
| | | showField: !showField |
| | | }) |
| | | } |
| | | |
| | | clickComponent = (e) => { |
| | | if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { |
| | | e.stopPropagation() |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { dict, card, visible, sqlVerifing } = this.state |
| | | const { dict, card, visible, sqlVerifing, showField } = this.state |
| | | let _style = resetStyle(card.style) |
| | | |
| | | return ( |
| | | <div className={`main-search-edit-list ${card.wrap.float} ${card.wrap.show || ''}`} onClick={this.clickComponent} id={card.uuid} style={card.style}> |
| | | <div className={`main-search-edit-list ${card.wrap.float} ${card.wrap.show || ''}`} onClick={this.clickComponent} id={card.uuid} style={_style}> |
| | | <Switch checkedChildren={dict['model.switch.open']} size="small" unCheckedChildren={dict['model.switch.close']} defaultChecked={showField} onChange={this.onFieldChange} /> |
| | | <DragElement |
| | | list={card.search} |
| | | showField={showField} |
| | | handleList={this.handleList} |
| | | handleMenu={this.handleSearch} |
| | | deleteMenu={this.deleteElement} |
| | |
| | | <Icon className="plus" title="添加" onClick={this.addSearch} type="plus" /> |
| | | <WrapComponent config={card} updateConfig={this.updateComponent}/> |
| | | <CopyComponent type="mainsearch" card={card}/> |
| | | <PasteComponent config={card} options={['search', 'form']} updateConfig={this.updateComponent} /> |
| | | <PasteComponent config={card} options={['search', 'form']} updateConfig={this.checkComponent} /> |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | | <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> |
| | | </div> |
| | |
| | | min-height: 50px; |
| | | position: relative; |
| | | background: #ffffff; |
| | | padding-bottom: 15px; |
| | | |
| | | .ant-form-item-control { |
| | | line-height: 1.5; |
| | | } |
| | | >.ant-switch { |
| | | position: absolute; |
| | | z-index: 3; |
| | | right: 10px; |
| | | bottom: 5px; |
| | | } |
| | | >.anticon-tool { |
| | | position: absolute; |
| | | z-index: 3; |
| | |
| | | } |
| | | > .ant-row { |
| | | min-height: 65px; |
| | | > .ant-col { |
| | | padding: 0 12px!important; |
| | | } |
| | | } |
| | | .ant-row .ant-col-6 { |
| | | padding: 0 12px!important; |
| | | >.ant-row:not(.ant-form-item) { |
| | | > .ant-col { |
| | | display: inline-block; |
| | | float: none; |
| | | vertical-align: top; |
| | | } |
| | | } |
| | | .ant-row.ant-form-item .ant-col { |
| | | padding: 0; |
| | |
| | | min-width: 100px!important; |
| | | width: 100%; |
| | | } |
| | | .check-card-edit-box { |
| | | margin-top: 5px!important; |
| | | } |
| | | .mob-list-item { |
| | | text-align: right; |
| | | line-height: 40px; |
| | | white-space: nowrap; |
| | | padding-right: 5px; |
| | | i { |
| | | margin-left: 5px; |
| | | } |
| | | } |
| | | } |
| | | .main-search-edit-list:not(.right) { |
| | | .pre-action { |
| | | display: none!important; |
| | | } |
| | | } |
| | | .main-search-edit-list.right { |
| | | .next-action { |
| | | display: none!important; |
| | | } |
| | | >.ant-row { |
| | | >.ant-col { |
| | | float: right; |
| | | } |
| | | >.ant-col.action { |
| | | display: none; |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | state = { |
| | | float: this.props.wrap.float, |
| | | roleList: [] |
| | | roleList: [], |
| | | appType: sessionStorage.getItem('appType') |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | |
| | | render() { |
| | | const { wrap } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { float, roleList } = this.state |
| | | const { roleList, appType } = this.state |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | |
| | | })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit}/>)} |
| | | </Form.Item> |
| | | </Col> |
| | | {appType !== 'mob' ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="高级搜索弹窗的宽度,注:当宽度值小于100时表示占窗口的百分比,大于100时表示宽度的绝对值。"> |
| | | <Icon type="question-circle" /> |
| | | 高级搜索 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('advanceWidth', { |
| | | initialValue: wrap.advanceWidth || 1000 |
| | | })(<InputNumber min={10} max={3000} precision={0}/>)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="右对齐时,隐藏搜索按钮。"> |
| | |
| | | {getFieldDecorator('float', { |
| | | initialValue: wrap.float || 'left' |
| | | })( |
| | | <Radio.Group onChange={(e) => this.setState({float: e.target.value})}> |
| | | <Radio.Group> |
| | | <Radio value="left">左对齐</Radio> |
| | | <Radio value="right">右对齐</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {float !== 'right' ? <Col span={12}> |
| | | <Col span={12}> |
| | | <Form.Item label="搜索按钮"> |
| | | {getFieldDecorator('show', { |
| | | initialValue: wrap.show || 'true' |
| | |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label="黑名单"> |
| | | {getFieldDecorator('blacklist', { |
| | |
| | | import PropTypes from 'prop-types' |
| | | import { fromJS } from 'immutable' |
| | | import { Form, Row, Col, Input, Select, Icon, Radio, notification, Tooltip, InputNumber, Cascader } from 'antd' |
| | | import { btnIcons, btnCustomClasses, formRule } from '@/utils/option.js' |
| | | import { btnCustomClasses, formRule } from '@/utils/option.js' |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import './index.scss' |
| | | |
| | | const { TextArea } = Input |
| | | const MkIcon = asyncComponent(() => import('@/components/mkIcon')) |
| | | const actionTypeOptions = { |
| | | pop: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'icon', 'class', 'execSuccess', 'execError', 'resetPageIndex', 'syncComponent', 'width'], |
| | | prompt: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'icon', 'class', 'execSuccess', 'execError', 'resetPageIndex', 'syncComponent', 'width'], |
| | | exec: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'icon', 'class', 'execSuccess', 'execError', 'resetPageIndex', 'syncComponent', 'width'], |
| | | pop: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'icon', 'class', 'execSuccess', 'execError', 'resetPageIndex', 'syncComponent', 'width', 'openmenu', 'open'], |
| | | prompt: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'icon', 'class', 'execSuccess', 'execError', 'resetPageIndex', 'syncComponent', 'width', 'openmenu', 'open'], |
| | | exec: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'icon', 'class', 'execSuccess', 'execError', 'resetPageIndex', 'syncComponent', 'width', 'openmenu', 'open'], |
| | | excelIn: ['label', 'Ot', 'OpenType', 'intertype', 'show', 'icon', 'class', 'sheet', 'execSuccess', 'execError', 'resetPageIndex', 'syncComponent', 'width'], |
| | | excelOut: ['label', 'OpenType', 'intertype', 'show', 'icon', 'class', 'execSuccess', 'execError', 'syncComponent', 'resetPageIndex', 'pagination', 'search', 'width'], |
| | | popview: ['label', 'Ot', 'OpenType', 'show', 'icon', 'class', 'popClose', 'resetPageIndex', 'width'], |
| | |
| | | interType: null, // 接口类型:内部、外部 |
| | | funcType: null, // 功能类型 |
| | | procMode: null, // 参数方式 |
| | | pageTemplate: null, |
| | | Ot: null, |
| | | requireOptions: [{ |
| | | value: 'notRequired', |
| | | text: this.props.dict['header.form.notRequired'] |
| | |
| | | let _opentype = card.OpenType // 打开方式 |
| | | let _intertype = card.intertype || 'system' // 接口类型 |
| | | let _funcType = card.funcType || '' // 功能按钮默认类型 |
| | | let _procMode = card.procMode || 'system' // 参数请求方式 |
| | | let _procMode = card.procMode || 'system' |
| | | let _Ot = card.Ot || 'requiredSgl' |
| | | let _pageTemplate = card.pageTemplate || '' |
| | | |
| | | let _options = this.getOptions(_opentype, _intertype, _funcType, card.pageTemplate, _procMode) |
| | | let _options = this.getOptions(_opentype, _intertype, _funcType, _pageTemplate, _procMode, _Ot) |
| | | |
| | | this.setState({ |
| | | Ot: _Ot, |
| | | openType: _opentype, |
| | | interType: _intertype, |
| | | procMode: _procMode, |
| | | funcType: _funcType, |
| | | pageTemplate: _pageTemplate, |
| | | formlist: this.props.formlist.map(item => { |
| | | if (item.key === 'class') { |
| | | item.options = btnCustomClasses |
| | |
| | | } else if (item.key === 'intertype') { |
| | | let iscustom = ['pop', 'prompt', 'exec'].includes(_opentype) |
| | | item.options = this.state.interTypeOptions.filter(op => (iscustom || op.value !== 'custom')) |
| | | } else if (item.key === 'icon') { |
| | | item.options = btnIcons |
| | | } else if (item.key === 'Ot') { |
| | | if (type === 'card') { |
| | | item.options = this.state.requireOptions.filter(op => ['notRequired', 'requiredSgl'].includes(op.value)) |
| | | } else if (card.pageTemplate === 'pay') { // 行级按钮、支付按钮,只能选单行 |
| | | } else if (_pageTemplate === 'pay') { // 行级按钮、支付按钮,只能选单行 |
| | | item.options = this.state.requireOptions.filter(op => ['requiredSgl'].includes(op.value)) |
| | | } else if (['innerpage', 'tab', 'popview', 'excelIn'].includes(_opentype)) { |
| | | item.options = this.state.requireOptions.filter(op => ['notRequired', 'requiredSgl'].includes(op.value)) |
| | |
| | | }) |
| | | } |
| | | |
| | | getOptions = (_opentype, _intertype, _funcType, _pageTemplate, _procMode) => { |
| | | let _options = fromJS(actionTypeOptions[_opentype]).toJS() // 选项列表 |
| | | getOptions = (_opentype, _intertype, _funcType, _pageTemplate, _procMode, _Ot) => { |
| | | let _options = actionTypeOptions[_opentype] ? fromJS(actionTypeOptions[_opentype]).toJS() : [] // 选项列表 |
| | | |
| | | if (_opentype === 'innerpage') { // 新页面,可选模板(自定义时,可填入外部链接) |
| | | if (_pageTemplate === 'custom') { |
| | |
| | | } |
| | | } |
| | | |
| | | if (_Ot !== 'notRequired' && _opentype !== 'excelOut') { |
| | | _options.push('controlField', 'controlVal') |
| | | } |
| | | if (_Ot === 'requiredSgl' && ['pop', 'prompt', 'exec'].includes(_opentype)) { |
| | | _options.push('swipe') |
| | | } |
| | | |
| | | return _options |
| | | } |
| | | |
| | |
| | | */ |
| | | optionChange = (key, value) => { |
| | | const { card, type } = this.props |
| | | const { openType, procMode } = this.state |
| | | const { openType, procMode, Ot, pageTemplate } = this.state |
| | | |
| | | if (key === 'OpenType') { |
| | | let _options = this.getOptions(value, 'system', this.state.funcType, card.pageTemplate, 'system') |
| | | let _options = this.getOptions(value, 'system', this.state.funcType, '', 'system', Ot) |
| | | |
| | | let _fieldval = {} |
| | | |
| | | let _formlist = this.state.formlist.map(item => { |
| | | item.hidden = !_options.includes(item.key) |
| | | |
| | |
| | | item.options = this.state.insertUpdateOptions |
| | | } |
| | | _fieldval.sqlType = '' |
| | | } else if (item.key === 'pageTemplate') { |
| | | item.initVal = '' |
| | | } |
| | | |
| | | return item |
| | |
| | | openType: value, |
| | | intertype: 'system', |
| | | procMode: 'system', |
| | | pageTemplate: '', |
| | | formlist: _formlist |
| | | }, () => { |
| | | if (value === 'excelIn') { |
| | |
| | | this.props.form.setFieldsValue(_fieldval) |
| | | }) |
| | | } else if (key === 'funcType') { |
| | | let _options = this.getOptions(openType, this.state.interType, value, card.pageTemplate, procMode) |
| | | let _options = this.getOptions(openType, this.state.interType, value, pageTemplate, procMode, Ot) |
| | | let _fieldval = {} |
| | | |
| | | this.setState({ |
| | |
| | | }) |
| | | } else if (key === 'pageTemplate') { |
| | | let _fieldval = {} |
| | | let _options = this.getOptions(openType, this.state.interType, this.state.funcType, value, procMode) |
| | | let _options = this.getOptions(openType, this.state.interType, this.state.funcType, value, procMode, Ot) |
| | | |
| | | this.setState({ |
| | | pageTemplate: value, |
| | | formlist: this.state.formlist.map(item => { |
| | | item.hidden = !_options.includes(item.key) |
| | | |
| | |
| | | this.props.form.setFieldsValue(_fieldval) |
| | | }) |
| | | } else if (key === 'intertype') { |
| | | let _options = this.getOptions(openType, value, this.state.funcType, '', procMode) |
| | | let _options = this.getOptions(openType, value, this.state.funcType, pageTemplate, procMode, Ot) |
| | | |
| | | this.setState({ |
| | | interType: value, |
| | |
| | | }) |
| | | }) |
| | | } else if (key === 'procMode') { |
| | | let _options = this.getOptions(openType, this.state.interType, this.state.funcType, '', value) |
| | | let _options = this.getOptions(openType, this.state.interType, this.state.funcType, pageTemplate, value, Ot) |
| | | |
| | | this.setState({ |
| | | procMode: value, |
| | |
| | | if (item.key === 'innerFunc') { |
| | | item.required = true |
| | | } |
| | | return item |
| | | }) |
| | | }) |
| | | } else if (key === 'Ot') { |
| | | let _options = this.getOptions(openType, this.state.interType, this.state.funcType, pageTemplate, procMode, value) |
| | | |
| | | this.setState({ |
| | | Ot: value, |
| | | formlist: this.state.formlist.map(item => { |
| | | item.hidden = !_options.includes(item.key) |
| | | return item |
| | | }) |
| | | }) |
| | |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'select') { // 下拉搜索 |
| | | } else if (item.type === 'select') { |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.tooltip ? |
| | |
| | | })( |
| | | <Select |
| | | showSearch |
| | | filterOption={(input, option) => option.props.children[2].toLowerCase().indexOf(input.toLowerCase()) >= 0} |
| | | allowClear={item.allowClear === true} |
| | | filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} |
| | | onChange={(value) => {this.optionChange(item.key, value)}} |
| | | getPopupContainer={() => document.getElementById('winter')} |
| | | > |
| | | {item.options.map((option, index) => |
| | | <Select.Option id={`${index}`} title={option.text} key={`${index}`} value={option.value}> |
| | | {item.key === 'icon' && option.value && <Icon type={option.value} />} {option.text} |
| | | <Select.Option key={index} value={(option.value || option.field)}> |
| | | {(option.text || option.label)} |
| | | </Select.Option> |
| | | )} |
| | | </Select> |
| | |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'icon') { |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.label}> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal, |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: this.props.dict['form.required.select'] + item.label + '!' |
| | | } |
| | | ] |
| | | })( |
| | | <MkIcon allowClear/> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'mcascader') { |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | |
| | | if (!err) { |
| | | values.uuid = card.uuid |
| | | values.verify = card.verify || null |
| | | values.modal = card.modal || null |
| | | |
| | | if (values.show === 'icon' && !values.icon) { |
| | | notification.warning({ |
| | |
| | | import React from 'react' |
| | | import { useDrag, useDrop } from 'react-dnd' |
| | | import { Icon, Button, Popover } from 'antd' |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import './index.scss' |
| | | |
| | | const Card = ({ id, card, moveCard, findCard, editCard, delCard, copyCard, changeStyle, profileCard, doubleClickCard }) => { |
| | |
| | | } |
| | | |
| | | let btnElement = null |
| | | let _style = resetStyle(card.style) |
| | | if (card.show === 'icon') { |
| | | btnElement = ( |
| | | <Button |
| | | type="link" |
| | | icon={card.icon} |
| | | style={card.btnstyle} |
| | | style={_style} |
| | | onDoubleClick={() => doubleClickCard(id)} |
| | | >{card.icon ? '' : card.label}</Button> |
| | | ) |
| | |
| | | btnElement = ( |
| | | <Button |
| | | type="link" |
| | | style={card.btnstyle} |
| | | style={_style} |
| | | onDoubleClick={() => doubleClickCard(id)} |
| | | >{card.label}{card.icon ? <Icon type={card.icon}/> : null}</Button> |
| | | ) |
| | |
| | | btnElement = ( |
| | | <Button |
| | | icon={card.icon} |
| | | style={card.btnstyle} |
| | | style={_style} |
| | | onDoubleClick={() => doubleClickCard(id)} |
| | | > |
| | | {card.label} |
| | |
| | | * @param {*} usefulFields 存储过程可用的开始字段 |
| | | * @param {*} type 按钮类型,用于区分可选的打开方式 |
| | | */ |
| | | export function getActionForm (card, functip, setting, usefulFields, type, menulist = [], modules = []) { |
| | | export function getActionForm (card, functip, config, usefulFields, type, menulist = [], modules = []) { |
| | | let appType = sessionStorage.getItem('appType') |
| | | let setting = config.setting || {} |
| | | let columns = config.columns || [] |
| | | let appMenus = [] |
| | | let opentypes = [ |
| | | { |
| | |
| | | { value: 'pay', text: Formdict['model.pay'] }, |
| | | { value: 'custom', text: Formdict['header.form.custom'] } |
| | | ] |
| | | const isApp = sessionStorage.getItem('appType') === 'pc' |
| | | const isApp = ['pc', 'mob'].includes(appType) |
| | | |
| | | let funTypes = [ |
| | | { value: 'changeuser', text: Formdict['header.form.func.changeuser'] }, |
| | |
| | | ] |
| | | |
| | | if (isApp) { |
| | | opentypes = opentypes.filter(item => item.value !== 'tab') |
| | | pageTemps = [ |
| | | { value: 'page', text: '菜单' }, |
| | | // { value: 'page', text: '菜单' }, |
| | | { value: 'linkpage', text: '关联菜单' }, |
| | | { value: 'billprint', text: '单据打印' }, |
| | | { value: 'pay', text: Formdict['model.pay'] }, |
| | |
| | | } else { |
| | | appMenus = [] |
| | | } |
| | | |
| | | if (appType === 'mob') { |
| | | opentypes = opentypes.filter(item => ['pop', 'prompt', 'exec', 'innerpage'].includes(item.value)) |
| | | } else { |
| | | opentypes = opentypes.filter(item => item.value !== 'tab') |
| | | } |
| | | } |
| | | |
| | | if (type === 'chart') { |
| | | if (type === 'chart' && appType !== 'mob') { |
| | | opentypes = opentypes.filter(item => item.value === 'excelIn' || item.value === 'excelOut') |
| | | } |
| | | |
| | |
| | | type: 'radio', |
| | | key: 'funcType', |
| | | label: Formdict['header.form.funcType'], |
| | | initVal: card.funcType || (isApp ? 'changeuser' : ''), |
| | | initVal: card.funcType || '', |
| | | required: true, |
| | | options: funTypes |
| | | }, |
| | |
| | | options: pageTemps |
| | | }, |
| | | { |
| | | type: 'radio', |
| | | key: 'open', |
| | | label: '链接方式', |
| | | initVal: card.open || 'blank', |
| | | required: true, |
| | | forbid: !isApp, |
| | | options: [{ |
| | | value: 'blank', |
| | | text: '新窗口' |
| | | }, { |
| | | value: 'self', |
| | | text: '当前窗口' |
| | | }] |
| | | }, |
| | | { |
| | | type: 'select', |
| | | key: 'linkmenu', |
| | | label: '关联菜单', |
| | | initVal: card.linkmenu || '', |
| | | required: true, |
| | | options: appMenus |
| | | }, |
| | | { |
| | | type: 'select', |
| | | key: 'copyMenuId', |
| | | label: '复制菜单', |
| | | initVal: card.copyMenuId || '', |
| | | required: false, |
| | | forbid: !isApp, |
| | | options: appMenus |
| | | }, |
| | | { |
| | |
| | | type: 'radio', |
| | | key: 'show', |
| | | label: "显示为", |
| | | initVal: card.show || 'icon', |
| | | initVal: card.show || 'button', |
| | | required: true, |
| | | options: [{ |
| | | value: 'icon', |
| | | text: '图标' |
| | | }, { |
| | | value: 'button', |
| | | text: '按钮' |
| | | text: '图标+文字' |
| | | }, { |
| | | value: 'link', |
| | | text: '链接' |
| | | text: '文字+图标' |
| | | }] |
| | | }, |
| | | { |
| | | type: 'select', |
| | | type: 'radio', |
| | | key: 'swipe', |
| | | label: "滑动显示", |
| | | initVal: card.swipe || 'false', |
| | | required: false, |
| | | forbid: (type !== 'datacard' || appType !== 'mob'), |
| | | options: [{ |
| | | value: 'false', |
| | | text: '否' |
| | | }, { |
| | | value: 'left', |
| | | text: '左滑' |
| | | }, { |
| | | value: 'right', |
| | | text: '右滑' |
| | | }] |
| | | }, |
| | | { |
| | | type: 'icon', |
| | | key: 'icon', |
| | | label: Formdict['model.icon'], |
| | | initVal: card.icon, |
| | |
| | | key: 'class', |
| | | label: Formdict['model.form.color'], |
| | | initVal: card.class, |
| | | tooltip: '此颜色为按钮初始化颜色,可在样式调整中修改。', |
| | | required: false, |
| | | options: [] |
| | | }, |
| | |
| | | initVal: card.syncComponent || [], |
| | | required: false, |
| | | options: modules |
| | | }, |
| | | { |
| | | type: 'select', |
| | | key: 'controlField', |
| | | label: '控制字段', |
| | | tooltip: '禁用控制字段,可根据数据控制按钮是否禁用。', |
| | | initVal: card.controlField || '', |
| | | required: false, |
| | | allowClear: true, |
| | | options: columns |
| | | }, |
| | | { |
| | | type: 'text', |
| | | key: 'controlVal', |
| | | label: '控制值', |
| | | tooltip: '当选择控制字段,且字段值与控制值相等时,按钮会禁用,多个值用逗号分隔。', |
| | | initVal: card.controlVal || '', |
| | | required: false |
| | | }, |
| | | { |
| | | type: 'select', |
| | | key: 'openmenu', |
| | | label: '打开菜单', |
| | | tooltip: '执行成功后需要打开的菜单。', |
| | | initVal: card.openmenu || '', |
| | | forbid: appType !== 'pc' && appType !== 'mob', |
| | | required: false, |
| | | allowClear: true, |
| | | options: appMenus |
| | | }, |
| | | { |
| | | type: 'radio', |
| | | key: 'open', |
| | | label: '打开方式', |
| | | initVal: card.open || 'blank', |
| | | required: true, |
| | | forbid: appType !== 'pc', |
| | | options: [{ |
| | | value: 'blank', |
| | | text: '新窗口' |
| | | }, { |
| | | value: 'self', |
| | | text: '当前窗口' |
| | | }] |
| | | } |
| | | ] |
| | | |
| | |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | appType: sessionStorage.getItem('appType'), |
| | | card: null, // 编辑中元素 |
| | | formlist: null, // 表单信息 |
| | | actionlist: null, // 按钮组 |
| | |
| | | * @description 搜索条件初始化 |
| | | */ |
| | | UNSAFE_componentWillMount () { |
| | | const { config } = this.props |
| | | |
| | | let actionlist = fromJS(config.action).toJS() || [] |
| | | |
| | | this.setState({ |
| | | actionlist: fromJS(this.props.config.action).toJS() |
| | | actionlist: actionlist.map(item => { |
| | | if (item.btnstyle) { // 兼容 |
| | | item.style = item.style || {} |
| | | item.style = {...item.style, ...item.btnstyle} |
| | | delete item.btnstyle |
| | | } |
| | | |
| | | return item |
| | | }) |
| | | }) |
| | | } |
| | | |
| | |
| | | if (comIds[0] !== config.uuid || comIds[1] !== 'actionlist') return |
| | | |
| | | let _card = fromJS(card).toJS() |
| | | _card.btnstyle = style |
| | | _card.style = style |
| | | |
| | | let _actionlist = actionlist.map(cell => { |
| | | if (cell.uuid === _card.uuid) return _card |
| | |
| | | changeBtnStyle = (element) => { |
| | | const { config } = this.props |
| | | |
| | | let _style = element.btnstyle ? fromJS(element.btnstyle).toJS() : {} |
| | | let options = ['font', 'border', 'background', 'margin'] |
| | | let _style = element.style ? fromJS(element.style).toJS() : {} |
| | | let options = ['font', 'border', 'background', 'margin', 'padding'] |
| | | |
| | | this.setState({ |
| | | card: element |
| | |
| | | this.setState({ |
| | | visible: true, |
| | | card: card, |
| | | formlist: getActionForm(card, functip, config.setting, usefulFields, this.props.type, menulist, modules) |
| | | formlist: getActionForm(card, functip, config, usefulFields, this.props.type, menulist, modules) |
| | | }) |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | if (item.uuid === btn.uuid) { |
| | | btn.btnstyle = item.btnstyle || {} |
| | | btn.style = item.style || {} |
| | | |
| | | if (btn.class !== item.class || btn.show !== item.show || !btn.btnstyle.color) { |
| | | if (btn.class !== item.class || btn.show !== item.show || !btn.style.color) { |
| | | if (btn.show === 'link' || btn.show === 'icon') { |
| | | btn.btnstyle.color = color[btn.class] |
| | | btn.btnstyle.backgroundColor = 'transparent' |
| | | btn.style.color = color[btn.class] |
| | | btn.style.backgroundColor = 'transparent' |
| | | } else { |
| | | btn.btnstyle.color = '#ffffff' |
| | | btn.btnstyle.backgroundColor = color[btn.class] |
| | | btn.style.color = '#ffffff' |
| | | btn.style.backgroundColor = color[btn.class] |
| | | } |
| | | } |
| | | return btn |
| | |
| | | */ |
| | | deleteElement = (card) => { |
| | | const { config } = this.props |
| | | const { dict } = this.state |
| | | const { dict, appType } = this.state |
| | | let _this = this |
| | | |
| | | confirm({ |
| | |
| | | let _actionlist = fromJS(_this.state.actionlist).toJS() |
| | | |
| | | _actionlist = _actionlist.filter(item => item.uuid !== card.uuid) |
| | | |
| | | if (!card.origin) { |
| | | MKEmitter.emit('delButtons', [card.uuid]) |
| | | } |
| | | |
| | | let btnlog = config.btnlog || [] |
| | | if (card.OpenType === 'popview' || card.verify || card.modal) { |
| | |
| | | }, () => { |
| | | _this.props.updateaction({...config, action: _actionlist, btnlog}) |
| | | }) |
| | | |
| | | if (card.origin || appType === 'mob') return |
| | | if (appType === 'pc' && card.OpenType !== 'popview') return |
| | | |
| | | MKEmitter.emit('delButtons', [card.uuid]) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | |
| | | let _param = { |
| | | funcName: btn.innerFunc, |
| | | name: _config.setting.tableName || '', |
| | | fields: btn.fields, |
| | | fields: btn.modal ? btn.modal.fields : [], |
| | | menuNo: menu.MenuNo |
| | | } |
| | | newLText = Utils.formatOptions(FuncUtils.getfunc(_param, btn, menu, _config)) |
| | |
| | | * @description 按钮双击触发子配置 |
| | | */ |
| | | btnDoubleClick = (element) => { |
| | | if (sessionStorage.getItem('style-control') && sessionStorage.getItem('style-control') !== 'false') return |
| | | |
| | | if (sessionStorage.getItem('style-control') && sessionStorage.getItem('style-control') === 'true') return |
| | | |
| | | if (element.OpenType === 'pop' || element.OpenType === 'popview' || element.execMode === 'pop') { |
| | | this.props.setSubConfig(element) |
| | | } else if (element.OpenType === 'innerpage' && element.pageTemplate === 'page') { |
| | |
| | | } |
| | | button { |
| | | cursor: move; |
| | | height: auto; |
| | | min-height: 32px; |
| | | .anticon-table { |
| | | font-size: 10px; |
| | | position: absolute; |
| | | right: 1px; |
| | | bottom: 0px; |
| | | } |
| | | span { |
| | | font-style: inherit; |
| | | text-decoration: inherit; |
| | | font-weight: inherit; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | appType: sessionStorage.getItem('appType'), |
| | | visible: false, |
| | | data: [], |
| | | columns: [ |
| | |
| | | } |
| | | |
| | | revert = (item) => { |
| | | const { appType } = this.state |
| | | const data = this.state.data.filter(d => d.uuid !== item.uuid) |
| | | |
| | | this.setState({data}) |
| | | MKEmitter.emit('thawButtons', item.uuid) |
| | | this.props.handlelog('revert', data, item) |
| | | |
| | | if (appType === 'mob' || (appType === 'pc' && item.OpenType !== 'popview')) return |
| | | |
| | | MKEmitter.emit('thawButtons', item.uuid) |
| | | } |
| | | |
| | | handleDelete = (item) => { |
| | |
| | | import '@/assets/css/table.scss' |
| | | |
| | | const EditTable = asyncComponent(() => import('@/templates/zshare/editTable')) |
| | | const { confirm } = Modal |
| | | |
| | | class MarkColumn extends Component { |
| | | static propTpyes = { |
| | |
| | | resetMark = () => { |
| | | const { marks, columns, type } = this.props |
| | | let markColumns = fromJS(this.state.markColumns).toJS() |
| | | let _columns = fromJS(columns).toJS() |
| | | |
| | | let options = columns.map(col => { |
| | | _columns.unshift({field: '$Index', label: '序号'}) |
| | | |
| | | let options = _columns.map(col => { |
| | | return { |
| | | value: col.field, |
| | | label: col.label, |
| | |
| | | { |
| | | value: 'dynamic', |
| | | label: '动态值', |
| | | children: columns.map(cell => { |
| | | children: _columns.map(cell => { |
| | | return { |
| | | value: cell.field, |
| | | label: cell.label |
| | |
| | | } |
| | | ] |
| | | |
| | | if (type === 'line') { |
| | | if (type === 'line' || type === 'sequence') { |
| | | signs.pop() |
| | | } else if (type === 'slider') { |
| | | markColumns = markColumns.filter(col => { |
| | |
| | | } |
| | | |
| | | markSubmit = () => { |
| | | this.setState({ |
| | | visible: false |
| | | }) |
| | | let save = false |
| | | let input = document.getElementById('contrastValue') |
| | | let val = input && input.value ? input.value : '' |
| | | |
| | | if (!val) { |
| | | save = true |
| | | } |
| | | |
| | | let marks = this.state.marks.map(item => { |
| | | if (item.signType && item.signType[0] === 'background') { |
| | |
| | | item.fontColor = '' |
| | | } |
| | | } |
| | | if (val && item.contrastValue === val) { |
| | | save = true |
| | | } |
| | | return item |
| | | }) |
| | | |
| | | this.props.onSubmit(marks) |
| | | if (save) { |
| | | this.setState({ |
| | | visible: false |
| | | }) |
| | | this.props.onSubmit(marks) |
| | | } else { |
| | | const _this = this |
| | | confirm({ |
| | | title: '存在未保存标记,确定忽略吗?', |
| | | onOk() { |
| | | _this.setState({ visible: false }) |
| | | _this.props.onSubmit(marks) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } |
| | | } |
| | | |
| | | render() { |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import { Icon, Pagination } from 'antd-mobile' |
| | | |
| | | import './index.scss' |
| | | |
| | | class MobPagination extends Component { |
| | | render () { |
| | | return ( |
| | | <Pagination className="mob-pagination" total={5} |
| | | current={1} |
| | | locale={{ |
| | | prevText: (<span><Icon type="left" />上一页</span>), |
| | | nextText: (<span>下一页<Icon type="right" /></span>), |
| | | }} |
| | | /> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default MobPagination |
New file |
| | |
| | | .mob-pagination { |
| | | .am-button::before { |
| | | display: none; |
| | | } |
| | | .am-button { |
| | | border: none; |
| | | font-size: 16px; |
| | | background: transparent; |
| | | .am-icon { |
| | | position: relative; |
| | | top: 5px; |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import './index.scss' |
| | | |
| | | const SearchComponent = asyncComponent(() => import('@/menu/components/share/searchcomponent')) |
| | |
| | | hideSearch: PropTypes.any, // 隐藏搜索条件 |
| | | config: PropTypes.object, // 配置信息 |
| | | updateComponent: PropTypes.func // 配置更新 |
| | | } |
| | | |
| | | state = { |
| | | appType: sessionStorage.getItem('appType') |
| | | } |
| | | |
| | | componentDidMount () { |
| | |
| | | changeStyle = () => { |
| | | const { config } = this.props |
| | | |
| | | // MKEmitter.emit('changeStyle', [config.uuid, 'header'], ['font', 'height', 'border'], config.headerStyle) |
| | | MKEmitter.emit('changeStyle', [config.uuid, 'header'], ['font', 'border'], config.headerStyle) |
| | | } |
| | | |
| | | render() { |
| | | const { config, defaultshow, hideSearch } = this.props |
| | | const { appType } = this.state |
| | | |
| | | let title = config.plot ? config.plot.title : config.wrap.title |
| | | let show = true |
| | | |
| | | if (!title && appType === 'mob' && config.type === 'card' && config.subtype === 'datacard' && config.action && config.action.length) { |
| | | title = ' ' |
| | | } |
| | | |
| | | if (defaultshow === 'hidden') { |
| | | if (!title && (!config.search || config.search.length === 0)) { |
| | | show = false |
| | | } |
| | | } |
| | | let _style = resetStyle(config.headerStyle) |
| | | |
| | | return ( |
| | | <div className={'normal-header' + (!show ? ' hidden' : '')} style={config.headerStyle}> |
| | | <div className={'normal-header' + (!show ? ' hidden' : '') + (config.wrap && config.wrap.searchable === 'true' ? ' tree-search' : '')} style={_style}> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | |
| | | } trigger="hover"> |
| | | <span className="title">{title}</span> |
| | | </Popover> |
| | | {config.wrap && config.wrap.searchable === 'true' ? <span className="ant-input-search ant-input-affix-wrapper"><span className="ant-input-suffix"><Icon type="search" /></span></span> : null} |
| | | {hideSearch !== 'true' && config.search ? <SearchComponent config={config} updatesearch={this.props.updateComponent}/> : null} |
| | | </div> |
| | | ) |
| | |
| | | height: 45px; |
| | | border-bottom: 1px solid #e8e8e8; |
| | | overflow: hidden; |
| | | line-height: 45px; |
| | | |
| | | .title { |
| | | text-decoration: inherit; |
| | | font-weight: inherit; |
| | | font-style: inherit; |
| | | float: left; |
| | | line-height: 45px; |
| | | line-height: inherit; |
| | | margin-left: 10px; |
| | | position: relative; |
| | | z-index: 1; |
| | | min-height: 45px; |
| | | min-width: 30px; |
| | | } |
| | | .model-custom-header-search-list { |
| | | flex: 1; |
| | | } |
| | | .ant-input-search.ant-input-affix-wrapper { |
| | | width: calc(100% - 140px); |
| | | max-width: 130px; |
| | | margin-top: 8px; |
| | | margin-right: 25px; |
| | | float: right; |
| | | height: 28px; |
| | | border-radius: 20px; |
| | | border: 1px solid #d9d9d9; |
| | | opacity: 0.6; |
| | | } |
| | | } |
| | | .normal-header:not(.tree-search) { |
| | | display: flex; |
| | | } |
| | | .normal-header.hidden { |
| | | display: none; |
| | |
| | | this.setState({visible: true}) |
| | | } |
| | | |
| | | resetconfig = (item, copyBtns) => { |
| | | resetconfig = (item, copyBtns, config) => { |
| | | let _uuid = Utils.getuuid() |
| | | |
| | | if (item.OpenType === 'popview') { |
| | |
| | | item.uuid = _uuid |
| | | } |
| | | |
| | | if (item.copyType === 'cardcell') { |
| | | if (item.copyType === 'cardcell' && config.subtype === 'datacard') { |
| | | item.setting = item.setting || {} |
| | | item.$cardType = 'extendCard' |
| | | item.setting.width = item.setting.width || 6 |
| | | |
| | | if (item.elements) { |
| | | item.elements = item.elements.map(cell => { |
| | | if (cell.datatype === 'dynamic') { |
| | | cell.datatype = 'static' |
| | | } |
| | | cell.uuid = Utils.getuuid() |
| | | return cell |
| | | }) |
| | | } |
| | | if (item.backElements) { |
| | | item.backElements = item.backElements.map(cell => { |
| | | if (cell.datatype === 'dynamic') { |
| | | cell.datatype = 'static' |
| | | } |
| | | cell.uuid = Utils.getuuid() |
| | | return cell |
| | | }) |
| | | } |
| | | } else if (item.copyType === 'cardcell') { |
| | | item.setting = item.setting || {} |
| | | item.setting.width = item.setting.width || 6 |
| | | delete item.$cardType |
| | | |
| | | if (item.elements) { |
| | | item.elements = item.elements.map(cell => { |
| | |
| | | pasteSubmit = () => { |
| | | const { options } = this.props |
| | | this.pasteFormRef.handleConfirm().then(res => { |
| | | |
| | | if (!options.includes(res.copyType)) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '配置信息格式错误!', |
| | | duration: 5 |
| | | }) |
| | | notification.warning({ top: 92, message: '配置信息格式错误!', duration: 5 }) |
| | | return |
| | | } |
| | | |
| | |
| | | let config = fromJS(this.props.config).toJS() |
| | | let copyBtns = new Map() |
| | | |
| | | res = this.resetconfig(res, copyBtns) |
| | | res = this.resetconfig(res, copyBtns, config) |
| | | delete res.copyType |
| | | |
| | | copyBtns = [...copyBtns.values()] |
| | |
| | | MKEmitter.emit('copyButtons', copyBtns) |
| | | } |
| | | |
| | | if (type === 'action') { |
| | | if (config.type === 'form' && config.subtype === 'stepform') { |
| | | this.props.updateConfig(res) |
| | | this.setState({visible: false}) |
| | | return |
| | | } else if (type === 'action') { |
| | | config.action = config.action || [] |
| | | config.action = config.action.filter(item => !item.origin) |
| | | |
| | | if (['line', 'bar', 'scatter'].includes(config.type) && !['excelOut', 'excelIn'].includes(res.OpenType)) { |
| | | notification.warning({ top: 92, message: '图表中不支持此类按钮!', duration: 5 }) |
| | | return |
| | | } |
| | | MKEmitter.emit('addButton', config.uuid, res) |
| | | } else if (type === 'search' || type === 'form') { |
| | | config.search = config.search || [] |
| | |
| | | let keys = config.search.map(item => item.field.toLowerCase()) |
| | | |
| | | if (type === 'form') { |
| | | if (['number', 'switch', 'textarea', 'checkcard', 'fileupload', 'hint', 'color', 'funcvar'].includes(res.type)) { |
| | | if (['number', 'switch', 'textarea', 'fileupload', 'hint', 'color', 'funcvar'].includes(res.type)) { |
| | | res.type = 'text' |
| | | } else if (res.type === 'radio') { |
| | | res.type = 'select' |
| | |
| | | config.search.push(res) |
| | | } else if (type === 'cardcell') { |
| | | config.subcards.push(res) |
| | | } else if (type === 'menucell') { |
| | | config.subMenus.push(res) |
| | | } else if (type === 'cols') { |
| | | config.cols = config.cols.filter(col => !col.origin) |
| | | |
| | |
| | | import { Icon, Select, DatePicker, Input, Popover, Form } from 'antd' |
| | | import moment from 'moment' |
| | | |
| | | import DateGroup from '../dategroup' |
| | | import DateGroup from '@/menu/components/search/main-search/dategroup' |
| | | import './index.scss' |
| | | |
| | | const { MonthPicker, WeekPicker, RangePicker } = DatePicker |
| | |
| | | .common-drawarea-placeholder { |
| | | width: 100%; |
| | | line-height: 65px; |
| | | text-align: center; |
| | | color: #bcbcbc; |
| | | } |
| | |
| | | return |
| | | } |
| | | |
| | | if ((res.type === 'select' || res.type === 'multiselect' || res.type === 'link') && res.resourceType === '1' && /\s/.test(res.dataSource)) { |
| | | if (['select', 'multiselect', 'link', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) { |
| | | this.setState({ |
| | | sqlVerifing: true |
| | | }) |
| | |
| | | } |
| | | |
| | | state = { |
| | | url: this.props.value, |
| | | url: '', |
| | | visible: '' |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { value } = this.props |
| | | let val = '' |
| | | |
| | | if (value) { |
| | | val = value |
| | | } else if (this.props['data-__meta']) { |
| | | val = this.props['data-__meta'].initialValue || '' |
| | | } |
| | | |
| | | this.setState({ |
| | | url: val, |
| | | }) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | |
| | | width={visible !== 'system' ? 600 : 1000} |
| | | closable={false} |
| | | maskClosable={false} |
| | | okText="确定" |
| | | cancelText="取消" |
| | | onOk={this.popSubmit} |
| | | onCancel={() => {this.setState({visible: ''})}} |
| | | destroyOnClose |
| | |
| | | originlist: [], |
| | | list: [], |
| | | pagelist: [], |
| | | fileList: [], |
| | | searchKey: '', |
| | | pageSize: 12, |
| | | pageIndex: 1, |
| | |
| | | let list = originlist |
| | | let pagelist = list.filter((item, index) => index < this.state.pageSize) |
| | | |
| | | this.setState({originlist, list, url: '', searchKey: '', pageIndex: 1, fileList: [], pagelist}) |
| | | this.setState({originlist, list, url: '', searchKey: '', pageIndex: 1, pagelist}) |
| | | } |
| | | |
| | | changeSearch = () => { |
| | |
| | | this.setState({pageIndex: page, pagelist}) |
| | | } |
| | | |
| | | changeFile = (vals) => { |
| | | this.setState({fileList: vals}) |
| | | |
| | | if (vals && vals[0] && vals[0].status === 'done' && vals[0].response) { |
| | | this.setState({url: vals[0].response}) |
| | | } |
| | | changeFile = (val) => { |
| | | this.setState({url: val}) |
| | | } |
| | | |
| | | selectItem = (item) => { |
| | |
| | | |
| | | render () { |
| | | const { type, keyword } = this.props |
| | | const { list, url, pagelist, fileList, searchKey, pageIndex, pageSize, selectId, editvisible, card } = this.state |
| | | const { list, url, pagelist, searchKey, pageIndex, pageSize, selectId, editvisible, card } = this.state |
| | | |
| | | return ( |
| | | <div className="mk-source-pop-wrap"> |
| | |
| | | <TextArea id="source-input" value={url} rows={4} onChange={this.changeValue}/> |
| | | </Form.Item> : null} |
| | | {keyword === 'upload' ? <Form.Item label="上传" labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={{xs: { span: 24 }, sm: { span: 20 }}}> |
| | | <FileUpload value={fileList} onChange={this.changeFile} accept={type === 'video' ? '.mp4,.webm,.ogg' : '.jpg,.png,.gif,.pjp,.pjpeg,.jpeg,.jfif,.webp'} maxFile={1} fileType={type === 'video' ? 'text' : 'picture'} /> |
| | | <FileUpload config={{ |
| | | initval: '', |
| | | suffix: type === 'video' ? '.mp4,.webm,.ogg' : '.jpg,.png,.gif,.pjp,.pjpeg,.jpeg,.jfif,.webp', |
| | | maxfile: 1, |
| | | fileType: type === 'video' ? 'text' : 'picture' |
| | | }} onChange={this.changeFile} /> |
| | | </Form.Item> : null} |
| | | {keyword === 'system' ? |
| | | <Search value={searchKey} placeholder="" onChange={(e) => this.setState({searchKey: e.target.value})} onSearch={this.changeSearch} enterButton/> : null} |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Select, Input } from 'antd' |
| | | |
| | | import './index.scss' |
| | | |
| | | const { Option } = Select |
| | | |
| | | class StyleInput extends Component { |
| | | static propTpyes = { |
| | | defaultValue: PropTypes.any, |
| | | options: PropTypes.any, |
| | | value: PropTypes.any, |
| | | onChange: PropTypes.func, |
| | | } |
| | | |
| | | state = { |
| | | value: '', |
| | | unit: '', |
| | | options: null |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { value, options } = this.props |
| | | |
| | | let val = value || '' |
| | | let unit = options[0] |
| | | |
| | | if (val) { |
| | | if (val.indexOf('px') > -1) { |
| | | unit = 'px' |
| | | } else if (val.indexOf('%') > -1) { |
| | | unit = '%' |
| | | } else if (val.indexOf('vw') > -1) { |
| | | unit = 'vw' |
| | | } else if (val.indexOf('vh') > -1) { |
| | | unit = 'vh' |
| | | } |
| | | } |
| | | |
| | | let _val = parseFloat(val) |
| | | |
| | | if (isNaN(_val)) { |
| | | _val = '' |
| | | } |
| | | |
| | | this.setState({value: _val, options: options, unit}) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | UNSAFE_componentWillReceiveProps(nextProps) { |
| | | if (nextProps.value === '' && this.state.value !== '') { |
| | | this.setState({value: ''}) |
| | | } else if (nextProps.value && nextProps.value !== `${this.state.value}${this.state.unit}`) { |
| | | let val = nextProps.value |
| | | let unit = this.state.unit |
| | | |
| | | if (val) { |
| | | if (val.indexOf('px') > -1) { |
| | | unit = 'px' |
| | | } else if (val.indexOf('%') > -1) { |
| | | unit = '%' |
| | | } else if (val.indexOf('vw') > -1) { |
| | | unit = 'vw' |
| | | } else if (val.indexOf('vh') > -1) { |
| | | unit = 'vh' |
| | | } |
| | | } |
| | | |
| | | let _val = parseFloat(val) |
| | | |
| | | if (isNaN(_val)) { |
| | | _val = '' |
| | | } |
| | | this.setState({value: _val, unit}) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新,清除快捷键设置 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | } |
| | | |
| | | changeValue = (e) => { |
| | | const { unit } = this.state |
| | | let val = e.target.value |
| | | |
| | | if (/\d+\.$/.test(val)) { |
| | | this.setState({ |
| | | value: val |
| | | }) |
| | | return |
| | | } |
| | | let _val = parseFloat(val) |
| | | |
| | | if (isNaN(_val)) { |
| | | _val = '' |
| | | } |
| | | |
| | | this.setState({ |
| | | value: _val, |
| | | }, () => { |
| | | this.props.onChange(_val !== '' ? `${_val}${unit}` : '') |
| | | }) |
| | | } |
| | | |
| | | changeUnit = (val) => { |
| | | const { value } = this.state |
| | | |
| | | this.setState({unit: val}, () => { |
| | | this.props.onChange(value !== '' ? `${value}${val}` : '') |
| | | }) |
| | | } |
| | | |
| | | render () { |
| | | const { value, options, unit } = this.state |
| | | |
| | | return ( |
| | | <div className="style-input-wrap"> |
| | | <Input value={value} addonAfter={ |
| | | options.length > 1 ? |
| | | <Select value={unit} onChange={this.changeUnit}> |
| | | {options.map(item => <Option key={item} value={item}>{item}</Option>)} |
| | | </Select> : |
| | | <div className="single-unit">{unit}</div> |
| | | } onChange={this.changeValue}/> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default StyleInput |
New file |
| | |
| | | .style-input-wrap { |
| | | line-height: 32px; |
| | | .ant-select { |
| | | width: 60px!important; |
| | | } |
| | | .single-unit { |
| | | width: 38px; |
| | | text-align: left; |
| | | color: rgba(255, 255, 255, 0.65); |
| | | } |
| | | } |
| | |
| | | func: 's_custom_components_adduptdel', |
| | | c_id: config.uuid, |
| | | images: Utils.getcloudurl(result.Images), |
| | | typename: sessionStorage.getItem('appType') || '', |
| | | c_name: res.name, |
| | | long_param: window.btoa(window.encodeURIComponent(JSON.stringify(template))), |
| | | del_type: '' |
| | |
| | | /** |
| | | * @description 获取显示列表单配置信息 |
| | | * @param {object} card // 搜索条件对象 |
| | | * @param {Array} menulist // 菜单列表-用于字段透视 |
| | | */ |
| | | export function getColumnForm (card, menulist = [], fields = []) { |
| | | export function getColumnForm (card, fields = []) { |
| | | let appType = sessionStorage.getItem('appType') |
| | | let roleList = sessionStorage.getItem('sysRoles') |
| | | if (roleList) { |
| | | try { |
| | |
| | | } |
| | | } else { |
| | | roleList = [] |
| | | } |
| | | |
| | | let menulist = [] |
| | | |
| | | if (appType === 'pc') { |
| | | menulist = sessionStorage.getItem('appMenus') |
| | | } else if (!appType) { |
| | | menulist = sessionStorage.getItem('fstMenuList') |
| | | } |
| | | |
| | | if (menulist) { |
| | | try { |
| | | menulist = JSON.parse(menulist) |
| | | } catch { |
| | | menulist = [] |
| | | } |
| | | } else { |
| | | menulist = [] |
| | | } |
| | | |
| | | let options = [{ |
| | |
| | | }, { |
| | | value: 'colspan', |
| | | text: '合并列' |
| | | }, { |
| | | value: 'index', |
| | | text: '序号' |
| | | }] |
| | | |
| | | if (!card.isSub) { |
| | |
| | | key: 'postfix', |
| | | label: Formdict['header.form.postfix'], |
| | | initVal: card.postfix || '', |
| | | tooltipClass: 'middle', |
| | | required: false, |
| | | readonly: false |
| | | }, |
| | | { |
| | | type: 'radio', |
| | | type: 'select', |
| | | key: 'lenWidRadio', |
| | | label: '长宽比', |
| | | initVal: card.lenWidRadio || '1:1', |
| | | required: true, |
| | | options: [ |
| | | { value: '1:1', text: '1:1' }, |
| | | { value: '3:2', text: '3:2' }, |
| | | { value: '4:3', text: '4:3' }, |
| | | { value: '16:9', text: '16:9' } |
| | | { value: '3:2', text: '3:2' }, |
| | | { value: '16:9', text: '16:9' }, |
| | | { value: '2:1', text: '2:1' }, |
| | | { value: '3:1', text: '3:1' }, |
| | | { value: '4:1', text: '4:1' }, |
| | | { value: '5:1', text: '5:1' }, |
| | | { value: '6:1', text: '6:1' }, |
| | | { value: '7:1', text: '7:1' }, |
| | | { value: '8:1', text: '8:1' }, |
| | | { value: '9:1', text: '9:1' }, |
| | | { value: '10:1', text: '10:1' }, |
| | | { value: '3:4', text: '3:4' }, |
| | | { value: '2:3', text: '2:3' }, |
| | | { value: '9:16', text: '9:16' }, |
| | | ] |
| | | }, |
| | | { |
| | |
| | | }, { |
| | | value: 'linkurl', |
| | | text: '链接' |
| | | }] |
| | | }], |
| | | forbidden: appType === 'mob' |
| | | }, |
| | | { |
| | | type: 'cascader', |
| | | type: appType === 'pc' ? 'select' : 'cascader', |
| | | key: 'linkmenu', |
| | | label: Formdict['model.menu'], |
| | | initVal: card.linkmenu || [], |
| | | initVal: card.linkmenu || (appType === 'pc' ? '' : []), |
| | | required: true, |
| | | options: menulist |
| | | options: menulist, |
| | | forbidden: appType === 'mob' |
| | | }, |
| | | { |
| | | type: 'textarea', |
| | | key: 'linkurl', |
| | | label: '链接地址', |
| | | initVal: card.linkurl || '', |
| | | required: true |
| | | required: true, |
| | | forbidden: appType === 'mob' |
| | | }, |
| | | { |
| | | type: 'multiselect', |
| | |
| | | label: '关联字段', |
| | | initVal: card.linkfields || [], |
| | | required: false, |
| | | options: fields |
| | | options: fields, |
| | | forbidden: appType === 'mob' |
| | | }, |
| | | { |
| | | type: 'radio', |
| | | key: 'open', |
| | | label: '打开方式', |
| | | initVal: card.open || 'blank', |
| | | required: false, |
| | | forbid: appType !== 'pc', |
| | | options: [ |
| | | { value: 'blank', text: '新窗口' }, |
| | | { value: 'self', text: '当前窗口' } |
| | | ] |
| | | }, |
| | | { |
| | | type: 'multiselect', |
| | |
| | | picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'blacklist', 'scale', 'lenWidRadio', 'picSort'], |
| | | colspan: ['label', 'type', 'Align', 'Hide', 'blacklist'], |
| | | custom: ['label', 'type', 'Align', 'Hide', 'Width', 'blacklist'], |
| | | action: ['label', 'type', 'Align', 'Width'] |
| | | action: ['label', 'type', 'Align', 'Width'], |
| | | index: ['label', 'type', 'Align', 'Width'] |
| | | } |
| | | |
| | | class MainSearch extends Component { |
| | |
| | | } |
| | | |
| | | editColumn = (column) => { |
| | | let menulist = sessionStorage.getItem('fstMenuList') |
| | | if (menulist) { |
| | | try { |
| | | menulist = JSON.parse(menulist) |
| | | } catch { |
| | | menulist = [] |
| | | } |
| | | } else { |
| | | menulist = [] |
| | | } |
| | | |
| | | let formlist = getColumnForm(column, menulist, this.props.fields) |
| | | let formlist = getColumnForm(column, this.props.fields) |
| | | let _options = fromJS(columnTypeOptions[column.type]).toJS() |
| | | if (column.type === 'text' || column.type === 'number') { |
| | | if (column.perspective === 'linkmenu') { |
| | | _options.push('linkmenu', 'linkfields') |
| | | _options.push('linkmenu', 'linkfields', 'open') |
| | | } else if (column.perspective === 'linkurl') { |
| | | _options.push('linkurl', 'linkfields') |
| | | _options.push('linkurl', 'linkfields', 'open') |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | }) |
| | | } else if (key === 'field') { |
| | | this.props.form.setFieldsValue({label: option.props.children}) |
| | | if (this.state.type === 'number') { |
| | | let values = {label: option.props.children} |
| | | if (/Decimal|int/ig.test(option.props.datatype)) { |
| | | let decimal = 0 |
| | | if (/Decimal/ig.test(option.props.datatype)) { |
| | | decimal = +option.props.datatype.replace(/Decimal\(18,/ig, '').replace(')', '') |
| | | } |
| | | this.props.form.setFieldsValue({decimal}) |
| | | values.type = 'number' |
| | | values.decimal = decimal |
| | | } else if (/nvarchar/ig.test(option.props.datatype)) { |
| | | values.type = 'text' |
| | | } |
| | | |
| | | if (values.type !== this.state.type) { |
| | | values.perspective = '' |
| | | let _options = fromJS(columnTypeOptions[values.type]).toJS() |
| | | |
| | | this.setState({ |
| | | type: values.type, |
| | | formlist: this.state.formlist.map(item => { |
| | | item.hidden = !_options.includes(item.key) |
| | | |
| | | return item |
| | | }) |
| | | }, () => { |
| | | this.props.form.setFieldsValue(values) |
| | | }) |
| | | } else { |
| | | this.props.form.setFieldsValue(values) |
| | | } |
| | | } else if (key === 'format' && value === 'percent') { |
| | | this.props.form.setFieldsValue({postfix: '%'}) |
| | |
| | | let _options = fromJS(columnTypeOptions[this.state.type]).toJS() |
| | | |
| | | if (value === 'linkmenu') { |
| | | _options.push('linkmenu', 'linkfields') |
| | | _options.push('linkmenu', 'linkfields', 'open') |
| | | } else if (value === 'linkurl') { |
| | | _options.push('linkurl', 'linkfields') |
| | | _options.push('linkurl', 'linkfields', 'open') |
| | | } |
| | | |
| | | this.setState({ |
| | |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.tooltip ? |
| | | <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}> |
| | | <Tooltip placement="topLeft" title={item.tooltip}> |
| | | <Icon type="question-circle" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.tooltip ? |
| | | <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}> |
| | | <Tooltip placement="topLeft" title={item.tooltip}> |
| | | <Icon type="question-circle" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'select') { // 下拉搜索 |
| | | } else if (item.type === 'select') { |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.label}> |
| | |
| | | getPopupContainer={() => document.getElementById('columnwinter')} |
| | | > |
| | | {item.options.map((option, index) => |
| | | <Select.Option key={`${option.value || option.field}${index}`} datatype={option.datatype || ''} value={option.value || option.field}> |
| | | {option.text || option.label} |
| | | <Select.Option key={index} datatype={option.datatype || ''} value={(option.value || option.field || option.MenuID)}> |
| | | {(option.text || option.label || option.MenuName)} |
| | | </Select.Option> |
| | | )} |
| | | </Select> |
| | |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.tooltip ? |
| | | <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}> |
| | | <Tooltip placement="topLeft" title={item.tooltip}> |
| | | <Icon type="question-circle" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | |
| | | if (this.props.rowSpan !== nextProps.rowSpan || this.props.colSpan !== nextProps.colSpan) { |
| | | return true |
| | | } |
| | | |
| | | if (!nextProps.column) return false |
| | | |
| | | return !is(fromJS(this.props.column), fromJS(nextProps.column)) || |
| | | !is(fromJS(this.props.fields), fromJS(nextProps.fields)) || |
| | | this.props.index !== nextProps.index || |
| | | this.props.rowSpan !== nextProps.rowSpan || |
| | | this.props.colSpan !== nextProps.colSpan |
| | | this.props.index !== nextProps.index |
| | | } |
| | | |
| | | render() { |
| | | const { connectDragSource, connectDropTarget, moveCol, addElement, updateCol, editColumn, deleteCol, index, column, align, fields, children, ...restProps } = this.props |
| | | const { connectDragSource, connectDropTarget, moveCol, addElement, updateCol, editColumn, changeStyle, deleteCol, index, column, align, fields, children, ...restProps } = this.props |
| | | |
| | | if (index !== undefined) { |
| | | return connectDragSource( |
| | |
| | | <Icon className="plus" title="添加" type="plus" onClick={() => this.props.addElement(column)} /> : null |
| | | } |
| | | <Icon className="edit" title="编辑" type="edit" onClick={() => this.props.editColumn(column)} /> |
| | | {column && column.type === 'custom' ? <Icon className="style" title="调整样式" onClick={() => this.props.changeStyle(column)} type="font-colors" /> : null} |
| | | <Icon className="close" title="删除" type="delete" onClick={this.deleteCol} /> |
| | | {column && ['text', 'number'].includes(column.type) ? <MarkColumn columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null } |
| | | </div> |
| | |
| | | |
| | | if (column && column.type === 'custom') { |
| | | return ( |
| | | <td style={{padding: 0, minWidth: column.Width || 100}} className={className}> |
| | | <td style={{padding: 0, minWidth: column.Width || 100, ...(column.style || {})}} className={className}> |
| | | <CardCellComponent cards={config} cardCell={column} elements={column.elements} updateElement={this.updateCard}/> |
| | | </td> |
| | | ) |
| | |
| | | } else if (column) { |
| | | return ( |
| | | <td style={{...style, minWidth: column.Width || 100}} className={className}> |
| | | {column.field} |
| | | {column.field || (column.type === 'index' ? '$Index' : '')} |
| | | {column.marks && column.marks.length ? <Icon className="profile" type="ant-design"/> : null} |
| | | </td> |
| | | ) |
| | |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | appType: sessionStorage.getItem('appType'), |
| | | tableId: '', |
| | | data: [{uuid: Utils.getuuid()}], |
| | | refresh: false, // 强制刷新 |
| | | columns: [], |
| | | fields: [], |
| | | editStyleCard: null, |
| | | lineMarks: [] |
| | | } |
| | | |
| | |
| | | this.updateCol(col) |
| | | } |
| | | |
| | | changeStyle = (col) => { |
| | | this.setState({ |
| | | editStyleCard: fromJS(col).toJS() |
| | | }) |
| | | |
| | | MKEmitter.emit('changeStyle', [col.uuid], ['font', 'padding'], col.style || {}) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | | const { editStyleCard } = this.state |
| | | |
| | | if (!editStyleCard || comIds[0] !== editStyleCard.uuid || comIds.length !== 1) return |
| | | |
| | | let _card = {...editStyleCard, style} |
| | | |
| | | this.updateCol(_card) |
| | | } |
| | | |
| | | cancelCol = () => { |
| | | const { card } = this.state |
| | | |
| | |
| | | } |
| | | |
| | | deleteCol = (col) => { |
| | | const { appType } = this.state |
| | | let _columns = fromJS(this.state.columns).toJS() |
| | | _columns = this.loopDelCol(_columns, col) |
| | | |
| | | if (col.type === 'action') { |
| | | let uuids = [] |
| | | col.elements && col.elements.forEach(c => { |
| | | uuids.push(c.uuid) |
| | | }) |
| | | MKEmitter.emit('delButtons', uuids) |
| | | } |
| | | _columns = this.loopDelCol(_columns, col) |
| | | |
| | | this.setState({ |
| | | columns: _columns |
| | | }, () => { |
| | | this.props.updatecolumn({...this.props.config, cols: _columns}) |
| | | }) |
| | | |
| | | if (col.type !== 'action' || appType === 'mob') return |
| | | |
| | | let uuids = [] |
| | | col.elements && col.elements.forEach(c => { |
| | | if (appType === 'pc' && c.OpenType !== 'popview') return |
| | | |
| | | uuids.push(c.uuid) |
| | | }) |
| | | |
| | | if (uuids.length === 0) return |
| | | |
| | | MKEmitter.emit('delButtons', uuids) |
| | | } |
| | | |
| | | updateLineMarks = (vals) => { |
| | |
| | | updateCol: this.updateCol, |
| | | addElement: this.addElement, |
| | | editColumn: this.editColumn, |
| | | changeStyle: this.changeStyle, |
| | | deleteCol: this.deleteCol, |
| | | }), |
| | | children: col.subcols && col.subcols.length ? this.handlecolumns(col.subcols, fields, config, true) : null, |
| | |
| | | }) |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('submitStyle', this.getStyle) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新,清除快捷键设置 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('submitStyle', this.getStyle) |
| | | } |
| | | |
| | | render() { |
| | | const { config } = this.props |
| | | const { fields, card, lineMarks, dict, tableId } = this.state |
| | |
| | | |
| | | 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} /> |
| | |
| | | rowKey="uuid" |
| | | size={config.wrap.size || 'middle'} |
| | | rowClassName="editable-row" |
| | | style={style} |
| | | bordered={config.wrap.bordered !== 'false'} |
| | | components={components} |
| | | dataSource={this.state.data} |
| | |
| | | .normal-table-columns { |
| | | position: relative; |
| | | .ant-table { |
| | | color: inherit; |
| | | font-size: inherit; |
| | | } |
| | | .ant-table-body { |
| | | overflow-x: auto; |
| | | tr { |
| | |
| | | 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; |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | appType: sessionStorage.getItem('appType'), |
| | | card: null, |
| | | back: false |
| | | } |
| | |
| | | { origin: true, uuid: Utils.getuuid(), label: 'label', type: 'date', match: 'greater' } |
| | | ], |
| | | action: [ |
| | | { origin: true, uuid: Utils.getuuid(), label: '添加', intertype: 'system', OpenType: 'pop', icon: 'plus', class: 'green', btnstyle: {color: 'rgb(255, 255, 255)', background: 'rgb(38, 194, 129)', marginRight: '15px'} }, |
| | | { origin: true, uuid: Utils.getuuid(), label: '修改', intertype: 'system', OpenType: 'pop', icon: 'form', class: 'purple', btnstyle: {color: 'rgb(255, 255, 255)', background: 'rgb(142, 68, 173)', marginRight: '15px'} }, |
| | | { origin: true, uuid: Utils.getuuid(), label: '删除', intertype: 'system', OpenType: 'prompt', icon: 'delete', class: 'danger', btnstyle: {color: 'rgb(255, 255, 255)', background: 'rgb(255, 77, 79)', marginRight: '15px'} } |
| | | { origin: true, uuid: Utils.getuuid(), label: '添加', intertype: 'system', OpenType: 'pop', icon: 'plus', class: 'green', style: {color: 'rgb(255, 255, 255)', background: 'rgb(38, 194, 129)', marginRight: '15px'} }, |
| | | { origin: true, uuid: Utils.getuuid(), label: '修改', intertype: 'system', OpenType: 'pop', icon: 'form', class: 'purple', style: {color: 'rgb(255, 255, 255)', background: 'rgb(142, 68, 173)', marginRight: '15px'} }, |
| | | { origin: true, uuid: Utils.getuuid(), label: '删除', intertype: 'system', OpenType: 'prompt', icon: 'delete', class: 'danger', style: {color: 'rgb(255, 255, 255)', background: 'rgb(255, 77, 79)', marginRight: '15px'} } |
| | | ], |
| | | name: card.name, |
| | | subtype: card.subtype, |
| | |
| | | _card.style = config.style |
| | | _card.headerStyle = config.headerStyle |
| | | |
| | | let oriUids = {} |
| | | _card.action = config.action.map(item => { |
| | | item.uuid = Utils.getuuid() |
| | | let _uuid = Utils.getuuid() |
| | | oriUids[item.uuid] = _uuid |
| | | item.uuid = _uuid |
| | | return item |
| | | }) |
| | | _card.search = config.search.map(item => { |
| | |
| | | } |
| | | return col |
| | | }) |
| | | |
| | | if (_card.wrap.doubleClick) { |
| | | _card.wrap.doubleClick = oriUids[_card.wrap.doubleClick] || '' |
| | | } |
| | | } |
| | | |
| | | this.setState({ |
| | |
| | | newcard.errorTime = 10 |
| | | newcard.verify = null |
| | | newcard.show = 'button' |
| | | newcard.btnstyle = {marginRight: '15px'} |
| | | newcard.style = {marginRight: '15px'} |
| | | |
| | | // 注册事件-添加按钮 |
| | | MKEmitter.emit('addButton', card.uuid, newcard) |
| | |
| | | } |
| | | |
| | | setSubConfig = (item) => { |
| | | const { card } = this.state |
| | | const { card, appType } = this.state |
| | | let btn = fromJS(item).toJS() |
| | | |
| | | if (btn.OpenType === 'pop' || btn.execMode === 'pop') { |
| | | if (!btn.modal) { |
| | | btn.modal = { |
| | | setting: { title: btn.label, width: 60, cols: '2', container: 'view', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' }, |
| | | setting: { title: btn.label, width: appType === 'mob' ? 100 : 60, cols: '2', container: 'view', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' }, |
| | | tables: [], |
| | | groups: [], |
| | | fields: [] |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { card } = this.state |
| | | const { card, appType } = this.state |
| | | let _style = resetStyle(card.style) |
| | | |
| | | return ( |
| | | <div className="menu-normal-table-edit-box" style={{...card.style, height: card.wrap.height}} onClick={this.clickComponent} id={card.uuid}> |
| | | <div className="menu-normal-table-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> |
| | | <NormalHeader defaultshow="hidden" hideSearch="true" config={card} updateComponent={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.addColumns} type="plus" /> |
| | | <Icon className="plus" title="添加搜索" onClick={this.addSearch} type="plus-circle" /> |
| | | {appType !== 'mob' ? <Icon className="plus" title="添加搜索" onClick={this.addSearch} type="plus-circle" /> : null} |
| | | <Icon className="plus" title="添加按钮" onClick={this.addButton} type="plus-square" /> |
| | | <WrapComponent config={card} updateConfig={this.updateComponent} /> |
| | | <CopyComponent type="normaltable" card={card}/> |
| | |
| | | wrapClassName="popview-modal" |
| | | title="表格设置" |
| | | visible={visible} |
| | | width={700} |
| | | width={750} |
| | | maskClosable={false} |
| | | okText={dict['model.submit']} |
| | | onOk={this.verifySubmit} |
| | |
| | | } |
| | | |
| | | state = { |
| | | roleList: [] |
| | | roleList: [], |
| | | appType: sessionStorage.getItem('appType') |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | |
| | | render() { |
| | | const { wrap, config } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { roleList } = this.state |
| | | const { roleList, appType } = this.state |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {appType !== 'mob' ? <Col span={12}> |
| | | <Form.Item label="可收起"> |
| | | {getFieldDecorator('collapse', { |
| | | initialValue: wrap.collapse || 'false' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio key="true" value="true"> 是 </Radio> |
| | | <Radio key="false" value="false"> 否 </Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={12}> |
| | | <Form.Item label="表格大小"> |
| | | {getFieldDecorator('size', { |
| | |
| | | </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" /> |
| | |
| | | })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | {appType !== 'mob' ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="高级搜索弹窗的宽度,注:当宽度值小于100时表示占窗口的百分比,大于100时表示宽度的绝对值。"> |
| | | <Icon type="question-circle" /> |
| | | 高级搜索 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('advanceWidth', { |
| | | initialValue: wrap.advanceWidth || 1000 |
| | | })(<InputNumber min={10} max={3000} precision={0} onPressEnter={this.handleSubmit}/>)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {appType !== 'mob' ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="双击表格中行,触发的按钮。"> |
| | | <Icon type="question-circle" /> |
| | |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | </Col> : null} |
| | | <Col span={12}> |
| | | <Form.Item label="黑名单"> |
| | | {getFieldDecorator('blacklist', { |
| | |
| | | import React, { Component } from 'react' |
| | | import { Tabs } from 'antd' |
| | | import { is, fromJS } from 'immutable' |
| | | import { DndProvider, DragSource, DropTarget } from 'react-dnd' |
| | | |
| | | // Drag & Drop node |
| | |
| | | const newOrder = this.state.order.slice() |
| | | const { children } = this.props |
| | | |
| | | if (dragKey === 'tool' || hoverKey === 'tool') return |
| | | |
| | | React.Children.forEach(children, c => { |
| | | if (newOrder.indexOf(c.key) === -1) { |
| | | newOrder.push(c.key) |
| | |
| | | |
| | | newOrder.splice(dragIndex, 1) |
| | | newOrder.splice(hoverIndex, 0, dragKey) |
| | | let _order = newOrder.filter(item => item !== 'tool') |
| | | |
| | | this.setState({ |
| | | order: [..._order, 'tool'] |
| | | order: newOrder |
| | | }) |
| | | this.props.tabsMove(_order) |
| | | this.props.tabsMove(newOrder) |
| | | } |
| | | |
| | | renderTabBar = (props, DefaultTabBar) => ( |
| | |
| | | </DefaultTabBar> |
| | | ) |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) || |
| | | !is(fromJS(nextProps.children), fromJS(this.props.children)) || |
| | | nextProps.tabPosition !== this.props.tabPosition || |
| | | nextProps.type !== this.props.type |
| | | } |
| | | |
| | | render() { |
| | | const { order } = this.state |
| | | const { children } = this.props |
| | | |
| | | const tabs = [] |
| | | React.Children.forEach(children, c => { |
| | | tabs.push(c) |
| | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | import DraggableTabs from './dragabletabs' |
| | | |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import MenuUtils from '@/utils/utils-custom.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | appType: sessionStorage.getItem('appType'), |
| | | tabs: null, |
| | | editab: null, |
| | | labelvisible: false |
| | |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('submitStyle', this.getStyle) |
| | | MKEmitter.addListener('submitSearch', this.getSearch) |
| | | MKEmitter.addListener('tabsChange', this.handleTabsChange) |
| | | MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle) |
| | | } |
| | |
| | | return |
| | | } |
| | | MKEmitter.removeListener('submitStyle', this.getStyle) |
| | | MKEmitter.removeListener('submitSearch', this.getSearch) |
| | | MKEmitter.removeListener('tabsChange', this.handleTabsChange) |
| | | MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle) |
| | | } |
| | |
| | | this.tabLabelRef.handleConfirm().then(res => { |
| | | editab.label = res.label |
| | | editab.icon = res.icon |
| | | editab.hasSearch = res.hasSearch || '' |
| | | editab.blacklist = res.blacklist |
| | | |
| | | if (editab.uuid) { |
| | |
| | | |
| | | tabs.subtabs = tabs.subtabs.filter(t => t.uuid !== tab.uuid) |
| | | |
| | | let uuids = MenuUtils.getDelButtonIds({...tab, type: 'group'}) |
| | | |
| | | confirm({ |
| | | title: '确定删除标签?', |
| | | content: '', |
| | | onOk() { |
| | | _this.setState({tabs}) |
| | | _this.props.updateConfig(tabs) |
| | | |
| | | if (uuids.length === 0) return |
| | | |
| | | MKEmitter.emit('delButtons', uuids) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | |
| | | this.props.updateConfig(tabs) |
| | | } |
| | | |
| | | getSearch = (config) => { |
| | | const { tabs } = this.state |
| | | |
| | | if (tabs.uuid !== config.uuid) return |
| | | |
| | | let _tabs = fromJS(tabs).toJS() |
| | | |
| | | _tabs.subtabs = _tabs.subtabs.map(t => { |
| | | if (t.uuid === config.tabId) { |
| | | t.search = config.search |
| | | } |
| | | return t |
| | | }) |
| | | |
| | | this.setState({ |
| | | tabs: _tabs |
| | | }) |
| | | this.props.updateConfig(_tabs) |
| | | } |
| | | |
| | | setSearch = (tab) => { |
| | | const { tabs } = this.state |
| | | let card = { |
| | | uuid: tabs.uuid, |
| | | tabId: tab.uuid, |
| | | search: tab.search |
| | | } |
| | | |
| | | if (!card.search) { |
| | | card.search = { |
| | | floor: 1, |
| | | setting: { type: 'title', field: '', title: '', focus: 'true', btn: 'hidden' }, |
| | | groups: [], |
| | | fields: [] |
| | | } |
| | | } |
| | | MKEmitter.emit('changeSearch', card) |
| | | } |
| | | |
| | | clickComponent = (e) => { |
| | | if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { |
| | | e.stopPropagation() |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { tabs, dict, labelvisible, editab } = this.state |
| | | const { tabs, dict, labelvisible, editab, appType } = this.state |
| | | let _style = resetStyle(tabs.style) |
| | | |
| | | return ( |
| | | <div className="menu-tabs-edit-box" style={tabs.style} onClick={this.clickComponent} id={tabs.uuid}> |
| | | <div className={'menu-tabs-edit-box ' + tabs.setting.display} style={_style} onClick={this.clickComponent} id={tabs.uuid}> |
| | | <DraggableTabs tabPosition={tabs.setting.position} type={tabs.setting.tabStyle} tabsMove={this.moveSwitch}> |
| | | {tabs.subtabs.map(tab => ( |
| | | <TabPane tab={ |
| | |
| | | <span>{tab.icon ? <Icon type={tab.icon} /> : null}{tab.label}</span> |
| | | </Popover> |
| | | } key={tab.uuid}> |
| | | {appType === 'mob' && tabs.setting.position === 'top' && tabs.setting.display === 'inline-block' && tab.hasSearch === 'icon' ? |
| | | <Icon className="search-icon" onDoubleClick={() => this.setSearch(tab)} type="search" /> : null} |
| | | <TabComponents config={tab} handleList={this.updateTabComponent} deleteCard={this.deleteCard} /> |
| | | </TabPane> |
| | | ))} |
| | | <TabPane disabled tab={ |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <Icon className="plus" title="添加标签" type="plus" onClick={this.tabAdd} /> |
| | | <SettingComponent config={tabs} updateConfig={this.updateComponent} /> |
| | | <CopyComponent type="tabs" card={tabs}/> |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | | <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(tabs.uuid)} /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <Icon type="tool" /> |
| | | </Popover> |
| | | } key="tool"> |
| | | </TabPane> |
| | | </DraggableTabs> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <Icon className="plus" title="添加标签" type="plus" onClick={this.tabAdd} /> |
| | | <SettingComponent config={tabs} updateConfig={this.updateComponent} /> |
| | | <CopyComponent type="tabs" card={tabs}/> |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | | <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(tabs.uuid)} /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <Icon type="tool" /> |
| | | </Popover> |
| | | <Modal |
| | | wrapClassName="popview-modal" |
| | | title={'标签编辑'} |
| | |
| | | <TabLabelComponent |
| | | dict={dict} |
| | | tab={editab} |
| | | setting={tabs.setting} |
| | | inputSubmit={this.tabLabelSubmit} |
| | | wrappedComponentRef={(inst) => this.tabLabelRef = inst} |
| | | /> |
| | |
| | | background-repeat: no-repeat; |
| | | background-size: cover; |
| | | |
| | | >.anticon-tool { |
| | | position: absolute; |
| | | z-index: 2; |
| | | font-size: 16px; |
| | | right: 1px; |
| | | top: 1px; |
| | | cursor: pointer; |
| | | padding: 5px; |
| | | background: rgba(255, 255, 255, 0.55); |
| | | } |
| | | |
| | | .ant-tabs.ant-tabs-left, .ant-tabs.ant-tabs-bottom { |
| | | .tab-shell-inner { |
| | | padding-top: 25px; |
| | | } |
| | | } |
| | | |
| | | .ant-tabs-tabpane-active { |
| | | min-height: 200px; |
| | | } |
| | |
| | | } |
| | | |
| | | .ant-tabs .ant-tabs-left-bar .ant-tabs-tab { |
| | | padding: 0px; |
| | | text-align: right; |
| | | > span { |
| | | display: inline-block; |
| | | padding: 8px 24px; |
| | | } |
| | | .anticon-tool { |
| | | padding: 8px 24px; |
| | | } |
| | | } |
| | | .ant-tabs .ant-tabs-right-bar .ant-tabs-tab { |
| | | padding: 0px; |
| | | text-align: left; |
| | | > span { |
| | | display: inline-block; |
| | | padding: 8px 24px; |
| | | } |
| | | .anticon-tool { |
| | | padding: 8px 24px; |
| | | } |
| | | } |
| | | .ant-tabs-tab { |
| | | padding: 0px; |
| | | padding: 0px!important; |
| | | text-align: center; |
| | | > span { |
| | | display: inline-block; |
| | | padding: 12px 16px; |
| | | } |
| | | .anticon-tool { |
| | | color: rgba(0, 0, 0, 0.65); |
| | | font-size: 16px; |
| | | padding: 12px 16px; |
| | | margin-right: 0px; |
| | | min-width: 100%; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | .ant-tabs-bottom .ant-tabs-bottom-bar .ant-tabs-ink-bar { |
| | |
| | | > span { |
| | | padding: 0px 16px; |
| | | } |
| | | .anticon-tool { |
| | | padding: 0px 16px; |
| | | } |
| | | } |
| | | .ant-tabs-tab-active { |
| | | padding-left: 0px!important; |
| | |
| | | |
| | | .ant-tabs-card-bar { |
| | | .ant-tabs-tab { |
| | | padding: 0px; |
| | | > span { |
| | | display: inline-block; |
| | | padding: 0px 16px; |
| | | } |
| | | } |
| | | .ant-tabs-tab:last-child { |
| | | padding: 0px; |
| | | border: 0px; |
| | | background: transparent; |
| | | .anticon-tool { |
| | | padding: 12px 16px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .search-icon { |
| | | position: absolute; |
| | | top: 10px; |
| | | right: 40px; |
| | | font-size: 18px; |
| | | cursor: pointer; |
| | | padding: 3px; |
| | | } |
| | | } |
| | | .menu-tabs-edit-box:hover { |
| | | z-index: 1; |
| | | box-shadow: 0px 0px 4px #1890ff; |
| | | } |
| | | |
| | | .mob-shell { |
| | | .menu-tabs-edit-box.flex { |
| | | >.ant-tabs.ant-tabs-top, >.ant-tabs.ant-tabs-bottom { |
| | | >.ant-tabs-bar { |
| | | >.ant-tabs-nav-container { |
| | | >.ant-tabs-nav-wrap { |
| | | >.ant-tabs-nav-scroll { |
| | | >.ant-tabs-nav { |
| | | display: block; |
| | | >div { |
| | | display: flex; |
| | | >.ant-tabs-tab { |
| | | flex: 1; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | 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 AntvScatter = asyncComponent(() => import('@/menu/components/chart/antv-scatter')) |
| | | 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')) |
| | | const NormalTree = asyncComponent(() => import('@/menu/components/tree/antd-tree')) |
| | | const CarouselDataCard = asyncComponent(() => import('@/menu/components/carousel/data-card')) |
| | | const CarouselPropCard = asyncComponent(() => import('@/menu/components/carousel/prop-card')) |
| | | const TableCard = asyncComponent(() => import('@/menu/components/card/table-card')) |
| | | const NormalForm = asyncComponent(() => import('@/menu/components/form/normal-form')) |
| | | const NormalTable = asyncComponent(() => import('@/menu/components/table/normal-table')) |
| | | const NormalGroup = asyncComponent(() => import('@/menu/components/group/normal-group')) |
| | | const BraftEditor = asyncComponent(() => import('@/menu/components/editor/braft-editor')) |
| | | const CodeSandbox = asyncComponent(() => import('@/menu/components/code/sandbox')) |
| | | |
| | | const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => { |
| | | const originalIndex = findCard(id).index |
| | |
| | | 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 === 'tree') { |
| | | return (<NormalTree card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'scatter') { |
| | | return (<AntvScatter card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'form') { |
| | | return (<NormalForm 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') { |
| | |
| | | return (<NormalGroup group={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'editor') { |
| | | return (<BraftEditor card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'code') { |
| | | return (<CodeSandbox card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } |
| | | } |
| | | |
| | |
| | | title: `确定删除《${card.name}》吗?`, |
| | | content: hasComponent ? '当前组件中含有子组件!' : '', |
| | | onOk() { |
| | | MKEmitter.emit('delButtons', uuids) |
| | | handleList({...config, components: cards.filter(item => item.uuid !== card.uuid)}) |
| | | |
| | | if (uuids.length === 0) return |
| | | |
| | | MKEmitter.emit('delButtons', uuids) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | |
| | | |
| | | let name = '' |
| | | let names = { |
| | | bar: '柱状图', |
| | | bbar: '柱状图', |
| | | line: '折线图', |
| | | tabs: '标签组', |
| | | pie: '饼图', |
| | |
| | | table: '表格', |
| | | group: '分组', |
| | | editor: '富文本', |
| | | code: '自定义', |
| | | carousel: '轮播', |
| | | form: '表单', |
| | | dashboard: '仪表盘', |
| | | scatter: '散点图', |
| | | tree: '树形列表', |
| | | card: '卡片' |
| | | } |
| | | let i = 1 |
| | |
| | | .tab-shell-inner { |
| | | margin: -8px; |
| | | margin: 0px; |
| | | |
| | | >.ant-col { |
| | | padding: 8px; |
| | | } |
| | | .anticon { |
| | | cursor: unset; |
| | | } |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Input, Icon, Select } from 'antd' |
| | | import { Form, Row, Col, Input, Icon, Select, Radio } from 'antd' |
| | | |
| | | // import { formRule } from '@/utils/option.js' |
| | | import './index.scss' |
| | | |
| | | class SettingForm extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, // 字典项 |
| | | tab: PropTypes.object, // 数据源配置 |
| | | inputSubmit: PropTypes.func // 回车事件 |
| | | dict: PropTypes.object, |
| | | setting: PropTypes.object, |
| | | tab: PropTypes.object, |
| | | inputSubmit: PropTypes.func |
| | | } |
| | | |
| | | state = {roleList: []} |
| | | state = {roleList: [], appType: sessionStorage.getItem('appType')} |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | let roleList = sessionStorage.getItem('sysRoles') |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { tab } = this.props |
| | | const { tab, setting } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { roleList } = this.state |
| | | const { roleList, appType } = this.state |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {appType === 'mob' && setting.position === 'top' && setting.display === 'inline-block' ? <Col span={24}> |
| | | <Form.Item label="搜索"> |
| | | {getFieldDecorator('hasSearch', { |
| | | initialValue: tab.hasSearch || 'false' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="false">无</Radio> |
| | | <Radio value="icon">有</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={24}> |
| | | <Form.Item label="黑名单"> |
| | | {getFieldDecorator('blacklist', { |
| | |
| | | } |
| | | |
| | | state = { |
| | | appType: sessionStorage.getItem('appType'), |
| | | position: this.props.setting.position, |
| | | roleList: [] |
| | | } |
| | | |
| | |
| | | render() { |
| | | const { setting } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { roleList } = this.state |
| | | const { roleList, appType, position } = this.state |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | |
| | | {getFieldDecorator('position', { |
| | | initialValue: setting.position || 'top' |
| | | })( |
| | | <Select> |
| | | <Select onChange={(val) => this.setState({position: val})}> |
| | | <Select.Option key="top" value="top"> top </Select.Option> |
| | | <Select.Option key="bottom" value="bottom"> bottom </Select.Option> |
| | | <Select.Option key="left" value="left"> left </Select.Option> |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | {appType !== 'mob' ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="标签位置为top时有效,默认值为line。"> |
| | | <Icon type="question-circle" /> |
| | |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | </Col> : null} |
| | | {appType === 'mob' && (position === 'top' || position === 'bottom') ? <Col span={12}> |
| | | <Form.Item label="标签显示"> |
| | | {getFieldDecorator('display', { |
| | | initialValue: setting.display || 'flex' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="flex">弹性布局</Radio> |
| | | <Radio value="inline-block">定宽</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={12}> |
| | | <Form.Item label="黑名单"> |
| | | {getFieldDecorator('blacklist', { |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Popover, Tree } from 'antd' |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import MKEmitter from '@/utils/events.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 NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader')) |
| | | const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) |
| | | const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent')) |
| | | const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent')) |
| | | const WrapComponent = asyncIconComponent(() => import('./wrapsetting')) |
| | | |
| | | const { TreeNode } = Tree |
| | | |
| | | class AntdTree extends Component { |
| | | static propTpyes = { |
| | | card: PropTypes.object, |
| | | deletecomponent: PropTypes.func, |
| | | updateConfig: PropTypes.func, |
| | | } |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | card: null, |
| | | back: false |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { card } = this.props |
| | | |
| | | if (card.isNew) { |
| | | let _card = { |
| | | uuid: card.uuid, |
| | | type: card.type, |
| | | floor: card.floor, |
| | | tabId: card.tabId || '', |
| | | parentId: card.parentId || '', |
| | | dataName: card.dataName || '', |
| | | format: 'array', // 组件属性 - 数据格式 |
| | | pageable: false, // 组件属性 - 是否可分页 |
| | | switchable: true, // 组件属性 - 数据是否可切换 |
| | | width: card.width || 12, |
| | | name: card.name, |
| | | subtype: card.subtype, |
| | | setting: { interType: 'system' }, |
| | | wrap: { name: card.name, title: '', width: card.width || 12, showIcon: 'false', showLine: 'false', searchable: 'false' }, |
| | | style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' }, |
| | | headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' }, |
| | | columns: [], |
| | | scripts: [], |
| | | } |
| | | |
| | | if (card.config) { |
| | | let config = fromJS(card.config).toJS() |
| | | |
| | | _card.wrap = config.wrap |
| | | _card.wrap.name = card.name |
| | | _card.style = config.style |
| | | _card.headerStyle = config.headerStyle |
| | | } |
| | | |
| | | this.setState({ |
| | | card: _card |
| | | }) |
| | | this.props.updateConfig(_card) |
| | | } else { |
| | | this.setState({ |
| | | card: fromJS(card).toJS() |
| | | }) |
| | | } |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('submitStyle', this.getStyle) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新,清除快捷键设置 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('submitStyle', this.getStyle) |
| | | } |
| | | |
| | | /** |
| | | * @description 卡片行外层信息更新(数据源,样式等) |
| | | */ |
| | | updateComponent = (component) => { |
| | | this.setState({ |
| | | card: component |
| | | }) |
| | | |
| | | component.width = component.wrap.width |
| | | component.name = component.wrap.name |
| | | |
| | | this.props.updateConfig(component) |
| | | } |
| | | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['height', '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.setState({ |
| | | card: _card |
| | | }) |
| | | |
| | | this.props.updateConfig(_card) |
| | | } |
| | | |
| | | /** |
| | | * @description 更新搜索条件配置信息 |
| | | */ |
| | | updateconfig = (config) => { |
| | | this.setState({ |
| | | card: config |
| | | }) |
| | | this.props.updateConfig(config) |
| | | } |
| | | |
| | | 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-editor-sand-box" style={_style} 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"> |
| | | <WrapComponent config={card} updateConfig={this.updateComponent} /> |
| | | <CopyComponent type="normaltable" 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="删除组件" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> |
| | | <SettingComponent config={card} updateConfig={this.updateComponent} /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <Icon type="tool" /> |
| | | </Popover> |
| | | <div className="tree-box"> |
| | | <Tree defaultExpandAll={true} blockNode showIcon={card.wrap.showIcon === 'true'} showLine={card.wrap.showLine === 'true'} > |
| | | <TreeNode icon={<Icon type="folder-open" />} title="parent 0" key="0-0"> |
| | | <TreeNode icon={<Icon type="file" />} title="leaf 0-0" key="0-0-0" isLeaf /> |
| | | <TreeNode icon={<Icon type="file" />} title="leaf 0-1" key="0-0-1" isLeaf /> |
| | | </TreeNode> |
| | | <TreeNode icon={<Icon type="folder-open" />} title="parent 1" key="0-1"> |
| | | <TreeNode icon={<Icon type="file" />} title="leaf 1-0" key="0-1-0" isLeaf /> |
| | | <TreeNode icon={<Icon type="file" />} title="leaf 1-1" key="0-1-1" isLeaf /> |
| | | </TreeNode> |
| | | </Tree> |
| | | </div> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default AntdTree |
New file |
| | |
| | | .menu-editor-sand-box { |
| | | position: relative; |
| | | box-sizing: border-box; |
| | | background: #ffffff; |
| | | background-position: center center; |
| | | background-repeat: no-repeat; |
| | | background-size: cover; |
| | | min-height: 30px; |
| | | |
| | | .anticon-tool { |
| | | position: absolute; |
| | | z-index: 2; |
| | | font-size: 16px; |
| | | right: 1px; |
| | | top: 1px; |
| | | cursor: pointer; |
| | | padding: 5px; |
| | | background: rgba(255, 255, 255, 0.55); |
| | | } |
| | | .empty-content { |
| | | text-align: center; |
| | | font-size: 30px; |
| | | margin: 0; |
| | | line-height: 90px; |
| | | color: #bcbcbc; |
| | | } |
| | | } |
| | | .menu-editor-sand-box::after { |
| | | display: block; |
| | | content: ' '; |
| | | clear: both; |
| | | } |
| | | .menu-editor-sand-box:hover { |
| | | z-index: 1; |
| | | box-shadow: 0px 0px 4px #1890ff; |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Modal } from 'antd' |
| | | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import SettingForm from './settingform' |
| | | import './index.scss' |
| | | |
| | | class DataSource extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.any, |
| | | updateConfig: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | visible: false, |
| | | wrap: null |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { config } = this.props |
| | | |
| | | this.setState({wrap: fromJS(config.wrap).toJS()}) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | editDataSource = () => { |
| | | this.setState({ |
| | | visible: true |
| | | }) |
| | | } |
| | | |
| | | verifySubmit = () => { |
| | | const { config } = this.props |
| | | |
| | | this.verifyRef.handleConfirm().then(res => { |
| | | |
| | | this.setState({ |
| | | wrap: res, |
| | | visible: false |
| | | }) |
| | | this.props.updateConfig({...config, wrap: res}) |
| | | }) |
| | | } |
| | | |
| | | render () { |
| | | const { config } = this.props |
| | | const { visible, dict, wrap } = this.state |
| | | |
| | | return ( |
| | | <div className="model-menu-setting-wrap"> |
| | | <Icon type="edit" onClick={() => this.editDataSource()} /> |
| | | <Modal |
| | | wrapClassName="popview-modal" |
| | | title="基本设置" |
| | | visible={visible} |
| | | width={700} |
| | | maskClosable={false} |
| | | okText={dict['model.submit']} |
| | | onOk={this.verifySubmit} |
| | | onCancel={() => { this.setState({ visible: false }) }} |
| | | destroyOnClose |
| | | > |
| | | <SettingForm |
| | | dict={dict} |
| | | wrap={wrap} |
| | | config={config} |
| | | inputSubmit={this.verifySubmit} |
| | | wrappedComponentRef={(inst) => this.verifyRef = inst} |
| | | /> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default DataSource |
New file |
| | |
| | | .model-menu-setting-wrap { |
| | | display: inline-block; |
| | | |
| | | >.anticon-edit { |
| | | color: #1890ff; |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Input, Radio, Tooltip, Icon, InputNumber, Select } from 'antd' |
| | | |
| | | import './index.scss' |
| | | |
| | | class SettingForm extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, // 字典项 |
| | | config: PropTypes.object, // 卡片行信息 |
| | | wrap: PropTypes.object, // 数据源配置 |
| | | inputSubmit: PropTypes.func // 回车事件 |
| | | } |
| | | |
| | | state = { |
| | | roleList: [], |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | let roleList = sessionStorage.getItem('sysRoles') |
| | | if (roleList) { |
| | | try { |
| | | roleList = JSON.parse(roleList) |
| | | } catch { |
| | | roleList = [] |
| | | } |
| | | } else { |
| | | roleList = [] |
| | | } |
| | | |
| | | this.setState({roleList}) |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | | return new Promise((resolve, reject) => { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | resolve(values) |
| | | } else { |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | handleSubmit = (e) => { |
| | | e.preventDefault() |
| | | |
| | | if (this.props.inputSubmit) { |
| | | this.props.inputSubmit() |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { wrap, config } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { roleList } = this.state |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 8 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 16 } |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <div className="model-menu-setting-form"> |
| | | <Form {...formItemLayout}> |
| | | <Row gutter={24}> |
| | | <Col span={12}> |
| | | <Form.Item label="标题"> |
| | | {getFieldDecorator('title', { |
| | | initialValue: wrap.title || '' |
| | | })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="用于组件间的区分。"> |
| | | <Icon type="question-circle" /> |
| | | 组件名称 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('name', { |
| | | initialValue: wrap.name, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '组件名称!' |
| | | } |
| | | ] |
| | | })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="数据值字段。"> |
| | | <Icon type="question-circle" /> |
| | | Value |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('valueField', { |
| | | initialValue: wrap.valueField || '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + 'Value字段!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select> |
| | | {config.columns.map(option => |
| | | <Select.Option key={option.uuid} value={option.field}>{option.label}</Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="显示文字字段。"> |
| | | <Icon type="question-circle" /> |
| | | Label |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('labelField', { |
| | | initialValue: wrap.labelField || '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + 'Label字段!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select> |
| | | {config.columns.map(option => |
| | | <Select.Option key={option.uuid} value={option.field}>{option.label}</Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="父级字段。"> |
| | | <Icon type="question-circle" /> |
| | | Parent |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('parentField', { |
| | | initialValue: wrap.parentField || '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + 'Parent字段!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select> |
| | | {config.columns.map(option => |
| | | <Select.Option key={option.uuid} value={option.field}>{option.label}</Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title={'父级字段值与顶级标识相同时,视为顶级节点。'}> |
| | | <Icon type="question-circle" /> |
| | | 顶级标识 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('mark', { |
| | | initialValue: wrap.mark || '' |
| | | })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="栅格布局,每行等分为24列。"> |
| | | <Icon type="question-circle" /> |
| | | 宽度 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('width', { |
| | | initialValue: wrap.width || 24, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '宽度!' |
| | | } |
| | | ] |
| | | })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label="图标"> |
| | | {getFieldDecorator('showIcon', { |
| | | initialValue: wrap.showIcon || 'false' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="true">显示</Radio> |
| | | <Radio value="false">隐藏</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label="分割线"> |
| | | {getFieldDecorator('showLine', { |
| | | initialValue: wrap.showLine || 'false' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="true">显示</Radio> |
| | | <Radio value="false">隐藏</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label="过滤条件"> |
| | | {getFieldDecorator('searchable', { |
| | | initialValue: wrap.searchable || 'false' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="true">显示</Radio> |
| | | <Radio value="false">隐藏</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label="黑名单"> |
| | | {getFieldDecorator('blacklist', { |
| | | initialValue: wrap.blacklist || [] |
| | | })( |
| | | <Select |
| | | showSearch |
| | | mode="multiple" |
| | | filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} |
| | | > |
| | | {roleList.map(option => |
| | | <Select.Option key={option.uuid} value={option.value}>{option.text}</Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(SettingForm) |
New file |
| | |
| | | .model-menu-setting-form { |
| | | position: relative; |
| | | |
| | | .anticon-question-circle { |
| | | color: #c49f47; |
| | | margin-right: 3px; |
| | | } |
| | | .ant-input-number { |
| | | width: 100%; |
| | | } |
| | | .color-sketch-block { |
| | | position: relative; |
| | | top: 7px; |
| | | } |
| | | } |
| | |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | appType: sessionStorage.getItem('appType'), |
| | | sourcelist: [], |
| | | mainSearch: [], |
| | | visible: false, |
| | |
| | | |
| | | editDataSource = () => { |
| | | const { config } = this.props |
| | | const { appType } = this.state |
| | | |
| | | let search = [] |
| | | let parents = [] |
| | | let _conf = config |
| | | let getParents = (box) => { |
| | | box.components.forEach(item => { |
| | | if (item.type !== 'tabs') return |
| | | let menu = fromJS(window.GLOB.customMenu).toJS() |
| | | |
| | | item.subtabs.forEach(tab => { |
| | | if (_conf.parentId === tab.parentId && _conf.tabId === tab.uuid) { |
| | | parents.unshift(tab) |
| | | _conf = item |
| | | |
| | | if (_conf.parentId && _conf.tabId) { |
| | | getParents(tab) |
| | | } |
| | | } else { |
| | | getParents(tab) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | if (config.parentId && config.tabId) { |
| | | getParents(window.GLOB.customMenu) |
| | | } |
| | | |
| | | parents.unshift(window.GLOB.customMenu) |
| | | |
| | | parents.forEach(parent => { |
| | | parent.components.forEach(item => { |
| | | if (item.type === 'search') { |
| | | search = item.search |
| | | if (appType === 'mob') { |
| | | let ms = null |
| | | menu.components.forEach(item => { |
| | | if (item.type === 'topbar' && (item.wrap.type === 'search' || (item.wrap.type === 'navbar' && item.wrap.search === 'true'))) { |
| | | ms = item.search |
| | | } |
| | | }) |
| | | }) |
| | | |
| | | if (config.floor > 1) { |
| | | let _search = null |
| | | let filterComponent = (box) => { |
| | | box.components.forEach(item => { |
| | | if (_search) return |
| | | |
| | | if (item.uuid === config.uuid) { |
| | | _search = box.slist.pop() |
| | | } else if (item.type === 'group') { |
| | | item.components.forEach(m => { |
| | | if (m.uuid !== config.uuid) return |
| | | _search = box.slist.pop() |
| | | }) |
| | | } else if (item.type === 'tabs') { |
| | | let able = item.setting.display === 'inline-block' && item.setting.position === 'top' |
| | | item.subtabs.forEach(tab => { |
| | | if (able && tab.hasSearch === 'icon' && tab.search) { |
| | | tab.slist = [...box.slist, tab.search] |
| | | } else { |
| | | tab.slist = [...box.slist] |
| | | } |
| | | |
| | | filterComponent(tab) |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | menu.slist = [] |
| | | filterComponent(menu) |
| | | |
| | | if (_search) { |
| | | ms = _search |
| | | } |
| | | } |
| | | |
| | | if (ms) { |
| | | if (ms.setting.type === 'search') { |
| | | search.push({ |
| | | type: 'text', |
| | | label: '搜索栏', |
| | | field: ms.setting.field, |
| | | match: ms.setting.match, |
| | | required: ms.setting.required, |
| | | value: ms.setting.initval || '' |
| | | }) |
| | | } |
| | | ms.fields.forEach(item => { |
| | | if (item.type === 'range') { |
| | | item.initval = `${item.minValue},${item.maxValue}` |
| | | } |
| | | search.push(item) |
| | | }) |
| | | |
| | | ms.groups.forEach(group => { |
| | | if (group.setting.type === 'search') { |
| | | search.push({ |
| | | type: 'text', |
| | | label: group.wrap.name, |
| | | field: group.setting.field, |
| | | match: group.setting.match, |
| | | required: group.setting.required, |
| | | value: group.setting.initval || '' |
| | | }) |
| | | } |
| | | |
| | | group.fields.forEach(item => { |
| | | if (item.type === 'range') { |
| | | item.initval = `${item.minValue},${item.maxValue}` |
| | | } |
| | | search.push(item) |
| | | }) |
| | | }) |
| | | } |
| | | } else { |
| | | if (config.floor > 1) { |
| | | let _search = null |
| | | let filterComponent = (box) => { |
| | | box.components.forEach(item => { |
| | | if (_search) return |
| | | |
| | | if (item.type === 'search') { |
| | | box.slist = [...box.slist, item.search] |
| | | } else if (item.uuid === config.uuid) { |
| | | _search = box.slist.pop() |
| | | } else if (item.type === 'group') { |
| | | item.components.forEach(m => { |
| | | if (m.uuid !== config.uuid) return |
| | | _search = box.slist.pop() |
| | | }) |
| | | } else if (item.type === 'tabs') { |
| | | item.subtabs.forEach(tab => { |
| | | tab.slist = [...box.slist] |
| | | filterComponent(tab) |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | menu.slist = [] |
| | | filterComponent(menu) |
| | | |
| | | if (_search) { |
| | | search = _search |
| | | } |
| | | } else { |
| | | menu.components.forEach(item => { |
| | | if (item.type !== 'search') return |
| | | search = item.search |
| | | }) |
| | | } |
| | | } |
| | | |
| | | this.setState({ |
| | | visible: true, |
| | |
| | | return item |
| | | }) |
| | | } |
| | | |
| | | |
| | | if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { |
| | | window.GLOB.funcs.forEach(m => { |
| | | let reg = new RegExp('\\$ex@' + m.func_code + '@ex\\$', 'ig') |
| | | if (res.setting.dataresource) { |
| | | res.setting.dataresource = res.setting.dataresource.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`) |
| | | } |
| | | res.scripts.forEach(item => { |
| | | item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | this.setState({loading: false, visible: false}) |
| | | this.props.updateConfig({...config, ...res}) |
| | | }, () => { |
| | |
| | | if (!item.field) return |
| | | |
| | | if (item.type === 'group') { |
| | | if (item.transfer === 'true') { |
| | | _usefulFields.push(item.field) |
| | | } |
| | | _usefulFields.push(item.field) |
| | | _usefulFields.push(item.datefield) |
| | | _usefulFields.push(item.datefield + '1') |
| | | } else if (['dateweek', 'datemonth', 'daterange'].includes(item.type)) { |
| | |
| | | if (!item.field) return |
| | | |
| | | if (item.type === 'group') { |
| | | if (item.transfer === 'true') { |
| | | _usefulFields.push(item.field) |
| | | } |
| | | _usefulFields.push(item.field) |
| | | _usefulFields.push(item.datefield) |
| | | _usefulFields.push(item.datefield + '1') |
| | | } else if (['dateweek', 'datemonth', 'daterange'].includes(item.type)) { |
| | |
| | | </Col> |
| | | <Col span={24} className="sqlfield"> |
| | | <Form.Item label={'可用字段'}> |
| | | id, bid, loginuid, sessionuid, userid, username, fullname, login_city, appkey, time_id, orderBy, pageSize, pageIndex{usefulFields ? ', ' + usefulFields : ''} |
| | | id, bid, loginuid, sessionuid, userid, username, fullname, login_city, appkey, time_id, orderBy, pageSize, pageIndex{usefulFields ? ', ' + usefulFields : ''}{window.GLOB.urlFields && window.GLOB.urlFields.length > 0 ? ', ' + window.GLOB.urlFields.join(', ') : ''} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={10} style={{width: '43%'}}> |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { fromJS } from 'immutable' |
| | | import { Form, Tabs, Popconfirm, Icon, notification, Modal, Typography, Spin } from 'antd' |
| | | import { Form, Tabs, Popconfirm, Icon, notification, Modal, Typography, Spin, message } from 'antd' |
| | | import moment from 'moment' |
| | | |
| | | import Api from '@/api' |
| | |
| | | initsql: '', // sql验证时变量声明及赋值 |
| | | usefulfields: '', |
| | | defaultsql: '', // 默认Sql |
| | | defaultSearch: '', |
| | | systemScripts: [], |
| | | colColumns: [ |
| | | { |
| | |
| | | inputType: 'input', |
| | | editable: true, |
| | | unique: true, |
| | | copy: true, |
| | | width: '28%' |
| | | }, |
| | | { |
| | |
| | | getcomponentmarks(menu, config) |
| | | |
| | | let _setting = fromJS(config.setting).toJS() |
| | | let scripts = fromJS(config.scripts).toJS() |
| | | |
| | | if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { |
| | | window.GLOB.funcs.forEach(m => { |
| | | let reg = new RegExp(`\\/\\*\\$ex@${m.func_code}-begin\\*\\/[\\s\\S]+\\/\\*@ex\\$-end\\*\\/`, 'ig') |
| | | if (_setting.dataresource) { |
| | | _setting.dataresource = _setting.dataresource.replace(reg, `$ex@${m.func_code}@ex$`) |
| | | } |
| | | scripts && scripts.forEach(item => { |
| | | item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | let _search = this.formatSearch(search) |
| | | _search = Utils.joinMainSearchkey(_search) |
| | | |
| | | _search = _search.replace(/@\$@/ig, '') |
| | | _search = _search ? 'where ' + _search : '' |
| | | |
| | | this.setState({ |
| | | scripts, |
| | | columns: fromJS(config.columns).toJS(), |
| | | setting: _setting, |
| | | scripts: fromJS(config.scripts).toJS(), |
| | | searches: search, |
| | | defaultSearch: _search, |
| | | varMarks: Marks |
| | | }) |
| | | |
| | |
| | | return |
| | | } |
| | | |
| | | let _search = this.formatSearch(search) |
| | | _search = Utils.joinMainSearchkey(_search) |
| | | |
| | | _search = _search.replace(/@\$@/ig, '') |
| | | _search = _search ? 'where ' + _search : '' |
| | | |
| | | this.setState({ |
| | | searches: search, |
| | | defaultSearch: _search, |
| | | setting: res |
| | | }, () => { |
| | | this.sqlverify(() => { // 验证成功 |
| | |
| | | } |
| | | |
| | | getdefaultSql = () => { |
| | | const { columns, searches, setting } = this.state |
| | | const { columns, setting, defaultSearch } = this.state |
| | | let defaultsql = '' |
| | | let arr_field = columns.map(col => col.field).join(',') |
| | | |
| | | let _search = this.formatSearch(searches) |
| | | _search = Utils.joinMainSearchkey(_search) |
| | | |
| | | _search = _search.replace(/@\$@/ig, '') |
| | | _search = _search ? 'where ' + _search : '' |
| | | |
| | | if (setting.dataresource) { |
| | | let _dataresource = setting.dataresource |
| | |
| | | _dataresource = '(' + _dataresource + ') tb' |
| | | } |
| | | |
| | | defaultsql = `select top @pageSize@ ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by @orderBy@) as rows from ${_dataresource} ${_search}) tmptable where rows > (@pageSize@ * (@pageIndex@ - 1)) order by tmptable.rows` |
| | | defaultsql = `select top @pageSize@ ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by @orderBy@) as rows from ${_dataresource} ${defaultSearch}) tmptable where rows > (@pageSize@ * (@pageIndex@ - 1)) order by tmptable.rows` |
| | | } |
| | | |
| | | this.setState({defaultsql}) |
| | |
| | | * @param {Array} searches 搜索条件数组 |
| | | */ |
| | | formatSearch (searches) { |
| | | if (!searches || searches.length === 0) return [] |
| | | if (!searches) return [] |
| | | |
| | | let newsearches = [] |
| | | searches.forEach(search => { |
| | |
| | | required: search.required === 'true' |
| | | } |
| | | if (item.type === 'group') { |
| | | let copy = fromJS(item).toJS() |
| | | copy.key = search.datefield |
| | | item.key = search.datefield |
| | | item.type = 'daterange' |
| | | item.match = 'between' |
| | | item.value = [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')].join(',') |
| | | |
| | | item.value = search.initval && search.initval[0] ? search.initval[0] : '@$@' |
| | | item.match = '=' |
| | | |
| | | copy.type = 'daterange' |
| | | copy.match = 'between' |
| | | copy.value = [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')] |
| | | |
| | | if (search.transfer === 'true') { |
| | | newsearches.push(item) |
| | | } |
| | | newsearches.push(copy) |
| | | newsearches.push(item) |
| | | return |
| | | } else if (item.type === 'date') { |
| | | item.value = moment().format('YYYY-MM-DD') |
| | | } else if (item.type === 'datemonth') { |
| | | item.value = moment().format('YYYY-MM') |
| | | } else if (item.type === 'dateweek') { |
| | | item.value = [moment().startOf('week').format('YYYY-MM-DD'), moment().endOf('week').format('YYYY-MM-DD')] |
| | | item.value = moment().format('YYYY-MM-DD') |
| | | } else if (item.type === 'daterange') { |
| | | item.value = [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')] |
| | | } else if (item.type === 'multiselect') { |
| | | item.value = ['@$@'] |
| | | item.value = [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')].join(',') |
| | | } else if (item.type === 'range') { |
| | | |
| | | } else if (item.type === 'multiselect' || (item.type === 'checkcard' && search.multiple === 'true')) { |
| | | item.type = 'multi' |
| | | item.value = '@$@' |
| | | } else { |
| | | item.value = '@$@' |
| | | } |
| | | newsearches.push(item) |
| | | }) |
| | | |
| | | |
| | | return newsearches |
| | | } |
| | | |
| | |
| | | return |
| | | } |
| | | |
| | | let _search = this.formatSearch(search) |
| | | _search = Utils.joinMainSearchkey(_search) |
| | | |
| | | _search = _search.replace(/@\$@/ig, '') |
| | | _search = _search ? 'where ' + _search : '' |
| | | |
| | | this.setState({ |
| | | searches: search, |
| | | defaultSearch: _search, |
| | | setting: res |
| | | }, () => { |
| | | this.sqlverify(() => { resolve({setting: res, columns, scripts }) }, reject, false) |
| | |
| | | } |
| | | |
| | | sqlverify = (resolve, reject, change = false, testScripts) => { |
| | | const { columns, setting, scripts, searches } = this.state |
| | | const { columns, setting, scripts, searches, defaultSearch } = this.state |
| | | |
| | | let _scripts = scripts.filter(item => item.status !== 'false') |
| | | |
| | |
| | | } |
| | | |
| | | if ((setting.interType === 'system' && setting.execute !== 'false') || _scripts.length > 0) { |
| | | let result = SettingUtils.getDebugSql(setting, _scripts, columns, searches) |
| | | let result = SettingUtils.getDebugSql(setting, _scripts, columns, searches, defaultSearch) |
| | | |
| | | if (result.error) { |
| | | notification.warning({ |
| | |
| | | }) |
| | | } |
| | | |
| | | copyColumns = () => { |
| | | const { columns } = this.state |
| | | let m = [] |
| | | let n = [] |
| | | |
| | | columns.forEach(col => { |
| | | m.push(`${col.field}(${col.label})`) |
| | | n.push(col.field) |
| | | }) |
| | | |
| | | let oInput = document.createElement('input') |
| | | oInput.value = `/*${m.join(',')}*/ |
| | | ${n.join(',')}` |
| | | document.body.appendChild(oInput) |
| | | oInput.select() |
| | | document.execCommand('Copy') |
| | | document.body.removeChild(oInput) |
| | | |
| | | message.success('复制成功。') |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新 |
| | | */ |
| | |
| | | type="fields" |
| | | updatefield={this.updatefields} |
| | | /> |
| | | <Icon type="copy" onClick={this.copyColumns} style={{position: 'absolute', cursor: 'pointer', zIndex: 1, top: '-35px', right: '0px', color: '#1890ff'}} /> |
| | | <EditTable actions={['edit', 'move', 'copy', 'del']} type="datasourcefield" data={columns} columns={colColumns} onChange={(columns) => this.setState({columns})}/> |
| | | </TabPane> |
| | | <TabPane tab={ |
| | |
| | | import CodeMirror from '@/templates/zshare/codemirror' |
| | | import './index.scss' |
| | | |
| | | const { TextArea } = Input |
| | | |
| | | class SettingForm extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, // 字典项 |
| | |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '表名!' |
| | | }, |
| | | { |
| | | max: 50, |
| | | message: '表名最长为50个字符!' |
| | | } |
| | | ] |
| | | })(<Input placeholder={''} autoComplete="off" />)} |
| | | </Form.Item> |
| | |
| | | })(<Input placeholder={''} autoComplete="off" />)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {interType === 'outer' ? <Col span={8}> |
| | | {interType === 'outer' ? <Col className="outer-interface" span={24}> |
| | | <Form.Item label="接口地址"> |
| | | {getFieldDecorator('interface', { |
| | | initialValue: setting.interface || '', |
| | |
| | | message: this.props.dict['form.required.input'] + '接口地址!' |
| | | } |
| | | ] |
| | | })(<Input placeholder={''} autoComplete="off" />)} |
| | | })(<TextArea rows={2}/>)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {interType === 'outer' ? <Col className="outer-interface" span={24}> |
| | | <Form.Item label={<Tooltip placement="topLeft" title="正式系统接口地址,为空时使用接口地址"> |
| | | <Icon type="question-circle" /> |
| | | 正式地址 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('proInterface', { |
| | | initialValue: setting.proInterface || '' |
| | | })(<TextArea rows={2}/>)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {interType === 'outer' ? <Col span={8}> |
| | |
| | | </Col> : null} |
| | | {interType === 'system' ? <Col span={24} className="data-source" style={{paddingLeft: '7px'}}> |
| | | <Form.Item labelCol={{xs: { span: 24 }, sm: { span: 2 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 22 }} } label={ |
| | | <Tooltip placement="topLeft" title={'使用系统函数时,需填写数据源。注:数据权限替换符 $@ -> /* 或 \'\'、 @$ -> */ 或 \'\''}> |
| | | <Tooltip placement="topLeft" title={`使用系统函数时,需填写数据源。注:数据权限替换符 $@ -> /* 或 ''、 @$ -> */ 或 '';查询替换符 $select@ -> /* 或 ''、 @select$ -> */ 或 '';统计替换符 $sum@ -> /* 或 ''、 @sum$ -> */ 或 ''。`}> |
| | | <Icon type="question-circle" /> |
| | | 数据源 |
| | | </Tooltip> |
| | |
| | | </Radio.Group>)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={8}> |
| | | {config.type !== 'navbar' && config.type !== 'balcony' ? <Col span={8}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title={'该组件如果受其他组件控制,请选项相应的组件,没有时选“无”。'}> |
| | | <Icon type="question-circle" /> |
| | |
| | | <Cascader options={modules} onChange={this.changeSupModule} expandTrigger="hover" placeholder="" /> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | </Col> : null} |
| | | {config.pageable ? <Col span={8}> |
| | | <Form.Item label="分页"> |
| | | {getFieldDecorator('laypage', { |
| | |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {/* 1、不分页且不存在上级模块 */} |
| | | {(!config.pageable || (config.pageable && laypage === 'false')) && (!supModule || supModule.length === 0 || supModule[0] === 'empty') ? <Col span={8}> |
| | | {config.type !== 'navbar' && (!config.pageable || (config.pageable && laypage === 'false')) && (!supModule || supModule.length === 0 || supModule[0] === 'empty') ? <Col span={8}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title={'初始化加载时,是否与其他组件一同加载数据,注:仅在使用系统函数,且初始化加载数据时有效,分页请求时无效。'}> |
| | | <Icon type="question-circle" /> |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={8}> |
| | | {config.type !== 'navbar' && config.type !== 'balcony' ? <Col span={8}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title={'优先使用同级的搜索条件组件,同级搜索不存在时,依次向上选取,与当前组件的搜索条件一同用作数据过滤(当前组件的搜索条件优先)。'}> |
| | | <Icon type="question-circle" /> |
| | |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {useMSearch === 'true' ? <Col span={8}> |
| | | </Col> : null} |
| | | {config.type !== 'navbar' && config.type !== 'balcony' && useMSearch === 'true' ? <Col span={8}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title={'外层搜索条件改变时,是否刷新当前组件数据。'}> |
| | | <Icon type="question-circle" /> |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={8}> |
| | | {config.type !== 'navbar' && config.type !== 'balcony' ? <Col span={8}> |
| | | <Form.Item label="初始化数据"> |
| | | {getFieldDecorator('onload', { |
| | | initialValue: setting.onload || 'true' |
| | |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | </Col> : null} |
| | | </Row> |
| | | </Form> |
| | | </div> |
| | |
| | | .ant-radio-group { |
| | | white-space: nowrap; |
| | | } |
| | | .outer-interface { |
| | | .ant-form-item-label { |
| | | width: 10.5%; |
| | | } |
| | | .ant-form-item-control-wrapper { |
| | | width: 89.5%; |
| | | } |
| | | } |
| | | } |
| | |
| | | * @return {Object} setting 页面设置 |
| | | * @return {Array} columns 显示字段 |
| | | */ |
| | | static getDebugSql (setting, scripts, columns, searches = []) { |
| | | static getDebugSql (setting, scripts, columns, searches = [], defSearch) { |
| | | let sql = '' |
| | | let error = '' |
| | | let _dataresource = '' |
| | |
| | | _dataresource = setting.dataresource || '' |
| | | } |
| | | |
| | | if (window.GLOB.funcs && window.GLOB.funcs.length > 0) { |
| | | window.GLOB.funcs.forEach(item => { |
| | | let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig') |
| | | _dataresource = _dataresource.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`) |
| | | _customScript = _customScript.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`) |
| | | }) |
| | | } |
| | | |
| | | _dataresource = _dataresource.replace(/@\$|\$@/ig, '') |
| | | _customScript = _customScript.replace(/@\$|\$@/ig, '') |
| | | _dataresource = _dataresource.replace(/@select\$|\$select@/ig, '') |
| | | _customScript = _customScript.replace(/@select\$|\$select@/ig, '') |
| | | _dataresource = _dataresource.replace(/@sum\$|\$sum@/ig, '') |
| | | _customScript = _customScript.replace(/@sum\$|\$sum@/ig, '') |
| | | |
| | | if (_customScript) { |
| | | _customScript = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@login_city nvarchar(50) select @ErrorCode='',@retmsg ='' |
| | |
| | | _customScript = _customScript.replace(reg, '0') |
| | | }) |
| | | } |
| | | |
| | | |
| | | |
| | | // 正则替换 |
| | | let _regoptions = [] |
| | | let _fields = [] |
| | |
| | | reg: new RegExp('@' + item.datefield + '1@', 'ig') |
| | | }) |
| | | } |
| | | if (['dateweek', 'datemonth', 'daterange'].includes(item.type)) { |
| | | if (['dateweek', 'datemonth', 'daterange', 'range'].includes(item.type)) { |
| | | _regoptions.push({ |
| | | var: new RegExp('@' + item.field, 'ig'), |
| | | reg: new RegExp('@' + item.field + '@', 'ig') |
| | |
| | | } |
| | | }) |
| | | |
| | | let _search = '' |
| | | let _search = defSearch |
| | | |
| | | if (setting.queryType === 'statistics' && _dataresource) { |
| | | _regoptions.forEach(item => { |
| | |
| | | }, { |
| | | reg: new RegExp('@FullName@', 'ig'), |
| | | }) |
| | | if (setting.laypage !== 'false') { |
| | | if (setting.laypage === 'true') { |
| | | _regoptions.push({ |
| | | reg: new RegExp('@pageSize@', 'ig'), |
| | | }, { |
| | |
| | | if (setting.varMark) { |
| | | originscript = originscript.replace(/@ErrorCode/ig, '') |
| | | originscript = originscript.replace(/@retmsg/ig, '') |
| | | originscript = originscript.replace(/@UserName@/ig, '').replace(/@UserName/ig, '') |
| | | originscript = originscript.replace(/@FullName@/ig, '').replace(/@FullName/ig, '') |
| | | originscript = originscript.replace(/@login_city@/ig, '').replace(/@login_city/ig, '') |
| | | originscript = originscript.replace(/@id@/ig, '').replace(/@id/ig, '') |
| | | originscript = originscript.replace(/@bid@/ig, '').replace(/@bid/ig, '') |
| | | originscript = originscript.replace(/@loginuid@/ig, '').replace(/@loginuid/ig, '') |
| | |
| | | _dataresource = '(' + _dataresource + ') tb' |
| | | } |
| | | |
| | | _dataresource = `select${setting.laypage !== 'false' ? ' top 10' : ''} ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable ${setting.laypage !== 'false' ? 'where rows > 0' : ''} order by tmptable.rows` |
| | | if (setting.order) { |
| | | _dataresource = `select${setting.laypage === 'true' ? ' top 10' : ''} ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable ${setting.laypage === 'true' ? 'where rows > 0' : ''} order by tmptable.rows` |
| | | } else { |
| | | _dataresource = `select${setting.laypage === 'true' ? ' top 10' : ''} ${arr_field} from ${_dataresource} ${_search}` |
| | | } |
| | | } |
| | | |
| | | if (_customScript) { |
| | |
| | | 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 AntvScatter = asyncComponent(() => import('@/menu/components/chart/antv-scatter')) |
| | | 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')) |
| | | const Balcony = asyncComponent(() => import('@/menu/components/card/balcony')) |
| | | const NormalTree = asyncComponent(() => import('@/menu/components/tree/antd-tree')) |
| | | const CarouselDataCard = asyncComponent(() => import('@/menu/components/carousel/data-card')) |
| | | const CarouselPropCard = asyncComponent(() => import('@/menu/components/carousel/prop-card')) |
| | | const TableCard = asyncComponent(() => import('@/menu/components/card/table-card')) |
| | |
| | | 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 === 'tree') { |
| | | return (<NormalTree card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'scatter') { |
| | | return (<AntvScatter card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'form') { |
| | | return (<NormalForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'tabs') { |
| | |
| | | return (<BraftEditor card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'code') { |
| | | return (<CodeSandbox card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'balcony') { |
| | | return (<Balcony card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } |
| | | } |
| | | return ( |
| | |
| | | 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] |
| | |
| | | content: hasComponent ? '当前组件中含有子组件!' : '', |
| | | onOk() { |
| | | const _cards = cards.filter(item => item.uuid !== card.uuid) |
| | | MKEmitter.emit('delButtons', uuids) |
| | | handleList({...menu, components: _cards}) |
| | | setCards(_cards) |
| | | |
| | | if (uuids.length === 0) return |
| | | |
| | | MKEmitter.emit('delButtons', uuids) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | |
| | | code: '自定义', |
| | | carousel: '轮播', |
| | | form: '表单', |
| | | dashboard: '仪表盘', |
| | | scatter: '散点图', |
| | | tree: '树形列表', |
| | | balcony: '浮动卡', |
| | | card: '卡片' |
| | | } |
| | | let i = 1 |
| | |
| | | handleSave = (modal) => { |
| | | const { config, btn } = this.state |
| | | MKEmitter.emit('submitModal', config, btn, modal) |
| | | |
| | | this.setState({ |
| | | visible: false, |
| | | config: null, |
| | | btn: null |
| | | }) |
| | | } |
| | | |
| | | render () { |
| | |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import { getModalForm } from '@/templates/zshare/formconfig' |
| | | |
| | | import ModalForm from '@/templates/zshare/modalform' |
| | | import SourceElement from '@/templates/modalconfig/dragelement/source' |
| | | import SettingForm from '@/templates/modalconfig/settingform' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | |
| | | const { Panel } = Collapse |
| | | const { confirm } = Modal |
| | | const CommonDict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS |
| | | const ModalForm = asyncComponent(() => import('@/templates/zshare/modalform')) |
| | | const EditComponent = asyncComponent(() => import('@/templates/zshare/editcomponent')) |
| | | const DragElement = asyncComponent(() => import('@/templates/modalconfig/dragelement')) |
| | | const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent')) |
| | |
| | | dict: CommonDict, // 字典 |
| | | config: null, // 页面配置,包括模板类型、模态框设置、添加表名、表单列表 |
| | | visible: false, // 表单编辑模态框,显示控制 |
| | | tableVisible: false, // 数据表字段列表模态框,显示控制 |
| | | tableColumns: [], // 表格字段名列表 |
| | | fields: null, // 表单,可选字段(去重后) |
| | | formlist: null, // 表单编辑模态框,可编辑字段 |
| | | card: null, // 编辑元素 |
| | | closeloading: false, // 菜单保存中 |
| | | settingVisible: false, // 全局配置模态框 |
| | | closeVisible: false, // 关闭模态框 |
| | | tables: [], // 可用表名 |
| | | selectedTables: [], // 已选表名 |
| | | originConfig: null, // 原始菜单 |
| | | sources: null, // 表单类型 |
| | | sqlVerifing: false, // sql验证 |
| | | openEdition: '', // 编辑版本标记,防止多人操作 |
| | | showField: false, // 显示表单字段值 |
| | | standardform: null |
| | | } |
| | |
| | | if (card.uuid === item.uuid) { |
| | | index = i |
| | | } |
| | | if (item.type !== 'select' && item.type !== 'link' && item.type !== 'radio') return |
| | | if (!['select', 'link', 'radio', 'checkcard'].includes(item.type)) return |
| | | if (item.field && !uniq.has(item.field)) { |
| | | uniq.set(item.field, true) |
| | | |
| | |
| | | |
| | | _config.fields = _config.fields.filter(item => !item.origin) |
| | | |
| | | if ((res.type === 'select' || res.type === 'multiselect' || res.type === 'link') && res.resourceType === '1' && /\s/.test(res.dataSource)) { |
| | | if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) { |
| | | this.setState({ |
| | | sqlVerifing: true |
| | | }) |
| | |
| | | submitConfig = () => { |
| | | const { config } = this.state |
| | | |
| | | this.setState({originConfig: fromJS(config).toJS()}) |
| | | this.props.handleSave(config) |
| | | notification.success({ |
| | | top: 92, |
| | | message: '保存成功。', |
| | | duration: 2 |
| | | }) |
| | | } |
| | | |
| | | cancelConfig = () => { |
| | | const { config, originConfig } = this.state |
| | | |
| | | if (!is(fromJS(config), fromJS(originConfig))) { |
| | | this.setState({ |
| | | closeVisible: true |
| | | let _this = this |
| | | confirm({ |
| | | content: '配置信息未保存,确定返回吗?', |
| | | onOk() { |
| | | _this.props.handleBack() |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } else { |
| | | this.props.handleBack() |
| | |
| | | <Card title={dict['header.menu.form.configurable']} bordered={false} extra={ |
| | | <div> |
| | | <EditComponent dict={dict} options={['form']} config={this.state.config} refresh={(res) => this.updateConfig(res.config)}/> |
| | | <Button type="primary" onClick={this.submitConfig}>{dict['model.confirm']}</Button> |
| | | <Button onClick={this.cancelConfig}>{dict['model.cancel']}</Button> |
| | | <Button type="primary" onClick={this.submitConfig}>保存</Button> |
| | | <Button onClick={this.cancelConfig}>返回</Button> |
| | | </div> |
| | | } style={{ width: '100%' }}> |
| | | <Icon type="setting" onClick={this.changeSetting} /> |
| | |
| | | <Modal |
| | | title={this.state.dict['model.edit']} |
| | | visible={this.state.settingVisible} |
| | | width={700} |
| | | width={850} |
| | | maskClosable={false} |
| | | onOk={this.settingSave} |
| | | onCancel={() => { this.setState({ settingVisible: false }) }} |
| | |
| | | inputSubmit={this.settingSave} |
| | | wrappedComponentRef={(inst) => this.settingRef = inst} |
| | | /> |
| | | </Modal> |
| | | <Modal |
| | | bodyStyle={{textAlign: 'center', color: '#000000', fontSize: '16px'}} |
| | | closable={false} |
| | | maskClosable={false} |
| | | visible={this.state.closeVisible} |
| | | 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.props.handleBack}>{this.state.dict['model.notsave']}</Button>, |
| | | <Button key="cancel" onClick={() => { this.setState({closeVisible: false}) }}>{this.state.dict['model.cancel']}</Button> |
| | | ]} |
| | | destroyOnClose |
| | | > |
| | | {this.state.dict['header.menu.config.placeholder']} |
| | | </Modal> |
| | | </div> |
| | | ) |
| | |
| | | .ant-card-body { |
| | | position: relative; |
| | | padding: 0; |
| | | |
| | | .modal-fields-row.up_down { |
| | | .ant-form-item { |
| | | display: block!important; |
| | | .ant-form-item-label { |
| | | width: 100%!important; |
| | | text-align: left; |
| | | } |
| | | .ant-form-item-control-wrapper { |
| | | width: 100%!important; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .ant-modal-content { |
| | | max-width: 95%; |
| | | margin: 0 auto; |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | .modal-fields { |
| | | .ant-modal { |
| | | top: 50px; |
| | |
| | | c_id: item.uuid, |
| | | images: '', |
| | | c_name: item.title, |
| | | typename: sessionStorage.getItem('appType') || '', |
| | | long_param: '', |
| | | del_type: 'Y' |
| | | }).then(result => { |
| | |
| | | import Editor from '@/assets/mobimg/editor.png' |
| | | import SandBox from '@/assets/mobimg/sandbox.png' |
| | | import Pie1 from '@/assets/mobimg/ring.png' |
| | | import Pie3 from '@/assets/mobimg/nest.png' |
| | | import Pie2 from '@/assets/mobimg/nightingale.png' |
| | | import Mainsearch from '@/assets/mobimg/mainsearch.png' |
| | | 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' |
| | | import ratioboard from '@/assets/mobimg/ratioboard.png' |
| | | import scatter from '@/assets/mobimg/scatter.png' |
| | | import tree from '@/assets/mobimg/tree.png' |
| | | |
| | | // 组件配置信息 |
| | | export const menuOptions = [ |
| | |
| | | { type: 'menu', url: Mainsearch, component: 'search', subtype: 'mainsearch', title: '搜索条件', width: 24, forbid: ['billPrint'] }, |
| | | { type: 'menu', url: card1, component: 'card', subtype: 'datacard', title: '数据卡', width: 24 }, |
| | | { type: 'menu', url: card2, component: 'card', subtype: 'propcard', title: '属性卡', width: 24 }, |
| | | { type: 'menu', url: card2, component: 'balcony', subtype: 'balcony', title: '可浮动卡', width: 24 }, |
| | | { type: 'menu', url: form, component: 'form', subtype: 'stepform', title: '表单', width: 24 }, |
| | | { type: 'menu', url: Carousel, component: 'carousel', subtype: 'datacard', title: '轮播-动态数据', width: 24, forbid: ['billPrint'] }, |
| | | { type: 'menu', url: Carousel1, component: 'carousel', subtype: 'propcard', title: '轮播-静态数据', width: 24, forbid: ['billPrint'] }, |
| | | { type: 'menu', url: NormalTable, component: 'table', subtype: 'normaltable', title: '常用表', width: 24 }, |
| | | { type: 'menu', url: TableCard, component: 'table', subtype: 'tablecard', title: '表格', width: 12 }, |
| | | { type: 'menu', url: tree, component: 'tree', subtype: 'normaltree', title: '树形列表', width: 12 }, |
| | | { type: 'menu', url: line, component: 'line', subtype: 'line', title: '折线图', width: 24 }, |
| | | { type: 'menu', url: line1, component: 'line', subtype: 'line1', title: '阶梯折线图', width: 24 }, |
| | | { type: 'menu', url: bar, component: 'bar', subtype: 'bar', title: '柱状图', width: 24 }, |
| | | { 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: Pie3, component: 'pie', subtype: 'nest', 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: ratioboard, component: 'dashboard', subtype: 'ratioboard', title: '占比图', width: 12 }, |
| | | { type: 'menu', url: scatter, component: 'scatter', subtype: 'scatter', title: '散点图', width: 24 }, |
| | | { 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'] }, |
| | | ] |
| | |
| | | cell = this.resetconfig(cell, item, true, copyBtns) |
| | | return cell |
| | | }) |
| | | } else if (item.type === 'menubar') { |
| | | item.subMenus = item.subMenus.map(cell => { |
| | | cell.uuid = Utils.getuuid() |
| | | return cell |
| | | }) |
| | | } else if (item.type === 'card' || (item.type === 'table' && item.subtype === 'tablecard')) { |
| | | item.subcards.forEach(card => { |
| | | item.subcards && item.subcards.forEach(card => { |
| | | card.uuid = Utils.getuuid() |
| | | if (card.elements) { |
| | | if (sessionStorage.getItem('editMenuType') === 'popview') { |
| | |
| | | item.btnlog = [] |
| | | } |
| | | |
| | | let oriUids = {} |
| | | if (item.action) { |
| | | if (sessionStorage.getItem('editMenuType') === 'popview') { |
| | | item.action = item.action.filter(c => c.OpenType !== 'popview' && c.OpenType !== 'funcbutton') |
| | | } |
| | | item.action = item.action.map(cell => { |
| | | let _uuid = Utils.getuuid() |
| | | |
| | | oriUids[cell.uuid] = _uuid |
| | | |
| | | if (cell.OpenType === 'popview') { |
| | | let _cell = fromJS(cell).toJS() |
| | | _cell.$originUuid = _cell.uuid |
| | |
| | | return cell |
| | | }) |
| | | } |
| | | if (item.setting && item.setting.supModule) { |
| | | item.setting.supModule = '' |
| | | } |
| | | |
| | | if (item.wrap && item.wrap.doubleClick) { |
| | | item.wrap.doubleClick = oriUids[item.wrap.doubleClick] || '' |
| | | } |
| | | |
| | | return item |
| | | } |
| | |
| | | const { Tab } = this.props |
| | | |
| | | let isgroup = Tab && Tab.type === 'group' ? true : false |
| | | let options = ['tabs', 'datacard', 'propcard', 'mainsearch', 'group', 'normaltable', 'tablecard', 'line', 'bar', 'pie', 'dashboard', 'scatter'] |
| | | |
| | | if (sessionStorage.getItem('appType') === 'mob') { |
| | | options.push('menubar') |
| | | } |
| | | this.pasteFormRef.handleConfirm().then(res => { |
| | | if (!isgroup && !['tabs', 'datacard', 'propcard', 'mainsearch', 'group', 'normaltable', 'tablecard', 'line', 'bar', 'pie'].includes(res.copyType)) { |
| | | if (!isgroup && !options.includes(res.copyType)) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '配置信息格式错误!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } else if (isgroup && !['datacard', 'propcard', 'normaltable', 'tablecard', 'line', 'bar', 'pie'].includes(res.copyType)) { |
| | | } else if (isgroup && !['datacard', 'propcard', 'normaltable', 'tablecard', 'line', 'bar', 'pie', 'dashboard', 'scatter'].includes(res.copyType)) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '配置信息格式错误!', |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Input, Radio, notification } from 'antd' |
| | | import { Form, Row, Col, Input, Radio } from 'antd' |
| | | |
| | | import FileUpload from '@/tabviews/zshare/fileupload' |
| | | import './index.scss' |
| | |
| | | } |
| | | |
| | | state = { |
| | | urls: [], |
| | | linkurl: '', |
| | | plusType: 'upload' |
| | | } |
| | |
| | | return new Promise((resolve, reject) => { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | if (values.urls && values.urls[0].status === 'error') { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '请重新上传文件!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } else if (values.urls && values.urls[0] && values.urls[0].status !== 'done') { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '文件上传中,请稍后!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } else if (values.urls && values.urls[0] && values.urls[0].response) { |
| | | values.linkurl = values.urls[0].response |
| | | } else { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '未获取到文件路径!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | if (values.urls) { |
| | | values.linkurl = values.urls |
| | | } |
| | | resolve(values) |
| | | } else { |
| | |
| | | } |
| | | |
| | | changeType = (val) => { |
| | | const { linkurl, urls } = this.state |
| | | let _urls = this.props.form.getFieldValue('urls') || '' |
| | | let _url = this.props.form.getFieldValue('linkurl') || '' |
| | | let _url = '' |
| | | |
| | | if (val === 'input') { |
| | | if (_urls && _urls[0] && _urls[0].status === 'done' && (_urls[0].url || _urls[0].response)) { |
| | | _url = _urls[0].url || _urls[0].response |
| | | } else { |
| | | _url = linkurl || '' |
| | | } |
| | | } else { |
| | | _urls = urls.filter(item => item.status === 'done') |
| | | _url = linkurl |
| | | _url = this.props.form.getFieldValue('urls') || '' |
| | | } |
| | | |
| | | this.setState({plusType: val, urls: _urls, linkurl: _url}) |
| | | this.setState({plusType: val, linkurl: _url}) |
| | | } |
| | | |
| | | render() { |
| | | const { getFieldDecorator } = this.props.form |
| | | const { card } = this.props |
| | | const { urls, linkurl, plusType } = this.state |
| | | const { linkurl, plusType } = this.state |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | |
| | | {!card.id && card.typecharone === 'image' && plusType === 'upload' ? <Col span={24}> |
| | | <Form.Item label="图片上传"> |
| | | {getFieldDecorator('urls', { |
| | | initialValue: urls, |
| | | initialValue: '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | |
| | | } |
| | | ] |
| | | })( |
| | | <FileUpload accept=".jpg,.png,.gif,.pjp,.pjpeg,.jpeg,.jfif,.webp" maxFile={1} fileType={'picture'} /> |
| | | <FileUpload config={{ |
| | | initval: '', |
| | | suffix: '.jpg,.png,.gif,.pjp,.pjpeg,.jpeg,.jfif,.webp', |
| | | maxfile: 1, |
| | | fileType: 'picture' |
| | | }} /> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {!card.id && card.typecharone === 'video' && plusType === 'upload' ? <Col span={24}> |
| | | <Form.Item label="视频上传"> |
| | | {getFieldDecorator('urls', { |
| | | initialValue: urls, |
| | | initialValue: '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | |
| | | } |
| | | ] |
| | | })( |
| | | <FileUpload accept=".mp4,.webm,.ogg" maxFile={1} fileType={'text'} /> |
| | | <FileUpload config={{ |
| | | initval: '', |
| | | suffix: '.mp4,.webm,.ogg', |
| | | maxfile: 1, |
| | | fileType: 'text' |
| | | }}/> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | |
| | | const { confirm } = Modal |
| | | |
| | | const MenuForm = asyncComponent(() => import('./menuform')) |
| | | const Header = asyncComponent(() => import('@/menu/header')) |
| | | const SourceWrap = asyncComponent(() => import('@/menu/modulesource')) |
| | | const MenuShell = asyncComponent(() => import('@/menu/menushell')) |
| | | const ReplaceField = asyncComponent(() => import('@/menu/replaceField')) |
| | | const BgController = asyncComponent(() => import('@/menu/bgcontroller')) |
| | | const PasteController = asyncComponent(() => import('@/menu/pastecontroller')) |
| | | const PaddingController = asyncComponent(() => import('@/menu/padcontroller')) |
| | |
| | | updateCustomComponent = () => { |
| | | Api.getSystemConfig({ |
| | | func: 's_get_custom_components', |
| | | typename: sessionStorage.getItem('appType'), |
| | | typecharone: '' |
| | | }).then(res => { |
| | | let coms = [] |
| | |
| | | buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`) |
| | | _sort++ |
| | | }) |
| | | item.subcards.forEach(card => { |
| | | item.subcards && item.subcards.forEach(card => { |
| | | card.elements && card.elements.forEach(cell => { |
| | | if (cell.eleType !== 'button') return |
| | | this.checkBtn(cell) |
| | |
| | | window.GLOB.customMenu = config |
| | | } |
| | | |
| | | resetConfig = (config) => { |
| | | this.setState({ |
| | | config: {...config, components: []}, |
| | | }, () => { |
| | | this.setState({ |
| | | config: config |
| | | }) |
| | | }) |
| | | |
| | | window.GLOB.customMenu = config |
| | | } |
| | | |
| | | /** |
| | | * @description 更新常用表信息,快捷添加后更新配置信息 |
| | | */ |
| | |
| | | const { activeKey, MenuType, dict, config, menuloading, customComponents } = this.state |
| | | |
| | | return ( |
| | | <DndProvider backend={HTML5Backend}> |
| | | <div className="menu-body"> |
| | | <div className="menu-setting"> |
| | | <Collapse accordion activeKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}> |
| | | {/* 基本信息 */} |
| | | <Panel header={dict['mob.basemsg']} key="basedata"> |
| | | {/* 菜单信息 */} |
| | | {config ? <MenuForm dict={dict} config={config} btn={btn} updateConfig={this.updateConfig}/> : null} |
| | | {/* 表名添加 */} |
| | | {config ? <TableComponent config={config} updatetable={this.updatetable}/> : null} |
| | | </Panel> |
| | | {/* 组件添加 */} |
| | | <Panel header={dict['mob.component']} key="component"> |
| | | <SourceWrap MenuType={MenuType} /> |
| | | </Panel> |
| | | {customComponents && customComponents.length ? <Panel header="自定义组件" key="cuscomponent"> |
| | | <SourceWrap components={customComponents} MenuType={MenuType} /> |
| | | </Panel> : null} |
| | | <Panel header={'页面背景'} key="background"> |
| | | {config ? <BgController config={config} updateConfig={this.updateConfig} /> : null} |
| | | </Panel> |
| | | <Panel header={'页面内边距'} key="padding"> |
| | | {config ? <PaddingController config={config} updateConfig={this.updateConfig} /> : null} |
| | | </Panel> |
| | | </Collapse> |
| | | <div className="pc-poper-view"> |
| | | <Header /> |
| | | <DndProvider backend={HTML5Backend}> |
| | | <div className="menu-body"> |
| | | <div className="menu-setting"> |
| | | <Collapse accordion activeKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}> |
| | | {/* 基本信息 */} |
| | | <Panel header={dict['mob.basemsg']} key="basedata"> |
| | | {/* 菜单信息 */} |
| | | {config ? <MenuForm dict={dict} config={config} btn={btn} updateConfig={this.updateConfig}/> : null} |
| | | {/* 表名添加 */} |
| | | {config ? <TableComponent config={config} updatetable={this.updatetable}/> : null} |
| | | </Panel> |
| | | {/* 组件添加 */} |
| | | <Panel header={dict['mob.component']} key="component"> |
| | | <SourceWrap MenuType={MenuType} /> |
| | | </Panel> |
| | | {customComponents && customComponents.length ? <Panel header="自定义组件" key="cuscomponent"> |
| | | <SourceWrap components={customComponents} MenuType={MenuType} /> |
| | | </Panel> : null} |
| | | <Panel header={'页面背景'} key="background"> |
| | | {config ? <BgController config={config} updateConfig={this.updateConfig} /> : null} |
| | | </Panel> |
| | | <Panel header={'页面内边距'} key="padding"> |
| | | {config ? <PaddingController config={config} updateConfig={this.updateConfig} /> : null} |
| | | </Panel> |
| | | </Collapse> |
| | | </div> |
| | | <div className={'menu-view ' + (menuloading ? 'saving' : '')}> |
| | | <Card title={ |
| | | <div> {config && config.MenuName} </div> |
| | | } bordered={false} extra={ |
| | | <div> |
| | | <ReplaceField type="custom" config={config} updateConfig={this.resetConfig}/> |
| | | <StyleCombControlButton menu={config} /> |
| | | <PasteController type="menu" Tab={null} insert={this.insert} /> |
| | | {config ? <Switch className="big" checkedChildren={dict['mob.enable']} unCheckedChildren={dict['mob.disable']} checked={config.enabled} onChange={this.onEnabledChange} /> : null} |
| | | <Button type="primary" onClick={this.submitConfig} loading={menuloading}>{dict['mob.save']}</Button> |
| | | <Button type="default" onClick={this.closeView}>{dict['mob.return']}</Button> |
| | | </div> |
| | | } style={{ width: '100%' }}> |
| | | {config && config.components ? <MenuShell menu={config} handleList={this.updateConfig} /> : null} |
| | | </Card> |
| | | </div> |
| | | </div> |
| | | <div className={'menu-view ' + (menuloading ? 'saving' : '')}> |
| | | <Card title={ |
| | | <div> {config && config.MenuName} </div> |
| | | } bordered={false} extra={ |
| | | <div> |
| | | <StyleCombControlButton menu={config} /> |
| | | <PasteController type="menu" Tab={null} insert={this.insert} /> |
| | | {config ? <Switch className="big" checkedChildren={dict['mob.enable']} unCheckedChildren={dict['mob.disable']} checked={config.enabled} onChange={this.onEnabledChange} /> : null} |
| | | <Button type="primary" onClick={this.submitConfig} loading={menuloading}>{dict['mob.save']}</Button> |
| | | <Button type="default" onClick={this.closeView}>{dict['mob.return']}</Button> |
| | | </div> |
| | | } style={{ width: '100%' }}> |
| | | {config && config.components ? <MenuShell menu={config} handleList={this.updateConfig} /> : null} |
| | | </Card> |
| | | </div> |
| | | </div> |
| | | </DndProvider> |
| | | </DndProvider> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | |
| | | .pc-poper-view { |
| | | background: #000; |
| | | min-height: 100vh; |
| | | >.menu-body { |
| | | width: 100vw; |
| | | height: 100vh; |
| | | overflow-x: hidden; |
| | | position: relative; |
| | | background: #ffffff; |
| | | padding: 50px 0px 0px 0px; |
| | | |
| | | .menu-setting { |
| | | position: fixed; |
| | | left: 0; |
| | | top: 48px; |
| | | z-index: 10; |
| | | height: calc(100vh - 48px); |
| | | width: 300px; |
| | | background: #ffffff; |
| | | box-shadow: 0px 2px 5px #bcbcbc; |
| | | overflow-y: auto; |
| | | overflow-x: hidden; |
| | | |
| | | > .ant-collapse { |
| | | background-color: #ffffff; |
| | | .ant-collapse-item.ant-collapse-item-active { |
| | | border-bottom: 1px solid #d9d9d9; |
| | | } |
| | | .ant-collapse-header { |
| | | padding: 11px 16px 10px 40px; |
| | | border-bottom: 1px solid #d9d9d9; |
| | | background: #1890ff; |
| | | color: #ffffff; |
| | | } |
| | | .ant-collapse-content-box { |
| | | .ant-form-item { |
| | | margin-bottom: 10px; |
| | | } |
| | | .model-table-tablemanage-view { |
| | | >.ant-list { |
| | | margin-top: 20px; |
| | | .ant-list-item { |
| | | display: -webkit-box; |
| | | padding-right: 20px; |
| | | position: relative; |
| | | padding-left: 5px; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | -webkit-line-clamp: 2; |
| | | -webkit-box-orient: vertical; |
| | | min-height: 55px; |
| | | width: 100%; |
| | | .anticon { |
| | | position: absolute; |
| | | top: 0px; |
| | | right: 0px; |
| | | padding: 3px 3px 10px 10px; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | } |
| | | >.tables { |
| | | width: 66.66666667%!important; |
| | | } |
| | | >.ant-form-item-label { |
| | | width: 33.33333333%; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | >.ant-tabs { |
| | | >.ant-tabs-bar { |
| | | border-bottom: 1px solid #181F29; |
| | | margin-bottom: 0px; |
| | | min-height: 48px; |
| | | .ant-tabs-tab { |
| | | padding: 14px 16px; |
| | | color: rgba(255, 255, 255, 0.85); |
| | | } |
| | | .ant-tabs-tab-active.ant-tabs-tab { |
| | | color: #1890ff; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .menu-setting::-webkit-scrollbar { |
| | | width: 4px; |
| | | } |
| | | .menu-setting::-webkit-scrollbar-thumb { |
| | | border-radius: 5px; |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08); |
| | | background: rgba(0, 0, 0, 0.08); |
| | | } |
| | | .menu-setting::-webkit-scrollbar-track { |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); |
| | | border-radius: 3px; |
| | | border: 1px solid rgba(0, 0, 0, 0.07); |
| | | background: rgba(0, 0, 0, 0); |
| | | } |
| | | |
| | | .menu-view { |
| | | position: relative; |
| | | width: calc(100vw - 300px); |
| | | margin-left: 300px; |
| | | height: calc(100vh - 50px); |
| | | overflow-y: auto; |
| | | |
| | | > .ant-card { |
| | | >.ant-card-head { |
| | | margin-bottom: 0px; |
| | | position: relative; |
| | | .ant-card-head-title { |
| | | color: #1890ff; |
| | | padding: 5px 0; |
| | | } |
| | | .ant-card-extra { |
| | | padding: 5px 0; |
| | | button { |
| | | margin-left: 20px; |
| | | } |
| | | .ant-switch.big { |
| | | min-width: 60px; |
| | | height: 28px; |
| | | line-height: 28px; |
| | | margin-top: -2px; |
| | | .ant-switch-inner { |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | .ant-switch.big:after { |
| | | width: 24px; |
| | | height: 24px; |
| | | } |
| | | } |
| | | } |
| | | >.ant-card-body { |
| | | padding: 0px; |
| | | } |
| | | } |
| | | } |
| | | .menu-view.saving { |
| | | .anticon-tool { |
| | | display: none; |
| | | } |
| | | } |
| | | .menu-view::-webkit-scrollbar { |
| | | width: 7px; |
| | | } |
| | | .menu-view::-webkit-scrollbar-thumb { |
| | | border-radius: 5px; |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08); |
| | | background: rgba(0, 0, 0, 0.08); |
| | | } |
| | | .menu-view::-webkit-scrollbar-track { |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); |
| | | border-radius: 3px; |
| | | border: 1px solid rgba(0, 0, 0, 0.07); |
| | | background: rgba(0, 0, 0, 0); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Modal, Button, notification } from 'antd' |
| | | import moment from 'moment' |
| | | |
| | | import Api from '@/api' |
| | | import options from '@/store/options.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import SettingForm from './settingform' |
| | | import { queryTableSql } from '@/utils/option.js' |
| | | import './index.scss' |
| | | |
| | | class ReplaceField extends Component { |
| | | static propTpyes = { |
| | | type: PropTypes.string, |
| | | config: PropTypes.object, |
| | | updateConfig: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | visible: false, |
| | | loadingTable: false, |
| | | confirming: false, |
| | | tables: [], |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | trigger = () => { |
| | | const { tables } = this.state |
| | | |
| | | if (tables.length === 0) { |
| | | 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) // 云端数据验证 |
| | | |
| | | if (options.cloudServiceApi) { // 且存在云端地址 |
| | | param.rduri = options.cloudServiceApi |
| | | param.userid = sessionStorage.getItem('CloudUserID') || '' |
| | | param.LoginUID = sessionStorage.getItem('CloudLoginUID') || '' |
| | | } |
| | | |
| | | this.setState({ |
| | | loadingTable: true |
| | | }) |
| | | |
| | | Api.getSystemCacheConfig(param).then(res => { |
| | | if (res.status) { |
| | | this.setState({ |
| | | visible: true, |
| | | confirming: false, |
| | | tables: res.data, |
| | | loadingTable: false |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | confirming: false, |
| | | loadingTable: false |
| | | }) |
| | | notification.warning({ |
| | | top: 92, |
| | | message: res.message, |
| | | duration: 5 |
| | | }) |
| | | } |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | confirming: false, |
| | | visible: true |
| | | }) |
| | | } |
| | | } |
| | | |
| | | submit = () => { |
| | | let config = fromJS(this.props.config).toJS() |
| | | |
| | | this.settingRef.handleConfirm().then(res => { |
| | | this.setState({confirming: true}) |
| | | |
| | | let param = {func: 'sPC_Get_FieldName', TBName: res.table} |
| | | if (options.cloudServiceApi) { // 且存在云端地址 |
| | | param.rduri = options.cloudServiceApi |
| | | param.userid = sessionStorage.getItem('CloudUserID') || '' |
| | | param.LoginUID = sessionStorage.getItem('CloudLoginUID') || '' |
| | | } |
| | | |
| | | Api.getSystemCacheConfig(param).then(result => { |
| | | if (!result.status) { |
| | | this.setState({ |
| | | confirming: false |
| | | }) |
| | | notification.warning({ |
| | | top: 92, |
| | | message: result.message, |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | |
| | | let map = {} |
| | | |
| | | result.FDName.forEach(item => { |
| | | if (/NVARCHAR|INT|Decimal/ig.test(item.FieldType)) { |
| | | item.datatype = item.FieldType |
| | | } |
| | | map[item.FieldDec] = item |
| | | }) |
| | | |
| | | if (this.props.type === 'custom') { |
| | | let _replace = (components) => { |
| | | return components.map(item => { |
| | | if (item.type === 'tabs') { |
| | | item.subtabs.forEach(tab => { |
| | | tab.components = _replace(tab.components) |
| | | }) |
| | | return item |
| | | } else if (item.type === 'group') { |
| | | item.components = _replace(item.components) |
| | | return item |
| | | } |
| | | |
| | | if (item.columns) { |
| | | item.columns = item.columns.map(col => { |
| | | if (map[col.field]) { |
| | | col.field = map[col.field].FieldName |
| | | if (map[col.field].datatype) { |
| | | col.datatype = map[col.field].datatype |
| | | } |
| | | } |
| | | return col |
| | | }) |
| | | } |
| | | if (item.search) { |
| | | item.search = item.search.map(col => { |
| | | if (map[col.field]) { |
| | | col.field = map[col.field].FieldName |
| | | } |
| | | return col |
| | | }) |
| | | } |
| | | |
| | | if (item.action) { |
| | | item.action.forEach(m => { |
| | | if (m.modal && m.modal.fields) { |
| | | m.modal.fields = m.modal.fields.map(col => { |
| | | if (map[col.field]) { |
| | | col.field = map[col.field].FieldName |
| | | } |
| | | return col |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | if (item.subcards) { |
| | | item.subcards.forEach(card => { |
| | | if (card.elements) { // 卡片 |
| | | card.elements = card.elements.map(m => { |
| | | if (m.datatype === 'dynamic' && map[m.field]) { |
| | | m.field = map[m.field].FieldName |
| | | } |
| | | if (m.modal && m.modal.fields) { |
| | | m.modal.fields = m.modal.fields.map(col => { |
| | | if (map[col.field]) { |
| | | col.field = map[col.field].FieldName |
| | | } |
| | | return col |
| | | }) |
| | | } |
| | | return m |
| | | }) |
| | | } |
| | | |
| | | if (card.backElements) { // 卡片 |
| | | card.backElements = card.backElements.map(m => { |
| | | if (m.datatype === 'dynamic' && map[m.field]) { |
| | | m.field = map[m.field].FieldName |
| | | } |
| | | if (m.modal && m.modal.fields) { |
| | | m.modal.fields = m.modal.fields.map(col => { |
| | | if (map[col.field]) { |
| | | col.field = map[col.field].FieldName |
| | | } |
| | | return col |
| | | }) |
| | | } |
| | | return m |
| | | }) |
| | | } |
| | | |
| | | if (card.fields) { // 表单 |
| | | card.fields = card.fields.map(m => { |
| | | if (map[m.field]) { |
| | | m.field = map[m.field].FieldName |
| | | } |
| | | return m |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | if (item.elements) { |
| | | item.elements = item.elements.map(m => { |
| | | if (m.datatype === 'dynamic' && map[m.field]) { |
| | | m.field = map[m.field].FieldName |
| | | } |
| | | if (m.modal && m.modal.fields) { |
| | | m.modal.fields = m.modal.fields.map(col => { |
| | | if (map[col.field]) { |
| | | col.field = map[col.field].FieldName |
| | | } |
| | | return col |
| | | }) |
| | | } |
| | | return m |
| | | }) |
| | | } |
| | | |
| | | if (item.plot) { |
| | | if (item.plot.Xaxis && map[item.plot.Xaxis]) { |
| | | item.plot.Xaxis = map[item.plot.Xaxis].FieldName |
| | | } |
| | | // 统计图 |
| | | if (item.plot.InfoValue && map[item.plot.InfoValue]) { |
| | | item.plot.InfoValue = map[item.plot.InfoValue].FieldName |
| | | } |
| | | if (item.plot.InfoType && map[item.plot.InfoType]) { |
| | | item.plot.InfoType = map[item.plot.InfoType].FieldName |
| | | } |
| | | // 占比图 |
| | | if (item.plot.valueField && map[item.plot.valueField]) { |
| | | item.plot.valueField = map[item.plot.valueField].FieldName |
| | | } |
| | | if (item.plot.labelField && map[item.plot.labelField]) { |
| | | item.plot.labelField = map[item.plot.labelField].FieldName |
| | | } |
| | | // 饼图 |
| | | if (item.plot.type && map[item.plot.type]) { |
| | | item.plot.type = map[item.plot.type].FieldName |
| | | } |
| | | // 散点图 |
| | | if (item.plot.gender && map[item.plot.gender]) { |
| | | item.plot.gender = map[item.plot.gender].FieldName |
| | | } |
| | | if (item.Yaxis) { |
| | | if (Array.isArray(item.Yaxis)) { |
| | | item.Yaxis = item.Yaxis.map(m => { |
| | | if (map[m]) { |
| | | return map[m].FieldName |
| | | } |
| | | return m |
| | | }) |
| | | } else { |
| | | if (map[item.Yaxis]) { |
| | | item.Yaxis = map[item.Yaxis].FieldName |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (item.cols) { |
| | | let _update = (cols) => { |
| | | return cols.map(col => { |
| | | if (col.type === 'action' && col.elements) { |
| | | col.elements = col.elements.map(m => { |
| | | if (m.modal && m.modal.fields) { |
| | | m.modal.fields = m.modal.fields.map(col => { |
| | | if (map[col.field]) { |
| | | col.field = map[col.field].FieldName |
| | | } |
| | | return col |
| | | }) |
| | | } |
| | | |
| | | return m |
| | | }) |
| | | } else if (col.type === 'custom' && col.elements) { |
| | | col.elements = col.elements.map(m => { |
| | | if (m.datatype === 'dynamic' && map[m.field]) { |
| | | m.field = map[m.field].FieldName |
| | | } |
| | | |
| | | return m |
| | | }) |
| | | } else if (col.type === 'colspan') { |
| | | col.subcols = _update(col.subcols) |
| | | } else if (col.field) { |
| | | if (map[col.field]) { |
| | | col.field = map[col.field].FieldName |
| | | } |
| | | } |
| | | |
| | | return col |
| | | }) |
| | | } |
| | | |
| | | item.cols = _update(item.cols) |
| | | } |
| | | |
| | | return item |
| | | }) |
| | | } |
| | | |
| | | config.components = _replace(config.components) |
| | | } else if (this.props.type === 'table') { |
| | | config.columns = config.columns.map(col => { |
| | | if (col.field && map[col.field]) { |
| | | col.field = map[col.field].FieldName |
| | | } |
| | | return col |
| | | }) |
| | | config.search = config.search.map(col => { |
| | | if (col.field && map[col.field]) { |
| | | col.field = map[col.field].FieldName |
| | | } |
| | | if (col.datefield && map[col.datefield]) { |
| | | col.datefield = map[col.datefield].FieldName |
| | | } |
| | | return col |
| | | }) |
| | | } else if (this.props.type === 'form') { |
| | | config.fields = config.fields.map(col => { |
| | | if (col.field && map[col.field]) { |
| | | col.field = map[col.field].FieldName |
| | | } |
| | | return col |
| | | }) |
| | | } |
| | | |
| | | this.setState({ |
| | | confirming: false, |
| | | visible: false |
| | | }) |
| | | |
| | | notification.success({ |
| | | top: 92, |
| | | message: '更新已完成。', |
| | | duration: 3 |
| | | }) |
| | | this.props.updateConfig(config) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const { visible, loadingTable, tables, confirming } = this.state |
| | | |
| | | return ( |
| | | <div style={{display: 'inline-block'}}> |
| | | <Button className="mk-border-yellow" icon="swap" loading={loadingTable} onClick={this.trigger}>字段替换</Button> |
| | | <Modal |
| | | title="字段替换" |
| | | wrapClassName="replace-field-modal" |
| | | visible={visible} |
| | | width={600} |
| | | maskClosable={false} |
| | | onOk={this.submit} |
| | | onCancel={() => { this.setState({ visible: false })}} |
| | | confirmLoading={confirming} |
| | | destroyOnClose |
| | | > |
| | | <SettingForm tables={tables} wrappedComponentRef={(inst) => this.settingRef = inst}/> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default ReplaceField |
New file |
| | |
| | | .replace-field-modal { |
| | | .ant-modal { |
| | | top: 70px; |
| | | } |
| | | .ant-modal-body { |
| | | min-height: 150px; |
| | | padding-top: 40px; |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Tooltip, Icon, Select } from 'antd' |
| | | |
| | | import './index.scss' |
| | | |
| | | class SettingForm extends Component { |
| | | static propTpyes = { |
| | | tables: PropTypes.object |
| | | } |
| | | |
| | | state = {} |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | | return new Promise((resolve, reject) => { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | resolve(values) |
| | | } else { |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const { tables } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 8 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 16 } |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <Form {...formItemLayout}> |
| | | <Row gutter={24}> |
| | | <Col span={20}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="用于字段替换的表名。"> |
| | | <Icon type="question-circle" style={{color: '#c49f47', marginRight: '3px'}} /> |
| | | 表名 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('table', { |
| | | initialValue: '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: '请选择表名' |
| | | } |
| | | ] |
| | | })( |
| | | <Select |
| | | showSearch |
| | | filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} |
| | | > |
| | | {tables.map((option, i) => |
| | | <Select.Option key={i} title={option.Remark + ' (' + option.TbName + ')'} value={option.TbName}>{option.Remark + ' (' + option.TbName + ')'}</Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(SettingForm) |
copy from src/tabviews/zshare/mutilform/customSwitch/index.scss
copy to src/menu/replaceField/settingform/index.scss
| | |
| | | } |
| | | |
| | | state = { |
| | | label: '调整', |
| | | label: '批量调整', |
| | | parent: null, |
| | | type: '', |
| | | components: [] |
| | |
| | | triggerStyleChange = () => { |
| | | const { label, components } = this.state |
| | | |
| | | if (label === '调整') { |
| | | if (label === '批量调整') { |
| | | document.body.className = 'style-control' |
| | | sessionStorage.setItem('style-control', 'true') |
| | | this.setState({label: '退出'}) |
| | |
| | | |
| | | MKEmitter.emit('closeCombineStyle') |
| | | |
| | | this.setState({label: '调整', parent: null, components: []}) |
| | | this.setState({label: '批量调整', parent: null, components: []}) |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { label } = this.state |
| | | return ( |
| | | <Button className="style-control-button" icon="font-colors" title="调整样式" onClick={this.triggerStyleChange}>{label}</Button> |
| | | <Button className="style-control-button" icon="font-colors" title="批量调整样式" onClick={this.triggerStyleChange}>{label}</Button> |
| | | ) |
| | | } |
| | | } |
| | |
| | | bottom: 0; |
| | | right: 0; |
| | | z-index: 12; |
| | | background:rgba(0, 0, 0, 0.3); |
| | | background:rgba(0, 0, 0, 0.2); |
| | | } |
| | | .menu-body .menu-view >.ant-card >.ant-card-body { |
| | | position: relative; |
| | | z-index: 13; |
| | | background:#ffffff; |
| | | } |
| | | .menu-view { |
| | | .anticon-tool { |
| | | display: none; |
| | | } |
| | | } |
| | | .mk-mob-view .mob-shell { |
| | | .anticon-tool { |
| | | display: none; |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * @description 修改背景大小 |
| | | */ |
| | | changeBackgroundSize = (val) => { |
| | | this.updateStyle({backgroundSize: val}) |
| | | } |
| | | |
| | | /** |
| | | * @description 修改背景位置 |
| | | */ |
| | | changeBackgroundPositon= (val) => { |
| | | this.updateStyle({backgroundPositon: val}) |
| | | } |
| | | |
| | | /** |
| | | * @description 修改背景重复设置 |
| | | */ |
| | | changeBackgroundRepeat = (val) => { |
| | | this.updateStyle({backgroundRepeat: val}) |
| | | } |
| | | |
| | | /** |
| | | * @description 修改阴影颜色 ,颜色控件 |
| | | */ |
| | | changeShadowColor = (val) => { |
| | |
| | | label={<Icon title="宽度" type="column-width" />} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <StyleInput defaultValue={card.width || ''} options={['px', 'vh', 'vw']} onChange={this.changeWidth}/> |
| | | <StyleInput defaultValue={card.width || ''} options={['px', 'vh', 'vw', '%']} onChange={this.changeWidth}/> |
| | | </Form.Item> |
| | | </Col> |
| | | </Panel> : null} |
| | |
| | | <SourceComponent value={backgroundImage} type="" placement="right" onChange={this.imgChange}/> |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {!options.includes('backgroundColor') ? <Col span={24}> |
| | | <Form.Item |
| | | colon={false} |
| | | label="比例" |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <Select defaultValue={card.backgroundSize || 'cover'} onChange={this.changeBackgroundSize}> |
| | | <Option value="100%">100%</Option> |
| | | <Option value="100% 100%">100% 100%</Option> |
| | | <Option value="auto 100%">auto 100%</Option> |
| | | <Option value="contain">contain</Option> |
| | | <Option value="cover">cover</Option> |
| | | </Select> |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {!options.includes('backgroundColor') ? <Col span={24}> |
| | | <Form.Item |
| | | colon={false} |
| | | label="重复" |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <Select defaultValue={card.backgroundRepeat || 'no-repeat'} onChange={this.changeBackgroundRepeat}> |
| | | <Option value="repeat">repeat</Option> |
| | | <Option value="no-repeat">no-repeat</Option> |
| | | <Option value="repeat-x">repeat-x</Option> |
| | | <Option value="repeat-y">repeat-y</Option> |
| | | </Select> |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {!options.includes('backgroundColor') ? <Col span={24}> |
| | | <Form.Item |
| | | colon={false} |
| | | label="位置" |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <Select defaultValue={card.backgroundPositon || 'center'} onChange={this.changeBackgroundPositon}> |
| | | <Option value="center">center</Option> |
| | | <Option value="top">top</Option> |
| | | <Option value="bottom">bottom</Option> |
| | | </Select> |
| | | </Form.Item> |
| | | </Col> : null} |
| | | </Panel> : null} |
| | | {options.includes('border') ? <Panel header="边框" key="border"> |
| | | <Col span={24}> |
| | |
| | | label={<Icon title="上边距" type="arrow-up"/>} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <StyleInput defaultValue={card.marginTop || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'marginTop')}/> |
| | | <StyleInput defaultValue={card.marginTop || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginTop')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | |
| | | label={<Icon title="下边距" type="arrow-down"/>} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <StyleInput defaultValue={card.marginBottom || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'marginBottom')}/> |
| | | <StyleInput defaultValue={card.marginBottom || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginBottom')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | |
| | | label={<Icon title="左边距" type="arrow-left"/>} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <StyleInput defaultValue={card.marginLeft || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'marginLeft')}/> |
| | | <StyleInput defaultValue={card.marginLeft || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginLeft')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | |
| | | label={<Icon title="右边距" type="arrow-right"/>} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <StyleInput defaultValue={card.marginRight || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'marginRight')}/> |
| | | <StyleInput defaultValue={card.marginRight || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'marginRight')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | </Panel> : null} |
| | |
| | | label={<Icon title="上边距" type="arrow-up"/>} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <StyleInput defaultValue={card.paddingTop || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'paddingTop')}/> |
| | | <StyleInput defaultValue={card.paddingTop || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingTop')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | |
| | | label={<Icon title="下边距" type="arrow-down"/>} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <StyleInput defaultValue={card.paddingBottom || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'paddingBottom')}/> |
| | | <StyleInput defaultValue={card.paddingBottom || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingBottom')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | |
| | | label={<Icon title="左边距" type="arrow-left"/>} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <StyleInput defaultValue={card.paddingLeft || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'paddingLeft')}/> |
| | | <StyleInput defaultValue={card.paddingLeft || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingLeft')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | |
| | | label={<Icon title="右边距" type="arrow-right"/>} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <StyleInput defaultValue={card.paddingRight || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changeNormalStyle(val, 'paddingRight')}/> |
| | | <StyleInput defaultValue={card.paddingRight || '0px'} options={['px', 'vh', 'vw', '%']} onChange={(val) => this.changeNormalStyle(val, 'paddingRight')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | </Panel> : null} |
| | |
| | | label={<Icon title="浮动" type="swap" />} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <Radio.Group defaultValue={card.float || 'left'} onChange={(e) => this.changeNormalStyle(e.target.value, 'float')}> |
| | | <Radio.Group style={{whiteSpace: 'nowrap'}} defaultValue={card.float || 'left'} onChange={(e) => this.changeNormalStyle(e.target.value, 'float')}> |
| | | <Radio value="left">左浮动</Radio> |
| | | <Radio value="right">右浮动</Radio> |
| | | <Radio value="none">不浮动</Radio> |
| | |
| | | message: dict['form.required.input'] + '回调表名!' |
| | | }, |
| | | { |
| | | max: formRule.input.max, |
| | | message: formRule.input.message |
| | | max: 50, |
| | | message: '表名最长为50个字符!' |
| | | } |
| | | ] |
| | | })(<Input placeholder={''} autoComplete="off" />)} |
| | |
| | | import PropTypes from 'prop-types' |
| | | // import { is, fromJS } from 'immutable' |
| | | import { SketchPicker } from 'react-color' |
| | | import { Popover } from 'antd' |
| | | import { Popover, Icon } from 'antd' |
| | | |
| | | import './index.scss' |
| | | |
| | |
| | | } |
| | | state = { |
| | | color: '', |
| | | allowClear: false |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { defaultValue, value } = this.props |
| | | const { defaultValue, value, allowClear } = this.props |
| | | let initVal = '' |
| | | |
| | | if (this.props['data-__meta']) { |
| | |
| | | initVal = value |
| | | } |
| | | |
| | | this.setState({color: initVal}) |
| | | this.setState({color: initVal, allowClear: allowClear === true}) |
| | | } |
| | | |
| | | handleChange = (color) => { |
| | |
| | | }) |
| | | } |
| | | |
| | | clear = () => { |
| | | this.setState({ color: '' }, () => { |
| | | this.props.onChange && this.props.onChange('') |
| | | }) |
| | | } |
| | | |
| | | UNSAFE_componentWillReceiveProps(nextProps) { |
| | | if (nextProps.value !== undefined && nextProps.value !== this.state.color) { |
| | | this.setState({ color: nextProps.value }) |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { color } = this.state |
| | | const { color, allowClear } = this.state |
| | | return ( |
| | | <div className="color-sketch-block"> |
| | | <Popover content={ |
| | |
| | | <div className="color-sketch-block-inner" style={ {background: color} }></div> |
| | | </div> |
| | | </Popover> |
| | | <div className="color-sketch-value">{color}</div> |
| | | <div className="color-sketch-value">{color}{allowClear && color ? <Icon onClick={this.clear} type="close"/> : null}</div> |
| | | </div> |
| | | ) |
| | | } |
| | |
| | | height: 100%; |
| | | } |
| | | .color-sketch-value { |
| | | position: relative; |
| | | display: inline-block; |
| | | font-size: 13px; |
| | | width: 160px; |
| | |
| | | vertical-align: top; |
| | | white-space: nowrap; |
| | | overflow: visible; |
| | | |
| | | .anticon-close { |
| | | position: relative; |
| | | right: -10px; |
| | | font-size: 10px; |
| | | padding: 3px; |
| | | background: #eeeeee; |
| | | border-radius: 50%; |
| | | cursor: pointer; |
| | | opacity: 0; |
| | | transition: opacity 0.3s; |
| | | } |
| | | } |
| | | } |
| | | .color-sketch-block:hover { |
| | | .anticon-close { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | |
New file |
| | |
| | | import React from 'react' |
| | | import { useDrag, useDrop } from 'react-dnd' |
| | | import { Icon, Button, Popover, Switch, Checkbox, Form } from 'antd' |
| | | import moment from 'moment' |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import './index.scss' |
| | | |
| | | const CheckCard = asyncComponent(() => import('@/templates/modalconfig/checkCard')) |
| | | |
| | | const Card = ({ id, card, moveCard, findCard, editCard, closeCard, copyCard, showField }) => { |
| | | const originalIndex = findCard(id).index |
| | | const [{ isDragging }, drag] = useDrag({ |
| | | item: { type: 'form', id, originalIndex }, |
| | | collect: monitor => ({ |
| | | isDragging: monitor.isDragging(), |
| | | }), |
| | | }) |
| | | const [, drop] = useDrop({ |
| | | accept: 'form', |
| | | canDrop: () => true, |
| | | drop: (item) => { |
| | | const { id: draggedId, originalIndex } = item |
| | | |
| | | if (originalIndex === undefined) { |
| | | item.dropTargetId = id |
| | | } else if (draggedId && draggedId !== id) { |
| | | const { index: overIndex } = findCard(id) |
| | | moveCard(draggedId, overIndex) |
| | | } |
| | | } |
| | | }) |
| | | const opacity = isDragging ? 0 : 1 |
| | | |
| | | const edit = () => { |
| | | editCard(id) |
| | | } |
| | | |
| | | const close = () => { |
| | | closeCard(id) |
| | | } |
| | | |
| | | const copy = () => { |
| | | copyCard(id) |
| | | } |
| | | |
| | | let selectval = '' |
| | | if (card.type === 'select' || card.type === 'link') { |
| | | if (card.initval) { |
| | | let _option = card.options.filter(option => option.Value === card.initval)[0] |
| | | if (_option) { |
| | | selectval = _option.Text || '' |
| | | } else { |
| | | selectval = '' |
| | | } |
| | | } else if (card.setAll === 'true') { |
| | | selectval = card.emptyText || '空' |
| | | } |
| | | } |
| | | |
| | | let formItem = null |
| | | if (card.type === 'text' || card.type === 'number') { |
| | | formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className={'am-input-control ' + card.cursor}>{card.initval}</div>{card.scan && card.scan !== 'false' ? <div className="am-list-extra"><Icon type="scan" /></div> : null}</div></div>) |
| | | } else if (card.type === 'number') { |
| | | formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className={'am-input-control ' + card.cursor}>{card.initval}</div></div></div>) |
| | | } else if (card.type === 'select' || card.type === 'link') { |
| | | formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-input-control">{selectval || '请选择'}</div><div className="am-list-extra"><Icon type="right" /></div></div></div>) |
| | | } else if (card.type === 'date') { |
| | | formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-input-control">{card.initval ? moment().subtract(card.initval, 'days').format('YYYY-MM-DD') : '请选择'}</div><div className="am-list-extra"><Icon type="right" /></div></div></div>) |
| | | } else if (card.type === 'datemonth') { |
| | | formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-input-control">{card.initval ? moment().subtract(card.initval, 'month').format('YYYY-MM') : '请选择'}</div><div className="am-list-extra"><Icon type="right" /></div></div></div>) |
| | | } else if (card.type === 'datetime') { |
| | | formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-input-control">{card.initval ? moment().subtract(card.initval, 'days').format('YYYY-MM-DD HH:mm') : '请选择'}</div><div className="am-list-extra"><Icon type="right" /></div></div></div>) |
| | | } else if (card.type === 'textarea') { |
| | | let height = (card.maxRows || 2) * 25 |
| | | formItem = (<div className="am-list-item check-card"> |
| | | <div className="am-list-line"> |
| | | <div className="am-input-label">{card.label}</div> |
| | | <div className="am-input-control"> |
| | | <div style={{textAlign: 'left', position: 'relative', height, lineHeight: 1.5}}> |
| | | {card.initval ? card.initval : <span style={{color: '#bcbcbc'}}>请输入</span> } |
| | | {card.count === 'true' ? <span style={{position: 'absolute', right: 0, bottom: 0}}>0/{card.fieldlength}</span> : null} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div>) |
| | | } else if (card.type === 'fileupload') { |
| | | formItem = ( |
| | | <div className="am-list-item checkbox"> |
| | | <div className="am-list-line"> |
| | | <div className="am-input-label">{card.label}</div> |
| | | <div className="am-input-control" style={{textAlign: 'left'}}> |
| | | {card.fileType !== 'picture-card' ? <Icon type="upload" style={{position: 'absolute', right: '10px', top: '10px'}} /> : null} |
| | | {card.fileType === 'picture-card' ? <Button style={{width: '100px', marginBottom: '10px', height: '100px', fontSize: '50px', color: '#d9d9d9'}}><Icon type="plus" /></Button> : null} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | ) |
| | | } else if (card.type === 'funcvar') { |
| | | formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-input-control">{card.linkfield}</div></div></div>) |
| | | } else if (card.type === 'switch') { |
| | | formItem = (<div className="am-list-item"><div className="am-list-line"><div className="am-input-label">{card.label}</div><div className="am-list-switch"><Switch checked={card.initval}/></div></div></div>) |
| | | } else if (card.type === 'radio') { |
| | | let options = null |
| | | if (card.options && card.options.length > 0) { |
| | | options = card.options |
| | | } else { |
| | | options = [ |
| | | {key: 'A', Value: 'A', Text: 'A'}, |
| | | {key: 'B', Value: 'B', Text: 'B'}, |
| | | {key: 'C', Value: 'C', Text: 'C'} |
| | | ] |
| | | } |
| | | |
| | | formItem = ( |
| | | <div className={'am-list-item checkbox mk-radio ' + (card.arrange || '')}> |
| | | <div className="am-list-line"> |
| | | <div className="am-input-label">{card.label}</div> |
| | | <div className="am-input-control"> |
| | | {card.arrange !== 'line' ? <Checkbox.Group value={[card.initval]}> |
| | | {options.map(cell => <Checkbox key={cell.key} value={cell.Value}>{cell.Text}</Checkbox>)} |
| | | </Checkbox.Group> : <div className="mk-radio-group"> |
| | | {options.map(cell => (<div key={cell.key} className="mk-radio-wrapper"> |
| | | <span className="radio-value">{cell.Text}</span> |
| | | <span className={'radio-check ' + (card.initval === cell.Value ? 'checked' : '')}></span> |
| | | </div>))} |
| | | </div>} |
| | | </div> |
| | | </div> |
| | | </div>) |
| | | } else if (card.type === 'checkbox') { |
| | | let _val = card.initval ? card.initval.split(',') : [] |
| | | let options = null |
| | | if (card.options && card.options.length > 0) { |
| | | options = card.options |
| | | } else { |
| | | options = [ |
| | | {key: 'A', Value: 'A', Text: 'A'}, |
| | | {key: 'B', Value: 'B', Text: 'B'}, |
| | | {key: 'C', Value: 'C', Text: 'C'} |
| | | ] |
| | | } |
| | | |
| | | formItem = ( |
| | | <div className={'am-list-item checkbox ' + (card.arrange || '')}> |
| | | <div className="am-list-line"> |
| | | <div className="am-input-label">{card.label}</div> |
| | | <div className="am-input-control"> |
| | | {<Checkbox.Group value={_val}> |
| | | {options.map(cell => <Checkbox key={cell.key} value={cell.Value}>{cell.Text}</Checkbox>)} |
| | | </Checkbox.Group>} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | ) |
| | | |
| | | } else if (card.type === 'hint') { |
| | | formItem = <div className="am-list-item hint"> |
| | | <div className="am-list-line"> |
| | | <div className="am-input-label">{card.label}</div> |
| | | <div className="am-input-control"> |
| | | {card.message} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | } else if (card.type === 'split') { |
| | | formItem = <div className="split-line">{card.label}</div> |
| | | } else if (card.type === 'checkcard') { |
| | | formItem = (<div className="am-list-item check-card"> |
| | | <div className="am-list-line"> |
| | | {card.hidelabel !== 'true' ? <div className="am-input-label">{card.label}</div> : null} |
| | | <div className="am-input-control"> |
| | | <CheckCard config={card} /> |
| | | </div> |
| | | </div> |
| | | </div>) |
| | | } |
| | | |
| | | return ( |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <Icon className="edit" type="edit" onClick={edit} /> |
| | | <Icon className="copy" type="copy" onClick={copy} /> |
| | | <Icon className="close" type="close" onClick={close} /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <div className="page-card" style={{ opacity: opacity}}> |
| | | <div ref={node => drag(drop(node))}> |
| | | {card.type === 'split' ? formItem : <Form.Item |
| | | className={'ant-form-item' + (card.required === 'true' ? ' required' : '') + (card.splitline === 'false' ? ' no-boder' : '')} |
| | | > |
| | | {formItem} |
| | | {showField ? <div className="field-name">{card.field}{card.hidden === 'true' ? '(隐藏)' : ''}</div> : ''} |
| | | </Form.Item>} |
| | | </div> |
| | | </div> |
| | | </Popover> |
| | | ) |
| | | } |
| | | export default Card |
New file |
| | |
| | | import React, { useState } from 'react' |
| | | import { useDrop } from 'react-dnd' |
| | | import { is, fromJS } from 'immutable' |
| | | import update from 'immutability-helper' |
| | | import Utils from '@/utils/utils.js' |
| | | import Card from './card' |
| | | import './index.scss' |
| | | |
| | | const Container = ({list, setting, handleList, handleForm, closeForm, showField }) => { |
| | | const [cards, setCards] = useState(list) |
| | | const moveCard = (id, atIndex) => { |
| | | const { card, index } = findCard(id) |
| | | |
| | | if (!card) return |
| | | |
| | | const _cards = update(cards, { $splice: [[index, 1], [atIndex, 0, card]] }) |
| | | |
| | | handleList(_cards) |
| | | } |
| | | |
| | | if (!is(fromJS(cards), fromJS(list))) { |
| | | setCards(list) |
| | | } |
| | | |
| | | const findCard = id => { |
| | | const card = cards.filter(c => `${c.uuid}` === id)[0] |
| | | return { |
| | | card, |
| | | index: cards.indexOf(card), |
| | | } |
| | | } |
| | | |
| | | const editCard = id => { |
| | | const { card } = findCard(id) |
| | | delete card.focus |
| | | handleForm(card) |
| | | } |
| | | |
| | | const closeCard = id => { |
| | | const { card } = findCard(id) |
| | | closeForm(card) |
| | | } |
| | | |
| | | const copyCard = id => { |
| | | const { card, index: overIndex } = findCard(id) |
| | | |
| | | let _card = fromJS(card).toJS() |
| | | _card.uuid = Utils.getuuid() |
| | | _card.focus = true |
| | | |
| | | // 复制到剪切板 |
| | | let oInput = document.createElement('input') |
| | | let val = JSON.parse(JSON.stringify(_card)) |
| | | val.copyType = 'form' |
| | | |
| | | 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) |
| | | |
| | | const _cards = update(cards, { $splice: [[overIndex + 1, 0, _card]] }) |
| | | |
| | | setCards(_cards) |
| | | |
| | | handleList(_cards, _card) |
| | | } |
| | | |
| | | const [, drop] = useDrop({ |
| | | accept: 'form', |
| | | drop(item) { |
| | | if (item.hasOwnProperty('originalIndex')) { |
| | | return |
| | | } |
| | | |
| | | let newcard = {} |
| | | newcard.uuid = Utils.getuuid() |
| | | newcard.label = 'label' |
| | | newcard.type = item.subType |
| | | newcard.resourceType = '0' |
| | | newcard.options = [] |
| | | newcard.readonly = 'false' |
| | | newcard.required = 'true' |
| | | newcard.focus = true |
| | | |
| | | let targetId = '' |
| | | |
| | | if (item.dropTargetId) { |
| | | targetId = item.dropTargetId |
| | | delete item.dropTargetId |
| | | } else if (cards.length > 0) { |
| | | targetId = cards[cards.length - 1].uuid |
| | | } |
| | | |
| | | const { index: overIndex } = findCard(`${targetId}`) // cards为空时 overIndex 为 -1 |
| | | const _cards = update(cards, { $splice: [[overIndex + 1, 0, newcard]] }) |
| | | |
| | | setCards(_cards) |
| | | |
| | | handleList(_cards, newcard) |
| | | } |
| | | }) |
| | | |
| | | let style = {} |
| | | if (setting.paddingLeft) { |
| | | style.paddingLeft = setting.paddingLeft |
| | | } |
| | | if (setting.paddingRight) { |
| | | style.paddingRight = setting.paddingRight |
| | | } |
| | | |
| | | return ( |
| | | <div ref={drop} className="ant-row modal-fields-row mob-form" style={style}> |
| | | {cards.map(card => { |
| | | return <Card |
| | | id={card.uuid} |
| | | key={card.uuid} |
| | | card={card} |
| | | showField={showField} |
| | | moveCard={moveCard} |
| | | editCard={editCard} |
| | | closeCard={closeCard} |
| | | copyCard={copyCard} |
| | | findCard={findCard} |
| | | /> |
| | | })} |
| | | </div> |
| | | ) |
| | | } |
| | | export default Container |
New file |
| | |
| | | |
| | | .modal-fields-row { |
| | | padding-bottom: 35px; |
| | | .mob-col.ant-col { |
| | | display: inline-block; |
| | | float: none; |
| | | vertical-align: top; |
| | | padding-left: 1.2%; |
| | | padding-right: 1.2%; |
| | | } |
| | | .am-list-item { |
| | | font-size: 16px; |
| | | padding-left: 10px; |
| | | position: relative; |
| | | display: flex; |
| | | height: 44px; |
| | | min-height: 44px; |
| | | background-color: #fff; |
| | | vertical-align: middle; |
| | | overflow: hidden; |
| | | transition: background-color 200ms; |
| | | align-items: center; |
| | | |
| | | .am-list-line { |
| | | border-bottom: 1px solid #ddd; |
| | | align-items: center; |
| | | position: relative; |
| | | display: flex; |
| | | flex: 1 1; |
| | | align-self: stretch; |
| | | padding-right: 15px; |
| | | overflow: hidden; |
| | | .am-input-label { |
| | | width: 28%; |
| | | color: #000; |
| | | font-size: 16px; |
| | | margin-left: 0; |
| | | margin-right: 5px; |
| | | text-align: left; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | padding: 2px 0; |
| | | text-overflow: ellipsis; |
| | | } |
| | | .am-list-switch { |
| | | flex: 1; |
| | | text-align: right; |
| | | } |
| | | .am-input-control { |
| | | font-size: 16px; |
| | | flex: 1 1; |
| | | text-align: right; |
| | | } |
| | | .am-input-control.left { |
| | | text-align: left; |
| | | } |
| | | .am-list-extra { |
| | | display: block; |
| | | width: 15px; |
| | | height: 15px; |
| | | margin-left: 8px; |
| | | i { |
| | | vertical-align: top; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .am-list-item.check-card { |
| | | height: auto; |
| | | .am-list-line { |
| | | align-items: start; |
| | | display: block; |
| | | .check-card-edit-box { |
| | | margin-top: 0!important; |
| | | } |
| | | } |
| | | } |
| | | .am-list-item.hint { |
| | | height: auto; |
| | | .am-list-line { |
| | | align-items: start; |
| | | display: block; |
| | | .am-input-label { |
| | | line-height: 2; |
| | | } |
| | | .am-input-control { |
| | | font-size: 14px; |
| | | line-height: 1.5; |
| | | text-align: left; |
| | | padding-bottom: 5px; |
| | | } |
| | | } |
| | | } |
| | | .am-list-item.checkbox { |
| | | height: auto; |
| | | .am-list-line { |
| | | align-items: start; |
| | | display: block; |
| | | } |
| | | .mk-radio-group { |
| | | padding-left: 10px; |
| | | text-align: left; |
| | | |
| | | .mk-radio-wrapper:not(:last-child) { |
| | | border-bottom: 1px solid #ddd; |
| | | } |
| | | span { |
| | | display: inline-block; |
| | | } |
| | | .radio-value { |
| | | width: calc(100% - 50px); |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | padding: 2px 0; |
| | | text-overflow: ellipsis; |
| | | vertical-align: top; |
| | | } |
| | | .radio-check { |
| | | position: relative; |
| | | width: 50px; |
| | | height: 30px; |
| | | top: 8px; |
| | | } |
| | | .radio-check.checked::after { |
| | | content: ' '; |
| | | position: absolute; |
| | | display: table; |
| | | border: 1px solid #1890ff; |
| | | border-top: 0; |
| | | border-left: 0; |
| | | top: 50%; |
| | | left: 22%; |
| | | width: 12px; |
| | | height: 20px; |
| | | transform: rotate(45deg) scale(1) translate(-50%, -50%); |
| | | } |
| | | } |
| | | .ant-checkbox-group { |
| | | display: block; |
| | | padding-left: 10px; |
| | | .ant-checkbox-wrapper { |
| | | display: flex; |
| | | text-align: left; |
| | | font-size: 16px; |
| | | .ant-checkbox { |
| | | display: block; |
| | | width: 30px; |
| | | .ant-checkbox-inner { |
| | | width: 22px; |
| | | height: 22px; |
| | | top: 12px; |
| | | } |
| | | .ant-checkbox-inner::after { |
| | | width: 9px; |
| | | height: 14px; |
| | | } |
| | | } |
| | | .ant-checkbox + span { |
| | | display: block; |
| | | flex: 1 1; |
| | | border-bottom: 1px solid #ddd; |
| | | } |
| | | } |
| | | .ant-checkbox-wrapper:last-child { |
| | | .ant-checkbox + span { |
| | | border-bottom: none; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .am-list-item.checkbox.mk-radio { |
| | | .ant-checkbox-inner { |
| | | border-radius: 50%; |
| | | } |
| | | } |
| | | .am-list-item.checkbox:not(.line) { |
| | | .ant-checkbox-group { |
| | | .ant-checkbox-wrapper { |
| | | float: left; |
| | | margin-right: 15px; |
| | | .ant-checkbox + span { |
| | | border-bottom: none; |
| | | } |
| | | } |
| | | } |
| | | .mk-radio-group { |
| | | .mk-radio-wrapper { |
| | | float: left; |
| | | margin-right: 15px; |
| | | } |
| | | } |
| | | } |
| | | .split-line { |
| | | color: #1890ff; |
| | | font-size: 16px; |
| | | padding-left: 10px; |
| | | padding-top: 10px; |
| | | border-bottom: 1px solid #e9e9e9; |
| | | } |
| | | .check-card-edit-box .card-cell span { |
| | | line-height: 1.5; |
| | | } |
| | | .ant-form-item { |
| | | cursor: move; |
| | | display: flex; |
| | | margin-bottom: 0px; |
| | | .ant-form-item-control-wrapper::after { |
| | | content: ''; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | opacity: 0; |
| | | z-index: 1; |
| | | } |
| | | .field-name { |
| | | margin-left: 10px; |
| | | } |
| | | .ant-form-item-children { |
| | | vertical-align: top; |
| | | } |
| | | } |
| | | .ant-form-item.required { |
| | | .am-input-label::before { |
| | | display: inline-block; |
| | | margin-right: 4px; |
| | | color: #f5222d; |
| | | font-size: 14px; |
| | | font-family: SimSun, sans-serif; |
| | | line-height: 1; |
| | | content: '*'; |
| | | } |
| | | } |
| | | .ant-form-item.no-boder { |
| | | .am-list-line { |
| | | border-bottom: none; |
| | | } |
| | | } |
| | | } |
| | | .mob-form.modal-fields-row { |
| | | .page-card { |
| | | margin-bottom: 10px; |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Popover, Modal } from 'antd' |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | 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 WrapComponent = asyncIconComponent(() => import('./wrapsetting')) |
| | | const MenuComponent = asyncComponent(() => import('./menucomponent')) |
| | | const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) |
| | | const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent')) |
| | | const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent')) |
| | | const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader')) |
| | | |
| | | const { confirm } = Modal |
| | | |
| | | class NoramlMenuBar extends Component { |
| | | static propTpyes = { |
| | | card: PropTypes.object, |
| | | deletecomponent: PropTypes.func, |
| | | updateConfig: PropTypes.func, |
| | | } |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | card: null, |
| | | back: false |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { card } = this.props |
| | | |
| | | if (card.isNew) { |
| | | let _card = { |
| | | uuid: card.uuid, |
| | | type: card.type, |
| | | floor: card.floor, |
| | | tabId: '', |
| | | parentId: '', |
| | | dataName: card.dataName || '', |
| | | width: card.width || 24, |
| | | name: card.name, |
| | | subtype: card.subtype, |
| | | wrap: { name: card.name, width: card.width || 24, title: '' }, |
| | | style: { marginLeft: '0px', marginRight: '0px', marginTop: '8px', marginBottom: '8px' }, |
| | | headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' }, |
| | | subMenus: [{ |
| | | uuid: Utils.getuuid(), |
| | | setting: { type: 'menu', width: 6, sign: 'icon', icon: 'user', name: '客户', url: '', color: '#ffffff', iconFont: 20, padding: 12, background: '#1890ff', imgWidth: '' }, |
| | | style: { |
| | | paddingTop: '15px', paddingBottom: '15px' |
| | | } |
| | | }] |
| | | } |
| | | |
| | | if (card.config) { |
| | | let config = fromJS(card.config).toJS() |
| | | |
| | | _card.wrap = config.wrap |
| | | _card.wrap.name = card.name |
| | | _card.style = config.style |
| | | _card.headerStyle = config.headerStyle |
| | | |
| | | _card.subMenus = config.subMenus.map(item => { |
| | | item.uuid = Utils.getuuid() |
| | | |
| | | return item |
| | | }) |
| | | } |
| | | this.setState({ |
| | | card: _card |
| | | }) |
| | | this.props.updateConfig(_card) |
| | | } else { |
| | | this.setState({ |
| | | card: fromJS(card).toJS() |
| | | }) |
| | | } |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('submitStyle', this.getStyle) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新,清除快捷键设置 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('submitStyle', this.getStyle) |
| | | } |
| | | |
| | | /** |
| | | * @description 卡片行外层信息更新(数据源,样式等) |
| | | */ |
| | | updateComponent = (component) => { |
| | | this.setState({ |
| | | card: component |
| | | }) |
| | | |
| | | component.width = component.wrap.width |
| | | component.name = component.wrap.name |
| | | |
| | | this.props.updateConfig(component) |
| | | } |
| | | |
| | | /** |
| | | * @description 单个卡片信息更新 |
| | | */ |
| | | updateCard = (cell) => { |
| | | let card = fromJS(this.state.card).toJS() |
| | | |
| | | card.subMenus = card.subMenus.map(item => { |
| | | if (item.uuid === cell.uuid) return cell |
| | | return item |
| | | }) |
| | | |
| | | this.setState({card}) |
| | | |
| | | this.props.updateConfig(card) |
| | | } |
| | | |
| | | /** |
| | | * @description 单个卡片信息更新 |
| | | */ |
| | | deleteCard = (cell) => { |
| | | let card = fromJS(this.state.card).toJS() |
| | | let _this = this |
| | | |
| | | confirm({ |
| | | content: '确定删除卡片吗?', |
| | | onOk() { |
| | | card.subMenus = card.subMenus.filter(item => item.uuid !== cell.uuid) |
| | | |
| | | _this.setState({card}) |
| | | _this.props.updateConfig(card) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } |
| | | |
| | | 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.length !== 1 || comIds[0] !== card.uuid) return |
| | | |
| | | let _card = {...card, style} |
| | | |
| | | this.setState({ |
| | | card: _card |
| | | }) |
| | | |
| | | this.props.updateConfig(_card) |
| | | } |
| | | |
| | | addMenu = () => { |
| | | let card = fromJS(this.state.card).toJS() |
| | | |
| | | let newcard = { |
| | | uuid: Utils.getuuid(), |
| | | setting: { type: 'menu', width: 6, sign: 'icon', icon: 'user', name: '客户', url: '', color: '#ffffff', iconFont: 20, padding: 12, background: '#1890ff', imgWidth: '' }, |
| | | style: { |
| | | paddingTop: '15px', paddingBottom: '15px' |
| | | }, |
| | | isnew: true |
| | | } |
| | | |
| | | if (card.subMenus.length > 0) { |
| | | newcard = fromJS(card.subMenus.slice(-1)[0]).toJS() |
| | | newcard.uuid = Utils.getuuid() |
| | | newcard.isnew = true |
| | | } |
| | | |
| | | card.subMenus.push(newcard) |
| | | |
| | | this.setState({card}) |
| | | this.props.updateConfig(card) |
| | | } |
| | | |
| | | move = (item, direction) => { |
| | | let card = fromJS(this.state.card).toJS() |
| | | |
| | | let dragIndex = card.subMenus.findIndex(c => c.uuid === item.uuid) |
| | | let hoverIndex = null |
| | | |
| | | if (direction === 'left') { |
| | | hoverIndex = dragIndex - 1 |
| | | } else { |
| | | hoverIndex = dragIndex + 1 |
| | | } |
| | | |
| | | if (hoverIndex === -1 || hoverIndex === card.subMenus.length) return |
| | | |
| | | card.subMenus.splice(hoverIndex, 0, ...card.subMenus.splice(dragIndex, 1)) |
| | | |
| | | this.setState({card}) |
| | | this.props.updateConfig(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 offset = 0 |
| | | if (card.wrap.cardFloat && card.wrap.cardFloat !== 'left') { |
| | | let _width = 0 |
| | | card.subMenus.forEach(card => { |
| | | _width += card.setting.width |
| | | }) |
| | | offset = _width < 24 ? 24 - _width : 0 |
| | | if (card.wrap.cardFloat === 'center') { |
| | | offset = Math.floor(offset / 2) |
| | | } |
| | | } |
| | | |
| | | let _style = resetStyle(card.style) |
| | | |
| | | return ( |
| | | <div className="menu-menubar-edit-box" style={_style} 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"> |
| | | <Icon className="plus" title="添加菜单" onClick={this.addMenu} type="plus" /> |
| | | <WrapComponent config={card} updateConfig={this.updateComponent} /> |
| | | <CopyComponent type="normalmenu" card={card}/> |
| | | <PasteComponent config={card} options={['menucell']} updateConfig={this.updateComponent} /> |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | | <UserComponent config={card}/> |
| | | <Icon className="close" title="删除组件" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <Icon type="tool" /> |
| | | </Popover> |
| | | {card.subMenus.map((menu, index) => (<MenuComponent key={menu.uuid} offset={!index ? offset : 0} cards={card} card={menu} move={this.move} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))} |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default NoramlMenuBar |
New file |
| | |
| | | .menu-menubar-edit-box { |
| | | position: relative; |
| | | box-sizing: border-box; |
| | | background: #ffffff; |
| | | background-position: center center; |
| | | background-repeat: no-repeat; |
| | | background-size: cover; |
| | | min-height: 20px; |
| | | |
| | | .card-control { |
| | | position: absolute; |
| | | top: 0px; |
| | | left: 0px; |
| | | .anticon-tool { |
| | | right: auto; |
| | | left: 1px; |
| | | padding: 1px; |
| | | } |
| | | } |
| | | .anticon-tool { |
| | | position: absolute; |
| | | z-index: 2; |
| | | font-size: 16px; |
| | | right: 1px; |
| | | top: 1px; |
| | | cursor: pointer; |
| | | padding: 5px; |
| | | background: rgba(255, 255, 255, 0.55); |
| | | } |
| | | |
| | | .menu-item { |
| | | overflow: hidden; |
| | | position: relative; |
| | | min-height: 20px; |
| | | .menu-name { |
| | | text-align: center; |
| | | font-style: inherit; |
| | | font-weight: inherit; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | } |
| | | .menu-sign { |
| | | text-align: center; |
| | | .anticon { |
| | | border-radius: 50%; |
| | | } |
| | | img { |
| | | border-radius: 50%; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .menu-menubar-edit-box::after { |
| | | display: block; |
| | | content: ' '; |
| | | clear: both; |
| | | } |
| | | .menu-menubar-edit-box:hover { |
| | | z-index: 1; |
| | | box-shadow: 0px 0px 4px #1890ff; |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Modal, Popover, Icon, Col } from 'antd' |
| | | |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import SettingForm from './settingform' |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import './index.scss' |
| | | |
| | | const { confirm } = Modal |
| | | const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) |
| | | |
| | | class MenuBoxComponent extends Component { |
| | | static propTpyes = { |
| | | offset: PropTypes.any, // 偏移量 |
| | | cards: PropTypes.object, // 卡片行配置信息 |
| | | card: PropTypes.object, // 卡片配置信息 |
| | | move: PropTypes.func, // 卡片移动 |
| | | deleteElement: PropTypes.func, // 卡片删除 |
| | | updateElement: PropTypes.func // 菜单配置更新 |
| | | } |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | card: null, |
| | | formlist: null, |
| | | visible: false |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { card } = this.props |
| | | |
| | | this.setState({ |
| | | card: fromJS(card).toJS() |
| | | }) |
| | | } |
| | | |
| | | componentDidMount () { |
| | | const { card } = this.props |
| | | MKEmitter.addListener('submitStyle', this.getStyle) |
| | | |
| | | if (card.isnew) { |
| | | this.setState({ |
| | | visible: true |
| | | }) |
| | | } |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | const { cards } = this.props |
| | | |
| | | return !is(fromJS(cards.wrap), fromJS(nextProps.cards.wrap)) || !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新,清除快捷键设置 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('submitStyle', this.getStyle) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | | const { cards } = this.props |
| | | const { card } = this.state |
| | | |
| | | if (comIds.length !== 2 || comIds[0] !== cards.uuid || comIds[1] !== card.uuid) return |
| | | |
| | | let _card = fromJS(card).toJS() |
| | | _card.style = style |
| | | |
| | | this.setState({ |
| | | card: _card |
| | | }) |
| | | |
| | | this.props.updateElement(_card) |
| | | } |
| | | |
| | | changeStyle = () => { |
| | | const { cards } = this.props |
| | | const { card } = this.state |
| | | |
| | | let _style = card.style ? fromJS(card.style).toJS() : {} |
| | | let options = ['font', 'border', 'padding'] |
| | | |
| | | MKEmitter.emit('changeStyle', [cards.uuid, card.uuid], options, _style) |
| | | } |
| | | |
| | | settingSubmit = () => { |
| | | const { card } = this.state |
| | | |
| | | this.settingRef.handleConfirm().then(res => { |
| | | let _card = {...card, setting: res} |
| | | |
| | | if (!card.isnew && card.setting.type === 'menu' && _card.setting.type !== 'menu') { |
| | | const _this = this |
| | | confirm({ |
| | | content: '菜单属性由“菜单”切换至其他类型时,菜单将被重置,即解除之前菜单的绑定关系,确定修改吗?', |
| | | onOk() { |
| | | _card.uuid = Utils.getuuid() |
| | | _this.setState({ visible: false, card: _card }) |
| | | _this.props.updateElement(_card) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } else { |
| | | delete _card.isnew |
| | | this.setState({ visible: false, card: _card }) |
| | | this.props.updateElement(_card) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | cancel = () => { |
| | | const { card } = this.state |
| | | |
| | | if (card.isnew) { |
| | | let _card = fromJS(card).toJS() |
| | | delete _card.isnew |
| | | |
| | | this.setState({ visible: false, card: _card }) |
| | | this.props.updateElement(_card) |
| | | } else { |
| | | this.setState({ visible: false }) |
| | | } |
| | | } |
| | | |
| | | changeMenu = () => { |
| | | const { card } = this.state |
| | | |
| | | if (card.setting.type === 'link') { |
| | | window.open(card.setting.linkurl) |
| | | } else { |
| | | MKEmitter.emit('changeEditMenu', { |
| | | MenuID: card.setting.type === 'linkmenu' ? card.setting.linkMenuId : card.uuid, |
| | | copyMenuId: card.setting.type === 'menu' ? card.setting.copyMenuId : '', |
| | | MenuNo: card.setting.MenuNo || '', |
| | | MenuName: card.setting.name, |
| | | }) |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { cards, offset } = this.props |
| | | const { card, visible, dict } = this.state |
| | | |
| | | let _style = {...card.style} |
| | | |
| | | if (_style.shadow) { |
| | | _style.boxShadow = '0 0 4px ' + _style.shadow |
| | | } |
| | | |
| | | _style = resetStyle(_style) |
| | | |
| | | return ( |
| | | <Col span={card.setting.width || 6} offset={offset || 0}> |
| | | <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={() => this.setState({visible: true})} /> |
| | | <CopyComponent type="menucell" card={card}/> |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <Icon className="plus" title="左移" type="arrow-left" onClick={() => this.props.move(card, 'left')} /> |
| | | <Icon className="close" title="右移" type="arrow-right" onClick={() => this.props.move(card, 'right')} /> |
| | | </div> |
| | | } trigger="hover" getPopupContainer={() => document.getElementById(card.uuid + 'swap')}> |
| | | <Icon type="swap" id={card.uuid + 'swap'}/> |
| | | </Popover> |
| | | <Icon className="close" title="删除菜单" type="delete" onClick={() => this.props.deleteElement(card)} /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <div className="menu-item" onDoubleClick={() => this.changeMenu()} style={_style}> |
| | | {card.setting.sign === 'icon' ? <div className="menu-sign"> |
| | | <Icon style={{ |
| | | fontSize: card.setting.iconFont || 20, |
| | | padding: card.setting.padding, |
| | | background: card.setting.background, |
| | | color: card.setting.color |
| | | }} type={card.setting.icon}/> |
| | | </div> : <div className="menu-sign"> |
| | | <img style={{width: card.setting.imgWidth, height: card.setting.imgWidth}} src={card.setting.url} alt=""/> |
| | | </div>} |
| | | <div className="menu-name">{card.setting.name}</div> |
| | | </div> |
| | | </Popover> |
| | | <Modal |
| | | wrapClassName="popview-modal" |
| | | title={'菜单设置'} |
| | | visible={visible} |
| | | width={800} |
| | | maskClosable={false} |
| | | okText={dict['model.submit']} |
| | | onOk={this.settingSubmit} |
| | | onCancel={this.cancel} |
| | | destroyOnClose |
| | | > |
| | | <SettingForm |
| | | dict={dict} |
| | | cards={cards} |
| | | setting={card.setting} |
| | | inputSubmit={this.settingSubmit} |
| | | wrappedComponentRef={(inst) => this.settingRef = inst} |
| | | /> |
| | | </Modal> |
| | | </Col> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default MenuBoxComponent |
copy from src/tabviews/zshare/mutilform/customSwitch/index.scss
copy to src/mob/components/menubar/normal-menubar/menucomponent/index.scss
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Radio, Tooltip, Icon, Input, InputNumber, Select } from 'antd' |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import './index.scss' |
| | | |
| | | const { TextArea } = Input |
| | | const SourceComponent = asyncComponent(() => import('@/menu/components/share/sourcecomponent')) |
| | | const ColorSketch = asyncComponent(() => import('@/mob/colorsketch')) |
| | | const MkIcon = asyncComponent(() => import('@/components/mkIcon')) |
| | | |
| | | class SettingForm extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, // 字典项 |
| | | cards: PropTypes.object, // 卡片集 |
| | | setting: PropTypes.object, // 数据源配置 |
| | | inputSubmit: PropTypes.func // 回车事件 |
| | | } |
| | | |
| | | state = { |
| | | type: this.props.setting.type, |
| | | sign: this.props.setting.sign, |
| | | menulist: [] |
| | | } |
| | | |
| | | UNSAFE_componentWillMount() { |
| | | let menulist = sessionStorage.getItem('appMenus') |
| | | |
| | | if (menulist) { |
| | | try { |
| | | menulist = JSON.parse(menulist) |
| | | } catch { |
| | | menulist = [] |
| | | } |
| | | } else { |
| | | menulist = [] |
| | | } |
| | | this.setState({menulist}) |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | | return new Promise((resolve, reject) => { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | resolve(values) |
| | | } else { |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | handleSubmit = (e) => { |
| | | e.preventDefault() |
| | | |
| | | if (this.props.inputSubmit) { |
| | | this.props.inputSubmit() |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { setting } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { menulist, type, sign } = this.state |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 8 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 16 } |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <div className="model-menubar-menu-card-setting-form"> |
| | | <Form {...formItemLayout}> |
| | | <Row gutter={24}> |
| | | <Col span={12}> |
| | | <Form.Item label="菜单名称"> |
| | | {getFieldDecorator('name', { |
| | | initialValue: setting.name || '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '菜单名称!' |
| | | } |
| | | ] |
| | | })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label="菜单参数"> |
| | | {getFieldDecorator('MenuNo', { |
| | | initialValue: setting.MenuNo || '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '菜单参数!' |
| | | } |
| | | ] |
| | | })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="栅格布局,每行等分为24列。"> |
| | | <Icon type="question-circle" /> |
| | | 卡片宽度 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('width', { |
| | | initialValue: setting.width || 24, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '宽度!' |
| | | } |
| | | ] |
| | | })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit}/>)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label="菜单属性"> |
| | | {getFieldDecorator('type', { |
| | | initialValue: type, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '类型!' |
| | | } |
| | | ] |
| | | })( |
| | | <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => this.setState({type: e.target.value})}> |
| | | <Radio value="menu">菜单</Radio> |
| | | <Radio value="linkmenu">关联菜单</Radio> |
| | | <Radio value="link">链接</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {type === 'menu' ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="复制菜单仅在当前菜单不存在时有效。"> |
| | | <Icon type="question-circle" style={{color: '#c49f47', marginRight: '3px'}}/> |
| | | 复制菜单 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('copyMenuId', { |
| | | initialValue: setting.copyMenuId || '' |
| | | })( |
| | | <Select allowClear> |
| | | {menulist.map(item => (<Select.Option key={item.MenuID} value={item.MenuID}>{item.MenuName}</Select.Option>))} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {type === 'linkmenu' ? <Col span={12}> |
| | | <Form.Item label="关联菜单"> |
| | | {getFieldDecorator('linkMenuId', { |
| | | initialValue: setting.linkMenuId || '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '关联菜单!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select |
| | | showSearch |
| | | filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} |
| | | > |
| | | {menulist.map(option => |
| | | <Select.Option key={option.MenuID} value={option.MenuID}>{option.MenuName}</Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {type === 'link' ? <Col span={24} className="textarea"> |
| | | <Form.Item label="链接"> |
| | | {getFieldDecorator('linkurl', { |
| | | initialValue: setting.linkurl || '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '链接!' |
| | | } |
| | | ] |
| | | })( <TextArea rows={2}/> )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={12}> |
| | | <Form.Item label="标志"> |
| | | {getFieldDecorator('sign', { |
| | | initialValue: sign, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '标志!' |
| | | } |
| | | ] |
| | | })( |
| | | <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => this.setState({sign: e.target.value})}> |
| | | <Radio value="icon">图标</Radio> |
| | | <Radio value="image">图片</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {sign === 'icon' ? <Col span={12}> |
| | | <Form.Item label="图标"> |
| | | {getFieldDecorator('icon', { |
| | | initialValue: setting.icon || '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '图标!' |
| | | } |
| | | ] |
| | | })( |
| | | <MkIcon /> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {sign === 'icon' ? <Col span={12}> |
| | | <Form.Item label="字体大小"> |
| | | {getFieldDecorator('iconFont', { |
| | | initialValue: setting.iconFont || 20 |
| | | })( |
| | | <InputNumber min={12} max={200} precision={0} onPressEnter={this.handleSubmit}/> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {sign === 'icon' ? <Col span={12}> |
| | | <Form.Item label="内边距"> |
| | | {getFieldDecorator('padding', { |
| | | initialValue: setting.padding || 12 |
| | | })( |
| | | <InputNumber min={0} max={200} precision={0} onPressEnter={this.handleSubmit}/> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {sign === 'icon' ? <Col span={12}> |
| | | <Form.Item label="字体颜色"> |
| | | {getFieldDecorator('color', { |
| | | initialValue: setting.color || '#ffffff' |
| | | })( |
| | | <ColorSketch /> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {sign === 'icon' ? <Col span={12}> |
| | | <Form.Item label="背景色"> |
| | | {getFieldDecorator('background', { |
| | | initialValue: setting.background || '#1890ff' |
| | | })( |
| | | <ColorSketch /> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {sign === 'image' ? <Col span={12}> |
| | | <Form.Item label="图片地址"> |
| | | {getFieldDecorator('url', { |
| | | initialValue: setting.url || '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '图片地址!' |
| | | } |
| | | ] |
| | | })( |
| | | <SourceComponent type="" placement="right"/> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {sign === 'image' ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="图片宽度与高度相当,使用的图片比例应为1:1。"> |
| | | <Icon type="question-circle" /> |
| | | 图片宽度 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('imgWidth', { |
| | | initialValue: setting.imgWidth || 36 |
| | | })( |
| | | <InputNumber min={10} max={500} precision={0} onPressEnter={this.handleSubmit}/> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | </Row> |
| | | </Form> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(SettingForm) |
New file |
| | |
| | | .model-menubar-menu-card-setting-form { |
| | | position: relative; |
| | | |
| | | .anticon-question-circle { |
| | | color: #c49f47; |
| | | margin-right: 3px; |
| | | } |
| | | .ant-input-number { |
| | | width: 100%; |
| | | } |
| | | .textarea { |
| | | .ant-form-item-label { |
| | | width: 16%; |
| | | } |
| | | .ant-form-item-control-wrapper { |
| | | width: 84%; |
| | | } |
| | | } |
| | | .ant-radio-wrapper { |
| | | margin-right: 3px; |
| | | } |
| | | .color-sketch-block { |
| | | margin-top: 7px; |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Modal } from 'antd' |
| | | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import SettingForm from './settingform' |
| | | import './index.scss' |
| | | |
| | | class DataSource extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.any, |
| | | updateConfig: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | visible: false, |
| | | wrap: null |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { config } = this.props |
| | | |
| | | this.setState({wrap: fromJS(config.wrap).toJS()}) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | editDataSource = () => { |
| | | this.setState({ |
| | | visible: true |
| | | }) |
| | | } |
| | | |
| | | verifySubmit = () => { |
| | | const { config } = this.props |
| | | |
| | | this.verifyRef.handleConfirm().then(res => { |
| | | |
| | | this.setState({ |
| | | wrap: res, |
| | | visible: false |
| | | }) |
| | | this.props.updateConfig({...config, wrap: res}) |
| | | }) |
| | | } |
| | | |
| | | render () { |
| | | const { config } = this.props |
| | | const { visible, dict, wrap } = this.state |
| | | |
| | | return ( |
| | | <div className="model-menu-setting-wrap"> |
| | | <Icon type="edit" title="编辑" onClick={() => this.editDataSource()} /> |
| | | <Modal |
| | | wrapClassName="popview-modal" |
| | | title={config.type === 'table' ? '表格设置' : '卡片设置'} |
| | | visible={visible} |
| | | width={800} |
| | | maskClosable={false} |
| | | okText={dict['model.submit']} |
| | | onOk={this.verifySubmit} |
| | | onCancel={() => { this.setState({ visible: false }) }} |
| | | destroyOnClose |
| | | > |
| | | <SettingForm |
| | | dict={dict} |
| | | wrap={wrap} |
| | | config={config} |
| | | inputSubmit={this.verifySubmit} |
| | | wrappedComponentRef={(inst) => this.verifyRef = inst} |
| | | /> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default DataSource |
New file |
| | |
| | | .model-menu-setting-wrap { |
| | | display: inline-block; |
| | | |
| | | >.anticon-edit { |
| | | color: #1890ff; |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Input, Radio, Tooltip, Icon, InputNumber, Select } from 'antd' |
| | | |
| | | import './index.scss' |
| | | |
| | | class SettingForm extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, // 字典项 |
| | | config: PropTypes.object, // 卡片行信息 |
| | | wrap: PropTypes.object, // 数据源配置 |
| | | inputSubmit: PropTypes.func // 回车事件 |
| | | } |
| | | |
| | | state = { |
| | | roleList: [], |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | let roleList = sessionStorage.getItem('sysRoles') |
| | | if (roleList) { |
| | | try { |
| | | roleList = JSON.parse(roleList) |
| | | } catch { |
| | | roleList = [] |
| | | } |
| | | } else { |
| | | roleList = [] |
| | | } |
| | | |
| | | this.setState({roleList}) |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | | return new Promise((resolve, reject) => { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | resolve(values) |
| | | } else { |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | handleSubmit = (e) => { |
| | | e.preventDefault() |
| | | |
| | | if (this.props.inputSubmit) { |
| | | this.props.inputSubmit() |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { wrap } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { roleList } = this.state |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 8 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 16 } |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <div className="model-menubar-menu-setting-form"> |
| | | <Form {...formItemLayout}> |
| | | <Row gutter={24}> |
| | | <Col span={12}> |
| | | <Form.Item label="标题"> |
| | | {getFieldDecorator('title', { |
| | | initialValue: wrap.title || '' |
| | | })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="用于组件间的区分。"> |
| | | <Icon type="question-circle" /> |
| | | 组件名称 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('name', { |
| | | initialValue: wrap.name, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '组件名称!' |
| | | } |
| | | ] |
| | | })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="栅格布局,每行等分为24列。"> |
| | | <Icon type="question-circle" /> |
| | | 宽度 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('width', { |
| | | initialValue: wrap.width || 24, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '宽度!' |
| | | } |
| | | ] |
| | | })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label="对齐方式"> |
| | | {getFieldDecorator('float', { |
| | | initialValue: wrap.float || 'left' |
| | | })( |
| | | <Radio.Group style={{whiteSpace: 'nowrap'}}> |
| | | <Radio key="left" value="left"> 左对齐 </Radio> |
| | | <Radio key="center" value="center"> 居中 </Radio> |
| | | <Radio key="right" value="right"> 右对齐 </Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label="黑名单"> |
| | | {getFieldDecorator('blacklist', { |
| | | initialValue: wrap.blacklist || [] |
| | | })( |
| | | <Select |
| | | showSearch |
| | | mode="multiple" |
| | | filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} |
| | | > |
| | | {roleList.map(option => |
| | | <Select.Option key={option.uuid} value={option.value}>{option.text}</Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(SettingForm) |
New file |
| | |
| | | .model-menubar-menu-setting-form { |
| | | position: relative; |
| | | |
| | | .anticon-question-circle { |
| | | color: #c49f47; |
| | | margin-right: 3px; |
| | | } |
| | | .ant-input-number { |
| | | width: 100%; |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Popover } from 'antd' |
| | | |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | |
| | | import MKEmitter from '@/utils/events.js' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import './index.scss' |
| | | |
| | | const WrapComponent = asyncIconComponent(() => import('./wrapsetting')) |
| | | const MenuComponent = asyncIconComponent(() => import('./menusetting')) |
| | | const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) |
| | | |
| | | class NormalNavbar extends Component { |
| | | static propTpyes = { |
| | | card: PropTypes.object, |
| | | deletecomponent: PropTypes.func, |
| | | updateConfig: PropTypes.func, |
| | | } |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | card: null, |
| | | back: false |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { card } = this.props |
| | | |
| | | if (card.isNew) { |
| | | let _card = { |
| | | uuid: card.uuid, |
| | | type: card.type, |
| | | floor: card.floor, |
| | | format: 'object', // 组件属性 - 数据格式 |
| | | pageable: false, // 组件属性 - 是否可分页 |
| | | switchable: false, // 组件属性 - 数据是否可切换 |
| | | dataName: card.dataName || '', |
| | | width: card.width || 24, |
| | | name: card.name, |
| | | subtype: card.subtype, |
| | | setting: { interType: 'system' }, |
| | | wrap: { name: card.name, datatype: 'static', height: 50 }, |
| | | style: {borderTopColor: '#bcbcbc', borderTopWidth: '1px', paddingTop: '5px', fontSize: '13px' }, |
| | | menus: [], |
| | | columns: [], |
| | | scripts: [], |
| | | } |
| | | |
| | | if (card.config) { |
| | | let config = fromJS(card.config).toJS() |
| | | |
| | | _card.wrap = config.wrap |
| | | _card.wrap.name = card.name |
| | | _card.style = config.style |
| | | } |
| | | |
| | | this.setState({ |
| | | card: _card |
| | | }) |
| | | this.props.updateConfig(_card) |
| | | } else { |
| | | this.setState({ |
| | | card: fromJS(card).toJS() |
| | | }) |
| | | } |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('submitStyle', this.getStyle) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新,清除快捷键设置 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('submitStyle', this.getStyle) |
| | | } |
| | | |
| | | /** |
| | | * @description 卡片行外层信息更新(数据源,样式等) |
| | | */ |
| | | updateComponent = (component) => { |
| | | this.setState({ |
| | | card: component |
| | | }) |
| | | |
| | | component.width = component.wrap.width |
| | | component.name = component.wrap.name |
| | | |
| | | this.props.updateConfig(component) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | | const { card } = this.state |
| | | |
| | | if (comIds[0] !== card.uuid) return |
| | | |
| | | let _card = {...card, style} |
| | | |
| | | this.setState({ |
| | | card: _card |
| | | }) |
| | | |
| | | this.props.updateConfig(_card) |
| | | } |
| | | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['font', 'background', 'border', 'padding'], card.style) |
| | | } |
| | | |
| | | clickComponent = (e) => { |
| | | if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { |
| | | e.stopPropagation() |
| | | MKEmitter.emit('clickComponent', this.state.card) |
| | | } |
| | | } |
| | | |
| | | changeMenu = (menu) => { |
| | | if (menu.property === 'link') { |
| | | window.open(menu.link) |
| | | } else { |
| | | MKEmitter.emit('changeEditMenu', { |
| | | MenuID: menu.property === 'linkmenu' ? menu.linkMenuId : menu.MenuID, |
| | | copyMenuId: menu.property === 'menu' ? menu.copyMenuId : '', |
| | | MenuNo: menu.MenuNo, |
| | | MenuName: menu.name, |
| | | }) |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { card } = this.state |
| | | |
| | | let _style = {...card.style} |
| | | if (_style.shadow) { |
| | | _style.boxShadow = '0 0 4px ' + _style.shadow |
| | | } |
| | | _style.height = card.wrap.height |
| | | |
| | | return ( |
| | | <div className="normal-navbar-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <MenuComponent config={card} updateConfig={this.updateComponent} /> |
| | | <WrapComponent config={card} updateConfig={this.updateComponent} /> |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | | <Icon className="close" title="删除组件" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> |
| | | {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null} |
| | | {card.wrap.datatype === 'static' ? <Icon style={{color: '#eeeeee', cursor: 'not-allowed'}} type="setting"/> : null} |
| | | </div> |
| | | } trigger="hover"> |
| | | <Icon type="tool" /> |
| | | </Popover> |
| | | <div className="menu"> |
| | | {card.menus.map(menu => { |
| | | return ( |
| | | <div key={menu.MenuID} className="am-tab-bar-tab" onDoubleClick={() => this.changeMenu(menu)}> |
| | | {menu.icon ? <div className="am-tab-bar-tab-icon"> |
| | | <span className="am-badge am-tab-bar-tab-badge tab-badge"> |
| | | <Icon type={menu.icon} /> |
| | | {menu.tip ? <sup className="am-badge-text"></sup> : null} |
| | | </span> |
| | | </div> : null} |
| | | <p className="am-tab-bar-tab-title">{menu.name}</p> |
| | | </div> |
| | | ) |
| | | })} |
| | | </div> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default NormalNavbar |
New file |
| | |
| | | .normal-navbar-edit-box { |
| | | position: absolute; |
| | | bottom: 0px; |
| | | left: 0px; |
| | | width: 100%; |
| | | box-sizing: border-box; |
| | | background: #ffffff; |
| | | background-position: center center; |
| | | background-repeat: no-repeat; |
| | | background-size: cover; |
| | | min-height: 30px; |
| | | z-index: 3; |
| | | |
| | | .menu { |
| | | height: 100%; |
| | | display: flex; |
| | | font-size: inherit; |
| | | color: inherit; |
| | | .am-tab-bar-tab { |
| | | position: relative; |
| | | text-align: center; |
| | | flex: 1; |
| | | cursor: pointer; |
| | | .anticon { |
| | | font-size: 150%; |
| | | } |
| | | .am-badge-text { |
| | | position: absolute; |
| | | top: -2px; |
| | | height: 8px; |
| | | width: 8px; |
| | | border-radius: 100%; |
| | | background: #ff5b05; |
| | | z-index: 1; |
| | | } |
| | | p { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .anticon-tool { |
| | | position: absolute; |
| | | z-index: 2; |
| | | font-size: 16px; |
| | | right: 1px; |
| | | top: 1px; |
| | | cursor: pointer; |
| | | padding: 5px; |
| | | background: rgba(255, 255, 255, 0.55); |
| | | } |
| | | |
| | | .card-item { |
| | | overflow: hidden; |
| | | position: relative; |
| | | background-color: #ffffff; |
| | | background-position: center center; |
| | | background-repeat: no-repeat; |
| | | background-size: cover; |
| | | min-height: 20px; |
| | | } |
| | | |
| | | .card-item:hover { |
| | | box-shadow: 0px 0px 2px #1890ff; |
| | | } |
| | | |
| | | .model-menu-card-cell-list .card-detail-row > .anticon-plus { |
| | | position: absolute; |
| | | right: -30px; |
| | | font-size: 16px; |
| | | } |
| | | .model-menu-action-list { |
| | | line-height: 40px; |
| | | .ant-row > .anticon-plus { |
| | | position: absolute; |
| | | right: -30px; |
| | | font-size: 16px; |
| | | } |
| | | } |
| | | .card-add-button { |
| | | text-align: right; |
| | | clear: left; |
| | | .anticon-plus { |
| | | font-size: 20px; |
| | | color: #26C281; |
| | | padding: 5px; |
| | | margin-right: 10px; |
| | | } |
| | | } |
| | | .ant-pagination { |
| | | float: right; |
| | | margin: 10px; |
| | | } |
| | | |
| | | .model-menu-action-list { |
| | | .page-card { |
| | | line-height: 55px; |
| | | } |
| | | } |
| | | } |
| | | .normal-navbar-edit-box::after { |
| | | display: block; |
| | | content: ' '; |
| | | clear: both; |
| | | } |
| | | .normal-navbar-edit-box:hover { |
| | | box-shadow: 0px 0px 4px #1890ff; |
| | | } |
| | | .top-menu-popover { |
| | | padding-top: 0!important; |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Modal } from 'antd' |
| | | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import MenuTable from './menutable' |
| | | import './index.scss' |
| | | |
| | | class DataSource extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.any, |
| | | updateConfig: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | visible: false |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | verifySubmit = () => { |
| | | const { config } = this.props |
| | | let menus = this.mTable.state.data || [] |
| | | |
| | | this.props.updateConfig({...config, menus}) |
| | | this.setState({visible: false}) |
| | | } |
| | | |
| | | render () { |
| | | const { config } = this.props |
| | | const { visible, dict } = this.state |
| | | |
| | | return ( |
| | | <div className="model-menu-setting-wrap"> |
| | | <Icon type="menu" title="菜单" onClick={() => this.setState({ visible: true })}/> |
| | | <Modal |
| | | wrapClassName="popview-modal" |
| | | title="菜单编辑" |
| | | visible={visible} |
| | | width={950} |
| | | maskClosable={false} |
| | | okText={dict['model.submit']} |
| | | onOk={this.verifySubmit} |
| | | onCancel={() => { this.setState({ visible: false }) }} |
| | | destroyOnClose |
| | | > |
| | | <MenuTable |
| | | menus={config.menus} |
| | | cols={config.columns} |
| | | ref={(ref) => { this.mTable = ref }} |
| | | /> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default DataSource |
New file |
| | |
| | | .model-menu-setting-wrap { |
| | | display: inline-block; |
| | | |
| | | >.anticon-menu { |
| | | color: purple; |
| | | } |
| | | |
| | | >.anticon-edit { |
| | | color: #1890ff; |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Input, Radio, Tooltip, Icon, Select } from 'antd' |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import './index.scss' |
| | | |
| | | const { TextArea } = Input |
| | | const MkIcon = asyncComponent(() => import('@/components/mkIcon')) |
| | | |
| | | class SettingForm extends Component { |
| | | static propTpyes = { |
| | | menu: PropTypes.object, // 菜单信息 |
| | | cols: PropTypes.array, // 字段集 |
| | | inputSubmit: PropTypes.func // 回车事件 |
| | | } |
| | | |
| | | state = { |
| | | property: this.props.menu.property || 'menu', |
| | | appMenus: [], |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | let appMenus = sessionStorage.getItem('appMenus') |
| | | if (appMenus) { |
| | | try { |
| | | appMenus = JSON.parse(appMenus) |
| | | } catch { |
| | | appMenus = [] |
| | | } |
| | | } else { |
| | | appMenus = [] |
| | | } |
| | | |
| | | this.setState({appMenus}) |
| | | } |
| | | |
| | | componentDidMount() { |
| | | const { menu } = this.props |
| | | |
| | | if (!menu.MenuID) { |
| | | let _form = document.getElementById('name') |
| | | _form && _form.select() |
| | | } |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | | return new Promise((resolve, reject) => { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | resolve(values) |
| | | } else { |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | handleSubmit = (e) => { |
| | | e.preventDefault() |
| | | |
| | | if (this.props.inputSubmit) { |
| | | this.props.inputSubmit() |
| | | } |
| | | } |
| | | |
| | | changeProperty = (e) => { |
| | | let val = e.target.value |
| | | |
| | | this.setState({property: val}) |
| | | } |
| | | |
| | | render() { |
| | | const { menu, cols } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { property, appMenus } = this.state |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 8 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 16 } |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <Form {...formItemLayout} className="mob-menu-form"> |
| | | <Row gutter={24}> |
| | | <Col span={12}> |
| | | <Form.Item label="菜单名称"> |
| | | {getFieldDecorator('name', { |
| | | initialValue: menu.name, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: '请输入菜单名称!' |
| | | } |
| | | ] |
| | | })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label="菜单参数"> |
| | | {getFieldDecorator('MenuNo', { |
| | | initialValue: menu.MenuNo || '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: '请输入菜单参数!' |
| | | } |
| | | ] |
| | | })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label="图标"> |
| | | {getFieldDecorator('icon', { |
| | | initialValue: menu.icon || '' |
| | | })( |
| | | <MkIcon allowClear /> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="绑定提示字段后,会在菜单右上角显示提示信息。注:在添加图标时有效。"> |
| | | <Icon type="question-circle" style={{color: '#c49f47', marginRight: '3px'}}/> |
| | | 提示 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('tip', { |
| | | initialValue: menu.tip || '' |
| | | })( |
| | | <Select allowClear> |
| | | {cols.map(item => <Select.Option key={item.uuid} value={item.field}>{item.label}</Select.Option>)} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label="菜单属性"> |
| | | {getFieldDecorator('property', { |
| | | initialValue: menu.property || 'menu' |
| | | })( |
| | | <Radio.Group onChange={this.changeProperty} style={{whiteSpace: 'nowrap'}}> |
| | | <Radio value="menu">菜单</Radio> |
| | | <Radio value="linkmenu">关联菜单</Radio> |
| | | <Radio value="link">链接</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label="隐藏"> |
| | | {getFieldDecorator('hidden', { |
| | | initialValue: menu.hidden || 'false' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="false">否</Radio> |
| | | <Radio value="true">是</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {property === 'link' ? <Col span={24}> |
| | | <Form.Item label="链接地址" className="textarea"> |
| | | {getFieldDecorator('link', { |
| | | initialValue: menu.link || '', |
| | | rules: [{ |
| | | required: true, |
| | | message: '请输入链接地址!' |
| | | }] |
| | | })(<TextArea rows={2} />)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {property === 'linkmenu' ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="关联当前app中已有的菜单。"> |
| | | <Icon type="question-circle" style={{color: '#c49f47', marginRight: '3px'}}/> |
| | | 关联菜单 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('linkMenuId', { |
| | | initialValue: menu.linkMenuId || '', |
| | | rules: [{ |
| | | required: true, |
| | | message: '请选择关联菜单!' |
| | | }] |
| | | })( |
| | | <Select> |
| | | {appMenus.map(item => (<Select.Option key={item.MenuID} value={item.MenuID}>{item.MenuName}</Select.Option>))} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {property === 'menu' ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="复制菜单仅在当前菜单不存在时有效。"> |
| | | <Icon type="question-circle" style={{color: '#c49f47', marginRight: '3px'}}/> |
| | | 复制菜单 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('copyMenuId', { |
| | | initialValue: menu.copyMenuId || '' |
| | | })( |
| | | <Select> |
| | | {appMenus.map(item => (<Select.Option key={item.MenuID} value={item.MenuID}>{item.MenuName}</Select.Option>))} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | </Row> |
| | | </Form> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(SettingForm) |
New file |
| | |
| | | .mob-menu-form { |
| | | .ant-form-item.textarea { |
| | | .ant-form-item-label { |
| | | width: 16%; |
| | | } |
| | | .ant-form-item-control-wrapper { |
| | | width: 84%; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Table, Button, Modal, Icon } from 'antd' |
| | | |
| | | import MenuForm from '../menuform' |
| | | import Utils from '@/utils/utils.js' |
| | | // import MKEmitter from '@/utils/events.js' |
| | | import './index.scss' |
| | | |
| | | const { confirm } = Modal |
| | | |
| | | class MenuTable extends Component { |
| | | static propTpyes = { |
| | | menus: PropTypes.array, // 卡片行信息 |
| | | cols: PropTypes.array, // 字段集 |
| | | } |
| | | |
| | | state = { |
| | | data: [], |
| | | editMenu: null, |
| | | columns: [ |
| | | { title: '菜单名称', dataIndex: 'name', key: 'name' }, |
| | | { title: '菜单参数', dataIndex: 'MenuNo', key: 'MenuNo' }, |
| | | { title: '菜单属性', dataIndex: 'property', key: 'property', render: text => { |
| | | const trans = {menu: '菜单', link: '链接', linkmenu: '关联菜单'} |
| | | |
| | | return trans[text] |
| | | }}, |
| | | { title: '图标', dataIndex: 'icon', key: 'icon', render: (text, record) => { |
| | | return text ? <Icon type={text} /> : '' |
| | | }}, |
| | | { title: '是否隐藏', dataIndex: 'hidden', key: 'hidden', render: (text, record) => { |
| | | const trans = {'true': '是', 'false': '否'} |
| | | return trans[text] || '否' |
| | | }}, |
| | | { title: '操作', key: 'operation', align: 'center', width: '190px', render: (text, record) => |
| | | (<div> |
| | | <Button type="link" style={{padding: '0 5px', marginRight: '5px'}} onClick={() => this.editMenu(record)}>编辑</Button> |
| | | <Button type="link" style={{color: '#ff4d4f', padding: '0 5px', marginRight: '5px'}} onClick={() => this.delMenu(record)}>删除</Button> |
| | | <Icon type="arrow-up" style={{color: '#26C281', cursor: 'pointer', padding: '0 5px', marginRight: '5px'}} onClick={() => this.moveUp(record)}/> |
| | | <Icon type="arrow-down" style={{color: '#ff4d4f', cursor: 'pointer', padding: '0 5px'}} onClick={() => this.moveDown(record)}/> |
| | | </div>) |
| | | } |
| | | ] |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { menus } = this.props |
| | | |
| | | this.setState({data: fromJS(menus).toJS()}) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | moveUp = (record) => { |
| | | let data = fromJS(this.state.data).toJS() |
| | | |
| | | let dragIndex = data.findIndex(c => c.MenuID === record.MenuID) |
| | | let hoverIndex = dragIndex - 1 |
| | | |
| | | if (hoverIndex === -1) return |
| | | |
| | | data.splice(hoverIndex, 0, ...data.splice(dragIndex, 1)) |
| | | this.setState({data}) |
| | | } |
| | | |
| | | moveDown = (record) => { |
| | | let data = fromJS(this.state.data).toJS() |
| | | |
| | | let dragIndex = data.findIndex(c => c.MenuID === record.MenuID) |
| | | let hoverIndex = dragIndex + 1 |
| | | |
| | | if (hoverIndex === data.length) return |
| | | |
| | | data.splice(hoverIndex, 0, ...data.splice(dragIndex, 1)) |
| | | this.setState({data}) |
| | | } |
| | | |
| | | delMenu = (record) => { |
| | | const { data } = this.state |
| | | const _this = this |
| | | |
| | | confirm({ |
| | | title: '确定删除吗?', |
| | | content: '', |
| | | onOk() { |
| | | _this.setState({data: data.filter(item => item.MenuID !== record.MenuID)}) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } |
| | | |
| | | editMenu = (record) => { |
| | | this.setState({editMenu: record, visible: true}) |
| | | } |
| | | |
| | | plusMenu = () => { |
| | | let _menu = { |
| | | name: '菜单', |
| | | property: 'menu' |
| | | } |
| | | |
| | | this.setState({editMenu: _menu, visible: true}) |
| | | } |
| | | |
| | | menuSubmit = () => { |
| | | const { editMenu, data } = this.state |
| | | |
| | | this.menuRef.handleConfirm().then(res => { |
| | | let _menu = {...editMenu, ...res} |
| | | let _data = fromJS(data).toJS() |
| | | |
| | | if (!_menu.MenuID) { |
| | | _menu.MenuID = Utils.getuuid() |
| | | _data.push(_menu) |
| | | } else { |
| | | _data = _data.map(item => { |
| | | if (item.MenuID === _menu.MenuID) { |
| | | return _menu |
| | | } else { |
| | | return item |
| | | } |
| | | }) |
| | | } |
| | | |
| | | if (editMenu.MenuID && editMenu.property === 'menu' && _menu.property !== 'menu') { |
| | | const _this = this |
| | | confirm({ |
| | | content: '菜单属性由“菜单”切换至其他类型时,菜单将被重置,即解除之前菜单的绑定关系,确定修改吗?', |
| | | onOk() { |
| | | _data = _data.map(item => { |
| | | if (item.MenuID === _menu.MenuID) { |
| | | item.MenuID = Utils.getuuid() |
| | | } |
| | | return item |
| | | }) |
| | | _this.setState({data: _data, editMenu: null, visible: false}) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } else { |
| | | this.setState({data: _data, editMenu: null, visible: false}) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | menuUpdate = (res) => { |
| | | const { data } = this.state |
| | | |
| | | this.setState({ |
| | | data: data.map(item => { |
| | | if (item.MenuID === res.MenuID) { |
| | | return res |
| | | } else { |
| | | return item |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const { cols } = this.props |
| | | const { columns, data, visible, editMenu } = this.state |
| | | |
| | | return ( |
| | | <div className="menu-control-wrap"> |
| | | <Button className="menu-plus mk-green" onClick={this.plusMenu}>添加</Button> |
| | | <Table |
| | | rowKey="MenuID" |
| | | columns={columns} |
| | | dataSource={data} |
| | | pagination={false} |
| | | /> |
| | | <Modal |
| | | title="编辑" |
| | | visible={visible} |
| | | width={750} |
| | | maskClosable={false} |
| | | onOk={this.menuSubmit} |
| | | onCancel={() => { this.setState({ visible: false }) }} |
| | | destroyOnClose |
| | | > |
| | | <MenuForm |
| | | menu={editMenu} |
| | | cols={cols} |
| | | inputSubmit={this.menuSubmit} |
| | | wrappedComponentRef={(inst) => this.menuRef = inst} |
| | | /> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default MenuTable |
New file |
| | |
| | | .menu-control-wrap { |
| | | position: relative; |
| | | |
| | | .menu-plus { |
| | | float: right; |
| | | position: relative; |
| | | z-index: 1; |
| | | margin-bottom: 5px; |
| | | } |
| | | .ant-empty { |
| | | margin: 5px 0; |
| | | } |
| | | thead tr { |
| | | background: #fbfbfb; |
| | | } |
| | | tbody > tr { |
| | | background: #ffffff; |
| | | } |
| | | |
| | | .ant-table-body { |
| | | margin: 0!important; |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Modal } from 'antd' |
| | | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import SettingForm from './settingform' |
| | | import './index.scss' |
| | | |
| | | class DataSource extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.any, |
| | | updateConfig: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | visible: false, |
| | | wrap: null |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { config } = this.props |
| | | |
| | | this.setState({wrap: fromJS(config.wrap).toJS()}) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | editDataSource = () => { |
| | | this.setState({ |
| | | visible: true |
| | | }) |
| | | } |
| | | |
| | | verifySubmit = () => { |
| | | const { config } = this.props |
| | | |
| | | this.verifyRef.handleConfirm().then(res => { |
| | | |
| | | this.setState({ |
| | | wrap: res, |
| | | visible: false |
| | | }) |
| | | this.props.updateConfig({...config, wrap: res}) |
| | | }) |
| | | } |
| | | |
| | | render () { |
| | | const { visible, dict, wrap } = this.state |
| | | |
| | | return ( |
| | | <div className="model-menu-setting-wrap"> |
| | | <Icon type="edit" title="编辑" onClick={() => this.editDataSource()} /> |
| | | <Modal |
| | | wrapClassName="popview-modal" |
| | | title="菜单栏设置" |
| | | visible={visible} |
| | | width={800} |
| | | maskClosable={false} |
| | | okText={dict['model.submit']} |
| | | onOk={this.verifySubmit} |
| | | onCancel={() => { this.setState({ visible: false }) }} |
| | | destroyOnClose |
| | | > |
| | | <SettingForm |
| | | dict={dict} |
| | | wrap={wrap} |
| | | inputSubmit={this.verifySubmit} |
| | | wrappedComponentRef={(inst) => this.verifyRef = inst} |
| | | /> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default DataSource |
New file |
| | |
| | | .model-menu-setting-wrap { |
| | | display: inline-block; |
| | | |
| | | >.anticon-edit { |
| | | color: #1890ff; |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Input, InputNumber, Tooltip, Icon, Radio } from 'antd' |
| | | |
| | | import './index.scss' |
| | | |
| | | class SettingForm extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, // 字典项 |
| | | wrap: PropTypes.object, // 数据源配置 |
| | | inputSubmit: PropTypes.func // 回车事件 |
| | | } |
| | | |
| | | state = {} |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | | return new Promise((resolve, reject) => { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | resolve(values) |
| | | } else { |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | handleSubmit = (e) => { |
| | | e.preventDefault() |
| | | |
| | | if (this.props.inputSubmit) { |
| | | this.props.inputSubmit() |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { wrap } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 8 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 16 } |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <div className="model-menu-setting-form"> |
| | | <Form {...formItemLayout}> |
| | | <Row gutter={24}> |
| | | <Col span={12}> |
| | | <Form.Item label="导航栏名称"> |
| | | {getFieldDecorator('name', { |
| | | initialValue: wrap.name, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '导航栏名称!' |
| | | } |
| | | ] |
| | | })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label="菜单参数"> |
| | | {getFieldDecorator('MenuNo', { |
| | | initialValue: wrap.MenuNo, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '菜单参数!' |
| | | } |
| | | ] |
| | | })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="选择静态值,无需配置数据源。"> |
| | | <Icon type="question-circle" /> |
| | | 数据来源 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('datatype', { |
| | | initialValue: wrap.datatype || 'static' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="dynamic">动态</Radio> |
| | | <Radio value="static">静态</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label="高度"> |
| | | {getFieldDecorator('height', { |
| | | initialValue: wrap.height || 50, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '高度!' |
| | | } |
| | | ] |
| | | })(<InputNumber min={30} max={200} precision={0} onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(SettingForm) |
New file |
| | |
| | | .model-menu-setting-form { |
| | | position: relative; |
| | | |
| | | .anticon-question-circle { |
| | | color: #c49f47; |
| | | margin-right: 3px; |
| | | } |
| | | .ant-input-number { |
| | | width: 100%; |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Popover } from 'antd' |
| | | |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | |
| | | import MKEmitter from '@/utils/events.js' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import './index.scss' |
| | | |
| | | const WrapComponent = asyncIconComponent(() => import('./wrapsetting')) |
| | | |
| | | class NormalNavbar extends Component { |
| | | static propTpyes = { |
| | | card: PropTypes.object, |
| | | deletecomponent: PropTypes.func, |
| | | updateConfig: PropTypes.func, |
| | | } |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | card: null, |
| | | back: false |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { card } = this.props |
| | | |
| | | if (card.isNew) { |
| | | let _card = { |
| | | uuid: card.uuid, |
| | | type: card.type, |
| | | floor: card.floor, |
| | | width: 24, |
| | | subtype: card.subtype, |
| | | wrap: { type: 'navbar', height: 50, title: 'NavBar', back: 'true', search: 'false', logout: 'false' }, |
| | | style: {borderBottomColor: '#bcbcbc', borderBottomWidth: '1px', paddingLeft: '10px', paddingRight: '10px', lineHeight: '2.8', fontSize: '18px' }, |
| | | } |
| | | |
| | | if (card.config) { |
| | | let config = fromJS(card.config).toJS() |
| | | |
| | | _card.wrap = config.wrap |
| | | _card.style = config.style |
| | | } |
| | | |
| | | this.setState({ |
| | | card: _card |
| | | }) |
| | | this.props.updateConfig(_card) |
| | | } else { |
| | | this.setState({ |
| | | card: fromJS(card).toJS() |
| | | }) |
| | | } |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('submitStyle', this.getStyle) |
| | | MKEmitter.addListener('submitSearch', this.getSearch) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新,清除快捷键设置 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('submitStyle', this.getStyle) |
| | | MKEmitter.removeListener('submitSearch', this.getSearch) |
| | | } |
| | | |
| | | /** |
| | | * @description 卡片行外层信息更新(数据源,样式等) |
| | | */ |
| | | updateComponent = (component) => { |
| | | this.setState({ |
| | | card: component |
| | | }) |
| | | |
| | | this.props.updateConfig(component) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | | const { card } = this.state |
| | | |
| | | if (comIds[0] !== card.uuid) return |
| | | |
| | | let _card = {...card, style} |
| | | |
| | | this.setState({ |
| | | card: _card |
| | | }) |
| | | |
| | | this.props.updateConfig(_card) |
| | | } |
| | | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['font', 'background', 'border', 'padding', 'shadow'], card.style) |
| | | } |
| | | |
| | | clickComponent = (e) => { |
| | | if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { |
| | | e.stopPropagation() |
| | | MKEmitter.emit('clickComponent', this.state.card) |
| | | } |
| | | } |
| | | |
| | | changeMenu = (menu) => { |
| | | if (menu.property === 'link') { |
| | | window.open(menu.link) |
| | | } else { |
| | | MKEmitter.emit('changeEditMenu', { |
| | | MenuID: menu.property === 'linkmenu' ? menu.linkMenuId : menu.MenuID, |
| | | copyMenuId: menu.property === 'menu' ? menu.copyMenuId : '', |
| | | MenuNo: menu.MenuNo, |
| | | MenuName: menu.name, |
| | | }) |
| | | } |
| | | } |
| | | |
| | | getSearch = (config) => { |
| | | const { card } = this.state |
| | | |
| | | if (card.uuid !== config.uuid) return |
| | | |
| | | this.setState({ |
| | | card: config |
| | | }) |
| | | |
| | | this.props.updateConfig(config) |
| | | } |
| | | |
| | | setSearch = () => { |
| | | let card = fromJS(this.state.card).toJS() |
| | | |
| | | if (!card.search) { |
| | | card.search = { |
| | | floor: 1, |
| | | setting: { type: 'title', field: '', title: '', focus: 'true', btn: 'hidden' }, |
| | | groups: [], |
| | | fields: [] |
| | | } |
| | | } |
| | | this.props.updateConfig(card) |
| | | MKEmitter.emit('changeSearch', card) |
| | | } |
| | | |
| | | render() { |
| | | const { card } = this.state |
| | | |
| | | let _style = {...card.style} |
| | | if (_style.shadow) { |
| | | _style.boxShadow = '0 0 4px ' + _style.shadow |
| | | } |
| | | |
| | | return ( |
| | | <div className="normal-topbar-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <WrapComponent config={card} updateConfig={this.updateComponent} /> |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | | <Icon className="close" title="删除组件" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <Icon type="tool" /> |
| | | </Popover> |
| | | <div className="am-navbar"> |
| | | <div className="am-navbar-left"> |
| | | {card.wrap.back !== 'false' ? <Icon type="left" /> : null} |
| | | </div> |
| | | {card.wrap.type !== 'search' ? |
| | | <div className="am-navbar-title">{card.wrap.title || ''}</div> : |
| | | <div className="am-navbar-search" onDoubleClick={this.setSearch}><div className="search-bar"><Icon type="search" /></div></div> |
| | | } |
| | | <div className="am-navbar-right"> |
| | | {card.wrap.search === 'true' ? <Icon type="search" onDoubleClick={this.setSearch}/> : null} |
| | | {card.wrap.logout === 'true' ? <Icon type="ellipsis" /> : null} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default NormalNavbar |
New file |
| | |
| | | .normal-topbar-edit-box { |
| | | position: absolute; |
| | | top: 0px; |
| | | left: 0px; |
| | | width: 100%; |
| | | box-sizing: border-box; |
| | | background: #ffffff; |
| | | background-position: center center; |
| | | background-repeat: no-repeat; |
| | | background-size: cover; |
| | | height: 50px; |
| | | z-index: 3; |
| | | |
| | | .anticon-tool { |
| | | position: absolute; |
| | | z-index: 2; |
| | | font-size: 16px; |
| | | right: 1px; |
| | | top: 1px; |
| | | cursor: pointer; |
| | | padding: 5px; |
| | | background: rgba(255, 255, 255, 0.55); |
| | | color: rgba(0, 0, 0, 0.65); |
| | | } |
| | | .am-navbar { |
| | | height: 100%; |
| | | display: flex; |
| | | font-style: inherit; |
| | | font-weight: inherit; |
| | | .am-navbar-left { |
| | | width: 30px; |
| | | text-align: left; |
| | | color: #1890ff; |
| | | font-size: 20px; |
| | | line-height: 50px; |
| | | } |
| | | .am-navbar-title { |
| | | text-align: center; |
| | | font-style: inherit; |
| | | font-weight: inherit; |
| | | flex: 1; |
| | | } |
| | | .am-navbar-search { |
| | | flex: 1; |
| | | padding: 0 5px; |
| | | .search-bar { |
| | | height: 30px; |
| | | line-height: 30px; |
| | | padding: 0 10px; |
| | | color:rgba(0, 0, 0, 0.65); |
| | | border: 1px solid #E9EDF0; |
| | | background: #E9EDF0; |
| | | border-radius: 4px; |
| | | position: relative; |
| | | top: 50%; |
| | | transform: translateY(-50%); |
| | | cursor: pointer; |
| | | font-size: 18px; |
| | | } |
| | | } |
| | | .am-navbar-right { |
| | | text-align: right; |
| | | color: #1890ff; |
| | | min-width: 30px; |
| | | font-size: 20px; |
| | | line-height: 50px; |
| | | .anticon-search { |
| | | margin-right: 5px; |
| | | padding: 5px; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .normal-topbar-edit-box::after { |
| | | display: block; |
| | | content: ' '; |
| | | clear: both; |
| | | } |
| | | .normal-topbar-edit-box:hover { |
| | | box-shadow: 0px 0px 4px #1890ff; |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Modal } from 'antd' |
| | | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import SettingForm from './settingform' |
| | | import './index.scss' |
| | | |
| | | class DataSource extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.any, |
| | | updateConfig: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | visible: false, |
| | | wrap: null |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { config } = this.props |
| | | |
| | | this.setState({wrap: fromJS(config.wrap).toJS()}) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | editDataSource = () => { |
| | | this.setState({ |
| | | visible: true |
| | | }) |
| | | } |
| | | |
| | | verifySubmit = () => { |
| | | const { config } = this.props |
| | | |
| | | this.verifyRef.handleConfirm().then(res => { |
| | | |
| | | this.setState({ |
| | | wrap: res, |
| | | visible: false |
| | | }) |
| | | this.props.updateConfig({...config, wrap: res}) |
| | | }) |
| | | } |
| | | |
| | | render () { |
| | | const { visible, dict, wrap } = this.state |
| | | |
| | | return ( |
| | | <div className="model-menu-setting-wrap"> |
| | | <Icon type="edit" title="编辑" onClick={() => this.editDataSource()} /> |
| | | <Modal |
| | | wrapClassName="popview-modal" |
| | | title="导航栏设置" |
| | | visible={visible} |
| | | width={750} |
| | | maskClosable={false} |
| | | okText={dict['model.submit']} |
| | | onOk={this.verifySubmit} |
| | | onCancel={() => { this.setState({ visible: false }) }} |
| | | destroyOnClose |
| | | > |
| | | <SettingForm |
| | | dict={dict} |
| | | wrap={wrap} |
| | | inputSubmit={this.verifySubmit} |
| | | wrappedComponentRef={(inst) => this.verifyRef = inst} |
| | | /> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default DataSource |
New file |
| | |
| | | .model-menu-setting-wrap { |
| | | display: inline-block; |
| | | |
| | | >.anticon-edit { |
| | | color: #1890ff; |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Input, Radio, Tooltip, Icon } from 'antd' |
| | | |
| | | import './index.scss' |
| | | |
| | | class SettingForm extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, // 字典项 |
| | | wrap: PropTypes.object, // 数据源配置 |
| | | inputSubmit: PropTypes.func // 回车事件 |
| | | } |
| | | |
| | | state = { |
| | | type: this.props.wrap.type || 'navbar' |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | | return new Promise((resolve, reject) => { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | resolve(values) |
| | | } else { |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | handleSubmit = (e) => { |
| | | e.preventDefault() |
| | | |
| | | if (this.props.inputSubmit) { |
| | | this.props.inputSubmit() |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { wrap } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { type } = this.state |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 8 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 16 } |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <div className="model-menu-setting-form"> |
| | | <Form {...formItemLayout}> |
| | | <Row gutter={24}> |
| | | <Col span={12}> |
| | | <Form.Item label="类型"> |
| | | {getFieldDecorator('type', { |
| | | initialValue: wrap.type || 'navbar' |
| | | })( |
| | | <Radio.Group onChange={(e) => this.setState({type: e.target.value})}> |
| | | <Radio value="navbar">导航栏</Radio> |
| | | <Radio value="search">搜索栏</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="使用搜索栏时,标题用于搜索条件隐藏时显示。"> |
| | | <Icon type="question-circle" /> |
| | | 标题 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('title', { |
| | | initialValue: wrap.title || '' |
| | | })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label="返回"> |
| | | {getFieldDecorator('back', { |
| | | initialValue: wrap.back || 'true' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="true">显示</Radio> |
| | | <Radio value="false">隐藏</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {type === 'navbar' ? <Col span={12}> |
| | | <Form.Item label="搜索"> |
| | | {getFieldDecorator('search', { |
| | | initialValue: wrap.search || 'false' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="true">显示</Radio> |
| | | <Radio value="false">隐藏</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="点击退出时,返回第一个页面。"> |
| | | <Icon type="question-circle" /> |
| | | 退出 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('logout', { |
| | | initialValue: wrap.logout || 'false' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="true">显示</Radio> |
| | | <Radio value="false">隐藏</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(SettingForm) |
New file |
| | |
| | | .model-menu-setting-form { |
| | | position: relative; |
| | | |
| | | .anticon-question-circle { |
| | | color: #c49f47; |
| | | margin-right: 3px; |
| | | } |
| | | .ant-input-number { |
| | | width: 100%; |
| | | } |
| | | } |
| | |
| | | import React, {Component} from 'react' |
| | | import { Radio } from 'antd' |
| | | |
| | | import avatar from '@/assets/img/avatar.jpg' |
| | | import MainLogo from '@/assets/img/main-logo.png' |
| | |
| | | class MobHeader extends Component { |
| | | state = { |
| | | avatar: sessionStorage.getItem('CloudAvatar') || avatar, |
| | | userName: sessionStorage.getItem('CloudUserName') |
| | | userName: sessionStorage.getItem('CloudUserName'), |
| | | typename: sessionStorage.getItem('typename') |
| | | } |
| | | |
| | | changeView = (e) => { |
| | | let val = e.target.value |
| | | this.props.changeView(val) |
| | | } |
| | | |
| | | render () { |
| | | const { typename } = this.state |
| | | return ( |
| | | <header className="mob-header-container"> |
| | | <div className="header-logo"><img src={MainLogo} alt=""/></div> |
| | | {typename === 'pad' ? <div className="change-view"> |
| | | <Radio.Group defaultValue="vertical" onChange={this.changeView}> |
| | | <Radio value="vertical">竖屏</Radio> |
| | | <Radio value="horizontal">横屏</Radio> |
| | | </Radio.Group> |
| | | </div> : null} |
| | | <div className="header-user"> |
| | | <img src={this.state.avatar} alt=""/> |
| | | <span> |
| | |
| | | } |
| | | } |
| | | } |
| | | .change-view { |
| | | position: absolute; |
| | | left: calc(50% - 70px); |
| | | top: 12px; |
| | | .ant-radio-wrapper { |
| | | color: #ffffff; |
| | | } |
| | | } |
| | | } |
| | |
| | | import './index.scss' |
| | | |
| | | const AntvBar = asyncComponent(() => import('@/menu/components/chart/antv-bar')) |
| | | const MainSearch = asyncComponent(() => import('@/menu/components/search/main-search')) |
| | | // 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 AntvScatter = asyncComponent(() => import('@/menu/components/chart/antv-scatter')) |
| | | 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')) |
| | |
| | | const NormalForm = asyncComponent(() => import('@/menu/components/form/normal-form')) |
| | | const NormalGroup = asyncComponent(() => import('@/menu/components/group/normal-group')) |
| | | const CodeSandbox = asyncComponent(() => import('@/menu/components/code/sandbox')) |
| | | const BraftEditor = asyncComponent(() => import('@/menu/components/editor/braft-editor')) |
| | | const NormalLogin = asyncComponent(() => import('@/pc/components/login/normal-login')) |
| | | const NormalNavbar = asyncComponent(() => import('@/mob/components/navbar/normal-navbar')) |
| | | const NormalTopbar = asyncComponent(() => import('@/mob/components/topbar/normal-navbar')) |
| | | const NormalMenuBar = asyncComponent(() => import('@/mob/components/menubar/normal-menubar')) |
| | | const Balcony = asyncComponent(() => import('@/menu/components/card/balcony')) |
| | | |
| | | const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => { |
| | | const originalIndex = findCard(id).index |
| | |
| | | style = { opacity: 0.3} |
| | | } |
| | | |
| | | let col = 'ant-col-' + (card.width || 24) |
| | | if (card.type === 'login') { |
| | | let height = '' |
| | | if (card.wrap && card.wrap.height) { |
| | | // scaleview |
| | | height = card.wrap.height.replace(/\d+vw/ig, (word) => { |
| | | return parseFloat(word) * (window.GLOB.winWidth || 420) / 100 + 'px' |
| | | // return parseFloat(word) * 350 / 100 + 'px' |
| | | }).replace(/\d+vh/ig, (word) => { |
| | | return parseFloat(word) * (window.GLOB.winHeight || 738) / 100 + 'px' |
| | | // return parseFloat(word) * 615 / 100 + 'px' |
| | | }) |
| | | } |
| | | |
| | | style.minHeight = height |
| | | } |
| | | |
| | | const getCardComponent = () => { |
| | | if (card.type === 'bar' || card.type === 'line') { |
| | | return (<AntvBar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'search') { |
| | | return (<MainSearch card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | // } else if (card.type === 'search') { |
| | | // 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 === 'scatter') { |
| | | return (<AntvScatter card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'form') { |
| | | return (<NormalForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'tabs') { |
| | |
| | | return (<NormalGroup group={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'code') { |
| | | return (<CodeSandbox card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'editor') { |
| | | return (<BraftEditor card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'login') { |
| | | return (<NormalLogin card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'navbar') { |
| | | return (<NormalNavbar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'topbar') { |
| | | return (<NormalTopbar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'menubar') { |
| | | return (<NormalMenuBar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'balcony') { |
| | | return (<Balcony card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } |
| | | } |
| | | return ( |
| | | <div className={'ant-col mk-component-card ant-col-' + (card.width || 24)} ref={node => drag(drop(node))} style={style}> |
| | | {getCardComponent()} |
| | | </div> |
| | | ) |
| | | |
| | | if (card.type === 'navbar' || card.type === 'topbar') { |
| | | return getCardComponent() |
| | | } else { |
| | | return ( |
| | | <div className={'ant-col mk-component-card ' + col} ref={node => drag(drop(node))} style={style}> |
| | | {getCardComponent()} |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | export default Card |
| | |
| | | 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] |
| | |
| | | let uuids = MenuUtils.getDelButtonIds(card) |
| | | |
| | | confirm({ |
| | | title: `确定删除《${card.name}》吗?`, |
| | | title: `确定删除${card.name ? `《${card.name}》` : '组件'}吗?`, |
| | | content: hasComponent ? '当前组件中含有子组件!' : '', |
| | | onOk() { |
| | | MKEmitter.emit('delButtons', uuids) |
| | | const _cards = cards.filter(item => item.uuid !== card.uuid) |
| | | handleList({...menu, components: _cards}) |
| | | setCards(_cards) |
| | | |
| | | if (uuids.length === 0) return |
| | | |
| | | MKEmitter.emit('delButtons', uuids) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | |
| | | }) |
| | | return |
| | | } |
| | | } else if (item.component === 'navbar') { |
| | | if (cards.filter(card => card.type === 'navbar').length > 0) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '菜单栏不可重复添加!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | } else if (item.component === 'topbar') { |
| | | if (cards.filter(card => card.type === 'topbar').length > 0) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '导航栏不可重复添加!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | } |
| | | |
| | | let name = '' |
| | |
| | | editor: '富文本', |
| | | code: '自定义', |
| | | carousel: '轮播', |
| | | dashboard: '仪表盘', |
| | | form: '表单', |
| | | card: '卡片' |
| | | card: '卡片', |
| | | navbar: '导航栏', |
| | | menubar: '菜单栏', |
| | | login: '登录' |
| | | } |
| | | let i = 1 |
| | | |
| | |
| | | } |
| | | |
| | | const { index: overIndex } = findCard(`${targetId}`) |
| | | const _cards = update(cards, { $splice: [[overIndex + 1, 0, newcard]] }) |
| | | let _cards = update(cards, { $splice: [[overIndex + 1, 0, newcard]] }) |
| | | let Topbar = null |
| | | let Navbar = null |
| | | _cards = _cards.filter(item => { |
| | | if (item.type === 'topbar') { |
| | | Topbar = item |
| | | } else if (item.type === 'navbar') { |
| | | Navbar = item |
| | | } |
| | | |
| | | return item.type !== 'topbar' && item.type !== 'navbar' |
| | | }) |
| | | |
| | | if (Topbar) { |
| | | _cards.unshift(Topbar) |
| | | } |
| | | if (Navbar) { |
| | | _cards.push(Navbar) |
| | | } |
| | | |
| | | handleList({...menu, components: _cards}) |
| | | setCards(_cards) |
| | |
| | | }) |
| | | |
| | | return ( |
| | | <div ref={drop} className="mob-shell-inner" id="menu-shell-inner" style={menu.style}> |
| | | <div className="ant-row"> |
| | | <div ref={drop} className="mob-shell-inner" id="menu-shell-inner"> |
| | | <div className="ant-row" style={menu.style}> |
| | | {cards.map(card => ( |
| | | <Card |
| | | id={card.uuid} |
| | |
| | | updateConfig={updateConfig} |
| | | /> |
| | | ))} |
| | | {cards.length === 0 ? |
| | | <Empty description="请添加组件" /> : null |
| | | } |
| | | </div> |
| | | {cards.length === 0 ? |
| | | <Empty description="请添加组件" /> : null |
| | | } |
| | | </div> |
| | | ) |
| | | } |
| | |
| | | .mob-shell-inner { |
| | | // scaleview |
| | | width: 120%; |
| | | height: 120%; |
| | | overflow-y: auto; |
| | | overflow-x: hidden; |
| | | background: #ffffff; |
| | | box-shadow: 0px 0px 2px #000000; |
| | | transform: scale(0.8333333333333334, 0.8333333333333334); |
| | | transform-origin: left top; |
| | | .mk-component-card { |
| | | position: relative; |
| | | } |
| | | >.ant-empty { |
| | | padding-top: 150px; |
| | | >.ant-row { |
| | | min-height: 100%; |
| | | >.ant-empty { |
| | | padding-top: 150px; |
| | | } |
| | | } |
| | | } |
| | | .mob-shell-inner::-webkit-scrollbar { |
| | | width: 2px; |
| | | } |
| | | .mob-shell-inner::-webkit-scrollbar-thumb { |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13); |
| | | background: rgba(0, 0, 0, 0.23); |
| | | border-radius: 5px; |
| | | } |
| | | .mob-shell-inner::-webkit-scrollbar-track { |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); |
| | | border: 1px solid rgba(0, 0, 0, 0.07); |
| | | background: rgba(0, 0, 0, 0); |
| | | border-radius: 3px; |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import { is, fromJS } from 'immutable' |
| | | |
| | | import MKEmitter from '@/utils/events.js' |
| | | import ModalConfig from '@/mob/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) |
| | | } |
| | | |
| | | 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 |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { DndProvider } from 'react-dnd' |
| | | import HTML5Backend from 'react-dnd-html5-backend' |
| | | import moment from 'moment' |
| | | import { Button, Modal, Collapse, notification, Switch, Icon } 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 SourceElement from '@/templates/modalconfig/dragelement/source' |
| | | import SettingForm from '@/templates/modalconfig/settingform' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import { SearchItems } from './source' |
| | | import './index.scss' |
| | | |
| | | const { Panel } = Collapse |
| | | const { confirm } = Modal |
| | | const CommonDict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS |
| | | const PasteComponent = asyncComponent(() => import('./pastecomponent')) |
| | | const ModalForm = asyncComponent(() => import('@/templates/zshare/modalform')) |
| | | const DragElement = asyncComponent(() => import('@/mob/components/formdragelement')) |
| | | const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent')) |
| | | |
| | | class ComModalConfig extends Component { |
| | | static propTpyes = { |
| | | btn: PropTypes.object, |
| | | handleSave: PropTypes.func, |
| | | handleBack: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | dict: CommonDict, // 字典 |
| | | config: null, // 页面配置,包括模板类型、模态框设置、添加表名、表单列表 |
| | | visible: false, // 表单编辑模态框,显示控制 |
| | | formlist: null, // 表单编辑模态框,可编辑字段 |
| | | card: null, // 编辑元素 |
| | | settingVisible: false, // 全局配置模态框 |
| | | originConfig: null, // 原始菜单 |
| | | sqlVerifing: false, // sql验证 |
| | | showField: false, // 显示表单字段值 |
| | | standardform: null |
| | | } |
| | | |
| | | /** |
| | | * @description 数据预处理 |
| | | */ |
| | | UNSAFE_componentWillMount () { |
| | | const { btn } = this.props |
| | | |
| | | let _config = btn.modal |
| | | _config.version = '1.0' |
| | | |
| | | this.setState({ |
| | | config: _config, |
| | | originConfig: fromJS(_config).toJS() |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 表单变化 |
| | | * 1、表单拖拽添加时,检查是否存在示例表单,如存在则去除示例 |
| | | * 2、表单移动后,保存移动后的顺序 |
| | | * 3、新增表单时,直接打开编辑框 |
| | | */ |
| | | handleList = (list, newcard) => { |
| | | let _config = fromJS(this.state.config).toJS() |
| | | |
| | | if (list.length > _config.fields.length) { |
| | | _config.fields = list.filter(item => !item.origin) |
| | | |
| | | this.setState({ |
| | | config: _config |
| | | }, () => { |
| | | this.handleForm(newcard) |
| | | }) |
| | | } else { |
| | | _config.fields = list |
| | | this.setState({config: _config}) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 表单编辑 |
| | | * 1、显示编辑弹窗-visible |
| | | * 2、保存编辑项-card |
| | | * 3、设置编辑参数项-formlist |
| | | */ |
| | | handleForm = (_card) => { |
| | | const { componentConfig } = this.props |
| | | const { config } = this.state |
| | | let card = fromJS(_card).toJS() |
| | | let _inputfields = [] |
| | | let _tabfields = [] |
| | | let _linkableFields = [] |
| | | let _linksupFields = [{ |
| | | value: '', |
| | | text: '空' |
| | | }] |
| | | let standardform = null |
| | | |
| | | _inputfields = config.fields.filter(item => item.type === 'text' || item.type === 'number' || item.type === 'textarea' || item.type === 'color') |
| | | _tabfields = config.fields.filter(item => card.field !== item.field && item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) |
| | | _tabfields.unshift({field: '', text: '原表单'}) |
| | | |
| | | let uniq = new Map() |
| | | uniq.set(card.field, true) |
| | | let index = null |
| | | config.fields.forEach((item, i) => { |
| | | if (card.uuid === item.uuid) { |
| | | index = i |
| | | } |
| | | if (!['select', 'link', 'radio', 'checkcard'].includes(item.type)) return |
| | | if (item.field && !uniq.has(item.field)) { |
| | | uniq.set(item.field, true) |
| | | |
| | | _linkableFields.push({ |
| | | value: item.field, |
| | | text: item.label + ' (表单)' |
| | | }) |
| | | _linksupFields.push({ |
| | | value: item.field, |
| | | text: item.label |
| | | }) |
| | | } |
| | | }) |
| | | if (index !== null) { |
| | | if (index === 0) { |
| | | standardform = config.fields[index + 1] || null |
| | | } else { |
| | | standardform = config.fields[index - 1] || null |
| | | } |
| | | } |
| | | |
| | | componentConfig.columns.forEach(col => { |
| | | if (col.field && !uniq.has(col.field)) { |
| | | uniq.set(col.field, true) |
| | | |
| | | _linkableFields.push({ |
| | | value: col.field, |
| | | text: col.label + ' (显示列)' |
| | | }) |
| | | } |
| | | }) |
| | | |
| | | if (card.linkSubField && card.linkSubField.length > 0) { |
| | | let fields = _inputfields.map(item => item.field) |
| | | card.linkSubField = card.linkSubField.filter(item => fields.includes(item)) |
| | | } |
| | | |
| | | if (!card.span && standardform && standardform.span) { |
| | | card.span = standardform.span |
| | | card.labelwidth = standardform.labelwidth |
| | | } |
| | | |
| | | this.setState({ |
| | | standardform, |
| | | visible: true, |
| | | card: card, |
| | | formlist: getModalForm(card, _inputfields, _tabfields, _linkableFields, _linksupFields, !!this.props.editTab) |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 编辑后提交 |
| | | * 1、获取编辑后的表单信息 |
| | | * 2、去除可能存在的示例表单 |
| | | * 3、通过loading刷新 |
| | | */ |
| | | handleSubmit = () => { |
| | | this.formRef.handleConfirm().then(res => { |
| | | let _config = fromJS(this.state.config).toJS() |
| | | let fieldrepet = false // 字段重复 |
| | | let labelrepet = false // 提示文字重复 |
| | | |
| | | _config.fields = _config.fields.map(item => { |
| | | if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) { |
| | | fieldrepet = true |
| | | } else if (res.label && item.uuid !== res.uuid && item.label === res.label) { |
| | | labelrepet = true |
| | | } |
| | | |
| | | if (item.uuid === res.uuid) { |
| | | return res |
| | | } else { |
| | | return item |
| | | } |
| | | }) |
| | | |
| | | if (fieldrepet) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '字段已存在!', |
| | | duration: 10 |
| | | }) |
| | | return |
| | | } else if (labelrepet) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '名称已存在!', |
| | | duration: 10 |
| | | }) |
| | | return |
| | | } |
| | | |
| | | _config.fields = _config.fields.filter(item => !item.origin) |
| | | |
| | | if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) { |
| | | this.setState({ |
| | | sqlVerifing: true |
| | | }) |
| | | |
| | | let param = { |
| | | func: 's_debug_sql', |
| | | exec_type: 'y', |
| | | LText: res.dataSource |
| | | } |
| | | |
| | | param.LText = param.LText.replace(/@\$|\$@/ig, '') |
| | | |
| | | param.LText = Utils.formatOptions(param.LText) |
| | | param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') |
| | | param.secretkey = Utils.encrypt('', param.timestamp) |
| | | |
| | | if (window.GLOB.mainSystemApi && res.database === 'sso') { |
| | | param.rduri = window.GLOB.mainSystemApi |
| | | } |
| | | |
| | | Api.getLocalConfig(param).then(result => { |
| | | if (result.status) { |
| | | this.setState({ |
| | | sqlVerifing: false, |
| | | config: _config, |
| | | card: null, |
| | | visible: false |
| | | }) |
| | | } else { |
| | | this.setState({sqlVerifing: false}) |
| | | |
| | | Modal.error({ |
| | | title: result.message |
| | | }) |
| | | } |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | config: _config, |
| | | card: null, |
| | | visible: false |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 表单删除并刷新 |
| | | */ |
| | | closeForm = (card) => { |
| | | let _this = this |
| | | |
| | | confirm({ |
| | | content: `确定删除${card.label ? `<<${card.label}>>` : ''}吗?`, |
| | | onOk() { |
| | | let _config = fromJS(_this.state.config).toJS() |
| | | _config.fields = _config.fields.filter(item => !(item.uuid === card.uuid)) |
| | | |
| | | _this.setState({ |
| | | config: _config, |
| | | }) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } |
| | | |
| | | submitConfig = () => { |
| | | const { config } = this.state |
| | | |
| | | this.setState({originConfig: fromJS(config).toJS()}) |
| | | this.props.handleSave(config) |
| | | notification.success({ |
| | | top: 92, |
| | | message: '保存成功。', |
| | | duration: 2 |
| | | }) |
| | | } |
| | | |
| | | cancelConfig = () => { |
| | | const { config, originConfig } = this.state |
| | | |
| | | if (!is(fromJS(config), fromJS(originConfig))) { |
| | | let _this = this |
| | | confirm({ |
| | | content: '配置信息未保存,确定返回吗?', |
| | | onOk() { |
| | | _this.props.handleBack() |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } else { |
| | | this.props.handleBack() |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 全局设置模态框 |
| | | */ |
| | | changeSetting = () => { |
| | | this.setState({ |
| | | settingVisible: true |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 保存全局设置 |
| | | */ |
| | | settingSave = () => { |
| | | const {config} = this.state |
| | | this.settingRef.handleConfirm().then(res => { |
| | | this.setState({ |
| | | config: {...config, setting: res}, |
| | | settingVisible: false |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | editModalCancel = () => { |
| | | const { config, card } = this.state |
| | | |
| | | if (card.focus) { |
| | | let _fields = config.fields.filter(item => item.uuid !== card.uuid) |
| | | let _config = {...config, fields: _fields} |
| | | |
| | | this.setState({ |
| | | card: null, |
| | | config: _config, |
| | | visible: false |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | card: null, |
| | | visible: false |
| | | }) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 更新 |
| | | */ |
| | | updateConfig = (config) => { |
| | | this.setState({ |
| | | config |
| | | }) |
| | | } |
| | | |
| | | insert = (config) => { |
| | | this.setState({ |
| | | config |
| | | }, () => { |
| | | this.handleForm(config.fields[config.fields.length - 1]) |
| | | }) |
| | | } |
| | | |
| | | render () { |
| | | const { config, dict } = this.state |
| | | |
| | | return ( |
| | | <div className="mob-form-board"> |
| | | <DndProvider backend={HTML5Backend}> |
| | | <div className="tools"> |
| | | <Collapse accordion defaultActiveKey="1" bordered={false}> |
| | | <Panel header={dict['header.menu.form']} key="1"> |
| | | <div className="search-element"> |
| | | {SearchItems.map((item, index) => { |
| | | return (<SourceElement key={index} content={item}/>) |
| | | })} |
| | | </div> |
| | | <FieldsComponent |
| | | config={config} |
| | | type="form" |
| | | updatefield={this.updateConfig} |
| | | /> |
| | | </Panel> |
| | | </Collapse> |
| | | </div> |
| | | <div className="modal-control"> |
| | | <Button icon="setting" onClick={this.changeSetting}>设置</Button> |
| | | <Button type="primary" onClick={this.submitConfig}>保存</Button> |
| | | <Button onClick={this.cancelConfig}>返回</Button> |
| | | <PasteComponent config={config} updateConfig={this.insert} /> |
| | | <Switch checkedChildren={dict['model.switch.open']} unCheckedChildren={dict['model.switch.close']} defaultChecked={this.state.showField} onChange={(val) => this.setState({showField: val})} /> |
| | | </div> |
| | | <div className="setting"> |
| | | <div className="mob-shell" style={{width: window.GLOB.shellWidth, height: window.GLOB.shellHeight}}> |
| | | <div className="mob-shell-inner"> |
| | | <div className="am-navbar"> |
| | | <Icon type="close" /> |
| | | <div className="am-navbar-title">{config.setting.title}</div> |
| | | </div> |
| | | <DragElement |
| | | list={config.fields} |
| | | setting={config.setting} |
| | | showField={this.state.showField} |
| | | placeholder={this.state.dict['header.form.modal.placeholder']} |
| | | handleList={this.handleList} |
| | | handleForm={this.handleForm} |
| | | closeForm={this.closeForm} |
| | | /> |
| | | <Button className="modal-submit" type="primary">确定</Button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </DndProvider> |
| | | <Modal |
| | | title={this.state.dict['model.edit']} |
| | | visible={this.state.visible} |
| | | width={850} |
| | | onCancel={this.editModalCancel} |
| | | onOk={this.handleSubmit} |
| | | confirmLoading={this.state.sqlVerifing} |
| | | destroyOnClose |
| | | > |
| | | <ModalForm |
| | | dict={this.state.dict} |
| | | card={this.state.card} |
| | | formlist={this.state.formlist} |
| | | inputSubmit={this.handleSubmit} |
| | | standardform={this.state.standardform} |
| | | wrappedComponentRef={(inst) => this.formRef = inst} |
| | | /> |
| | | </Modal> |
| | | <Modal |
| | | title={this.state.dict['model.edit']} |
| | | visible={this.state.settingVisible} |
| | | width={850} |
| | | maskClosable={false} |
| | | onOk={this.settingSave} |
| | | onCancel={() => { this.setState({ settingVisible: false }) }} |
| | | destroyOnClose |
| | | > |
| | | <SettingForm |
| | | config={config} |
| | | dict={this.state.dict} |
| | | isSubTab={!!this.props.editTab} |
| | | inputSubmit={this.settingSave} |
| | | wrappedComponentRef={(inst) => this.settingRef = inst} |
| | | /> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default ComModalConfig |
src/mob/modalconfig/index.scss
src/mob/modalconfig/pastecomponent/index.jsx
src/mob/modalconfig/pastecomponent/index.scss
src/mob/modalconfig/source.jsx
src/mob/modulesource/index.jsx
src/mob/modulesource/option.jsx
src/mob/searchconfig/controller.jsx
src/mob/searchconfig/groupdragelement/card.jsx
src/mob/searchconfig/groupdragelement/index.jsx
src/mob/searchconfig/groupdragelement/index.scss
src/mob/searchconfig/groupform/index.jsx
src/mob/searchconfig/groupform/index.scss
src/mob/searchconfig/index.jsx
src/mob/searchconfig/index.scss
src/mob/searchconfig/pastecomponent/index.jsx
src/mob/searchconfig/pastecomponent/index.scss
src/mob/searchconfig/searchdragelement/card.jsx
src/mob/searchconfig/searchdragelement/index.jsx
src/mob/searchconfig/searchdragelement/index.scss
src/mob/searchconfig/settingform/index.jsx
src/mob/searchconfig/settingform/index.scss
src/mob/searchconfig/source.jsx
src/pc/bgcontroller/index.jsx
src/pc/components/login/normal-login/index.jsx
src/pc/components/login/normal-login/index.scss
src/pc/components/login/normal-login/loginform.jsx
src/pc/components/login/wrapsetting/index.jsx
src/pc/components/login/wrapsetting/index.scss
src/pc/components/login/wrapsetting/settingform/index.jsx
src/pc/components/login/wrapsetting/settingform/index.scss
src/pc/components/navbar/normal-navbar/index.jsx
src/pc/components/navbar/normal-navbar/linksetting/linkform/index.jsx
src/pc/components/navbar/normal-navbar/menusetting/menuform/index.jsx
src/pc/components/navbar/normal-navbar/menusetting/menutable/index.jsx
src/pc/components/navbar/normal-navbar/wrapsetting/settingform/index.jsx
src/pc/components/navbar/normal-navbar/wrapsetting/settingform/index.scss
src/pc/createview/index.jsx
src/pc/createview/index.scss
src/pc/createview/settingform/index.jsx
src/pc/createview/settingform/index.scss
src/pc/menushell/card.jsx
src/pc/menushell/index.jsx
src/pc/modulesource/index.jsx
src/pc/modulesource/option.jsx
src/pc/quotecomponent/index.jsx
src/pc/transfer/index.jsx
src/pc/transfer/index.scss
src/pc/transfer/settingform/index.jsx
src/pc/transfer/settingform/index.scss
src/router/index.js
src/tabviews/calendar/index.jsx
src/tabviews/commontable/index.jsx
src/tabviews/custom/components/card/balcony/index.jsx
src/tabviews/custom/components/card/balcony/index.scss
src/tabviews/custom/components/card/cardcellList/index.jsx
src/tabviews/custom/components/card/cardcellList/index.scss
src/tabviews/custom/components/card/data-card/index.jsx
src/tabviews/custom/components/card/data-card/index.scss
src/tabviews/custom/components/card/prop-card/index.jsx
src/tabviews/custom/components/card/prop-card/index.scss
src/tabviews/custom/components/card/table-card/index.jsx
src/tabviews/custom/components/carousel/data-card/index.jsx
src/tabviews/custom/components/carousel/data-card/index.scss
src/tabviews/custom/components/carousel/prop-card/index.jsx
src/tabviews/custom/components/carousel/prop-card/index.scss
src/tabviews/custom/components/chart/antv-bar-line/index.jsx
src/tabviews/custom/components/chart/antv-bar-line/index.scss
src/tabviews/custom/components/chart/antv-dashboard/index.jsx
src/tabviews/custom/components/chart/antv-dashboard/index.scss
src/tabviews/custom/components/chart/antv-pie/index.jsx
src/tabviews/custom/components/chart/antv-pie/index.scss
src/tabviews/custom/components/chart/antv-scatter/asyncButtonComponent.jsx
src/tabviews/custom/components/chart/antv-scatter/index.jsx
src/tabviews/custom/components/chart/antv-scatter/index.scss
src/tabviews/custom/components/code/sand-box/index.jsx
src/tabviews/custom/components/editor/braft-editor/index.jsx
src/tabviews/custom/components/form/normal-form/index.jsx
src/tabviews/custom/components/form/normal-form/index.scss
src/tabviews/custom/components/group/normal-group/index.jsx
src/tabviews/custom/components/share/normalTable/index.jsx
src/tabviews/custom/components/share/normalTable/index.scss
src/tabviews/custom/components/share/normalheader/index.jsx
src/tabviews/custom/components/share/normalheader/index.scss
src/tabviews/custom/components/share/tabtransfer/index.jsx
src/tabviews/custom/components/table/normal-table/index.jsx
src/tabviews/custom/components/table/normal-table/index.scss
src/tabviews/custom/components/tabs/antv-tabs/index.jsx
src/tabviews/custom/components/tree/antd-tree/index.jsx
src/tabviews/custom/components/tree/antd-tree/index.scss
src/tabviews/custom/index.jsx
src/tabviews/custom/index.scss
src/tabviews/formtab/formgroup/index.jsx
src/tabviews/home/index.jsx
src/tabviews/scriptmanage/config.jsx
src/tabviews/scriptmanage/index.jsx
src/tabviews/subtable/index.jsx
src/tabviews/subtabtable/index.jsx
src/tabviews/tabmanage/index.jsx
src/tabviews/treepage/index.jsx
src/tabviews/verupmanage/config.jsx
src/tabviews/zshare/actionList/asyncButtonComponent.jsx
src/tabviews/zshare/actionList/changeuserbutton/index.jsx
src/tabviews/zshare/actionList/excelInbutton/index.jsx
src/tabviews/zshare/actionList/exceloutbutton/index.jsx
src/tabviews/zshare/actionList/newpagebutton/index.jsx
src/tabviews/zshare/actionList/normalbutton/index.jsx
src/tabviews/zshare/actionList/popupbutton/index.jsx
src/tabviews/zshare/actionList/printbutton/index.jsx
src/tabviews/zshare/actionList/tabbutton/index.jsx
src/tabviews/zshare/dategroup/index.jsx (deleted)
src/tabviews/zshare/fileupload/index.jsx
src/tabviews/zshare/fileupload/index.scss
src/tabviews/zshare/imgScale/index.jsx
src/tabviews/zshare/imgScale/index.scss
src/tabviews/zshare/mutilform/checkCard/index.jsx
src/tabviews/zshare/mutilform/checkCard/index.scss
src/tabviews/zshare/mutilform/customSwitch/index.jsx (deleted)
src/tabviews/zshare/mutilform/customTextArea/index.jsx (deleted)
src/tabviews/zshare/mutilform/index.jsx
src/tabviews/zshare/mutilform/mkCheckCard/index.jsx
src/tabviews/zshare/mutilform/mkCheckCard/index.scss
src/tabviews/zshare/mutilform/mkCheckbox/index.jsx
src/tabviews/zshare/mutilform/mkCheckbox/index.scss
src/tabviews/zshare/mutilform/mkColor/index.jsx
src/tabviews/zshare/mutilform/mkColor/index.scss
src/tabviews/zshare/mutilform/mkDatePicker/index.jsx
src/tabviews/zshare/mutilform/mkDatePicker/index.scss
src/tabviews/zshare/mutilform/mkInput/index.jsx
src/tabviews/zshare/mutilform/mkInput/index.scss
src/tabviews/zshare/mutilform/mkNumberInput/index.jsx
src/tabviews/zshare/mutilform/mkNumberInput/index.scss
src/tabviews/zshare/mutilform/mkRadio/index.jsx
src/tabviews/zshare/mutilform/mkRadio/index.scss
src/tabviews/zshare/mutilform/mkSelect/index.jsx
src/tabviews/zshare/mutilform/mkSelect/index.scss
src/tabviews/zshare/mutilform/mkSwitch/index.jsx
src/tabviews/zshare/mutilform/mkSwitch/index.scss
src/tabviews/zshare/mutilform/mkTextArea/index.jsx
src/tabviews/zshare/mutilform/mkTextArea/index.scss
src/tabviews/zshare/normalTable/index.jsx
src/tabviews/zshare/topSearch/advanceform/index.jsx
src/tabviews/zshare/topSearch/advanceform/index.scss
src/tabviews/zshare/topSearch/dategroup/index.jsx
src/tabviews/zshare/topSearch/dategroup/index.scss
src/tabviews/zshare/topSearch/dategroup/quarterpicker/index.jsx
src/tabviews/zshare/topSearch/dategroup/quarterpicker/index.scss
src/tabviews/zshare/topSearch/dategroup/yearpicker/index.jsx
src/tabviews/zshare/topSearch/dategroup/yearpicker/index.scss
src/tabviews/zshare/topSearch/index.jsx
src/tabviews/zshare/topSearch/index.scss
src/tabviews/zshare/topSearch/mkDatePicker/index.jsx
src/tabviews/zshare/topSearch/mkDatePicker/index.scss
src/tabviews/zshare/topSearch/mkSelect/index.jsx
src/tabviews/zshare/topSearch/mkSelect/index.scss
src/templates/calendarconfig/source.jsx
src/templates/comtableconfig/index.jsx
src/templates/comtableconfig/source.jsx
src/templates/formtabconfig/index.jsx
src/templates/formtabconfig/settingform/index.jsx
src/templates/menuconfig/editfirstmenu/index.jsx
src/templates/menuconfig/editsecmenu/index.jsx
src/templates/menuconfig/editthdmenu/index.jsx
src/templates/modalconfig/checkCard/index.jsx
src/templates/modalconfig/checkCard/index.scss
src/templates/modalconfig/dragelement/card.jsx
src/templates/modalconfig/dragelement/index.jsx
src/templates/modalconfig/index.jsx
src/templates/modalconfig/settingform/index.jsx
src/templates/modalconfig/settingform/index.scss
src/templates/sharecomponent/actioncomponent/actionform/index.jsx
src/templates/sharecomponent/actioncomponent/index.scss
src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.jsx
src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
src/templates/sharecomponent/columncomponent/columnform/index.jsx
src/templates/sharecomponent/fieldscomponent/index.jsx
src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx
src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx
src/templates/sharecomponent/searchcomponent/index.jsx
src/templates/sharecomponent/searchcomponent/index.scss
src/templates/sharecomponent/searchcomponent/searcheditable/index.jsx
src/templates/sharecomponent/searchcomponent/searchform/index.jsx
src/templates/sharecomponent/searchcomponent/searchform/index.scss
src/templates/sharecomponent/settingcalcomponent/index.jsx
src/templates/sharecomponent/settingcalcomponent/verifycard/index.jsx
src/templates/sharecomponent/settingcalcomponent/verifycard/settingform/index.jsx
src/templates/sharecomponent/settingcalcomponent/verifycard/utils.jsx
src/templates/sharecomponent/settingcomponent/index.jsx
src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx
src/templates/sharecomponent/settingcomponent/settingform/datasource/index.scss
src/templates/sharecomponent/settingcomponent/settingform/index.jsx
src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx
src/templates/sharecomponent/settingcomponent/settingform/utils.jsx
src/templates/sharecomponent/tablecomponent/index.jsx
src/templates/sharecomponent/treesettingcomponent/index.jsx
src/templates/sharecomponent/treesettingcomponent/settingform/datasource/index.jsx
src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx
src/templates/sharecomponent/treesettingcomponent/settingform/utils.jsx
src/templates/subtableconfig/index.jsx
src/templates/subtableconfig/source.jsx
src/templates/treepageconfig/index.jsx
src/templates/zshare/basetransferform/index.jsx
src/templates/zshare/customscript/index.jsx
src/templates/zshare/editTable/index.jsx
src/templates/zshare/editTable/index.scss
src/templates/zshare/editcomponent/index.jsx
src/templates/zshare/formconfig.jsx
src/templates/zshare/modalform/datatable/index.jsx
src/templates/zshare/modalform/datatable/index.scss
src/templates/zshare/modalform/index.jsx
src/templates/zshare/modalform/index.scss
src/templates/zshare/modalform/modaleditable/index.jsx
src/templates/zshare/verifycard/callbackcustomscript/index.jsx
src/templates/zshare/verifycard/customform/index.jsx
src/templates/zshare/verifycard/customscript/index.jsx
src/templates/zshare/verifycard/index.jsx
src/utils/option.js
src/utils/utils-custom.js
src/utils/utils-datamanage.js
src/utils/utils.js
src/views/appmanage/header/index.jsx
src/views/appmanage/header/index.scss
src/views/appmanage/index.jsx
src/views/appmanage/index.scss
src/views/appmanage/scriptform/index.jsx
src/views/appmanage/scriptform/index.scss
src/views/appmanage/submutilform/index.jsx
src/views/appmanage/submutilform/index.scss
src/views/appmanage/transform/index.jsx
src/views/appmanage/transform/index.scss
src/views/billprint/index.jsx
src/views/billprint/index.scss
src/views/design/header/index.jsx
src/views/design/header/index.scss
src/views/design/index.jsx
src/views/design/sidemenu/config.jsx
src/views/interface/api/index.js
src/views/interface/header/index.jsx
src/views/interface/header/index.scss
src/views/interface/history/index.jsx
src/views/interface/history/index.scss
src/views/interface/index.jsx
src/views/interface/index.scss
src/views/interface/workspace/editTable/index.jsx
src/views/interface/workspace/editTable/index.scss
src/views/interface/workspace/index.jsx
src/views/interface/workspace/index.scss
src/views/interface/workspace/request/index.jsx
src/views/interface/workspace/request/index.scss
src/views/login/index.jsx
src/views/login/index.scss
src/views/login/loginform.jsx
src/views/menudesign/homeform/index.jsx
src/views/menudesign/index.jsx
src/views/menudesign/index.scss
src/views/menudesign/printmenuform/index.jsx
src/views/menudesign/printmenuform/index.scss
src/views/mobdesign/index.jsx
src/views/mobdesign/index.scss
src/views/mobdesign/menuform/index.jsx
src/views/pcdesign/index.jsx
src/views/pcdesign/index.scss
src/views/pcdesign/menuform/index.jsx
src/views/printTemplate/index.jsx
src/views/printTemplate/mutilform/index.jsx
src/views/printTemplate/mutilform/index.scss
src/views/printTemplate/option.js
src/views/printTemplate/print.js
src/views/rolemanage/header/index.jsx
src/views/rolemanage/header/index.scss
src/views/rolemanage/index.jsx
src/views/rolemanage/index.scss |