From 9b6ce1a5778c6e1a813237e87588c0052aae1bbb Mon Sep 17 00:00:00 2001 From: king <18310653075@163.com> Date: 星期三, 29 四月 2020 17:26:15 +0800 Subject: [PATCH] 2020-04-29 --- src/templates/sharecomponent/columncomponent/columnform/index.scss | 19 src/templates/sharecomponent/chartgroupcomponent/searchform/index.scss | 24 src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.scss | 0 src/templates/zshare/viewdragelement/index.scss | 41 src/assets/img/微信图片_20200426165043.png | 0 src/templates/sharecomponent/actioncomponent/verifyprint/editable/index.jsx | 241 src/templates/zshare/verifycard/customscript/index.jsx | 45 src/assets/img/bar3.png | 0 src/locales/zh-CN/model.js | 24 src/templates/zshare/chartcomponent/index.jsx | 437 + src/templates/modalconfig/index.jsx | 18 src/templates/sharecomponent/searchcomponent/searchform/index.scss | 24 src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx | 296 + src/templates/sharecomponent/tablecomponent/index.jsx | 455 + src/tabviews/commontable/index.jsx | 2 src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx | 825 +++ src/templates/sharecomponent/actioncomponent/dragaction/card.jsx | 60 src/assets/css/main.scss | 25 src/assets/img/A_qpizTrPVB-IAAAAAAAAAAABkARQnAQ.png | 0 src/assets/img/pie1.png | 0 src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.jsx | 127 src/assets/img/A_aFXQS7yyDyUAAAAAAAAAAABkARQnAQ.png | 0 src/templates/subtableconfig/index.jsx | 1697 ----- src/templates/zshare/exceleditable/index.jsx | 2 src/assets/img/bar1.png | 0 src/templates/sharecomponent/columncomponent/dragcolumn/index.scss | 6 src/templates/sharecomponent/searchcomponent/searcheditable/index.jsx | 265 src/templates/sharecomponent/columncomponent/colspanform/index.scss | 8 src/templates/zshare/viewdragelement/card.jsx | 48 package-lock.json | 194 src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.jsx | 202 src/assets/img/line3.png | 0 src/templates/sharecomponent/actioncomponent/verifyexcelin/uniqueform/index.jsx | 149 src/templates/zshare/viewdragelement/index.jsx | 85 src/templates/comtableconfig/index.jsx | 66 src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx | 101 src/templates/zshare/verifycardexcelin/index.jsx | 14 src/components/dragelement/index.jsx | 2 src/templates/sharecomponent/chartgroupcomponent/dragchartview/index.scss | 41 src/templates/zshare/chartcomponent/index.scss | 7 src/templates/sharecomponent/chartgroupcomponent/searcheditable/index.scss | 36 src/templates/sharecomponent/columncomponent/dragcolumn/index.jsx | 165 src/tabviews/subtable/index.jsx | 2 src/templates/sharecomponent/actioncomponent/index.scss | 84 src/templates/zshare/modaleditable/index.jsx | 4 src/assets/img/line1.png | 0 src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx | 461 + src/templates/sharecomponent/searchcomponent/searcheditable/index.scss | 36 src/templates/comtableconfig/source.jsx | 4 src/templates/sharecomponent/columncomponent/dragcolumn/card.jsx | 58 src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx | 155 src/assets/img/bar4.png | 0 src/templates/subtableconfig/index.scss | 262 src/templates/sharecomponent/fieldscomponent/index.scss | 27 src/templates/sharecomponent/searchcomponent/dragsearch/index.scss | 6 src/templates/modalconfig/source.jsx | 4 src/templates/zshare/verifycardprint/editable/index.jsx | 2 src/templates/sharecomponent/actioncomponent/dragaction/index.jsx | 179 src/components/sidemenu/index.jsx | 2 src/templates/sharecomponent/actioncomponent/dragaction/index.scss | 6 src/templates/zshare/transferform/index.scss | 4 src/templates/zshare/chartform/index.scss | 25 src/templates/sharecomponent/chartgroupcomponent/dragchartview/card.jsx | 48 src/templates/zshare/chartform/index.jsx | 379 + src/templates/sharecomponent/actioncomponent/actionform/index.scss | 33 src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.scss | 0 src/assets/img/bar2.png | 0 src/templates/sharecomponent/chartgroupcomponent/searcheditable/index.jsx | 265 src/templates/sharecomponent/fieldscomponent/editcard/index.jsx | 157 src/templates/sharecomponent/columncomponent/gridbtnform/index.scss | 8 src/templates/formtabconfig/source.jsx | 4 src/components/sidemenu/config.jsx | 0 src/templates/sharecomponent/chartgroupcomponent/chartform/index.scss | 25 src/templates/sharecomponent/actioncomponent/verifyexcelin/index.scss | 70 src/templates/sharecomponent/actioncomponent/actionform/index.jsx | 657 ++ src/templates/sharecomponent/columncomponent/index.scss | 85 src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.scss | 0 src/templates/zshare/pasteform/index.jsx | 5 src/templates/zshare/chartcompile/index.jsx | 213 src/templates/sharecomponent/tablecomponent/index.scss | 7 src/assets/img/pie2.png | 0 src/templates/sharecomponent/columncomponent/gridbtnform/index.jsx | 218 src/templates/zshare/createinterface/index.jsx | 33 src/templates/sharecomponent/actioncomponent/verifyexcelout/index.scss | 62 src/templates/sharecomponent/searchcomponent/index.scss | 84 src/templates/sharecomponent/searchcomponent/searchform/index.jsx | 475 + src/templates/subtableconfig/source.jsx | 16 src/templates/zshare/verifycardexcelout/index.jsx | 4 src/templates/formtabconfig/index.jsx | 28 src/templates/sharecomponent/chartgroupcomponent/index.scss | 24 src/templates/sharecomponent/searchcomponent/index.jsx | 280 + src/templates/zshare/editcomponent/index.jsx | 17 src/templates/sharecomponent/fieldscomponent/index.jsx | 252 src/templates/sharecomponent/actioncomponent/verifyprint/editable/index.scss | 48 src/templates/sharecomponent/columncomponent/index.jsx | 437 + src/templates/zshare/verifycard/customform/index.jsx | 6 src/templates/sharecomponent/columncomponent/colspanform/index.jsx | 193 src/locales/en-US/model.js | 24 src/assets/img/line4.png | 0 src/templates/sharecomponent/chartgroupcomponent/chartform/index.jsx | 379 + src/templates/zshare/chartcompile/index.scss | 31 src/utils/utils.js | 2 src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx | 339 + src/templates/sharecomponent/fieldscomponent/editcard/index.scss | 49 src/templates/zshare/formconfig.jsx | 377 + src/templates/zshare/verifycard/index.jsx | 287 src/templates/zshare/tabdragelement/card.jsx | 2 src/templates/sharecomponent/actioncomponent/verifyprint/index.scss | 60 src/tabviews/zshare/verifycard/index.jsx | 2 src/templates/sharecomponent/actioncomponent/index.jsx | 921 +++ src/assets/img/line2.png | 0 src/templates/sharecomponent/chartgroupcomponent/searchform/index.jsx | 475 + package.json | 1 src/templates/sharecomponent/chartgroupcomponent/dragchartview/index.jsx | 74 src/utils/modelutils.js | 1620 +++++ src/templates/sharecomponent/actioncomponent/verifyexcelin/uniqueform/index.scss | 0 src/templates/sharecomponent/chartgroupcomponent/index.jsx | 234 src/templates/sharecomponent/columncomponent/columnform/index.jsx | 376 + 118 files changed, 14,560 insertions(+), 1,898 deletions(-) diff --git a/package-lock.json b/package-lock.json index de3c4c6..005b31c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -87,6 +87,29 @@ "tslib": "1.10.0" } }, + "@antv/data-set": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/@antv/data-set/-/data-set-0.11.4.tgz", + "integrity": "sha512-rS0xMvclsv59wh2yDmCshC55/HvXBbwpEmoTr+ErSY4SKGKSTOwXjZ90W/fJMSfacMPOGDbG7R77kCP8cSTu5w==", + "requires": { + "@antv/hierarchy": "0.6.3", + "@antv/util": "2.0.8", + "d3-composite-projections": "1.3.2", + "d3-dsv": "1.2.0", + "d3-geo": "1.6.4", + "d3-geo-projection": "2.1.2", + "d3-hexjson": "1.1.0", + "d3-hierarchy": "1.1.9", + "d3-sankey": "0.9.1", + "d3-voronoi": "1.1.4", + "dagre": "0.8.5", + "point-at-length": "1.1.0", + "regression": "2.0.1", + "simple-statistics": "6.1.1", + "topojson-client": "3.1.0", + "wolfy87-eventemitter": "5.2.9" + } + }, "@antv/dom-util": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@antv/dom-util/-/dom-util-2.0.2.tgz", @@ -194,6 +217,14 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/@antv/gl-matrix/-/gl-matrix-2.7.1.tgz", "integrity": "sha512-oOWcVNlpELIKi9x+Mm1Vwbz8pXfkbJKykoCIOJ/dNK79hSIANbpXJ5d3Rra9/wZqK6MC961B7sybFhPlLraT3Q==" + }, + "@antv/hierarchy": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@antv/hierarchy/-/hierarchy-0.6.3.tgz", + "integrity": "sha512-91YZUiZFXK8zp2nC2C+4FEc1LDIPZ5Q4YQbzMnKhH+7nei4QCfIdXPrPh0EKRws78CVt2hxR5gHD7zq6UlokAQ==", + "requires": { + "@antv/util": "2.0.8" + } }, "@antv/matrix-util": { "version": "2.0.7", @@ -2065,6 +2096,11 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "abs-svg-path": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/abs-svg-path/-/abs-svg-path-0.1.1.tgz", + "integrity": "sha1-32Acjo0roQ1KdtYl4japo5wnI78=" }, "accepts": { "version": "1.3.7", @@ -4413,15 +4449,85 @@ "type": "1.0.3" } }, + "d3-array": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", + "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" + }, + "d3-collection": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz", + "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==" + }, "d3-color": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.0.tgz", "integrity": "sha512-TzNPeJy2+iEepfiL92LAAB7fvnp/dV2YwANPVHdDWmYMm23qIJBYww3qT8I8C1wXrmrg4UWs7BKc2tKIgyjzHg==" }, + "d3-composite-projections": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/d3-composite-projections/-/d3-composite-projections-1.3.2.tgz", + "integrity": "sha512-dao+Dd/EEYBX+FqNYwe/4putAsMXWewSgDj5sETRFsj1z4X/CVI6ctmZhqvpa/MVYCFHoWV9Issu+20OU5VmbA==", + "requires": { + "d3-geo": "1.12.0", + "d3-path": "1.0.9" + }, + "dependencies": { + "d3-geo": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.0.tgz", + "integrity": "sha512-NalZVW+6/SpbKcnl+BCO67m8gX+nGeJdo6oGL9H6BRUGUL1e+AtPcP4vE4TwCQ/gl8y5KE7QvBzrLn+HsKIl+w==", + "requires": { + "d3-array": "1.2.4" + } + } + } + }, + "d3-dsv": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz", + "integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==", + "requires": { + "commander": "2.20.0", + "iconv-lite": "0.4.24", + "rw": "1.3.3" + } + }, "d3-ease": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.6.tgz", "integrity": "sha512-SZ/lVU7LRXafqp7XtIcBdxnWl8yyLpgOmzAk0mWBI9gXNzLDx5ybZgnRbH9dN/yY5tzVBqCQ9avltSnqVwessQ==" + }, + "d3-geo": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.6.4.tgz", + "integrity": "sha1-8g4eRhyxhF9ai+Vatvh2VCp+MZk=", + "requires": { + "d3-array": "1.2.4" + } + }, + "d3-geo-projection": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/d3-geo-projection/-/d3-geo-projection-2.1.2.tgz", + "integrity": "sha1-ffjh6dBG1jHGUJ9+UxNX1K3CSqM=", + "requires": { + "commander": "2.20.0", + "d3-array": "1.2.4", + "d3-geo": "1.6.4" + } + }, + "d3-hexjson": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-hexjson/-/d3-hexjson-1.1.0.tgz", + "integrity": "sha512-fHXGMnA1iYBg0Kw5jqSm9kZDRyw4Mq74AzJzUM/FiCDy9a47xM5qj2+ofTaZbeku9tHsRtoujolHiqmD3s3EHA==", + "requires": { + "d3-array": "1.2.4" + } + }, + "d3-hierarchy": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz", + "integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==" }, "d3-interpolate": { "version": "1.4.0", @@ -4431,15 +4537,52 @@ "d3-color": "1.4.0" } }, + "d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" + }, "d3-regression": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/d3-regression/-/d3-regression-1.3.4.tgz", "integrity": "sha512-o5nwONeooEfy+L98Ej+WPccb6LgLKtsnXLuWzXb8Ta1mN95Jy0Aw9X2TxV+S+OW+NcrBfEjxSURoSlQfVAEkrg==" }, + "d3-sankey": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.9.1.tgz", + "integrity": "sha512-nnRkDaUMjBdeuGg+kWGdA+tjG1AVTnJ+Ykw7ff7CZHVI17Hm5sy8n0UXykVffn13aNHwK5wPOdOt1gS1ZEaF+A==", + "requires": { + "d3-array": "1.2.4", + "d3-collection": "1.0.7", + "d3-shape": "1.3.7" + } + }, + "d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "requires": { + "d3-path": "1.0.9" + } + }, "d3-timer": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==" + }, + "d3-voronoi": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz", + "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==" + }, + "dagre": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz", + "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==", + "requires": { + "graphlib": "2.1.8", + "lodash": "4.17.15" + } }, "damerau-levenshtein": { "version": "1.0.5", @@ -8104,6 +8247,14 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==" }, + "graphlib": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", + "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", + "requires": { + "lodash": "4.17.15" + } + }, "growly": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", @@ -11656,6 +11807,11 @@ "json-parse-better-errors": "1.0.2" } }, + "parse-svg-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz", + "integrity": "sha1-en7A0esG+lMlx9PgCbhZoJtdSes=" + }, "parse5": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", @@ -11857,6 +12013,16 @@ "integrity": "sha512-jd9olUr9D7do+RN8Wspzhpxhgp1n6Vd0NtQ4SFkmIACZoEL1nkyAdW9Ygrinjec0vgDcWjscFQQ1gDW8rsfKTg==", "requires": { "ts-pnp": "1.1.2" + } + }, + "point-at-length": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/point-at-length/-/point-at-length-1.1.0.tgz", + "integrity": "sha1-CtcuvQmA1/WhqxIpbAVfnrazDlc=", + "requires": { + "abs-svg-path": "0.1.1", + "isarray": "0.0.1", + "parse-svg-path": "0.1.2" } }, "portfinder": { @@ -14112,6 +14278,11 @@ } } }, + "regression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regression/-/regression-2.0.1.tgz", + "integrity": "sha1-jSnD6CJKEIUMNeM36FqLL6w7DIc=" + }, "relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", @@ -14413,6 +14584,11 @@ "requires": { "aproba": "1.2.0" } + }, + "rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=" }, "rxjs": { "version": "6.5.3", @@ -14989,6 +15165,11 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "simple-statistics": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/simple-statistics/-/simple-statistics-6.1.1.tgz", + "integrity": "sha512-zGwn0DDRa9Zel4H4n2pjTFIyGoAGpnpjrGIctreCxj5XWrcx9v7Xy7270FkC967WMmcvuc8ZU7m0ZG+hGN7gAA==" }, "simple-swizzle": { "version": "0.2.2", @@ -15919,6 +16100,14 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "topojson-client": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz", + "integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==", + "requires": { + "commander": "2.20.0" + } }, "tough-cookie": { "version": "2.4.3", @@ -16952,6 +17141,11 @@ "string-width": "1.0.2" } }, + "wolfy87-eventemitter": { + "version": "5.2.9", + "resolved": "https://registry.npmjs.org/wolfy87-eventemitter/-/wolfy87-eventemitter-5.2.9.tgz", + "integrity": "sha512-P+6vtWyuDw+MB01X7UeF8TaHBvbCovf4HPEMF/SV7BdDc1SMTiBy13SRD71lQh4ExFTG1d/WNzDGDCyOKSMblw==" + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", diff --git a/package.json b/package.json index 781b4e4..c53b0cd 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "0.1.0", "private": true, "dependencies": { + "@antv/data-set": "^0.11.4", "@antv/g2": "^4.0.7", "@antv/g2plot": "^1.0.3", "@babel/core": "7.5.5", diff --git a/src/assets/css/main.scss b/src/assets/css/main.scss index 1554c1c..0cad06f 100644 --- a/src/assets/css/main.scss +++ b/src/assets/css/main.scss @@ -175,6 +175,27 @@ z-index: 1090!important; } +.mk-normal-dropdown { + .ant-dropdown-menu { + max-height: 250px; + overflow-y: auto; + } + .ant-dropdown-menu::-webkit-scrollbar { + width: 7px; + } + .ant-dropdown-menu::-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); + } + .ant-dropdown-menu::-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); + } +} + // 纭鎻愮ず妗嗛珮搴� .ant-modal.ant-modal-confirm { top: 38vh; @@ -247,4 +268,8 @@ border: 1px solid rgba(0, 0, 0, 0.07); background: rgba(0, 0, 0, 0); } +} + +.ant-drawer { + z-index: 1080!important; } \ No newline at end of file diff --git a/src/assets/img/A_aFXQS7yyDyUAAAAAAAAAAABkARQnAQ.png b/src/assets/img/A_aFXQS7yyDyUAAAAAAAAAAABkARQnAQ.png new file mode 100644 index 0000000..4b06a07 --- /dev/null +++ b/src/assets/img/A_aFXQS7yyDyUAAAAAAAAAAABkARQnAQ.png Binary files differ diff --git a/src/assets/img/A_qpizTrPVB-IAAAAAAAAAAABkARQnAQ.png b/src/assets/img/A_qpizTrPVB-IAAAAAAAAAAABkARQnAQ.png new file mode 100644 index 0000000..15e708a --- /dev/null +++ b/src/assets/img/A_qpizTrPVB-IAAAAAAAAAAABkARQnAQ.png Binary files differ diff --git a/src/assets/img/bar1.png b/src/assets/img/bar1.png new file mode 100644 index 0000000..977b4ec --- /dev/null +++ b/src/assets/img/bar1.png Binary files differ diff --git a/src/assets/img/bar2.png b/src/assets/img/bar2.png new file mode 100644 index 0000000..0a9d95e --- /dev/null +++ b/src/assets/img/bar2.png Binary files differ diff --git a/src/assets/img/bar3.png b/src/assets/img/bar3.png new file mode 100644 index 0000000..0766655 --- /dev/null +++ b/src/assets/img/bar3.png Binary files differ diff --git a/src/assets/img/bar4.png b/src/assets/img/bar4.png new file mode 100644 index 0000000..bea9459 --- /dev/null +++ b/src/assets/img/bar4.png Binary files differ diff --git a/src/assets/img/line1.png b/src/assets/img/line1.png new file mode 100644 index 0000000..55a628e --- /dev/null +++ b/src/assets/img/line1.png Binary files differ diff --git a/src/assets/img/line2.png b/src/assets/img/line2.png new file mode 100644 index 0000000..c44f1d6 --- /dev/null +++ b/src/assets/img/line2.png Binary files differ diff --git a/src/assets/img/line3.png b/src/assets/img/line3.png new file mode 100644 index 0000000..b3a44b0 --- /dev/null +++ b/src/assets/img/line3.png Binary files differ diff --git a/src/assets/img/line4.png b/src/assets/img/line4.png new file mode 100644 index 0000000..cebfa94 --- /dev/null +++ b/src/assets/img/line4.png Binary files differ diff --git a/src/assets/img/pie1.png b/src/assets/img/pie1.png new file mode 100644 index 0000000..83c04c3 --- /dev/null +++ b/src/assets/img/pie1.png Binary files differ diff --git a/src/assets/img/pie2.png b/src/assets/img/pie2.png new file mode 100644 index 0000000..4584a7e --- /dev/null +++ b/src/assets/img/pie2.png Binary files differ diff --git "a/src/assets/img/\345\276\256\344\277\241\345\233\276\347\211\207_20200426165043.png" "b/src/assets/img/\345\276\256\344\277\241\345\233\276\347\211\207_20200426165043.png" new file mode 100644 index 0000000..92d46cf --- /dev/null +++ "b/src/assets/img/\345\276\256\344\277\241\345\233\276\347\211\207_20200426165043.png" Binary files differ diff --git a/src/components/dragelement/index.jsx b/src/components/dragelement/index.jsx index 4af0471..203eb77 100644 --- a/src/components/dragelement/index.jsx +++ b/src/components/dragelement/index.jsx @@ -65,7 +65,7 @@ <Icon type="plus" /> </div> <Button type="primary" onClick={thawmenu}>{dict['header.thawmenu']}</Button> - <Button type="primary" onClick={confirm}>{dict['header.confirm']}</Button> + <Button type="primary" onClick={confirm}>{dict['model.confirm']}</Button> <Button onClick={cancel}>{dict['header.close']}</Button> </div> ) diff --git a/src/components/sidemenu/config.js b/src/components/sidemenu/config.jsx similarity index 100% rename from src/components/sidemenu/config.js rename to src/components/sidemenu/config.jsx diff --git a/src/components/sidemenu/index.jsx b/src/components/sidemenu/index.jsx index b4c157b..fe497e4 100644 --- a/src/components/sidemenu/index.jsx +++ b/src/components/sidemenu/index.jsx @@ -7,7 +7,7 @@ import asyncComponent from '@/utils/asyncComponent' import { modifyTabview, resetEditLevel } from '@/store/action' -import { SySMenuList } from './config.js' +import { SySMenuList } from './config' import options from '@/store/options.js' import zhCN from '@/locales/zh-CN/header.js' import enUS from '@/locales/en-US/header.js' diff --git a/src/locales/en-US/comtable.js b/src/locales/en-US/model.js similarity index 84% rename from src/locales/en-US/comtable.js rename to src/locales/en-US/model.js index 7a12562..db9719b 100644 --- a/src/locales/en-US/comtable.js +++ b/src/locales/en-US/model.js @@ -1,9 +1,10 @@ export default { - 'header.confirm': 'Ok', + 'model.confirm': 'Ok', 'header.submit': 'Submit', - 'header.delete': 'Delete', + 'model.delete': 'Delete', 'header.cancel': 'Cancel', - 'header.edit': 'Edit', + 'model.edit': 'Edit', + 'model.copy': 'Copy', 'header.return': 'Back', 'header.save': 'Save', 'header.notsave': 'Do not save', @@ -65,6 +66,7 @@ 'header.form.column.itemsUnit': 'Items', 'header.form.column.action': 'Action', 'header.form.name': 'Name', + 'header.form.title': 'Title', 'header.form.field': 'Field', 'header.form.field.placeholder': '璇疯緭鍏ュ瓧娈靛悕', 'header.form.innerFunc': 'Internal function', @@ -228,16 +230,22 @@ 'header.form.clickscale': '鐐瑰嚮缂╂斁', 'header.form.easyCode': '鍔╄鐮�', 'header.modal.form.edit': '琛ㄥ崟-缂栬緫', - 'header.modal.search.edit': '鎼滅储鏉′欢-缂栬緫', - 'header.modal.action.edit': '鎸夐挳-缂栬緫', + 'model.searchCriteria': 'Search Criteria', + 'model.action': '鎸夐挳', 'header.modal.action.copy': '鎸夐挳-澶嶅埗', 'header.modal.form.copy': '琛ㄥ崟-澶嶅埗', 'header.modal.column.edit': '鏄剧ず鍒�-缂栬緫', 'header.modal.colspan.edit': '鍚堝苟鍒�-缂栬緫', 'header.modal.gridbtn.edit': '鎿嶄綔鍒�-缂栬緫', 'header.modal.tabs.edit': '鏍囩-缂栬緫', - 'header.modal.func.innerface': '鍐呴儴鎺ュ彛: 鍙嚜瀹氫箟鏁版嵁澶勭悊鍑芥暟锛屽嚱鏁板悕绉伴渶浠ableField绛夊瓧绗﹀紑濮嬶紱鏈缃椂浼氳皟鐢ㄧ郴缁熷嚱鏁帮紝浣跨敤绯荤粺鍑芥暟闇�瀹屽杽鏁版嵁婧愬強鎿嶄綔绫诲瀷;', - 'header.modal.func.outface': '澶栭儴鎺ュ彛: 鍙嚜瀹氫箟鏁版嵁澶勭悊鍑芥暟锛屾彁浜ゆ暟鎹粡杩囧唴閮ㄥ嚱鏁板鐞嗗悗锛屼紶鍏ュ閮ㄦ帴鍙o紝鏈缃椂锛屾暟鎹細鐩存帴浼犲叆澶栭儴鎺ュ彛銆�', + 'model.field.exist': '瀛楁宸插瓨鍦�', + 'model.name.exist': '鍚嶇О宸插瓨鍦�', 'form.required.input': 'Please enter the ', - 'form.required.select': '璇烽�夋嫨' + 'form.required.select': '璇烽�夋嫨', + 'model.tooltip.table.guide': '姝ゅ鍙互娣诲姞椤甸潰閰嶇疆鐩稿叧鐨勫父鐢ㄨ〃锛屽彲閫氳繃宸ュ叿鏍忎腑鐨勬坊鍔犳寜閽紝鍙壒閲忔坊鍔犺〃鏍肩浉鍏冲瓧娈点��', + 'model.tooltip.search.guide': '鍦ㄥ乏渚у伐鍏锋爮銆婃悳绱€�嬩腑锛岄�夋嫨瀵瑰簲鎼滅储妗嗘嫋鑷虫澶勬坊鍔狅紱鎴栫偣鍑绘寜閽�婃坊鍔犳悳绱㈡潯浠躲�嬫壒閲忔坊鍔狅紝閫夋嫨鎵归噺娣诲姞鏃讹紝闇�鎻愬墠閫夋嫨浣跨敤琛ㄣ��', + 'model.tooltip.action.guide': '鍦ㄥ乏渚у伐鍏锋爮銆婃寜閽�嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬寜閽嫋鑷虫澶勬坊鍔狅紝濡傞�夋嫨鎸夐挳绫诲瀷涓鸿〃鍗曘�佹柊鏍囩椤电瓑鍚湁閰嶇疆椤甸潰鐨勬寜閽紝鍙湪宸︿晶宸ュ叿鏍�-鎸夐挳-鍙厤缃寜閽锛岀偣鍑绘寜閽畬鎴愮浉鍏抽厤缃�傛敞锛氬綋璁剧疆鎸夐挳鏄剧ず浣嶇疆涓鸿〃鏍兼椂锛屾樉绀哄垪浼氬鍔犳搷浣滃垪銆�', + 'model.tooltip.column.guide': '鍦ㄥ乏渚у伐鍏锋爮銆婃樉绀哄垪銆嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬樉绀哄垪鎷栬嚦姝ゅ娣诲姞锛涙垨鐐瑰嚮銆婃坊鍔犳樉绀哄垪銆嬫寜閽壒閲忔坊鍔狅紝閫夋嫨鎵归噺娣诲姞鏃讹紝闇�鎻愬墠閫夋嫨浣跨敤琛ㄣ�傛敞锛氭坊鍔犲悎骞跺垪鏃讹紝闇�璁剧疆鍙�夊垪銆�', + 'model.tooltip.func.innerface': '鍐呴儴鎺ュ彛: 鍙嚜瀹氫箟鏁版嵁澶勭悊鍑芥暟锛屽嚱鏁板悕绉伴渶浠ableField绛夊瓧绗﹀紑濮嬶紱鏈缃椂浼氳皟鐢ㄧ郴缁熷嚱鏁帮紝浣跨敤绯荤粺鍑芥暟闇�瀹屽杽鏁版嵁婧愬強鎿嶄綔绫诲瀷;', + 'model.tooltip.func.outface': '澶栭儴鎺ュ彛: 鍙嚜瀹氫箟鏁版嵁澶勭悊鍑芥暟锛屾彁浜ゆ暟鎹粡杩囧唴閮ㄥ嚱鏁板鐞嗗悗锛屼紶鍏ュ閮ㄦ帴鍙o紝鏈缃椂锛屾暟鎹細鐩存帴浼犲叆澶栭儴鎺ュ彛銆�', } \ No newline at end of file diff --git a/src/locales/zh-CN/comtable.js b/src/locales/zh-CN/model.js similarity index 84% rename from src/locales/zh-CN/comtable.js rename to src/locales/zh-CN/model.js index df7f890..1360bd4 100644 --- a/src/locales/zh-CN/comtable.js +++ b/src/locales/zh-CN/model.js @@ -1,9 +1,10 @@ export default { - 'header.confirm': '纭畾', + 'model.confirm': '纭畾', 'header.submit': '鎻愪氦', - 'header.delete': '鍒犻櫎', + 'model.delete': '鍒犻櫎', 'header.cancel': '鍙栨秷', - 'header.edit': '缂栬緫', + 'model.edit': '缂栬緫', + 'model.copy': '澶嶅埗', 'header.return': '杩斿洖', 'header.save': '淇濆瓨', 'header.notsave': '涓嶄繚瀛�', @@ -65,6 +66,7 @@ 'header.form.column.itemsUnit': '椤�', 'header.form.column.action': '鎿嶄綔', 'header.form.name': '鍚嶇О', + 'header.form.title': '鏍囬', 'header.form.field': '瀛楁', 'header.form.field.placeholder': '璇疯緭鍏ュ瓧娈靛悕', 'header.form.innerFunc': '鍐呴儴鍑芥暟', @@ -228,16 +230,22 @@ 'header.form.clickscale': '鐐瑰嚮缂╂斁', 'header.form.easyCode': '鍔╄鐮�', 'header.modal.form.edit': '琛ㄥ崟-缂栬緫', - 'header.modal.search.edit': '鎼滅储鏉′欢-缂栬緫', - 'header.modal.action.edit': '鎸夐挳-缂栬緫', + 'model.searchCriteria': '鎼滅储鏉′欢', + 'model.action': 'Button', 'header.modal.action.copy': '鎸夐挳-澶嶅埗', 'header.modal.form.copy': '琛ㄥ崟-澶嶅埗', 'header.modal.column.edit': '鏄剧ず鍒�-缂栬緫', 'header.modal.colspan.edit': '鍚堝苟鍒�-缂栬緫', 'header.modal.gridbtn.edit': '鎿嶄綔鍒�-缂栬緫', 'header.modal.tabs.edit': '鏍囩-缂栬緫', - 'header.modal.func.innerface': '鍐呴儴鎺ュ彛: 鍙嚜瀹氫箟鏁版嵁澶勭悊鍑芥暟锛屽嚱鏁板悕绉伴渶浠ableField绛夊瓧绗﹀紑濮嬶紱鏈缃椂浼氳皟鐢ㄧ郴缁熷嚱鏁帮紝浣跨敤绯荤粺鍑芥暟闇�瀹屽杽鏁版嵁婧愬強鎿嶄綔绫诲瀷;', - 'header.modal.func.outface': '澶栭儴鎺ュ彛: 鍙嚜瀹氫箟鏁版嵁澶勭悊鍑芥暟锛屾彁浜ゆ暟鎹粡杩囧唴閮ㄥ嚱鏁板鐞嗗悗锛屼紶鍏ュ閮ㄦ帴鍙o紝鏈缃椂锛屾暟鎹細鐩存帴浼犲叆澶栭儴鎺ュ彛銆�', + 'model.field.exist': '瀛楁宸插瓨鍦�', + 'model.name.exist': '鍚嶇О宸插瓨鍦�', 'form.required.input': '璇疯緭鍏�', - 'form.required.select': '璇烽�夋嫨' + 'form.required.select': '璇烽�夋嫨', + 'model.tooltip.table.guide': '姝ゅ鍙互娣诲姞椤甸潰閰嶇疆鐩稿叧鐨勫父鐢ㄨ〃锛屽彲閫氳繃宸ュ叿鏍忎腑鐨勬坊鍔犳寜閽紝鍙壒閲忔坊鍔犺〃鏍肩浉鍏冲瓧娈点��', + 'model.tooltip.search.guide': '鍦ㄥ乏渚у伐鍏锋爮銆婃悳绱€�嬩腑锛岄�夋嫨瀵瑰簲鎼滅储妗嗘嫋鑷虫澶勬坊鍔狅紱鎴栫偣鍑绘寜閽�婃坊鍔犳悳绱㈡潯浠躲�嬫壒閲忔坊鍔狅紝閫夋嫨鎵归噺娣诲姞鏃讹紝闇�鎻愬墠閫夋嫨浣跨敤琛ㄣ��', + 'model.tooltip.action.guide': '鍦ㄥ乏渚у伐鍏锋爮銆婃寜閽�嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬寜閽嫋鑷虫澶勬坊鍔狅紝濡傞�夋嫨鎸夐挳绫诲瀷涓鸿〃鍗曘�佹柊鏍囩椤电瓑鍚湁閰嶇疆椤甸潰鐨勬寜閽紝鍙湪宸︿晶宸ュ叿鏍�-鎸夐挳-鍙厤缃寜閽锛岀偣鍑绘寜閽畬鎴愮浉鍏抽厤缃�傛敞锛氬綋璁剧疆鎸夐挳鏄剧ず浣嶇疆涓鸿〃鏍兼椂锛屾樉绀哄垪浼氬鍔犳搷浣滃垪銆�', + 'model.tooltip.column.guide': '鍦ㄥ乏渚у伐鍏锋爮銆婃樉绀哄垪銆嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬樉绀哄垪鎷栬嚦姝ゅ娣诲姞锛涙垨鐐瑰嚮銆婃坊鍔犳樉绀哄垪銆嬫寜閽壒閲忔坊鍔狅紝閫夋嫨鎵归噺娣诲姞鏃讹紝闇�鎻愬墠閫夋嫨浣跨敤琛ㄣ�傛敞锛氭坊鍔犲悎骞跺垪鏃讹紝闇�璁剧疆鍙�夊垪銆�', + 'model.tooltip.func.innerface': '鍐呴儴鎺ュ彛: 鍙嚜瀹氫箟鏁版嵁澶勭悊鍑芥暟锛屽嚱鏁板悕绉伴渶浠ableField绛夊瓧绗﹀紑濮嬶紱鏈缃椂浼氳皟鐢ㄧ郴缁熷嚱鏁帮紝浣跨敤绯荤粺鍑芥暟闇�瀹屽杽鏁版嵁婧愬強鎿嶄綔绫诲瀷;', + 'model.tooltip.func.outface': '澶栭儴鎺ュ彛: 鍙嚜瀹氫箟鏁版嵁澶勭悊鍑芥暟锛屾彁浜ゆ暟鎹粡杩囧唴閮ㄥ嚱鏁板鐞嗗悗锛屼紶鍏ュ閮ㄦ帴鍙o紝鏈缃椂锛屾暟鎹細鐩存帴浼犲叆澶栭儴鎺ュ彛銆�', } \ No newline at end of file diff --git a/src/tabviews/commontable/index.jsx b/src/tabviews/commontable/index.jsx index 0f79790..9b83524 100644 --- a/src/tabviews/commontable/index.jsx +++ b/src/tabviews/commontable/index.jsx @@ -174,6 +174,7 @@ } if (_curUserConfig.action[item.uuid]) { + delete _curUserConfig.action[item.uuid].label item = {...item, ..._curUserConfig.action[item.uuid]} } @@ -283,6 +284,7 @@ if (_curUserConfig) { _columns = _columns.map(item => { if (_curUserConfig.columns[item.uuid]) { + delete _curUserConfig.columns[item.uuid].label item = {...item, ..._curUserConfig.columns[item.uuid]} } diff --git a/src/tabviews/subtable/index.jsx b/src/tabviews/subtable/index.jsx index f044c02..88105fc 100644 --- a/src/tabviews/subtable/index.jsx +++ b/src/tabviews/subtable/index.jsx @@ -175,6 +175,7 @@ config.action = config.action.map(item => { if (userConfig.action[item.uuid]) { + delete userConfig.action[item.uuid].label item = {...item, ...userConfig.action[item.uuid]} } @@ -270,6 +271,7 @@ if (userConfig) { _columns = _columns.map(item => { if (userConfig.columns[item.uuid]) { + delete userConfig.columns[item.uuid].label item = {...item, ...userConfig.columns[item.uuid]} } diff --git a/src/tabviews/zshare/verifycard/index.jsx b/src/tabviews/zshare/verifycard/index.jsx index 23bdd7b..9cc08f8 100644 --- a/src/tabviews/zshare/verifycard/index.jsx +++ b/src/tabviews/zshare/verifycard/index.jsx @@ -144,6 +144,7 @@ subconfig.action = subconfig.action.map(item => { if (subUserConfig.action[item.uuid]) { + delete subUserConfig.action[item.uuid].label item = {...item, ...subUserConfig.action[item.uuid]} } if (item.execMode) { @@ -215,6 +216,7 @@ if (subUserConfig) { _columns = _columns.map(item => { if (subUserConfig.columns[item.uuid]) { + delete subUserConfig.columns[item.uuid].label item = {...item, ...subUserConfig.columns[item.uuid]} } diff --git a/src/templates/comtableconfig/index.jsx b/src/templates/comtableconfig/index.jsx index ac8f3cc..c3135c9 100644 --- a/src/templates/comtableconfig/index.jsx +++ b/src/templates/comtableconfig/index.jsx @@ -10,8 +10,8 @@ import Api from '@/api' import Utils from '@/utils/utils.js' import options from '@/store/options.js' -import zhCN from '@/locales/zh-CN/comtable.js' -import enUS from '@/locales/en-US/comtable.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' import { getSearchForm, getActionForm, getColumnForm } from '@/templates/zshare/formconfig' import { queryTableSql } from '@/utils/option.js' @@ -455,8 +455,8 @@ handleAction = (card, type) => { let ableField = this.props.permFuncField.join(', ') let functip = <div> - <p style={{marginBottom: '5px'}}>{this.state.dict['header.modal.func.innerface'].replace('@ableField', ableField)}</p> - <p>{this.state.dict['header.modal.func.outface']}</p> + <p style={{marginBottom: '5px'}}>{this.state.dict['model.tooltip.func.innerface'].replace('@ableField', ableField)}</p> + <p>{this.state.dict['model.tooltip.func.outface']}</p> </div> this.setState({ @@ -1272,22 +1272,13 @@ this.menuformRef.handleConfirm().then(res => { this.actionFormRef.handleConfirm().then(result => { - if (!['pop', 'exec', 'prompt'].includes(result.OpenType) || result.funcType || result.intertype !== 'inner' || result.innerFunc ) { - notification.warning({ - top: 92, - message: '鎵撳紑鏂瑰紡涓� 寮圭獥锛堣〃鍗曪級銆佹彁绀烘鎴栫洿鎺ユ墽琛岋紝涓斾娇鐢ㄧ郴缁熷嚱鏁版椂锛屾墠鍙互鍒涘缓鎺ュ彛锛�', - duration: 5 - }) - return - } - let _menu = { type: 'main', MenuID: menu.MenuID, menuName: res.menuName, menuNo: res.menuNo } - + this.refs.btnCreatInterface.triggerInInterface(result, config, _menu) }) }) @@ -1330,7 +1321,7 @@ confirm({ content: `纭畾鍒犻櫎<<${element.card.label}>>鍚楋紵`, - okText: this.state.dict['header.confirm'], + okText: this.state.dict['model.confirm'], cancelText: this.state.dict['header.cancel'], onOk() { let _config = null @@ -2110,7 +2101,7 @@ if (config.isAdd) { confirm({ content: '鑿滃崟灏氭湭鎻愪氦锛岀‘瀹氭斁寮冧繚瀛樺悧锛�', - okText: this.state.dict['header.confirm'], + okText: this.state.dict['model.confirm'], cancelText: this.state.dict['header.cancel'], onOk() { _this.props.handleView() @@ -2209,25 +2200,6 @@ }) } - const textmatch = { // 閫夋嫨text鏃跺尮閰嶈鍒� - text: 'like', - number: 'like', - datetime: 'like', - date: 'like' - } - const selectmatch = { // 閫夋嫨select鏃跺尮閰嶈鍒� - text: '=', - number: '=', - datetime: '=', - date: '=' - } - const datematch = { // 閫夋嫨dateRange鏃跺尮閰嶈鍒� - text: 'between', - number: 'between', - datetime: 'between', - date: 'between' - } - // 鑾峰彇宸查�夊瓧娈甸泦鍚� let cards = this.refs.searchcard.state.selectCards @@ -2255,12 +2227,12 @@ if (cell.type !== item.type) { // 鏁版嵁绫诲瀷淇敼 if (cell.type === 'select') { - item.match = selectmatch[cell.datatype] + item.match = '=' } else if (cell.type === 'daterange') { - item.match = datematch[cell.datatype] + item.match = 'between' } else { cell.type = 'text' - item.match = textmatch[cell.datatype] + item.match = 'like' } item.type = cell.type @@ -2277,11 +2249,11 @@ _columns.forEach(item => { let _match = '' if (item.type === 'select') { - _match = selectmatch[item.datatype] + _match = '=' } else if (item.type === 'daterange') { - _match = datematch[item.datatype] + _match = 'between' } else { - _match = textmatch[item.datatype] + _match = 'like' } let newcard = { @@ -2734,7 +2706,7 @@ confirm({ content: `纭畾鏂板缓鏍囩缁勫悧锛焋, - okText: this.state.dict['header.confirm'], + okText: this.state.dict['model.confirm'], cancelText: this.state.dict['header.cancel'], onOk() { let newgroup = 'tabs' + Utils.getuuid() @@ -2759,7 +2731,7 @@ confirm({ content: `纭畾鍒犻櫎鏍囩缁勫悧锛焋, - okText: this.state.dict['header.confirm'], + okText: this.state.dict['model.confirm'], cancelText: this.state.dict['header.cancel'], onOk() { @@ -3119,7 +3091,7 @@ hasbtncrtinter ? <CreateInterface key="interface" dict={this.state.dict} ref="btnCreatInterface" trigger={this.btnCreatInterface}/> : null, modaltype === 'actionEdit' ? <CreateFunc key="create" dict={this.state.dict} ref="btnCreatFunc" trigger={this.creatFunc}/> : null, <Button key="cancel" onClick={this.editModalCancel}>{this.state.dict['header.cancel']}</Button>, - <Button key="confirm" type="primary" onClick={this.handleSubmit}>{this.state.dict['header.confirm']}</Button> + <Button key="confirm" type="primary" onClick={this.handleSubmit}>{this.state.dict['model.confirm']}</Button> ]} destroyOnClose > @@ -3210,7 +3182,7 @@ {/* 鏍规嵁瀛楁鍚嶆坊鍔犳樉绀哄垪鍙婃悳绱㈡潯浠� */} <Modal wrapClassName="common-table-fields-modal" - title={this.state.dict['header.edit']} + title={this.state.dict['model.edit']} visible={this.state.tableVisible} width={'65vw'} maskClosable={false} @@ -3279,7 +3251,7 @@ </Modal> {/* 璁剧疆鍏ㄥ眬閰嶇疆鍙婂垪琛ㄦ暟鎹簮 */} <Modal - title={this.state.dict['header.edit']} + title={this.state.dict['model.edit']} visible={this.state.settingVisible} width={750} maskClosable={false} @@ -3292,7 +3264,7 @@ <CreateInterface key="interface" dict={this.state.dict} ref="tableCreatInterface" trigger={this.tableCreatInterface}/>, <CreateFunc key="create" dict={this.state.dict} ref="tableCreatFunc" trigger={this.tableCreatFunc}/>, <Button key="cancel" onClick={() => { this.setState({ settingVisible: false }) }}>{this.state.dict['header.cancel']}</Button>, - <Button key="confirm" type="primary" loading={this.state.sqlVerifing} onClick={this.settingSave}>{this.state.dict['header.confirm']}</Button> + <Button key="confirm" type="primary" loading={this.state.sqlVerifing} onClick={this.settingSave}>{this.state.dict['model.confirm']}</Button> ]} destroyOnClose > diff --git a/src/templates/comtableconfig/source.jsx b/src/templates/comtableconfig/source.jsx index 8fc542e..06db883 100644 --- a/src/templates/comtableconfig/source.jsx +++ b/src/templates/comtableconfig/source.jsx @@ -1,6 +1,6 @@ import Utils from '@/utils/utils.js' -import zhCN from '@/locales/zh-CN/comtable.js' -import enUS from '@/locales/en-US/comtable.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' const CommonDict = (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS diff --git a/src/templates/formtabconfig/index.jsx b/src/templates/formtabconfig/index.jsx index dcc9b60..5cc4586 100644 --- a/src/templates/formtabconfig/index.jsx +++ b/src/templates/formtabconfig/index.jsx @@ -8,8 +8,8 @@ import { Button, Card, Modal, Collapse, notification, Spin, Select, List, Icon, Empty, Switch, Tooltip } from 'antd' import Api from '@/api' -import zhCN from '@/locales/zh-CN/comtable.js' -import enUS from '@/locales/en-US/comtable.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' import Utils from '@/utils/utils.js' import { getModalForm, getActionForm } from '@/templates/zshare/formconfig' import { queryTableSql } from '@/utils/option.js' @@ -498,8 +498,8 @@ handleAction = (card) => { let ableField = this.props.permFuncField.join(', ') let functip = <div> - <p style={{marginBottom: '5px'}}>{this.state.dict['header.modal.func.innerface'].replace('@ableField', ableField)}</p> - <p>{this.state.dict['header.modal.func.outface']}</p> + <p style={{marginBottom: '5px'}}>{this.state.dict['model.tooltip.func.innerface'].replace('@ableField', ableField)}</p> + <p>{this.state.dict['model.tooltip.func.outface']}</p> </div> this.setState({ @@ -953,7 +953,7 @@ let _this = this confirm({ content: `纭畾鍒犻櫎<<${element.card.label}>>鍚楋紵`, - okText: this.state.dict['header.confirm'], + okText: this.state.dict['model.confirm'], cancelText: this.state.dict['header.cancel'], onOk() { let _config = JSON.parse(JSON.stringify(_this.state.config)) @@ -1439,7 +1439,7 @@ if (config.isAdd) { confirm({ content: '鎸夐挳閰嶇疆灏氭湭鎻愪氦锛岀‘瀹氭斁寮冧繚瀛樺悧锛�', - okText: this.state.dict['header.confirm'], + okText: this.state.dict['model.confirm'], cancelText: this.state.dict['header.cancel'], onOk() { _this.handleViewBack() @@ -1860,7 +1860,7 @@ confirm({ content: `纭畾鏂板缓鏍囩缁勫悧锛焋, - okText: this.state.dict['header.confirm'], + okText: this.state.dict['model.confirm'], cancelText: this.state.dict['header.cancel'], onOk() { let newgroup = 'tabs' + Utils.getuuid() @@ -1882,7 +1882,7 @@ confirm({ content: `纭畾鍒犻櫎鏍囩缁勫悧锛焋, - okText: this.state.dict['header.confirm'], + okText: this.state.dict['model.confirm'], cancelText: this.state.dict['header.cancel'], onOk() { @@ -1921,7 +1921,7 @@ confirm({ content: `纭畾鍒犻櫎鍒嗙粍<<${group.label}>>鍚楋紵`, - okText: this.state.dict['header.confirm'], + okText: this.state.dict['model.confirm'], cancelText: this.state.dict['header.cancel'], onOk() { let groups = config.groups.filter(item => !(item.uuid === group.uuid)) @@ -2245,7 +2245,7 @@ </Modal> {/* 缂栬緫鎸夐挳锛氬鍒躲�佺紪杈� */} <Modal - title={this.state.dict['header.modal.action.edit']} + title={this.state.dict['model.action'] + '-' + this.state.dict['model.edit']} visible={modaltype === 'actionEdit'} width={700} maskClosable={false} @@ -2254,7 +2254,7 @@ this.state.card && this.state.card.btnType !== 'cancel' ? <CreateFunc key="create" dict={this.state.dict} ref="btnCreatFunc" trigger={this.creatFunc}/> : null, <Button key="cancel" onClick={this.editModalCancel}>{this.state.dict['header.cancel']}</Button>, - <Button key="confirm" type="primary" onClick={this.handleSubmit}>{this.state.dict['header.confirm']}</Button> + <Button key="confirm" type="primary" onClick={this.handleSubmit}>{this.state.dict['model.confirm']}</Button> ]} destroyOnClose > @@ -2290,7 +2290,7 @@ {/* 鏍规嵁瀛楁鍚嶆坊鍔犳樉绀哄垪鍙婃悳绱㈡潯浠� */} <Modal wrapClassName="common-table-fields-modal" - title={this.state.dict['header.edit']} + title={this.state.dict['model.edit']} visible={this.state.tableVisible} width={'65vw'} maskClosable={false} @@ -2335,7 +2335,7 @@ </Modal> {/* 璁剧疆鍏ㄥ眬閰嶇疆鍙婂垪琛ㄦ暟鎹簮 */} <Modal - title={this.state.dict['header.edit']} + title={this.state.dict['model.edit']} visible={this.state.settingVisible} width={700} maskClosable={false} @@ -2347,7 +2347,7 @@ footer={[ <CreateFunc key="create" dict={this.state.dict} ref="tableCreatFunc" trigger={this.tableCreatFunc}/>, <Button key="cancel" onClick={() => { this.setState({ settingVisible: false }) }}>{this.state.dict['header.cancel']}</Button>, - <Button key="confirm" type="primary" loading={this.state.sqlVerifing} onClick={this.settingSave}>{this.state.dict['header.confirm']}</Button> + <Button key="confirm" type="primary" loading={this.state.sqlVerifing} onClick={this.settingSave}>{this.state.dict['model.confirm']}</Button> ]} destroyOnClose > diff --git a/src/templates/formtabconfig/source.jsx b/src/templates/formtabconfig/source.jsx index 7b7e8b4..962016e 100644 --- a/src/templates/formtabconfig/source.jsx +++ b/src/templates/formtabconfig/source.jsx @@ -1,6 +1,6 @@ import Utils from '@/utils/utils.js' -import zhCN from '@/locales/zh-CN/comtable.js' -import enUS from '@/locales/en-US/comtable.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' const CommonDict = (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS diff --git a/src/templates/modalconfig/index.jsx b/src/templates/modalconfig/index.jsx index 1557bfb..b8b88f2 100644 --- a/src/templates/modalconfig/index.jsx +++ b/src/templates/modalconfig/index.jsx @@ -8,9 +8,9 @@ import { Button, Card, Modal, Collapse, notification, Select, List, Icon, Empty } from 'antd' import Api from '@/api' -import zhCN from '@/locales/zh-CN/comtable.js' import Utils from '@/utils/utils.js' -import enUS from '@/locales/en-US/comtable.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' import { getModalForm } from '@/templates/zshare/formconfig' import { queryTableSql } from '@/utils/option.js' @@ -689,7 +689,7 @@ confirm({ content: `纭畾鍒犻櫎<<${card.label}>>鍚楋紵`, - okText: this.state.dict['header.confirm'], + okText: this.state.dict['model.confirm'], cancelText: this.state.dict['header.cancel'], onOk() { let _config = JSON.parse(JSON.stringify(_this.state.config)) @@ -794,7 +794,7 @@ if (isOrigin) { confirm({ content: '灏氭湭鎻愪氦锛岀‘瀹氭斁寮冧繚瀛樺悧锛�', - okText: this.state.dict['header.confirm'], + okText: this.state.dict['model.confirm'], cancelText: this.state.dict['header.cancel'], onOk() { _this.handleViewBack() @@ -1110,7 +1110,7 @@ confirm({ content: `纭畾鍒犻櫎鍒嗙粍<<${group.label}>>鍚楋紵`, - okText: this.state.dict['header.confirm'], + okText: this.state.dict['model.confirm'], cancelText: this.state.dict['header.cancel'], onOk() { let _config = JSON.parse(JSON.stringify(_this.state.config)) @@ -1364,7 +1364,7 @@ <span>{this.state.dict['header.cancel']}</span> </button> <button type="button" className="ant-btn ant-btn-primary"> - <span>{this.state.dict['header.confirm']}</span> + <span>{this.state.dict['model.confirm']}</span> </button> </div> <div className="action-mask"></div> @@ -1374,7 +1374,7 @@ </div> </DndProvider> <Modal - title={this.state.modalType !== 'copy' ? this.state.dict['header.edit'] : this.state.dict['header.modal.form.copy']} + title={this.state.modalType !== 'copy' ? this.state.dict['model.edit'] : this.state.dict['header.modal.form.copy']} visible={this.state.visible} width={700} onCancel={this.editModalCancel} @@ -1393,7 +1393,7 @@ </Modal> <Modal wrapClassName="modal-fields" - title={this.state.dict['header.edit']} + title={this.state.dict['model.edit']} visible={this.state.tableVisible} width={'65vw'} maskClosable={false} @@ -1411,7 +1411,7 @@ } </Modal> <Modal - title={this.state.dict['header.edit']} + title={this.state.dict['model.edit']} visible={this.state.settingVisible} width={700} maskClosable={false} diff --git a/src/templates/modalconfig/source.jsx b/src/templates/modalconfig/source.jsx index c340150..8c4276e 100644 --- a/src/templates/modalconfig/source.jsx +++ b/src/templates/modalconfig/source.jsx @@ -1,6 +1,6 @@ import Utils from '@/utils/utils.js' -import zhCN from '@/locales/zh-CN/comtable.js' -import enUS from '@/locales/en-US/comtable.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' const CommonDict = (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS diff --git a/src/templates/sharecomponent/actioncomponent/actionform/index.jsx b/src/templates/sharecomponent/actioncomponent/actionform/index.jsx new file mode 100644 index 0000000..5bb6f79 --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/actionform/index.jsx @@ -0,0 +1,657 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input, Select, Icon, Radio, notification, Tooltip, InputNumber } from 'antd' +import { btnIcons, btnClasses, formRule } from '@/utils/option.js' +import Utils from '@/utils/utils.js' +import './index.scss' + +const { TextArea } = Input + +class MainSearch extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + setting: PropTypes.object, // 椤甸潰璁剧疆 + formlist: PropTypes.any, // 琛ㄥ崟淇℃伅 + card: PropTypes.any, // 鎸夐挳淇℃伅 + tabs: PropTypes.array, // 鎵�鏈夋爣绛鹃〉 + inputSubmit: PropTypes.any // 鍥炶溅鎻愪氦浜嬩欢 + } + + state = { + formlist: null, // 琛ㄥ崟淇℃伅 + openType: null, // 鎵撳紑鏂瑰紡 + interType: null, // 鎺ュ彛绫诲瀷锛氬唴閮ㄣ�佸閮� + funcType: null, // 鍔熻兘绫诲瀷 + position: null, // 鎸夐挳浣嶇疆 + reqOptionSgl: [{ + value: 'requiredSgl', + text: this.props.dict['header.form.requiredSgl'] + }], + reqOptions: [{ + value: 'notRequired', + text: this.props.dict['header.form.notRequired'] + }, { + value: 'requiredSgl', + text: this.props.dict['header.form.requiredSgl'] + }], + reqOptionsMutil: [{ + value: 'notRequired', + text: this.props.dict['header.form.notRequired'] + }, { + value: 'requiredSgl', + text: this.props.dict['header.form.requiredSgl'] + }, { + value: 'required', + text: this.props.dict['header.form.required'] + }, { + value: 'requiredOnce', + text: this.props.dict['header.form.requiredOnce'] + }], + insertUpdateOptions: [{ + value: '', + text: this.props.dict['header.form.empty'] + }, { + value: 'insert', + text: this.props.dict['header.form.action.insert'] + }, { + value: 'update', + text: this.props.dict['header.form.action.update'] + }], + deleteOptions: [{ + value: '', + text: this.props.dict['header.form.empty'] + }, { + value: 'LogicDelete', + text: this.props.dict['header.form.action.LogicDelete'] + }, { + value: 'delete', + text: this.props.dict['header.form.action.delete'] + }, { + value: 'custom', + text: this.props.dict['header.form.custom'] + }] + } + + + UNSAFE_componentWillMount () { + let _opentype = '' // 鎵撳紑鏂瑰紡 + let _intertype = '' // 鎺ュ彛绫诲瀷 + let _position = '' // 鎸夐挳浣嶇疆 + let _tabType = '' // 鎸夐挳涓哄脊绐楋紙鏍囩锛夋椂锛屾爣绛剧殑绫诲瀷 + let _funcType = '' // 鍔熻兘鎸夐挳绫诲瀷 + let _options = null // 閫夐」鍒楄〃 + + this.props.formlist.forEach(form => { + if (form.key === 'OpenType') { + if (this.props.card.execMode) { // 杞崲鎵撳嵃鏃舵墦寮�鏂瑰紡 + _opentype = 'funcbutton' + } else { + _opentype = form.initVal + } + } else if (form.key === 'intertype') { + _intertype = form.initVal + } else if (form.key === 'position') { + _position = form.initVal + } else if (form.key === 'tabType') { + _tabType = form.initVal + } else if (form.key === 'funcType') { + _funcType = form.initVal + } + }) + + let _tabs = this.props.tabs.filter(tab => tab.type === _tabType) + + if (_opentype === 'innerpage') { // 鏂伴〉闈紙鍐呴儴锛夛紝鍙�夋ā鏉� + _options = ['label', 'Ot', 'OpenType', 'pageTemplate', 'icon', 'class', 'position'] + } else if (_opentype === 'outerpage') { // 鏂伴〉闈紙澶栭儴锛夛紝闇�瑕侀〉闈㈠湴鍧� + _options = ['label', 'Ot', 'OpenType', 'url', 'icon', 'class', 'position'] + } else if (_opentype === 'blank' || _opentype === 'tab') { // 鏂版爣绛炬垨褰撳墠椤甸潰鏇挎崲 + _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'tabTemplate'] + } else if (_opentype === 'popview') { // 妯℃�佹鏍囩椤� + _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'tabType', 'linkTab', 'popClose'] + } else if (_opentype === 'excelOut') { // 瀵煎叆瀵煎嚭 + if (_intertype === 'outer') { + _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'sysInterface', 'interface', 'outerFunc', 'icon', 'class', 'execSuccess', 'execError', 'pagination', 'search'] + } else { + _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'execSuccess', 'execError', 'pagination', 'search'] + } + } else if (_opentype === 'excelIn') { // 瀵煎叆瀵煎嚭 + if (_intertype === 'outer') { + _options = ['label', 'Ot', 'OpenType', 'intertype', 'innerFunc', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc', 'icon', 'class', 'sheet', 'execSuccess', 'execError'] + } else { + _options = ['label', 'Ot', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'sheet', 'execSuccess', 'execError'] + } + } else if (_opentype === 'funcbutton') { + if (!_funcType) { + _options = ['label', 'OpenType', 'funcType', 'icon', 'class'] + } else if (_funcType === 'changeuser') { + _options = ['label', 'OpenType', 'funcType', 'icon', 'class'] + } else if (_funcType === 'print') { + if (_intertype === 'outer') { + _options = ['label', 'OpenType', 'funcType', 'execMode', 'intertype', 'innerFunc', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError'] + } else { + _options = ['label', 'OpenType', 'funcType', 'execMode', 'intertype', 'innerFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError'] + } + } + } else { + if (_intertype === 'outer') { + _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError'] + } else { + _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'sql', 'sqlType'] + } + } + this.setState({ + openType: _opentype, + interType: _intertype, + position: _position, + funcType: _funcType, + formlist: this.props.formlist.map(item => { + if (item.key === 'class') { + item.options = btnClasses + } else if (item.key === 'icon') { + item.options = btnIcons + } else if (item.key === 'Ot') { + if (_opentype === 'innerpage' || _position === 'grid') { + item.options = this.state.reqOptionSgl + } else if (['outerpage', 'blank', 'tab', 'popview', 'excelIn'].includes(_opentype)) { + item.options = this.state.reqOptions + } else { + item.options = this.state.reqOptionsMutil + } + } else if (item.key === 'sqlType') { + if (['prompt', 'exec'].includes(_opentype)) { + item.options = this.state.deleteOptions + } else { + item.options = this.state.insertUpdateOptions + } + } else if (item.key === 'linkTab') { + item.options = [ + { + value: '', + text: '鏂板缓' + }, + ..._tabs + ] + } else if (item.key === 'OpenType') { + item.initVal = _opentype + } + + item.hidden = !_options.includes(item.key) + return item + }) + }) + } + + componentDidMount () { + const { card } = this.props + + if (card.focus) { + try { + let _form = document.getElementById('label') + _form.select() + } catch { + console.warn('琛ㄥ崟focus澶辫触锛�') + } + } + } + + /** + * @description 涓嬫媺鍒囨崲 + * 1銆佹墦寮�鏂瑰紡鍒囨崲锛岄噸缃彲瑙佽〃鍗曞拰琛ㄥ崟鍊� + * 2銆佹樉绀轰綅缃垏鎹紝閲嶇疆閫夋嫨琛� + * 3銆佸垏鎹㈡爣绛剧被鍨嬶紝閲嶇疆鍙�夋爣绛� + */ + openTypeChange = (key, value) => { + if (key === 'OpenType') { + let _options = null + if (value === 'innerpage') { + _options = ['label', 'Ot', 'OpenType', 'pageTemplate', 'icon', 'class', 'position'] + } else if (value === 'outerpage') { + _options = ['label', 'Ot', 'OpenType', 'url', 'icon', 'class', 'position'] + } else if (value === 'blank' || value === 'tab') { + _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'tabTemplate'] + } else if (value === 'popview') { + _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'tabType', 'linkTab', 'popClose'] + } else if (value === 'excelOut') { + if (this.state.interType === 'outer') { + _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'sysInterface', 'interface', 'outerFunc', 'icon', 'class', 'execSuccess', 'execError', 'pagination', 'search'] + } else { + _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'execSuccess', 'execError', 'pagination', 'search'] + } + } else if (value === 'excelIn') { + if (this.state.interType === 'outer') { + _options = ['label', 'Ot', 'OpenType', 'intertype', 'innerFunc', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc', 'icon', 'class', 'sheet', 'execSuccess', 'execError'] + } else { + _options = ['label', 'Ot', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'sheet', 'execSuccess', 'execError'] + } + } else if (value === 'funcbutton') { + if (!this.state.funcType) { + _options = ['label', 'OpenType', 'funcType', 'icon', 'class'] + } else if (this.state.funcType === 'changeuser') { + _options = ['label', 'OpenType', 'funcType', 'icon', 'class'] + } else if (this.state.funcType === 'print') { + if (this.state.interType === 'outer') { + _options = ['label', 'OpenType', 'funcType', 'execMode', 'intertype', 'innerFunc', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError'] + } else { + _options = ['label', 'OpenType', 'funcType', 'execMode', 'intertype', 'innerFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError'] + } + } + } else { + if (this.state.interType === 'inner') { + _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'sql', 'sqlType'] + } else { + _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc'] + } + } + + let _fieldval = {} + + let _formlist = this.state.formlist.map(item => { + item.hidden = !_options.includes(item.key) + + if (item.hidden) return item + + if (item.key === 'intertype') { + _fieldval.intertype = this.state.interType + } else if (item.key === 'Ot') { + if (value === 'innerpage' || this.state.position === 'grid') { + item.options = this.state.reqOptionSgl + _fieldval.Ot = 'requiredSgl' + } else if (['outerpage', 'blank', 'tab', 'popview'].includes(value)) { + item.options = this.state.reqOptions + _fieldval.Ot = 'requiredSgl' + } else if (value === 'excelIn') { + item.options = this.state.reqOptions + _fieldval.Ot = 'notRequired' + } else { + item.options = this.state.reqOptionsMutil + } + } else if (item.key === 'sqlType') { + if (['prompt', 'exec'].includes(value)) { + item.options = this.state.deleteOptions + } else { + item.options = this.state.insertUpdateOptions + } + _fieldval.sqlType = '' + } + + return item + }) + + this.setState({ + openType: value, + formlist: _formlist + }, () => { + this.props.form.setFieldsValue(_fieldval) + }) + } else if (key === 'position') { + let _fieldval = {} + + this.setState({ + position: value, + formlist: this.state.formlist.map(item => { + if (item.key === 'Ot') { + if (this.state.openType === 'innerpage' || value === 'grid') { + item.options = this.state.reqOptionSgl + _fieldval.Ot = 'requiredSgl' + } else if (['outerpage', 'blank', 'tab', 'popview'].includes(this.state.openType)) { + item.options = this.state.reqOptions + _fieldval.Ot = 'requiredSgl' + } else { + item.options = this.state.reqOptionsMutil + } + } + return item + }) + }, () => { + this.props.form.setFieldsValue(_fieldval) + }) + } else if (key === 'tabType') { + let _tabs = this.props.tabs.filter(tab => tab.type === value) + let _fieldval = {} + + this.setState({ + formlist: this.state.formlist.map(item => { + if (item.key === 'linkTab') { + item.options = [ + { + value: '', + text: '鏂板缓' + }, + ..._tabs + ] + } + return item + }) + }, () => { + this.props.form.setFieldsValue(_fieldval) + }) + } else if (key === 'funcType') { + let _options = null + if (!value) { + _options = ['label', 'OpenType', 'funcType', 'icon', 'class'] + } else if (value === 'changeuser') { + _options = ['label', 'OpenType', 'funcType', 'icon', 'class'] + } else if (value === 'print') { + if (this.state.interType === 'outer') { + _options = ['label', 'OpenType', 'funcType', 'execMode', 'intertype', 'innerFunc', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError'] + } else { + _options = ['label', 'OpenType', 'funcType', 'execMode', 'intertype', 'innerFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError'] + } + } + + this.setState({ + formlist: this.state.formlist.map(item => { + item.hidden = !_options.includes(item.key) + + if (item.hidden) return item + + if (item.key === 'Ot' && value === 'print') { + item.options = this.state.reqOptionsMutil + } + + return item + }) + }) + } + } + + onChange = (e, key) => { + const { openType } = this.state + let value = e.target.value + if (key === 'intertype') { + let _options = null + if (openType === 'excelOut') { + if (value === 'outer') { + _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'sysInterface', 'interface', 'outerFunc', 'icon', 'class', 'execSuccess', 'execError', 'pagination', 'search'] + } else { + _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'execSuccess', 'execError', 'pagination', 'search'] + } + } else if (openType === 'excelIn') { + if (value === 'outer') { + _options = ['label', 'Ot', 'OpenType', 'intertype', 'innerFunc', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc', 'icon', 'class', 'sheet', 'execSuccess', 'execError'] + } else { + _options = ['label', 'Ot', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'sheet', 'execSuccess', 'execError'] + } + } else if (openType === 'funcbutton') { + if (value === 'outer') { + _options = ['label', 'OpenType', 'funcType', 'execMode', 'intertype', 'innerFunc', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError'] + } else { + _options = ['label', 'OpenType', 'funcType', 'execMode', 'intertype', 'innerFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError'] + } + } else { + if (value === 'inner') { + _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'sql', 'sqlType'] + } else { + _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc'] + } + } + + this.setState({ + interType: value, + formlist: this.state.formlist.map(item => { + item.hidden = !_options.includes(item.key) + + if (item.key === 'interface') { + item.readonly = false + } else if (item.key === 'sysInterface') { + item.initVal = 'false' + } + return item + }) + }) + } else if (key === 'sysInterface') { + if (value === 'true') { + this.props.form.setFieldsValue({ + interface: window.GLOB.mainSystemApi || '' + }) + } + this.setState({ + formlist: this.state.formlist.map(item => { + if (item.key === 'interface' && value === 'true') { + item.readonly = true + } else if (item.key === 'interface') { + item.readonly = false + } + + return item + }) + }) + } + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + getFields() { + const { getFieldDecorator } = this.props.form + const fields = [] + + this.state.formlist.forEach((item, index) => { + if (item.hidden) return + + if (item.type === 'text') { // 鏂囨湰鎼滅储 + let _rules = [] + if (item.key === 'innerFunc') { + let str = '^(' + item.fields.join('|') + ')' + let _patten = new RegExp(str + formRule.func.innerPattern + '$', 'g') + _rules = [{ + pattern: _patten, + message: formRule.func.innerMessage + }, { + max: formRule.func.max, + message: formRule.func.maxMessage + }] + } else if (item.key === 'outerFunc' || item.key === 'callbackFunc') { + _rules = [{ + pattern: formRule.func.pattern, + message: formRule.func.message + }, { + max: formRule.func.max, + message: formRule.func.maxMessage + }] + } else { + _rules = [{ + max: formRule.input.max, + message: formRule.input.message + }] + } + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}> + <Icon type="question-circle" /> + {item.label} + </Tooltip> : item.label + }> + {getFieldDecorator(item.key, { + initialValue: item.initVal || '', + rules: [ + { + required: item.readonly ? false : !!item.required, + message: this.props.dict['form.required.input'] + item.label + '!' + }, + ..._rules + ] + })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + ) + } else if (item.type === 'number') { + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}> + <Icon type="question-circle" /> + {item.label} + </Tooltip> : item.label + }> + {getFieldDecorator(item.key, { + initialValue: item.initVal, + rules: [ + { + required: item.readonly ? false : !!item.required, + message: this.props.dict['form.required.input'] + item.label + '!' + } + ] + })(<InputNumber min={0} max={10000} precision={0} />)} + </Form.Item> + </Col> + ) + } else if (item.type === 'select') { // 涓嬫媺鎼滅储 + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} 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 + showSearch + filterOption={(input, option) => option.props.children[2].toLowerCase().indexOf(input.toLowerCase()) >= 0} + onChange={(value) => {this.openTypeChange(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> + )} + </Select> + )} + </Form.Item> + </Col> + ) + } else if (item.type === 'radio') { + 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 + '!' + } + ] + })( + <Radio.Group onChange={(e) => {this.onChange(e, item.key)}} 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 === 'textarea') { + fields.push( + <Col span={24} key={index}> + <Form.Item label={item.label} className="textarea"> + {getFieldDecorator(item.key, { + initialValue: item.initVal + })(<TextArea rows={4} />)} + </Form.Item> + </Col> + ) + } + }) + return fields + } + + handleConfirm = () => { + const { setting } = this.props + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + values.uuid = this.props.card.uuid + values.verify = this.props.card.verify || null + + if (values.OpenType === 'excelIn') { + values.position = 'toolbar' + } else if (values.OpenType === 'excelOut') { + if (values.intertype === 'inner' && !values.innerFunc) { + if ((setting.interType === 'inner' && setting.innerFunc) || setting.interType === 'outer') { + notification.warning({ + top: 92, + message: '琛ㄦ牸鏁版嵁鏌ヨ鏈娇鐢ㄦ暟鎹簮锛屽鍑篍xcel浣跨敤鍐呴儴鎺ュ彛鏃讹紝闇�鑷畾涔夊唴閮ㄥ嚱鏁帮紒', + duration: 5 + }) + return + } + } + + values.position = 'toolbar' + values.Ot = 'notRequired' + } else if (values.OpenType === 'popview' && !values.linkTab) { // 娌℃湁鍏宠仈鏍囩锛堟柊寤烘椂锛夛紝鍒涘缓鏂版爣绛綢d + values.linkTab = Utils.getuuid() + values.createTab = true // 鐢ㄤ簬鏍囪鎸夐挳澶嶅埗鏃讹紝鏄惁澶嶅埗鍘熸湁鏍囩 + } else if (values.OpenType === 'funcbutton') { // 杞崲鎵撳嵃鏃舵墦寮�鏂瑰紡 + values.position = 'toolbar' + if (values.funcType === 'print') { + values.OpenType = values.execMode + } + } + + if (values.innerFunc === '' && values.sql === '') { + notification.warning({ + top: 92, + message: this.props.dict['header.form.actionhelp.tablename'], + duration: 5 + }) + } else if (values.innerFunc === '' && values.sql !== '' && values.sqlType === '') { + notification.warning({ + top: 92, + message: this.props.dict['header.form.actionhelp.sqlType'], + duration: 5 + }) + } else { + resolve(values) + } + } else { + reject(err) + } + }) + }) + } + + render() { + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 7 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 17 } + } + } + return ( + <Form {...formItemLayout} className="ant-advanced-search-form commontable-action-form" id="winter"> + <Row gutter={24}>{this.getFields()}</Row> + </Form> + ) + } +} + +export default Form.create()(MainSearch) \ No newline at end of file diff --git a/src/templates/sharecomponent/actioncomponent/actionform/index.scss b/src/templates/sharecomponent/actioncomponent/actionform/index.scss new file mode 100644 index 0000000..c25cef2 --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/actionform/index.scss @@ -0,0 +1,33 @@ +.ant-advanced-search-form.commontable-action-form { + min-height: 190px; + .superconfig { + color: #1890ff; + cursor: pointer; + } + .textarea { + .ant-col-sm-7 { + width: 14%; + } + .ant-col-sm-17 { + width: 86%; + } + } + .ant-input-number { + width: 100%; + } + .anticon-question-circle { + color: #c49f47; + position: relative; + left: -3px; + } + .with-button { + .ant-form-item-control-wrapper { + padding-right: 63px; + } + .ant-btn { + position: absolute; + right: 12px; + top: 4.5px; + } + } +} \ No newline at end of file diff --git a/src/templates/sharecomponent/actioncomponent/dragaction/card.jsx b/src/templates/sharecomponent/actioncomponent/dragaction/card.jsx new file mode 100644 index 0000000..946a950 --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/dragaction/card.jsx @@ -0,0 +1,60 @@ +import React from 'react' +import { useDrag, useDrop } from 'react-dnd' +import { Icon, Button } from 'antd' +import './index.scss' + +const Card = ({ id, card, moveCard, findCard, editCard, delCard, copyCard, profileCard, hasDrop, doubleClickCard }) => { + const originalIndex = findCard(id).index + const [{ isDragging }, drag] = useDrag({ + item: { type: 'action', id, originalIndex }, + collect: monitor => ({ + isDragging: monitor.isDragging(), + }), + }) + const [, drop] = useDrop({ + accept: 'action', + canDrop: () => true, + drop: (item) => { + if (!item.hasOwnProperty('originalIndex')) { + hasDrop(card) + } + }, + hover({ id: draggedId }) { + if (!draggedId) return + if (draggedId !== id) { + const { index: overIndex } = findCard(id) + moveCard(draggedId, overIndex) + } + }, + }) + const opacity = isDragging ? 0 : 1 + + let hasProfile = false + if (['pop', 'prompt', 'exec'].includes(card.OpenType)) { + hasProfile = true + } else if (card.OpenType === 'excelIn' || card.OpenType === 'excelOut') { + hasProfile = true + } else if (card.funcType === 'print') { + hasProfile = true + } + + return ( + <div className="page-card" style={{ opacity: opacity}}> + <div ref={node => drag(drop(node))}> + <Button + className={'mk-btn mk-' + card.class} + icon={card.icon} + key={card.uuid} + onDoubleClick={() => doubleClickCard(id)} + > + {card.label}{card.position === 'grid' && <Icon type="table" />} + </Button> + </div> + <Icon className="edit" title="edit" type="edit" onClick={() => editCard(id)} /> + <Icon className="edit copy" title="copy" type="copy" onClick={() => copyCard(id)} /> + <Icon className="edit close" title="close" type="close" onClick={() => delCard(id)} /> + {hasProfile ? <Icon className="edit profile" title="verify" type="profile" onClick={() => profileCard(id)} /> : null} + </div> + ) +} +export default Card diff --git a/src/templates/sharecomponent/actioncomponent/dragaction/index.jsx b/src/templates/sharecomponent/actioncomponent/dragaction/index.jsx new file mode 100644 index 0000000..d6e05a2 --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/dragaction/index.jsx @@ -0,0 +1,179 @@ +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, placeholder, handleList, handleMenu, deleteMenu, profileMenu, doubleClickCard }) => { + let target = null + + const [cards, setCards] = useState(list) + const moveCard = (id, atIndex) => { + const { card, index } = findCard(id) + 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 doubleClickBtn = id => { + const { card } = findCard(id) + doubleClickCard(card) + } + + const editCard = id => { + const { card } = findCard(id) + handleMenu(card) + } + + const profileCard = id => { + const { card } = findCard(id) + profileMenu(card) + } + + const delCard = id => { + const { card } = findCard(id) + deleteMenu(card) + } + + const copyCard = id => { + const { card } = findCard(id) + let copycard = fromJS(card).toJS() + + copycard.uuid = Utils.getuuid() + copycard.origin = false + copycard.copyType = 'action' + copycard.label = copycard.label + '(copy)' + copycard.focus = true + + copycard.originCard = card + + if (copycard.OpenType === 'popview') { // 寰呭畬鍠� + copycard.linkTab = '' + } + + let _val = fromJS(copycard).toJS() + + try { + _val.uuid = Utils.getuuid() + _val = window.btoa(window.encodeURIComponent(JSON.stringify(_val))) + } catch { + console.warn('Stringify Failure') + _val = '' + } + + if (_val) { + let oInput = document.createElement('input') + oInput.value = _val + document.body.appendChild(oInput) + oInput.select() + document.execCommand('Copy') + document.body.removeChild(oInput) + } + + const { index: overIndex } = findCard(id) + + const _cards = update(cards, { $splice: [[overIndex + 1, 0, copycard]] }) + + handleList(_cards, copycard) + } + + const hasDrop = (item) => { + target = item + } + + const [, drop] = useDrop({ + accept: 'action', + drop(item) { + if (item.hasOwnProperty('originalIndex')) { + return + } + + let newcard = {} + newcard.uuid = Utils.getuuid() + newcard.focus = true + + newcard.label = 'button' + newcard.sqlType = '' + newcard.Ot = 'requiredSgl' + newcard.OpenType = item.subType + newcard.tabType = 'SubTable' + newcard.icon = '' + newcard.class = 'default' + newcard.intertype = 'inner' + newcard.method = 'POST' + newcard.position = 'toolbar' + newcard.execSuccess = 'grid' + newcard.execError = 'never' + newcard.popClose = 'never' + newcard.errorTime = 10 + newcard.verify = null + + if (item.subType === 'excelIn') { + // 瀵煎叆鍜屽鍑篹xcel锛屾寜閽悕绉扮洿鎺ヤ负瀵煎叆銆佸鍑� + newcard.label = item.label + } else if (item.subType === 'excelOut') { + newcard.label = item.label + newcard.intertype = setting.interType + newcard.innerFunc = setting.innerFunc + newcard.sysInterface = setting.sysInterface + newcard.outerFunc = setting.outerFunc + newcard.interface = setting.interface + } + + let targetId = cards.length > 0 ? cards[cards.length - 1].uuid : 0 + if (target) { + targetId = target.uuid + } + + const { index: overIndex } = findCard(`${targetId}`) + let targetIndex = overIndex + + targetIndex++ + + const _cards = update(cards, { $splice: [[targetIndex, 0, newcard]] }) + + handleList(_cards, newcard) + target = null + } + }) + + return ( + <div ref={drop} className="ant-row"> + {cards.map(card => ( + <Card + id={card.uuid} + key={card.uuid} + card={card} + moveCard={moveCard} + copyCard={copyCard} + editCard={editCard} + delCard={delCard} + findCard={findCard} + hasDrop={hasDrop} + profileCard={profileCard} + doubleClickCard={doubleClickBtn} + /> + ))} + + {cards.length === 0 ? + <div className="common-drawarea-placeholder"> + {placeholder} + </div> : null + } + </div> + ) +} +export default Container diff --git a/src/templates/sharecomponent/actioncomponent/dragaction/index.scss b/src/templates/sharecomponent/actioncomponent/dragaction/index.scss new file mode 100644 index 0000000..369ae98 --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/dragaction/index.scss @@ -0,0 +1,6 @@ +.common-drawarea-placeholder { + width: 100%; + line-height: 65px; + text-align: center; + color: #bcbcbc; +} \ No newline at end of file diff --git a/src/templates/sharecomponent/actioncomponent/index.jsx b/src/templates/sharecomponent/actioncomponent/index.jsx new file mode 100644 index 0000000..e7babb6 --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/index.jsx @@ -0,0 +1,921 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { fromJS } from 'immutable' +import { Icon, Tooltip, Modal, notification, Button } from 'antd' +import moment from 'moment' + +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 { getActionForm } from '@/templates/zshare/formconfig' + +import ActionForm from './actionform' +import VerifyCard from '@/templates/zshare/verifycard' +import CreateFunc from '@/templates/zshare/createfunc' +import CreateInterface from '@/templates/zshare/createinterface' +import VerifyPrint from './verifyprint' +import VerifyExcelIn from './verifyexcelin' +import VerifyExcelOut from './verifyexcelout' +import DragElement from './dragaction' +import './index.scss' + +const { confirm } = Modal + +// **鎮茶鑰呭線寰�姝g‘锛屼箰瑙傝�呭線寰�鎴愬姛 +class ActionComponent extends Component { + static propTpyes = { + type: PropTypes.string, // 鑿滃崟绫诲瀷锛屼富琛ㄦ垨瀛愯〃 + menu: PropTypes.object, // 鑿滃崟淇℃伅锛堣彍鍗昳d锛岃彍鍗曞弬鏁帮紝鑿滃崟鍚嶇О锛� + config: PropTypes.object, // 鑿滃崟閰嶇疆淇℃伅 + pasteContent: PropTypes.object, // 绮樿创閰嶇疆淇℃伅 + usefulFields: PropTypes.array, // 鑷畾涔夊嚱鏁板彲鐢ㄥ瓧娈� + tabs: PropTypes.array, // 鎵�鏈夋爣绛� + setSubConfig: PropTypes.func, // 璁剧疆瀛愰厤缃俊鎭� + updateaction: PropTypes.func // 鑿滃崟閰嶇疆鏇存柊 + } + + state = { + dict: (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS, + card: null, // 缂栬緫涓厓绱� + formlist: null, // 琛ㄥ崟淇℃伅 + actionlist: null, // 鎸夐挳缁� + copying: false, // 鎸夐挳澶嶅埗涓� + visible: false, // 妯℃�佹鎺у埗 + profVisible: false // 楠岃瘉淇℃伅妯℃�佹 + } + + /** + * @description 鎼滅储鏉′欢鍒濆鍖� + */ + UNSAFE_componentWillMount () { + this.setState({ + actionlist: fromJS(this.props.config.action).toJS() + }) + } + + /** + * @description 鐩戝惉鍒版寜閽鍒舵椂锛岃Е鍙戞寜閽紪杈� + */ + UNSAFE_componentWillReceiveProps (nextProps) { + const { actionlist } = this.state + + if (nextProps.pasteContent && nextProps.pasteContent.copyType === 'action') { + this.setState({actionlist: [...actionlist, nextProps.pasteContent]}) + this.handleAction(nextProps.pasteContent) + } + } + + /** + * @description 鎸夐挳椤哄簭璋冩暣锛屾垨鎷栨嫿娣诲姞 + */ + handleList = (list, card) => { + const { config } = this.props + + if (card) { + this.setState({actionlist: list}) + this.handleAction(card) + } else { + this.setState({actionlist: list}) + this.props.updateaction({...config, action: list}) + } + } + + /** + * @description 鎼滅储鏉′欢缂栬緫锛岃幏鍙栨悳绱㈡潯浠惰〃鍗曚俊鎭� + */ + handleAction = (card) => { + let ableField = this.props.usefulFields.join(', ') + let functip = <div> + <p style={{marginBottom: '5px'}}>{this.state.dict['model.tooltip.func.innerface'].replace('@ableField', ableField)}</p> + <p>{this.state.dict['model.tooltip.func.outface']}</p> + </div> + + this.setState({ + visible: true, + card: card, + formlist: getActionForm(card, functip, this.props.config, this.props.usefulFields, this.props.type) + }) + } + + /** + * @description 鍙栨秷淇濆瓨锛屽鏋滃厓绱犱负鏂版坊鍏冪礌锛屽垯浠庡簭鍒椾腑鍒犻櫎 + */ + editModalCancel = () => { + const { card } = this.state + + if (card.focus) { + let actionlist = fromJS(this.state.actionlist).toJS() + + actionlist = actionlist.filter(item => item.uuid !== card.uuid) + + this.setState({ + card: null, + actionlist: actionlist, + visible: false + }) + } else { + this.setState({ + card: null, + visible: false + }) + } + } + + /** + * @description 鎼滅储淇敼鍚庢彁浜や繚瀛� + * 1銆佸幓闄ょ郴缁熼粯璁ゆ悳绱㈡潯浠� + * 2銆佸瓧娈靛強鎻愮ず鏂囧瓧閲嶅鏍¢獙 + * 3銆佹洿鏂颁笅鎷夎彍鍗曞彲閫夐泦鍚� + * 4銆佷笅鎷夎彍鍗曟暟鎹簮璇硶楠岃瘉 + */ + handleSubmit = () => { + const { config, menu } = this.props + const { card } = this.state + let _actionlist = fromJS(this.state.actionlist).toJS() + + this.actionFormRef.handleConfirm().then(btn => { + _actionlist = _actionlist.filter(item => !item.origin || item.uuid === btn.uuid) + + let labelrepet = false + _actionlist = _actionlist.map(item => { + if (item.uuid !== btn.uuid && item.label === btn.label) { + labelrepet = true + } + + if (item.uuid === btn.uuid) { + return btn + } else { + return item + } + }) + + if (labelrepet) { + notification.warning({ + top: 92, + message: this.state.dict['model.name.exist'] + ' !', + duration: 5 + }) + return + } + + this.setState({ + copying: true + }) + + let copyActionId = '' // 鎸夐挳涓哄鍒舵椂锛岃褰曞綋鍓嶆寜閽殑Id锛岃彍鍗曞彇娑堜繚瀛樻椂锛屽垹闄ゅ鍒舵寜閽厤缃俊鎭� + + /** + * @description 鎸夐挳淇濆瓨鏍¢獙 + * 1銆佹鏌ユ寜閽槸鍚︿负琛ㄥ崟鎴栬〃鍗曟爣绛鹃〉锛屽鍓嶅悗涓�鑷达紝鍒欏鍒跺叾鍐呭 + * 2銆佹鏌ユ寜閽槸鍚︿负鏍囩椤碉紝濡傚墠鍚庝竴鑷达紝鍒欏鍒舵爣绛鹃〉 + */ + new Promise(resolve => { + if ( + !card.originCard || + (btn.OpenType === 'pop' && card.originCard.OpenType !== 'pop') || + (['tab', 'blank'].includes(btn.OpenType) && !['tab', 'blank'].includes(card.originCard.OpenType)) || + (btn.OpenType === 'popview' && (!btn.createTab || card.originCard.OpenType !== 'popview' || !card.originCard.linkTab)) + ) { // 鎸夐挳涓嶆槸澶嶅埗锛屾垨鎸夐挳鍓嶅悗绫诲瀷涓嶄竴鑷存椂锛岀洿鎺ヤ繚瀛� + resolve('save') + } else if (btn.OpenType === 'pop' || btn.OpenType === 'tab' || btn.OpenType === 'blank') { + resolve('subconf') + } else if (btn.OpenType === 'popview') { + resolve('subtab') + } else { + resolve('save') + } + }).then(result => { // 鏌ヨ鍘熸寜閽厤缃俊鎭� + if (result === 'save' || result === 'subtab') return result + + return Api.getSystemConfig({ + func: 'sPC_Get_LongParam', + MenuID: card.originCard.uuid + }) + }).then(result => { // 澶嶅埗鎸夐挳閰嶇疆淇℃伅锛屼繚瀛樿嚦鏂版坊鍔犳寜閽� + if (result === 'save' || result === 'subtab') return result + + if (result.status && result.LongParam) { + let _LongParam = '' + + // 瑙f瀽閰嶇疆 + if (result.LongParam) { + try { + _LongParam = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam))) + } catch (e) { + console.warn('Parse Failure') + _LongParam = '' + } + } + + let _temp = '' // 閰嶇疆淇℃伅绫诲瀷 + + // 淇敼妯℃�佹鏍囬鍚嶇О + if (btn.OpenType === 'pop' && _LongParam && _LongParam.type === 'Modal') { + try { + _LongParam.setting.title = btn.label + _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_LongParam))) + _temp = 'Modal' + } catch { + console.warn('Stringify Failure') + _LongParam = '' + _temp = '' + } + } else if (['tab', 'blank'].includes(btn.OpenType) && _LongParam && _LongParam.type === 'FormTab') { + try { + _LongParam.action = _LongParam.action.map(_btn => { + _btn.uuid = Utils.getuuid() + + return _btn + }) + _LongParam.tabgroups.forEach(_groupId => { + _LongParam[_groupId] = _LongParam[_groupId].map(_tab => { + _tab.uuid = Utils.getuuid() + + return _tab + }) + }) + _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_LongParam))) + _temp = 'FormTab' + } catch { + console.warn('Stringify Failure') + _LongParam = '' + _temp = '' + } + } + + if (!_temp) return 'save' + + let param = { + func: 'sPC_ButtonParam_AddUpt', + ParentID: menu.MenuID, + MenuID: btn.uuid, + MenuNo: menu.MenuNo, + Template: _temp, + MenuName: btn.label, + PageParam: JSON.stringify({Template: _temp}), + LongParam: _LongParam + } + + return Api.getSystemConfig(param) + } else { + if (!result.status) { + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } + return 'save' + } + }).then(result => { + if (result === 'save' || result === 'subtab') return result + + if (!result.status) { + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } else { + copyActionId = btn.uuid + } + + return 'save' + }).then(result => { // 鏌ヨ鍘熸寜閽叧鑱旀爣绛句俊鎭� + if (result === 'save') return result + + return Api.getSystemConfig({ + func: 'sPC_Get_LongParam', + MenuID: card.originCard.linkTab + }) + }).then(result => { // 鏍囩澶嶅埗 + if (result === 'save') return result + + let _LongParam = '' // 鏍囩閰嶇疆淇℃伅 + + if (!result.status) { + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } else if (result.LongParam) { + // 瑙f瀽鏍囩閰嶇疆 + try { + _LongParam = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam))) + } catch (e) { + console.warn('Parse Failure') + _LongParam = '' + } + } + + if (!_LongParam) { + return 'save' + } else { + copyActionId = btn.linkTab + + return new Promise(resolve => { + this.copytab(btn, _LongParam, resolve) + }) + } + }).then(() => { + // 鍒ゆ柇鏄惁瀛樺湪鎿嶄綔鍒� + let _hasGridbtn = _actionlist.filter(act => act.position === 'grid').length > 0 + let _gridBtn = config.gridBtn ? fromJS(config.gridBtn).toJS() : null + + if (_gridBtn) { + _gridBtn.display = _hasGridbtn + } else { + _gridBtn = { + display: _hasGridbtn, + Align: 'center', + IsSort: 'false', + uuid: Utils.getuuid(), + label: this.state.dict['header.form.column.action'], + type: 'action', + style: 'button', + show: 'horizontal', + Width: 120 + } + } + + this.setState({ + actionlist: _actionlist, + copying: false, + visible: false + }) + + this.props.updateaction({...config, action: _actionlist, gridBtn: _gridBtn}, copyActionId) + }) + }) + } + + /** + * @description 鏍囩澶嶅埗 + * 1銆佷繚瀛樻寜閽叧鑱旂殑鏂版爣绛� + * 2銆佷繚瀛樻爣绛炬寜閽俊鎭� + * 3銆佷繚瀛樻柊鏍囩涓寜閽殑瀛愰厤缃俊鎭� + */ + copytab = (btn, _tab, _resolve) => { + let _LongParam = '' + + _tab.uuid = btn.linkTab + _tab.tabName = _tab.tabName + moment().format('YYYY-MM-DD HH:mm:ss') + _tab.tabNo = _tab.tabNo + moment().format('YYYY-MM-DD HH:mm:ss') + + let param = { + func: 'sPC_Tab_AddUpt', + MenuID: _tab.uuid, + MenuNo: _tab.tabNo, + Template: _tab.Template, + MenuName: _tab.tabName, + Remark: _tab.Remark, + PageParam: JSON.stringify({Template: _tab.Template}), + Sort: 0 + } + + let _oriActions = [] + + let btnParam = { + func: 'sPC_Button_AddUpt', + Type: 40, + ParentID: _tab.uuid, + MenuNo: _tab.tabNo, + Template: _tab.Template, + PageParam: '', + LongParam: '', + LText: '' + } + + try { + let _linkchange = {} + btnParam.LText = [] + + _tab.action = _tab.action.map((item, index) => { + let uuid = Utils.getuuid() + + if (item.OpenType === 'pop') { + _oriActions.push({ + prebtn: JSON.parse(JSON.stringify(item)), + curuuid: uuid, + Template: 'Modal' + }) + } else if (item.OpenType === 'popview') { + _linkchange[item.linkTab] = Utils.getuuid() + + item.linkTab = _linkchange[item.linkTab] + } + + item.uuid = uuid + + btnParam.LText.push(`select '${item.uuid}' as menuid, '${item.label}' as menuname, '${(index + 1) * 10}' as Sort`) + + return item + }) + + if (_tab.funcs && _tab.funcs.length > 0) { + _tab.funcs = _tab.funcs.map(item => { + if (item.type === 'tab') { + item.linkTab = _linkchange[item.linkTab] + item.menuNo = '' + item.subfuncs = [] + } + + return item + }) + } + + btnParam.LText = btnParam.LText.join(' union all ') + btnParam.LText = Utils.formatOptions(btnParam.LText) + btnParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' + btnParam.secretkey = Utils.encrypt(btnParam.LText, btnParam.timestamp) + + _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_tab))) + } catch { + console.warn('Stringify Failure') + _LongParam = '' + _resolve('save') + return + } + + param.LongParam = _LongParam + + new Promise(resolve => { + Api.getSystemConfig(param).then(response => { + if (response.status) { + resolve(true) + } else { + notification.warning({ + top: 92, + message: response.message, + duration: 5 + }) + resolve(false) + } + }) + }).then(result => { + if (!result) return result + if (!btnParam.LText) return true + + return Api.getSystemConfig(btnParam) + }).then(result => { + if (result === false || result === true) return result + + if (result.status) { + return true + } else { + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + return false + } + }).then(result => { + if (!result) return result + if (_oriActions.length === 0) return true + + let deffers = _oriActions.map(item => { + return new Promise(resolve => { + Api.getSystemConfig({ + func: 'sPC_Get_LongParam', + MenuID: item.prebtn.uuid + }).then(response => { + if (!response.status || !response.LongParam) { + resolve(response) + } else { + let _param = { + func: 'sPC_ButtonParam_AddUpt', + ParentID: _tab.uuid, + MenuID: item.curuuid, + MenuNo: _tab.tabNo, + Template: item.Template, + MenuName: item.prebtn.label, + PageParam: JSON.stringify({Template: item.Template}), + LongParam: response.LongParam + } + Api.getSystemConfig(_param).then(resp => { + resolve(resp) + }) + } + }) + }) + }) + + return Promise.all(deffers) + }).then(result => { + let error = '' + + if (typeof(result) === 'object') { + result.forEach(resul => { + if (!resul.status && !error) { + error = resul + } + }) + } + + if (error) { + notification.warning({ + top: 92, + message: error.message, + duration: 5 + }) + } + + _resolve('save') + }) + } + + /** + * @description 鎸夐挳鍒犻櫎 + */ + deleteElement = (card) => { + const { config } = this.props + const { dict } = this.state + let _this = this + + confirm({ + content: dict['model.confirm'] + dict['model.delete'] + ` - ${card.label} 锛焋, + okText: dict['model.confirm'], + cancelText: this.state.dict['header.cancel'], + onOk() { + let _actionlist = fromJS(_this.state.actionlist).toJS() + + _actionlist = _actionlist.filter(item => item.uuid !== card.uuid) + + _this.setState({ + actionlist: _actionlist + }) + + let _hasGridbtn = _actionlist.filter(act => act.position === 'grid').length > 0 + let _gridBtn = config.gridBtn ? fromJS(config.gridBtn).toJS() : null + + if (_gridBtn) { + _gridBtn.display = _hasGridbtn + } else { + _gridBtn = { + display: _hasGridbtn, + Align: 'center', + IsSort: 'false', + uuid: Utils.getuuid(), + label: this.state.dict['header.form.column.action'], + type: 'action', + style: 'button', + show: 'horizontal', + Width: 120 + } + } + + let delcard = { + type: 'action', + card: card + } + + _this.props.updateaction({...config, action: _actionlist, gridBtn: _gridBtn}, '', delcard) + }, + onCancel() {} + }) + } + + /** + * @description 楠岃瘉淇℃伅閰嶇疆 + */ + profileAction = (element) => { + this.setState({ + profVisible: true, + card: element + }) + } + + /** + * @description 楠岃瘉淇℃伅淇濆瓨 + */ + verifySubmit = () => { + const { config } = this.props + const { card } = this.state + + this.verifyRef.handleConfirm().then(res => { + let _actionlist = fromJS(this.state.actionlist).toJS() + + _actionlist = _actionlist.filter(item => !item.origin || item.uuid === card.uuid) + + _actionlist = _actionlist.map(item => { + if (item.uuid === card.uuid) { + item.verify = res + } + + return item + }) + + this.setState({ + actionlist: _actionlist, + profVisible: false + }) + this.props.updateaction({...config, action: _actionlist}) + }) + } + + /** + * @description 鍒涘缓鎸夐挳瀛樺偍杩囩▼ + */ + creatFunc = () => { + const { menu, config } = this.props + let _config = fromJS(this.props.config).toJS() + + this.actionFormRef.handleConfirm().then(res => { + let btn = res // 鎸夐挳淇℃伅 + let newLText = '' // 鍒涘缓瀛樺偍杩囩▼sql + let DelText = '' // 鍒犻櫎瀛樺偍杩囩▼sql + + let _actionlist = fromJS(this.state.actionlist).toJS() + + _actionlist = _actionlist.filter(item => !item.origin || item.uuid === btn.uuid) + + let labelrepet = false + _actionlist = _actionlist.map(item => { + if (item.uuid !== btn.uuid && item.label === btn.label) { + labelrepet = true + } + + if (item.uuid === btn.uuid) { + return btn + } else { + return item + } + }) + + if (labelrepet) { + notification.warning({ + top: 92, + message: this.state.dict['model.name.exist'] + ' !', + duration: 5 + }) + return + } + + // 鍒涘缓瀛樺偍杩囩▼锛屽繀椤诲~鍐欏唴閮ㄥ嚱鏁板悕 + if (!btn.innerFunc) { + notification.warning({ + top: 92, + message: '璇峰~鍐欏唴閮ㄥ嚱鏁帮紒', + duration: 5 + }) + return + } + + new Promise(resolve => { + // 寮圭獥锛堣〃鍗曪級绫绘寜閽紝鍏堣幏鍙栨寜閽厤缃俊鎭紝濡傛灉灏氭湭閰嶇疆鎸夐挳鍒欎細鎶ラ敊骞剁粓姝€�� + // 鑾峰彇淇℃伅鍚庣敓鎴愬垹闄ゅ拰鍒涘缓瀛樺偍杩囩▼鐨勮鍙� + if (btn.OpenType === 'pop') { + Api.getSystemConfig({ + func: 'sPC_Get_LongParam', + MenuID: btn.uuid + }).then(res => { + let _LongParam = '' + if (res.status && res.LongParam) { + try { + _LongParam = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam))) + } catch (e) { + console.warn('Parse Failure') + _LongParam = '' + } + } + + if (_LongParam) { + let fields = [] + if (_LongParam.groups.length > 0) { + _LongParam.groups.forEach(group => { + fields = [...fields, ...group.sublist] + }) + } else { + fields = _LongParam.fields + } + + let _param = { + funcName: btn.innerFunc, + name: _config.setting.tableName || '', + fields: fields, + menuNo: menu.MenuNo + } + newLText = Utils.formatOptions(Utils.getfunc(_param, btn, menu, _config)) + DelText = Utils.formatOptions(Utils.dropfunc(btn.innerFunc)) + resolve(true) + } else { + notification.warning({ + top: 92, + message: '寮圭獥锛堣〃鍗曪級鎸夐挳锛岃鍏堥厤缃〃鍗曚俊鎭紒', + duration: 5 + }) + resolve(false) + } + }) + } else if (btn.OpenType === 'excelIn') { + if (btn.verify && btn.verify.sheet && btn.verify.columns && btn.verify.columns.length > 0) { + let _param = { + funcName: btn.innerFunc, + menuNo: menu.MenuNo + } + newLText = Utils.formatOptions(Utils.getexcelInfunc(_param, btn, menu)) + DelText = Utils.formatOptions(Utils.dropfunc(btn.innerFunc)) + resolve(true) + } else { + notification.warning({ + top: 92, + message: '璇峰畬鍠勫鍏xcel楠岃瘉淇℃伅锛�', + duration: 5 + }) + resolve(false) + } + } else if (btn.OpenType === 'excelOut') { + let _param = { + innerFunc: btn.innerFunc + } + + newLText = Utils.formatOptions(Utils.getTableFunc(_param, menu, _config)) // 鍒涘缓瀛樺偍杩囩▼sql + DelText = Utils.formatOptions(Utils.dropfunc(btn.innerFunc)) + + resolve(true) + } else { + let _param = { + funcName: btn.innerFunc, + name: _config.setting.tableName || '', + fields: '', + menuNo: menu.MenuNo + } + newLText = Utils.formatOptions(Utils.getfunc(_param, btn, menu, _config)) + DelText = Utils.formatOptions(Utils.dropfunc(btn.innerFunc)) + resolve(true) + } + }).then(res => { + if (!res) return + + this.refs.btnCreatFunc.exec(btn.innerFunc, newLText, DelText).then(result => { + if (result !== 'success') return + + // 鍒ゆ柇鏄惁瀛樺湪鎿嶄綔鍒� + let _hasGridbtn = _actionlist.filter(act => act.position === 'grid').length > 0 + let _gridBtn = config.gridBtn ? fromJS(config.gridBtn).toJS() : null + + if (_gridBtn) { + _gridBtn.display = _hasGridbtn + } else { + _gridBtn = { + display: _hasGridbtn, + Align: 'center', + IsSort: 'false', + uuid: Utils.getuuid(), + label: this.state.dict['header.form.column.action'], + type: 'action', + style: 'button', + show: 'horizontal', + Width: 120 + } + } + + this.setState({ + actionlist: _actionlist + }) + + this.props.updateaction({...config, action: _actionlist, gridBtn: _gridBtn}) + }) + }) + }) + } + + /** + * @description 鍒涘缓鎸夐挳鎺ュ彛锛堝啓鍏ワ級 + */ + btnCreatInterface = () => { + const { config, menu, type } = this.props + + this.actionFormRef.handleConfirm().then(result => { + + let _menu = { + type: type, + MenuID: menu.MenuID, + menuName: menu.MenuName, + menuNo: menu.MenuNo + } + + this.refs.btnCreatInterface.triggerInInterface(result, config, _menu) + }) + } + + /** + * @description 鎸夐挳鍙屽嚮瑙﹀彂瀛愰厤缃� + */ + btnDoubleClick = (element) => { + if (!element.origin && (element.OpenType === 'pop' || element.OpenType === 'popview' || element.OpenType === 'blank' || element.OpenType === 'tab')) { + this.props.setSubConfig(element) + } else { + notification.warning({ + top: 92, + message: '姝ゆ寜閽棤瀛愰厤缃」锛�', + duration: 5 + }) + } + } + + render() { + const { config } = this.props + const { actionlist, visible, card, dict, copying, profVisible } = this.state + + let hasbtncrtinter = false + if (card && !card.copyType && config.setting.interType === 'inner' && !config.setting.innerFunc && config.setting.dataresource) { + hasbtncrtinter = true + } + + return ( + <div className="model-table-action-list"> + <Tooltip placement="bottomLeft" overlayClassName="middle" title={dict['model.tooltip.action.guide']}> + <Icon type="question-circle" /> + </Tooltip> + <DragElement + list={actionlist} + setting={this.props.config.setting} + handleList={this.handleList} + handleMenu={this.handleAction} + deleteMenu={this.deleteElement} + profileMenu={this.profileAction} + doubleClickCard={this.btnDoubleClick} + placeholder={dict['header.form.action.placeholder']} + /> + {/* 缂栬緫鎸夐挳锛氬鍒躲�佺紪杈� */} + <Modal + title={dict['model.action'] + '-' + (card && card.copyType === 'action' ? dict['model.copy'] : dict['model.edit'])} + visible={visible} + width={750} + maskClosable={false} + onCancel={this.editModalCancel} + footer={[ + hasbtncrtinter ? <CreateInterface key="interface" dict={dict} ref="btnCreatInterface" trigger={this.btnCreatInterface}/> : null, + card && !card.copyType ? <CreateFunc key="create" dict={dict} ref="btnCreatFunc" trigger={this.creatFunc}/> : null, + <Button key="cancel" onClick={this.editModalCancel}>{dict['header.cancel']}</Button>, + <Button key="confirm" type="primary" loading={copying} onClick={this.handleSubmit}>{dict['model.confirm']}</Button> + ]} + destroyOnClose + > + <ActionForm + dict={dict} + card={card} + tabs={this.props.tabs} + formlist={this.state.formlist} + inputSubmit={this.handleSubmit} + setting={config.setting} + wrappedComponentRef={(inst) => this.actionFormRef = inst} + /> + </Modal> + {/* 鎸夐挳浣跨敤绯荤粺瀛樺偍杩囩▼鏃讹紝楠岃瘉淇℃伅妯℃�佹 */} + <Modal + wrapClassName="model-table-action-verify-modal" + title={'楠岃瘉淇℃伅'} + visible={profVisible} + width={'75vw'} + maskClosable={false} + style={{minWidth: '900px', maxWidth: '1200px'}} + okText={dict['header.submit']} + onOk={this.verifySubmit} + onCancel={() => { this.setState({ profVisible: false }) }} + destroyOnClose + > + {card && !card.execMode && card.OpenType !== 'excelIn' && card.OpenType !== 'excelOut' ? + <VerifyCard + floor={this.props.type} + card={card} + dict={dict} + config={config} + columns={config.columns} + wrappedComponentRef={(inst) => this.verifyRef = inst} + /> : null + } + {card && card.execMode ? + <VerifyPrint + card={card} + dict={dict} + columns={config.columns} + wrappedComponentRef={(inst) => this.verifyRef = inst} + /> : null + } + {card && card.OpenType === 'excelIn' ? + <VerifyExcelIn + card={card} + dict={dict} + columns={config.columns} + wrappedComponentRef={(inst) => this.verifyRef = inst} + /> : null + } + {card && card.OpenType === 'excelOut' ? + <VerifyExcelOut + card={card} + dict={dict} + wrappedComponentRef={(inst) => this.verifyRef = inst} + /> : null + } + </Modal> + </div> + ) + } +} + +export default ActionComponent \ No newline at end of file diff --git a/src/templates/sharecomponent/actioncomponent/index.scss b/src/templates/sharecomponent/actioncomponent/index.scss new file mode 100644 index 0000000..1304abf --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/index.scss @@ -0,0 +1,84 @@ +.model-table-action-list { + position: relative; + padding: 0px 25px 15px; + min-height: 82px; + .anticon-question-circle { + position: absolute; + left: 5px; + } + > .ant-row { + min-height: 80px; + } + .page-card { + display: inline-block; + margin: 0px 0px 0px 0px; + padding: 15px 10px 0 0; + position: relative; + div { + cursor: move; + } + .edit { + position: absolute; + left: 0; + top: 0px; + color: #1890ff; + cursor: pointer; + display: none; + } + .edit.copy { + left: 20px; + color: #26C281; + } + .edit.close { + left: 40px; + color: #ff4d4f; + } + .edit.profile { + left: 60px; + color: purple; + } + button { + min-width: 65px; + cursor: move; + .anticon-table { + font-size: 10px; + position: absolute; + right: 1px; + bottom: 0px; + } + } + } + .page-card:hover { + .edit { + display: inline-block; + } + } +} + +.model-table-action-verify-modal { + .ant-modal { + top: 50px; + padding-bottom: 5px; + .ant-modal-body { + max-height: calc(100vh - 190px); + overflow-y: auto; + .ant-empty { + margin: 15vh 8px; + } + } + .ant-modal-body::-webkit-scrollbar { + width: 7px; + } + .ant-modal-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); + } + .ant-modal-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); + background: rgba(0, 0, 0, 0); + } + } +} \ No newline at end of file diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.jsx new file mode 100644 index 0000000..b1e6c8f --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.jsx @@ -0,0 +1,202 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Select, Button, Input, InputNumber } from 'antd' +import './index.scss' + + +class UniqueForm extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + columns: PropTypes.array, // 鍒楀悕闆嗗悎 + columnChange: PropTypes.func // 淇敼鍑芥暟 + } + + state = { + editItem: null, // 缂栬緫鍏冪礌 + type: 'Nvarchar(50)', + locked: false + } + + edit = (record) => { + this.setState({ + editItem: record, + type: record.type || 'Nvarchar(50)' + }, () => { + if (!/^Nvarchar/.test(record.type)) { + this.props.form.setFieldsValue({ + min: record.min, + max: record.max + }) + } + }) + + this.props.form.setFieldsValue({ + Column: record.Column, + Text: record.Text, + required: record.required, + type: record.type + }) + if (record.type === 'Int' || /^Decimal/ig.test(record.type)) { + this.setState({ + locked: true + }) + } else { + this.setState({ + locked: false + }) + } + } + + typeChange = (val) => { + this.setState({ + type: val + }, () => { + if (val === 'Int' || /^Decimal/ig.test(val)) { + this.props.form.setFieldsValue({ + required: 'true', + }) + this.setState({ + locked: true + }) + } else { + this.setState({ + locked: false + }) + } + }) + } + + + handleConfirm = () => { + // const { columns } = this.props + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + values.uuid = this.state.editItem ? this.state.editItem.uuid : '' + + if (/^Nvarchar/ig.test(values.type)) { + values.limit = values.type.match(/\d+/)[0] + } else if (/^Decimal/ig.test(values.type)) { + values.limit = values.type.match(/\d+/ig)[1] + } else { + values.limit = '' + } + + this.props.columnChange(values) + this.setState({ + editItem: null, + locked: false, + type: 'Nvarchar(50)' + }) + this.props.form.setFieldsValue({ + Column: '', + Text: '', + required: 'true', + type: 'Nvarchar(50)' + }) + } + }) + } + + render() { + const { getFieldDecorator } = this.props.form + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + let haslimit = !/^Nvarchar/.test(this.state.type) + + return ( + <Form {...formItemLayout} className="verify-form"> + <Row gutter={24}> + <Col span={7}> + <Form.Item label={'Column'}> + {getFieldDecorator('Column', { + initialValue: '', + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + 'Column!' + } + ] + })(<Input placeholder="" autoComplete="off" />)} + </Form.Item> + </Col> + <Col span={7}> + <Form.Item label={'Text'}> + {getFieldDecorator('Text', { + initialValue: '', + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + 'Text!' + } + ] + })(<Input placeholder="" autoComplete="off" />)} + </Form.Item> + </Col> + <Col span={7}> + <Form.Item label={'绫诲瀷'}> + {getFieldDecorator('type', { + initialValue: 'Nvarchar(50)' + })( + <Select onChange={this.typeChange}> + <Select.Option value="Nvarchar(10)"> Nvarchar(10) </Select.Option> + <Select.Option value="Nvarchar(20)"> Nvarchar(20) </Select.Option> + <Select.Option value="Nvarchar(50)"> Nvarchar(50) </Select.Option> + <Select.Option value="Nvarchar(100)"> Nvarchar(100) </Select.Option> + <Select.Option value="Nvarchar(512)"> Nvarchar(512) </Select.Option> + <Select.Option value="Int"> Int </Select.Option> + <Select.Option value="Decimal(18,0)"> Decimal(18,0) </Select.Option> + <Select.Option value="Decimal(18,2)"> Decimal(18,2) </Select.Option> + <Select.Option value="Decimal(18,4)"> Decimal(18,4) </Select.Option> + <Select.Option value="Decimal(18,6)"> Decimal(18,6) </Select.Option> + </Select> + )} + </Form.Item> + </Col> + <Col span={3} className="add"> + <Button onClick={this.handleConfirm} type="primary" className="mk-green"> + 淇濆瓨 + </Button> + </Col> + <Col span={7}> + <Form.Item label={'鏄惁蹇呭~'}> + {getFieldDecorator('required', { + initialValue: 'true' + })( + <Select disabled={this.state.locked}> + <Select.Option value="false"> 鍚� </Select.Option> + <Select.Option value="true"> 鏄� </Select.Option> + </Select> + )} + </Form.Item> + </Col> + {haslimit ? <Col span={7}> + <Form.Item label={'鏈�灏忓��'}> + {getFieldDecorator('min', { + initialValue: '' + })(<InputNumber />)} + </Form.Item> + </Col> : null} + {haslimit ? <Col span={7}> + <Form.Item label={'鏈�澶у��'}> + {getFieldDecorator('max', { + initialValue: '' + })(<InputNumber />)} + </Form.Item> + </Col> : null} + </Row> + </Form> + ) + } +} + +export default Form.create()(UniqueForm) \ No newline at end of file diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.scss b/src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/columnform/index.scss diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx new file mode 100644 index 0000000..cbbd0d8 --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx @@ -0,0 +1,296 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input, Button, notification, Modal, Menu, Icon, Tooltip, Radio, Dropdown } from 'antd' +import moment from 'moment' + +import Utils from '@/utils/utils.js' +import Api from '@/api' +import './index.scss' + +const { TextArea } = Input + +class CustomForm extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + btn: PropTypes.object, // 鎸夐挳淇℃伅 + scripts: PropTypes.array, // 鑷畾涔夎剼鏈垪琛� + usefulfields: PropTypes.any, // 鍙敤瀛楁 + systemScripts: PropTypes.array, // 绯荤粺鑴氭湰 + scriptsChange: PropTypes.func // 琛ㄥ崟 + } + + state = { + editItem: null, + usefulfields: null, + loading: false, + verifySql: '' + } + + UNSAFE_componentWillMount () { + const {usefulfields, btn} = this.props + + let fields = usefulfields.map(item => item.Column) + if (!fields.includes('ID')) { + fields.unshift('ID') + } + if (!fields.includes('BID')) { + fields.unshift('BID') + } + + let _sql = `Declare @${btn.sheet} table (${usefulfields.map(item => item.Column + ' ' + item.type).join(',')},jskey nvarchar(50) ) + Declare @UserName nvarchar(50),@FullName nvarchar(50),@ErrorCode nvarchar(50), @retmsg nvarchar(4000) + Select @ErrorCode='', @retmsg='' + ` + + this.setState({ + verifySql: _sql, + usefulfields: fields.join(', ') + }) + } + + edit = (record) => { + this.setState({ + editItem: record + }) + + this.props.form.setFieldsValue({ + sql: record.sql, + position: record.position || 'back' + }) + } + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + values.uuid = this.state.editItem ? this.state.editItem.uuid : '' + + let _quot = values.sql.match(/'{1}/g) + let _lparen = values.sql.match(/\({1}/g) + let _rparen = values.sql.match(/\){1}/g) + + _quot = _quot ? _quot.length : 0 + _lparen = _lparen ? _lparen.length : 0 + _rparen = _rparen ? _rparen.length : 0 + + if (_quot % 2 !== 0) { + notification.warning({ + top: 92, + message: 'sql涓璡'蹇呴』鎴愬鍑虹幇', + duration: 5 + }) + return + } else if (_lparen !== _rparen) { + notification.warning({ + top: 92, + message: 'sql涓�()蹇呴』鎴愬鍑虹幇', + duration: 5 + }) + return + } else if (/--/ig.test(values.sql)) { + notification.warning({ + top: 92, + message: '鑷畾涔塻ql璇彞涓紝涓嶅彲鍑虹幇瀛楃 -- 锛屾敞閲婅鐢� /*鍐呭*/', + duration: 5 + }) + return + } + + let error = Utils.verifySql(values.sql, 'customscript') + + if (error) { + notification.warning({ + top: 92, + message: 'sql涓笉鍙娇鐢�' + error, + duration: 5 + }) + return + } + + let tail = ` + aaa: + ` + + let _initsql = '' + this.props.scripts.forEach(script => { + if (this.state.editItem && this.state.editItem.uuid === script.uuid) return + if (script.status === 'false' || script.position !== 'init') return + + _initsql += ` + ${script.sql} + ` + }) + + let param = { + func: 's_debug_sql', + LText: this.state.verifySql + _initsql + values.sql + tail + } + param.LText = Utils.formatOptions(param.LText) + param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' + param.secretkey = Utils.encrypt(param.LText, param.timestamp) + + this.setState({loading: true}) + Api.getLocalConfig(param).then(res => { + if (res.status) { + this.setState({ + loading: false, + editItem: null + }, () => { + this.props.scriptsChange(values) + }) + this.props.form.setFieldsValue({ + sql: '' + }) + } else { + this.setState({loading: false}) + + Modal.error({ + title: res.message + }) + } + }) + } + }) + } + + selectScript = (e) => { + const { systemScripts, usefulfields, btn } = this.props + + let option = '' + if (e.key === 'default') { + let fields = usefulfields.map(col => col.Column).join(',') + + if (fields) { + fields = fields + ',' + } + + option = { + name: '榛樿sql', + value: `Insert into ${btn.sheet} (${fields}createuserid,createuser,createstaff,bid)\nSelect ${fields}@userid,@username,@fullname,@BID From @${btn.sheet}` + } + } else { + option = systemScripts[+e.key] + } + + let _sql = this.props.form.getFieldValue('sql') + if (_sql) { + _sql = _sql + ` + + ` + } + + _sql = _sql.replace(/\s{6}$/, '') + _sql = _sql + `/*${option.name}*/ + ` + _sql = _sql.replace(/\s{4}$/, '') + _sql = _sql + option.value + + this.props.form.setFieldsValue({ + sql: _sql + }) + } + + render() { + const { systemScripts, btn } = this.props + const { usefulfields } = this.state + const { getFieldDecorator } = this.props.form + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <Form {...formItemLayout} className="verify-form" id="verifycard2"> + <Row gutter={24}> + {usefulfields ? <Col span={24} className="sqlfield"> + <Form.Item label={'鍙敤瀛楁'}> + {usefulfields} + </Form.Item> + </Col> : null} + <Col span={8} style={{whiteSpace: 'nowrap'}}> + <Form.Item style={{marginBottom: 0}} label={ + <Tooltip placement="bottomLeft" title={'鑷畾涔夎剼鏈笌榛樿sql浣嶇疆鍏崇郴銆�'}> + <Icon type="question-circle" style={{color: '#c49f47', marginRight: '5px'}} /> + 鎵ц浣嶇疆 + </Tooltip> + }> + {getFieldDecorator('position', { + initialValue: 'back' + })( + <Radio.Group> + <Radio value="init">鍒濆鍖�</Radio> + <Radio value="front">sql鍓�</Radio> + <Radio value="back">sql鍚�</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + <Col span={4} style={{lineHeight: '40px', textAlign: 'center'}}> + <Dropdown trigger={['click']} overlayClassName="mk-normal-dropdown" overlay={ + <Menu onClick={this.selectScript}> + <Menu.Item key="default">榛樿sql</Menu.Item> + {systemScripts.map((option, i) => + <Menu.Item key={i} value={option.value}>{option.name}</Menu.Item> + )} + {systemScripts.map((option, i) => + <Menu.Item key={i + '1'} value={option.value}>{option.name}</Menu.Item> + )} + </Menu> + }> + <span style={{color: '#1890ff', display: 'inline-block', cursor: 'pointer'}}> + 蹇嵎娣诲姞 <Icon type="down" style={{marginRight: '5px'}} /> + </span> + </Dropdown> + </Col> + {/* <Col span={8}> + <Form.Item style={{marginBottom: 0}} label={ + <Tooltip placement="bottomLeft" title={'浠庣郴缁熷嚱鏁伴泦涓�夋嫨闇�瑕佺殑鍑芥暟锛屽彲蹇�熸坊鍔犺嚦sql涓��'}> + <Icon type="question-circle" style={{color: '#c49f47', marginRight: '5px'}} /> + 蹇嵎娣诲姞 + </Tooltip> + }> + <Select value="" onChange={this.selectScript}> + {systemScripts.map((option, i) => + <Select.Option title={option.name} key={i} value={option.value}> + {option.name} + </Select.Option> + )} + </Select> + </Form.Item> + </Col> */} + <Col span={4} className="add"> + <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}> + 淇濆瓨 + </Button> + </Col> + <Col span={8} style={{textAlign: 'right'}}> + {btn.sheet ? <span style={{maxWidth: '100%', display: 'inline-block', position: 'relative', top: '20px', whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden'}}> + 琛ㄥ悕: {btn.sheet} + </span> : null} + </Col> + <Col span={24} className="sql"> + <Form.Item label={'sql'}> + {getFieldDecorator('sql', { + initialValue: '', + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + 'sql!' + } + ] + })(<TextArea rows={15} />)} + </Form.Item> + </Col> + </Row> + </Form> + ) + } +} + +export default Form.create()(CustomForm) \ No newline at end of file diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.scss b/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.scss diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx new file mode 100644 index 0000000..a9a815f --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx @@ -0,0 +1,825 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Tabs, Row, Col, Input, Button, Table, Popconfirm, Icon, notification, Modal, message, InputNumber, Radio } from 'antd' +import moment from 'moment' + +import Api from '@/api' +import Utils from '@/utils/utils.js' + +import UniqueForm from './uniqueform' +import ColumnForm from './columnform' +import CustomScript from './customscript' +import './index.scss' + +const { TabPane } = Tabs +const { confirm } = Modal + +class VerifyCard extends Component { + static propTpyes = { + columns: PropTypes.array, // 鏄剧ず鍒� + dict: PropTypes.object, // 瀛楀吀椤� + card: PropTypes.object, + } + + state = { + verify: {}, + systemScripts: [], + excelColumns: [ + { + title: 'Column', + dataIndex: 'Column', + width: '16%', + editable: true + }, + { + title: 'Text', + dataIndex: 'Text', + width: '19%', + editable: true + }, + { + title: '绫诲瀷', + dataIndex: 'type', + width: '12%', + editable: true + }, + { + title: '鏄惁蹇呭~', + dataIndex: 'required', + width: '12%', + editable: true, + render: (text, record) => record.required === 'true' ? '鏄�' : '鍚�' + }, + { + title: '鏈�灏忓��', + dataIndex: 'min', + width: '12%', + editable: true + }, + { + title: '鏈�澶у��', + dataIndex: 'max', + width: '12%', + editable: true + }, + { + title: '鎿嶄綔', + align: 'center', + dataIndex: 'operation', + render: (text, record) => + ( + <div> + <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'columns')} style={{color: '#1890ff'}}><Icon type="edit" /></span> + <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'columns', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span> + <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'columns', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> + <Popconfirm + title={this.props.dict['header.form.query.delete']} + okText={this.props.dict['model.confirm']} + cancelText={this.props.dict['header.cancel']} + onConfirm={() => this.handleDelete(record, 'columns') + }> + <span className="operation-btn" style={{color: '#ff4d4f'}}><Icon type="delete" /></span> + </Popconfirm> + </div> + ) + } + ], + uniqueColumns: [ + { + title: '瀛楁鍚�', + dataIndex: 'field', + width: '35%' + }, + { + title: '鎶ラ敊缂栫爜', + dataIndex: 'errorCode', + width: '12%' + }, + { + title: '楠岃瘉绫诲瀷', + dataIndex: 'verifyType', + width: '13%', + render: (text, record) => record.verifyType === 'logic' ? '閫昏緫楠岃瘉' : '鐗╃悊楠岃瘉' + }, + { + title: '鐘舵��', + dataIndex: 'status', + width: '15%', + render: (text, record) => record.status === 'false' ? + ( + <div> + {this.props.dict['header.form.status.forbidden']} + <Icon style={{marginLeft: '5px'}} type="stop" theme="twoTone" twoToneColor="#ff4d4f" /> + </div> + ) : + ( + <div> + {this.props.dict['header.form.status.open']} + <Icon style={{marginLeft: '5px'}} type="check-circle" theme="twoTone" twoToneColor="#52c41a" /> + </div> + ) + }, + { + title: '鎿嶄綔', + align: 'center', + width: '25%', + dataIndex: 'operation', + render: (text, record) => + (<div> + <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'unique')} style={{color: '#1890ff'}}><Icon type="edit" /></span> + <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'unique', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span> + <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'unique', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> + <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record, 'unique')} style={{color: '#8E44AD'}}><Icon type="swap" /></span> + <Popconfirm + title={this.props.dict['header.form.query.delete']} + okText={this.props.dict['model.confirm']} + cancelText={this.props.dict['header.cancel']} + onConfirm={() => this.handleDelete(record, 'unique') + }> + <span className="operation-btn" style={{color: '#ff4d4f'}}><Icon type="delete" /></span> + </Popconfirm> + </div>) + } + ], + scriptsColumns: [ + { + title: 'SQL', + dataIndex: 'sql', + width: '60%' + }, + { + title: '鎵ц浣嶇疆', + dataIndex: 'position', + width: '10%', + render: (text, record) => record.position !== 'front' ? 'sql鍚�' : 'sql鍓�' + }, + { + title: '鐘舵��', + dataIndex: 'status', + width: '10%', + render: (text, record) => record.status === 'false' ? + ( + <div> + {this.props.dict['header.form.status.forbidden']} + <Icon style={{marginLeft: '5px'}} type="stop" theme="twoTone" twoToneColor="#ff4d4f" /> + </div> + ) : + ( + <div> + {this.props.dict['header.form.status.open']} + <Icon style={{marginLeft: '5px'}} type="check-circle" theme="twoTone" twoToneColor="#52c41a" /> + </div> + ) + }, + { + title: '鎿嶄綔', + align: 'center', + width: '20%', + dataIndex: 'operation', + render: (text, record) => + (<div> + <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'scripts')} style={{color: '#1890ff'}}><Icon type="edit" /></span> + <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'scripts', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span> + <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'scripts', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> + <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record, 'scripts')} style={{color: '#8E44AD'}}><Icon type="swap" /></span> + <Popconfirm + title={this.props.dict['header.form.query.delete']} + okText={this.props.dict['model.confirm']} + cancelText={this.props.dict['header.cancel']} + onConfirm={() => this.handleDelete(record, 'scripts') + }> + <span className="operation-btn" style={{color: '#ff4d4f'}}><Icon type="delete" /></span> + </Popconfirm> + </div>) + } + ] + } + + UNSAFE_componentWillMount() { + let _verify = this.props.card.verify || {} + + let _columns = _verify.columns || [] + _columns = _columns.map(col => { + col.required = col.required || 'true' + col.type = col.type || 'Nvarchar(50)' + + if (/^Nvarchar/ig.test(col.type)) { + col.limit = col.type.match(/\d+/)[0] + } else if (/^Decimal/ig.test(col.type)) { + col.limit = col.type.match(/\d+/ig)[1] + } else { + col.limit = '' + } + + return col + }) + + this.setState({ + verify: { + ..._verify, + default: _verify.default || 'true', + sheet: _verify.sheet || 'Sheet1', + range: _verify.range || 0, + columns: _columns, + scripts: _verify.scripts || [], + uniques: _verify.uniques || [] + } + }) + } + + componentDidMount () { + let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from聽 s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort` + + _scriptSql = Utils.formatOptions(_scriptSql) + + let _sParam = { + func: 'sPC_Get_SelectedList', + LText: _scriptSql, + obj_name: 'data', + arr_field: 'funcname,longparam' + } + + _sParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' + _sParam.secretkey = Utils.encrypt(_sParam.LText, _sParam.timestamp) + + Api.getSystemConfig(_sParam).then(res => { + if (res.status) { + this.setState({ + systemScripts: res.data.map(item => { + return { + name: item.funcname, + value: Utils.formatOptions(item.longparam, true) + } + }) + }) + } else { + notification.warning({ + top: 92, + message: res.message, + duration: 5 + }) + } + }) + } + + columnFieldInput = () => { + const { columns } = this.props + const { verify } = this.state + + let _columns = JSON.parse(JSON.stringify(verify.columns)) + + let _cols = _columns.map(col => col.Column ) + + columns.forEach(col => { + if (col.field && !_cols.includes(col.field)) { + let _type = 'Nvarchar(50)' + let _limit = '50' + if (col.type === 'number' && col.decimal === 0) { + _type = 'Int' + _limit = '' + } else if (col.type === 'number') { + _type = 'Decimal(18,' + col.decimal + ')' + _limit = col.decimal + } + + let _cell = { + uuid: col.uuid, + Column: col.field, + Text: col.label, + type: _type, + limit: _limit, + required: 'true' + } + + if (_type !== 'Nvarchar(50)') { + _cell.min = 0 + _cell.max = 999999 + } + + _columns.push(_cell) + } + }) + + this.setState({ + verify: { + ...verify, + columns: _columns + } + }) + } + + columnChange = (values) => { + let verify = JSON.parse(JSON.stringify(this.state.verify)) + + if (values.uuid) { + verify.columns = verify.columns.map(item => { + if (item.uuid === values.uuid) { + return values + } else { + return item + } + }) + } else { + values.uuid = Utils.getuuid() + verify.columns.push(values) + } + + this.setState({ + verify: verify + }) + } + + uniqueChange = (values) => { + let verify = JSON.parse(JSON.stringify(this.state.verify)) + + if (values.uuid) { + verify.uniques = verify.uniques.map(item => { + if (item.uuid === values.uuid) { + return values + } else { + return item + } + }) + } else { + values.uuid = Utils.getuuid() + verify.uniques.push(values) + } + + this.setState({ + verify: verify + }) + } + + scriptsChange = (values) => { + let verify = JSON.parse(JSON.stringify(this.state.verify)) + + if (values.uuid) { + verify.scripts = verify.scripts.map(item => { + if (item.uuid === values.uuid) { + return values + } else { + return item + } + }) + } else { + values.uuid = Utils.getuuid() + verify.scripts.push(values) + } + + this.setState({ + verify: verify + }) + } + + handleDelete = (record, type) => { + const { verify } = this.state + + if (type === 'columns') { + verify.columns = verify.columns.filter(item => item.uuid !== record.uuid) + } else if (type === 'scripts') { + verify.scripts = verify.scripts.filter(item => item.uuid !== record.uuid) + } else if (type === 'unique') { + verify.uniques = verify.uniques.filter(item => item.uuid !== record.uuid) + } + + this.setState({ verify: verify }) + } + + handleEdit = (record, type) => { + if (type === 'columns') { + this.columnForm.edit(record) + } else if (type === 'scripts') { + this.scriptsForm.edit(record) + } else if (type === 'unique') { + this.uniqueForm.edit(record) + } + + let node = document.getElementById('verify-excel-box-tab').parentNode + + if (node && node.scrollTop) { + let inter = Math.ceil(node.scrollTop / 10) + + let timer = setInterval(() => { + if (node.scrollTop - inter > 0) { + node.scrollTop = node.scrollTop - inter + } else { + node.scrollTop = 0 + clearInterval(timer) + } + }, 10) + } + } + + handleStatus = (record, type) => { + let verify = JSON.parse(JSON.stringify(this.state.verify)) + record.status = record.status === 'false' ? 'true' : 'false' + + if (type === 'scripts') { + verify.scripts = verify.scripts.map(item => { + if (item.uuid === record.uuid) { + return record + } else { + return item + } + }) + } else if (type === 'unique') { + verify.uniques = verify.uniques.map(item => { + if (item.uuid === record.uuid) { + return record + } else { + return item + } + }) + } + + this.setState({ + verify: verify + }) + } + + handleUpDown = (record, type, direction) => { + let verify = JSON.parse(JSON.stringify(this.state.verify)) + let index = 0 + + if (type === 'columns') { + verify.columns = verify.columns.filter((item, i) => { + if (item.uuid === record.uuid) { + index = i + } + + return item.uuid !== record.uuid + }) + if ((index === 0 && direction === 'up') || (index === verify.columns.length && direction === 'down')) { + return + } + + if (direction === 'up') { + verify.columns.splice(index - 1, 0, record) + } else { + verify.columns.splice(index + 1, 0, record) + } + } else if (type === 'unique') { + verify.uniques = verify.uniques.filter((item, i) => { + if (item.uuid === record.uuid) { + index = i + } + + return item.uuid !== record.uuid + }) + if ((index === 0 && direction === 'up') || (index === verify.uniques.length && direction === 'down')) { + return + } + + if (direction === 'up') { + verify.uniques.splice(index - 1, 0, record) + } else { + verify.uniques.splice(index + 1, 0, record) + } + } else if (type === 'scripts') { + verify.scripts = verify.scripts.filter((item, i) => { + if (item.uuid === record.uuid) { + index = i + } + + return item.uuid !== record.uuid + }) + if ((index === 0 && direction === 'up') || (index === verify.scripts.length && direction === 'down')) { + return + } + + if (direction === 'up') { + verify.scripts.splice(index - 1, 0, record) + } else { + verify.scripts.splice(index + 1, 0, record) + } + } + + this.setState({ + verify: verify + }) + } + + handleConfirm = () => { + const { verify } = this.state + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + let _verify = {...verify, ...values} + + let cols = _verify.columns.map(col => col.Column) + cols = Array.from(new Set(cols)) + + if (_verify.columns.length === 0) { + notification.warning({ + top: 92, + message: '璇疯缃瓻xcel鍒楀瓧娈�!', + duration: 5 + }) + return + } else if (_verify.columns.length > cols.length) { + notification.warning({ + top: 92, + message: 'Excel鍒楀瓧娈靛悕锛屼笉鍙噸澶�!', + duration: 5 + }) + return + } else if (_verify.range === 1) { + let tEmptys = _verify.columns.filter(op => !op.Text) + if (tEmptys.length > 0) { + notification.warning({ + top: 92, + message: '蹇界暐棣栬鏃讹紝浼氫娇鐢═ext鍊兼牎楠孍xcel棣栬鍐呭锛孴ext鍊间笌Excel琛ㄩ琛屽唴瀹圭浉鍚岋紝涓斿潎涓嶅彲涓虹┖锛�', + duration: 5 + }) + return + } + } + + let _loading = false + if (this.columnForm && this.columnForm.state.editItem) { + _loading = true + } else if (this.scriptsForm && this.scriptsForm.state.editItem) { + _loading = true + } else if (this.uniqueForm && this.uniqueForm.state.editItem) { + _loading = true + } + + if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql')) { + _loading = true + } + + if (_loading) { + confirm({ + content: `瀛樺湪鏈繚瀛橀」锛岀‘瀹氭彁浜ゅ悧锛焋, + okText: this.props.dict['model.confirm'], + cancelText: this.props.dict['header.cancel'], + onOk() { + resolve(_verify) + }, + onCancel() {} + }) + } else { + resolve(_verify) + } + } else { + notification.warning({ + top: 92, + message: '璇疯缃瓻xcel琛ㄥ悕!', + duration: 5 + }) + } + }) + }) + } + + onOptionChange = (e, key) => { + const { verify } = this.state + let value = e.target.value + + this.setState({ + verify: {...verify, default: value} + }) + } + + showError = (errorType) => { + if (errorType === 'S') { + notification.success({ + top: 92, + message: '鎵ц鎴愬姛锛�', + duration: 2 + }) + } else if (errorType === 'Y') { + Modal.success({ + title: '鎵ц鎴愬姛锛�' + }) + } else if (errorType === 'F') { + notification.error({ + className: 'notification-custom-error', + top: 92, + message: '鎵ц澶辫触锛�', + duration: 10 + }) + } else if (errorType === 'N') { + notification.error({ + top: 92, + message: '鎵ц澶辫触锛�', + duration: 10 + }) + } else if (errorType === 'E') { + Modal.error({ + title: '鎵ц澶辫触锛�' + }) + } else if (errorType === 'NM') { + message.error('鎵ц澶辫触锛�') + } + } + + timeChange = (val, type) => { + const { verify } = this.state + + this.setState({ + verify: {...verify, [type]: val} + }) + } + + render() { + const { card } = this.props + const { getFieldDecorator } = this.props.form + const { verify, excelColumns, scriptsColumns, uniqueColumns } = this.state + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <div id="verify-excel-box-tab"> + <Tabs defaultActiveKey="1" className="verify-card-box" onChange={this.tabchange}> + <TabPane tab="鍩虹楠岃瘉" key="1"> + <Form {...formItemLayout}> + <Row gutter={24}> + <Col span={8}> + <Form.Item label={'Excel琛ㄥ悕'}> + {getFieldDecorator('sheet', { + initialValue: verify.sheet || '', + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + this.props.dict['header.form.tablename'] + '!' + } + ] + })(<Input placeholder="" autoComplete="off" />)} + </Form.Item> + </Col> + <Col span={8}> + <Form.Item label={'蹇界暐琛�'}> + {getFieldDecorator('range', { + initialValue: verify.range || 0 + })(<InputNumber min={0} max={100} precision={0} />)} + </Form.Item> + </Col> + {card.intertype === 'inner' && !card.innerFunc ? <Col span={8}> + <Form.Item label={'榛樿sql'}> + <Radio.Group value={verify.default} onChange={this.onOptionChange}> + <Radio value="true">鎵ц</Radio> + <Radio value="false">涓嶆墽琛�</Radio> + </Radio.Group> + </Form.Item> + </Col> : null} + </Row> + </Form> + </TabPane> + <TabPane tab="Excel鍒楄缃�" key="2x"> + <ColumnForm + dict={this.props.dict} + columns={verify.columns} + columnChange={this.columnChange} + wrappedComponentRef={(inst) => this.columnForm = inst} + /> + <Button className="excel-col-add mk-green" title="娣诲姞鏄剧ず鍒楀瓧娈�" onClick={this.columnFieldInput}> + 蹇嵎娣诲姞 + </Button> + <Table + bordered + rowKey="uuid" + className="custom-table" + dataSource={verify.columns} + columns={excelColumns} + pagination={false} + /> + </TabPane> + {card.intertype === 'inner' && !card.innerFunc ? <TabPane tab="鍞竴鎬ч獙璇�" key="3"> + <UniqueForm + fields={verify.columns} + dict={this.props.dict} + uniqueChange={this.uniqueChange} + wrappedComponentRef={(inst) => this.uniqueForm = inst} + /> + <Table + bordered + rowKey="uuid" + className="custom-table" + dataSource={verify.uniques} + columns={uniqueColumns} + pagination={false} + /> + </TabPane> : null} + {card.intertype === 'inner' && !card.innerFunc ? <TabPane tab="鑷畾涔夎剼鏈�" key="6"> + <CustomScript + dict={this.props.dict} + btn={this.props.card} + usefulfields={verify.columns} + scripts={verify.scripts} + systemScripts={this.state.systemScripts} + scriptsChange={this.scriptsChange} + wrappedComponentRef={(inst) => this.scriptsForm = inst} + /> + <Table + bordered + rowKey="uuid" + className="custom-table" + dataSource={verify.scripts} + columns={scriptsColumns} + pagination={false} + /> + </TabPane> : null} + <TabPane tab="淇℃伅鎻愮ず" key="7"> + <Form {...formItemLayout}> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> S </span> + <Button onClick={() => {this.showError('S')}} type="primary" size="small"> + 鏌ョ湅 + </Button> + </Form.Item> + </Col> + <Col span={8}> + <Form.Item label={'鍋滅暀鏃堕棿'}> + <InputNumber defaultValue={verify.stime || 2} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'stime')}} /> + </Form.Item> + </Col> + </Row> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> Y </span> + <Button onClick={() => {this.showError('Y')}} type="primary" size="small"> + 鏌ョ湅 + </Button> + </Form.Item> + </Col> + </Row> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> N </span> + <Button onClick={() => {this.showError('N')}} type="primary" size="small"> + 鏌ョ湅 + </Button> + </Form.Item> + </Col> + <Col span={8}> + <Form.Item label={'鍋滅暀鏃堕棿'}> + <InputNumber defaultValue={verify.ntime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ntime')}} /> + </Form.Item> + </Col> + </Row> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> F </span> + <Button onClick={() => {this.showError('F')}} type="primary" size="small"> + 鏌ョ湅 + </Button> + </Form.Item> + </Col> + <Col span={8}> + <Form.Item label={'鍋滅暀鏃堕棿'}> + <InputNumber defaultValue={verify.ftime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ftime')}} /> + </Form.Item> + </Col> + </Row> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> E </span> + <Button onClick={() => {this.showError('E')}} type="primary" size="small"> + 鏌ョ湅 + </Button> + </Form.Item> + </Col> + </Row> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> NM </span> + <Button onClick={() => {this.showError('NM')}} type="primary" size="small"> + 鏌ョ湅 + </Button> + </Form.Item> + </Col> + </Row> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> -1 </span> + 涓嶆彁绀� + </Form.Item> + </Col> + </Row> + </Form> + </TabPane> + </Tabs> + </div> + ) + } +} + +export default Form.create()(VerifyCard) \ No newline at end of file diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.scss b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.scss new file mode 100644 index 0000000..0831874 --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.scss @@ -0,0 +1,70 @@ +.verify-card-box { + .ant-tabs-nav-scroll { + text-align: center; + } + .ant-tabs-content { + min-height: 40vh; + } + table tr td { + word-wrap: break-word; + word-break: break-word; + } + .ant-input-number { + width: 100%; + } + .verify-form { + .sql { + .ant-col-sm-8 { + width: 10.5%; + } + .ant-col-sm-16 { + width: 89.5%; + padding-top: 4px; + } + } + .sqlfield { + .ant-form-item { + margin-bottom: 5px; + } + .ant-form-item-control { + line-height: 24px; + } + .ant-form-item-label { + line-height: 25px; + } + .ant-form-item-children { + line-height: 22px; + } + .ant-col-sm-8 { + width: 10.5%; + } + .ant-col-sm-16 { + width: 89.5%; + } + } + .add { + padding-top: 4px; + } + } + .custom-table .ant-empty { + margin: 20px 8px!important; + } + .errorval { + display: inline-block; + width: 30px; + } + .operation-btn { + display: inline-block; + font-size: 16px; + padding: 0 5px; + cursor: pointer; + } + .ant-tabs-tabpane { + position: relative; + .excel-col-add { + position: absolute; + right: 0; + top: 90px; + } + } +} \ No newline at end of file diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/uniqueform/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/uniqueform/index.jsx new file mode 100644 index 0000000..38ea99a --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/uniqueform/index.jsx @@ -0,0 +1,149 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Select, Button } from 'antd' +import './index.scss' + + +class UniqueForm extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + fields: PropTypes.array, // 琛ㄥ崟瀛楁 + uniqueChange: PropTypes.func // 淇敼鍑芥暟 + } + + state = { + editItem: null // 缂栬緫鍏冪礌 + } + + edit = (record) => { + this.setState({ + editItem: record + }) + + this.props.form.setFieldsValue({ + field: record.field.split(','), + errorCode: record.errorCode, + verifyType: record.verifyType || 'physical' + }) + } + + + handleConfirm = () => { + const { fields } = this.props + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + values.uuid = this.state.editItem ? this.state.editItem.uuid : '' + values.fieldlabel = values.field.map(field => { + let item = fields.filter(cell => cell.Column === field)[0] + let label = '' + if (item) { + label = item.Text + } + return label + }) + + values.fieldlabel = values.fieldlabel.join(',') + values.field = values.field.join(',') + + this.setState({ + editItem: null + }, () => { + this.props.uniqueChange(values) + }) + this.props.form.setFieldsValue({ + field: [], + }) + } + }) + } + + render() { + const { getFieldDecorator } = this.props.form + const { fields } = this.props + + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <Form {...formItemLayout} className="verify-form" id="verifycard1"> + <Row gutter={24}> + <Col span={8}> + <Form.Item label={'鍒楀悕'}> + {getFieldDecorator('field', { + initialValue: [], + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + '鍒楀悕!' + } + ] + })( + <Select + mode="multiple" + > + {fields.map(item => ( + <Select.Option key={item.uuid} value={item.Column}>{item.Text}</Select.Option> + ))} + </Select> + )} + </Form.Item> + </Col> + <Col span={6}> + <Form.Item label={'鎶ラ敊缂栫爜'}> + {getFieldDecorator('errorCode', { + initialValue: 'E', + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + '鎶ラ敊缂栫爜!' + } + ] + })( + <Select> + <Select.Option value="E"> E </Select.Option> + <Select.Option value="N"> N </Select.Option> + <Select.Option value="F"> F </Select.Option> + <Select.Option value="NM"> NM </Select.Option> + </Select> + )} + </Form.Item> + </Col> + <Col span={6}> + <Form.Item label={'楠岃瘉绫诲瀷'}> + {getFieldDecorator('verifyType', { + initialValue: 'physical', + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + '楠岃瘉绫诲瀷!' + } + ] + })( + <Select> + <Select.Option value="physical"> 鐗╃悊楠岃瘉 </Select.Option> + <Select.Option value="logic"> 閫昏緫楠岃瘉 </Select.Option> + </Select> + )} + </Form.Item> + </Col> + <Col span={4} className="add"> + <Button onClick={this.handleConfirm} className="mk-green"> + 淇濆瓨 + </Button> + </Col> + </Row> + </Form> + ) + } +} + +export default Form.create()(UniqueForm) \ No newline at end of file diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/uniqueform/index.scss b/src/templates/sharecomponent/actioncomponent/verifyexcelin/uniqueform/index.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/uniqueform/index.scss diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.jsx new file mode 100644 index 0000000..049e657 --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.jsx @@ -0,0 +1,127 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Button, Input, InputNumber } from 'antd' +import './index.scss' + +class UniqueForm extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + columns: PropTypes.array, // 鍒楀悕闆嗗悎 + columnChange: PropTypes.func // 淇敼鍑芥暟 + } + + state = { + editItem: null // 缂栬緫鍏冪礌 + } + + edit = (record) => { + this.setState({ + editItem: record + }) + + this.props.form.setFieldsValue({ + Column: record.Column, + Text: record.Text, + Width: record.Width, + }) + } + + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + values.uuid = this.state.editItem ? this.state.editItem.uuid : '' + + this.props.columnChange(values) + this.setState({ + editItem: null + }) + this.props.form.setFieldsValue({ + Column: '', + Text: '', + Width: 20, + }) + } + }) + } + + render() { + const { getFieldDecorator } = this.props.form + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <Form {...formItemLayout} className="verify-form"> + <Row gutter={24}> + <Col span={7}> + <Form.Item label={'Column'}> + {getFieldDecorator('Column', { + initialValue: '', + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + 'Column!' + } + ] + })(<Input placeholder="" autoComplete="off" />)} + </Form.Item> + </Col> + <Col span={7}> + <Form.Item label={'Text'}> + {getFieldDecorator('Text', { + initialValue: '', + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + 'Text!' + } + ] + })(<Input placeholder="" autoComplete="off" />)} + </Form.Item> + </Col> + <Col span={7}> + <Form.Item label={'Width'}> + {getFieldDecorator('Width', { + initialValue: 20, + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + 'Width!' + } + ] + })(<InputNumber min={5} max={200} precision={0} />)} + </Form.Item> + </Col> + <Col span={3} className="add"> + <Button onClick={this.handleConfirm} type="primary" className="mk-green"> + 淇濆瓨 + </Button> + </Col> + {/* <Col span={7}> + <Form.Item label={'绫诲瀷'}> + {getFieldDecorator('type', { + initialValue: 'text' + })( + <Select onChange={this.typeChange}> + <Select.Option value="text"> text </Select.Option> + <Select.Option value="number"> number </Select.Option> + </Select> + )} + </Form.Item> + </Col> */} + </Row> + </Form> + ) + } +} + +export default Form.create()(UniqueForm) \ No newline at end of file diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.scss b/src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/columnform/index.scss diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx new file mode 100644 index 0000000..cd33cc4 --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx @@ -0,0 +1,339 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Tabs, Row, Col, Button, Table, Popconfirm, Icon, notification, Modal, message, InputNumber } from 'antd' + +import Utils from '@/utils/utils.js' + +import ColumnForm from './columnform' +import './index.scss' + +const { TabPane } = Tabs + +class VerifyCard extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + card: PropTypes.object, + } + + state = { + verify: {}, + excelColumns: [ + { + title: 'Column', + dataIndex: 'Column', + width: '25%' + }, + { + title: 'Text', + dataIndex: 'Text', + width: '25%' + }, + { + title: 'Width', + dataIndex: 'Width', + width: '25%' + }, + { + title: '鎿嶄綔', + align: 'center', + dataIndex: 'operation', + render: (text, record) => + ( + <div> + <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'columns')} style={{color: '#1890ff'}}><Icon type="edit" /></span> + <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'columns', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span> + <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'columns', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> + <Popconfirm + title={this.props.dict['header.form.query.delete']} + okText={this.props.dict['model.confirm']} + cancelText={this.props.dict['header.cancel']} + onConfirm={() => this.handleDelete(record, 'columns') + }> + <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span> + </Popconfirm> + </div> + ) + } + ] + } + + UNSAFE_componentWillMount() { + let _verify = this.props.card.verify || {} + + let _columns = _verify.columns || [] + _columns = _columns.map(col => { + col.Width = col.Width || 20 + + return col + }) + + this.setState({ + verify: { + ..._verify, + columns: _columns, + } + }) + } + + columnChange = (values) => { + let verify = JSON.parse(JSON.stringify(this.state.verify)) + + if (values.uuid) { + verify.columns = verify.columns.map(item => { + if (item.uuid === values.uuid) { + return values + } else { + return item + } + }) + } else { + values.uuid = Utils.getuuid() + verify.columns.push(values) + } + + this.setState({ + verify: verify + }) + } + + handleDelete = (record, type) => { + const { verify } = this.state + + verify.columns = verify.columns.filter(item => item.uuid !== record.uuid) + + this.setState({ verify: verify }) + } + + handleEdit = (record, type) => { + this.columnForm.edit(record) + + let node = document.getElementById('verify-excelout-box-tab').parentNode + + if (node && node.scrollTop) { + let inter = Math.ceil(node.scrollTop / 10) + + let timer = setInterval(() => { + if (node.scrollTop - inter > 0) { + node.scrollTop = node.scrollTop - inter + } else { + node.scrollTop = 0 + clearInterval(timer) + } + }, 10) + } + } + + handleUpDown = (record, type, direction) => { + let verify = JSON.parse(JSON.stringify(this.state.verify)) + let index = 0 + + verify.columns = verify.columns.filter((item, i) => { + if (item.uuid === record.uuid) { + index = i + } + + return item.uuid !== record.uuid + }) + if ((index === 0 && direction === 'up') || (index === verify.columns.length && direction === 'down')) { + return + } + + if (direction === 'up') { + verify.columns.splice(index - 1, 0, record) + } else { + verify.columns.splice(index + 1, 0, record) + } + + this.setState({ + verify: verify + }) + } + + showError = (errorType) => { + if (errorType === 'S') { + notification.success({ + top: 92, + message: '鎵ц鎴愬姛锛�', + duration: 2 + }) + } else if (errorType === 'Y') { + Modal.success({ + title: '鎵ц鎴愬姛锛�' + }) + } else if (errorType === 'F') { + notification.error({ + className: 'notification-custom-error', + top: 92, + message: '鎵ц澶辫触锛�', + duration: 10 + }) + } else if (errorType === 'N') { + notification.error({ + top: 92, + message: '鎵ц澶辫触锛�', + duration: 10 + }) + } else if (errorType === 'E') { + Modal.error({ + title: '鎵ц澶辫触锛�' + }) + } else if (errorType === 'NM') { + message.error('鎵ц澶辫触锛�') + } + } + + timeChange = (val, type) => { + const { verify } = this.state + + this.setState({ + verify: {...verify, [type]: val} + }) + } + + handleConfirm = () => { + let verify = JSON.parse(JSON.stringify(this.state.verify)) + + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + let _cols = verify.columns.map(col => col.Column) + let _vcols = Array.from(new Set(_cols)) + + if (_cols.length > _vcols.length) { + notification.warning({ + top: 92, + message: 'Excel鍒楀瓧娈靛悕锛屼笉鍙噸澶�!', + duration: 5 + }) + + return + } + + resolve(verify) + }) + } + + render() { + const { verify, excelColumns } = this.state + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <div id="verify-excelout-box-tab"> + <Tabs defaultActiveKey="1" className="verify-card-box" onChange={this.tabchange}> + <TabPane tab="Excel瀵煎嚭鍒�" key="1"> + <ColumnForm + dict={this.props.dict} + columnChange={this.columnChange} + wrappedComponentRef={(inst) => this.columnForm = inst} + /> + <Table + bordered + rowKey="uuid" + className="custom-table" + dataSource={verify.columns} + columns={excelColumns} + pagination={false} + /> + </TabPane> + <TabPane tab="淇℃伅鎻愮ず" key="7"> + <Form {...formItemLayout}> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> S </span> + <Button onClick={() => {this.showError('S')}} type="primary" size="small"> + 鏌ョ湅 + </Button> + </Form.Item> + </Col> + <Col span={8}> + <Form.Item label={'鍋滅暀鏃堕棿'}> + <InputNumber defaultValue={verify.stime || 2} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'stime')}} /> + </Form.Item> + </Col> + </Row> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> Y </span> + <Button onClick={() => {this.showError('Y')}} type="primary" size="small"> + 鏌ョ湅 + </Button> + </Form.Item> + </Col> + </Row> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> N </span> + <Button onClick={() => {this.showError('N')}} type="primary" size="small"> + 鏌ョ湅 + </Button> + </Form.Item> + </Col> + <Col span={8}> + <Form.Item label={'鍋滅暀鏃堕棿'}> + <InputNumber defaultValue={verify.ntime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ntime')}} /> + </Form.Item> + </Col> + </Row> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> F </span> + <Button onClick={() => {this.showError('F')}} type="primary" size="small"> + 鏌ョ湅 + </Button> + </Form.Item> + </Col> + <Col span={8}> + <Form.Item label={'鍋滅暀鏃堕棿'}> + <InputNumber defaultValue={verify.ftime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ftime')}} /> + </Form.Item> + </Col> + </Row> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> E </span> + <Button onClick={() => {this.showError('E')}} type="primary" size="small"> + 鏌ョ湅 + </Button> + </Form.Item> + </Col> + </Row> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> NM </span> + <Button onClick={() => {this.showError('NM')}} type="primary" size="small"> + 鏌ョ湅 + </Button> + </Form.Item> + </Col> + </Row> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> -1 </span> + 涓嶆彁绀� + </Form.Item> + </Col> + </Row> + </Form> + </TabPane> + </Tabs> + </div> + ) + } +} + +export default Form.create()(VerifyCard) \ No newline at end of file diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.scss b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.scss new file mode 100644 index 0000000..017545b --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.scss @@ -0,0 +1,62 @@ +.verify-card-box { + .ant-tabs-nav-scroll { + text-align: center; + } + .ant-tabs-content { + min-height: 40vh; + } + table tr td { + word-wrap: break-word; + word-break: break-word; + } + .ant-input-number { + width: 100%; + } + .verify-form { + .sql { + .ant-col-sm-8 { + width: 10.5%; + } + .ant-col-sm-16 { + width: 89.5%; + padding-top: 4px; + } + } + .sqlfield { + .ant-form-item { + margin-bottom: 5px; + } + .ant-form-item-control { + line-height: 24px; + } + .ant-form-item-label { + line-height: 25px; + } + .ant-form-item-children { + line-height: 22px; + } + .ant-col-sm-8 { + width: 10.5%; + } + .ant-col-sm-16 { + width: 89.5%; + } + } + .add { + padding-top: 4px; + } + } + .custom-table .ant-empty { + margin: 20px 8px!important; + } + .errorval { + display: inline-block; + width: 30px; + } + .operation-btn { + display: inline-block; + font-size: 16px; + padding: 0 5px; + cursor: pointer; + } +} \ No newline at end of file diff --git a/src/templates/sharecomponent/actioncomponent/verifyprint/editable/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyprint/editable/index.jsx new file mode 100644 index 0000000..e328414 --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/verifyprint/editable/index.jsx @@ -0,0 +1,241 @@ +import React, {Component} from 'react' +import { Table, Input, Button, Popconfirm, Form, Icon } from 'antd' +import Utils from '@/utils/utils.js' +import './index.scss' + +const EditableContext = React.createContext() + +const EditableRow = ({ form, index, ...props }) => ( + <EditableContext.Provider value={form}> + <tr {...props} /> + </EditableContext.Provider> +) + +const EditableFormRow = Form.create()(EditableRow) + +class EditableCell extends Component { + state = { + editing: false + } + + toggleEdit = () => { + const editing = !this.state.editing + this.setState({ editing }, () => { + if (editing && this.input && this.input.select) { + this.input.select() + } else if (editing && this.input && this.input.focus) { + this.input.focus() + } + }) + } + + save = e => { + const { record, handleSave } = this.props + this.form.validateFields((error, values) => { + handleSave({ ...record, ...values }) + if (error && error[e.currentTarget.id]) { + return + } + this.toggleEdit() + }) + } + + renderCell = form => { + this.form = form + const { children, dataIndex, record } = this.props + const { editing } = this.state + + return editing ? ( + <Form.Item style={{ margin: 0 }}> + {form.getFieldDecorator(dataIndex, { + rules: [ + { + required: true, + message: 'NOT NULL.', + }, + ], + initialValue: record[dataIndex] + })(<Input ref={node => (this.input = node)} autoComplete="off" onPressEnter={this.save} onBlur={this.save} />)} + </Form.Item> + ) : ( + <div + className="editable-cell-value-wrap" + onClick={this.toggleEdit} + > + {children} + </div> + ) + } + + render() { + const { + editable, + dataIndex, + title, + record, + index, + handleSave, + children, + ...restProps + } = this.props + return ( + <td {...restProps}> + {editable ? ( + <EditableContext.Consumer style={{padding: 0}}>{this.renderCell}</EditableContext.Consumer> + ) : ( + children + )} + </td> + ) + } +} + +class EditTable extends Component { + constructor(props) { + super(props) + + let columns = [ + { + title: 'Value', + dataIndex: 'Value', + width: '40%', + editable: true + }, + { + title: 'Text', + dataIndex: 'Text', + width: '40%', + editable: true + }, + { + title: '鎿嶄綔', + align: 'center', + dataIndex: 'operation', + render: (text, record) => + this.state.dataSource.length >= 1 ? ( + <div> + <span className="operation-btn" title={props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span> + <span className="operation-btn" title={props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> + <Popconfirm + title={props.dict['header.form.query.delete']} + okText={props.dict['model.confirm']} + cancelText={props.dict['header.cancel']} + onConfirm={() => this.handleDelete(record.key) + }> + <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span> + </Popconfirm> + </div> + ) : null, + } + ] + + this.state = { + columns: columns, + dataSource: props.data, + count: props.data.length, + linkSubFields: props.linkSubFields + } + } + + handleUpDown = (record, direction) => { + const { dataSource } = this.state + let index = 0 + + let _data = dataSource.filter((item, i) => { + if (item.key === record.key) { + index = i + } + + return item.key !== record.key + }) + if ((index === 0 && direction === 'up') || (index === dataSource.length - 1 && direction === 'down')) { + return + } + + if (direction === 'up') { + _data.splice(index - 1, 0, record) + } else { + _data.splice(index + 1, 0, record) + } + + this.setState({ + dataSource: _data + }) + } + + handleDelete = key => { + const dataSource = [...this.state.dataSource] + this.setState({ dataSource: dataSource.filter(item => item.key !== key) }) + } + + handleAdd = () => { + const { count, dataSource } = this.state + const newData = { + key: Utils.getuuid(), + Value: `${count}`, + Text: `${count}` + } + + this.setState({ + dataSource: [...dataSource, newData], + count: count + 1 + }) + } + + handleSave = row => { + const newData = [...this.state.dataSource] + const index = newData.findIndex(item => row.key === item.key) + const item = newData[index] + newData.splice(index, 1, { + ...item, + ...row + }) + this.setState({ dataSource: newData }) + } + + UNSAFE_componentWillReceiveProps () { + + } + + render() { + const { dataSource } = this.state + const components = { + body: { + row: EditableFormRow, + cell: EditableCell + } + } + const columns = this.state.columns.map(col => { + if (!col.editable) { + return col + } + return { + ...col, + onCell: record => ({ + record, + editable: col.editable, + dataIndex: col.dataIndex, + title: col.title, + handleSave: this.handleSave, + }) + } + }) + return ( + <div className="print-verify-edit-table"> + <Button onClick={this.handleAdd} className="add-row mk-green"> + 娣诲姞 + </Button> + <Table + components={components} + rowClassName={() => 'editable-row'} + bordered + dataSource={dataSource} + columns={columns} + pagination={false} + /> + </div> + ) + } +} + +export default EditTable \ No newline at end of file diff --git a/src/templates/sharecomponent/actioncomponent/verifyprint/editable/index.scss b/src/templates/sharecomponent/actioncomponent/verifyprint/editable/index.scss new file mode 100644 index 0000000..8b237cd --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/verifyprint/editable/index.scss @@ -0,0 +1,48 @@ +.print-verify-edit-table { + margin: 10px 20px; + .add-row { + position: absolute; + z-index: 1; + right: 32px; + top: -40px; + } + .ant-table-thead > tr > th { + padding: 10px 16px; + } + .ant-table-tbody > tr > td { + padding: 0px 16px; + } + .editable-cell-value-wrap { + cursor: pointer; + height: 40px; + width: 500px; + display: table-cell; + vertical-align: middle; + word-wrap: break-word; + word-break: break-word; + .ant-input { + height: 30px; + padding: 0 11px; + } + } + .ant-form-item-control-wrapper { + width: 100%; + } + .ant-table-placeholder { + padding: 5px 16px; + .ant-empty-normal { + margin: 0; + } + } + .operation-btn { + margin-right: 10px; + cursor: pointer; + } + .ant-table-content { + .ant-table-placeholder { + .ant-empty.ant-empty-normal { + margin: 50px 8px; + } + } + } +} diff --git a/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx new file mode 100644 index 0000000..452d7ed --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx @@ -0,0 +1,461 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Tabs, Row, Col, Button, notification, Modal, message, InputNumber, Input, Select, Radio } from 'antd' +import moment from 'moment' +import {UnControlled as CodeMirror} from 'react-codemirror2' +import 'codemirror/mode/javascript/javascript' + +import Api from '@/api' +import Utils from '@/utils/utils.js' +import EditTable from './editable' + +import 'codemirror/lib/codemirror.css' +// import 'codemirror/theme/solarized.css' +import 'codemirror/theme/cobalt.css' + +import './index.scss' + +const { TabPane } = Tabs +let _printFunc = null // antd 鏃犳硶鑾峰彇 codemirror 鍐呭锛屾墜鍔ㄦ帶鍒� + +class VerifyCard extends Component { + static propTpyes = { + floor: PropTypes.any, // 鏄惁涓哄瓙琛� + btnTab: PropTypes.any, // 琛ㄥ崟鏍囩椤碉紙鎸夐挳锛夊弬鏁� + config: PropTypes.any, // 琛ㄥ崟鏍囩椤靛弬鏁� + dict: PropTypes.object, // 瀛楀吀椤� + card: PropTypes.object, + columns: PropTypes.array + } + + state = { + verify: {}, + templates: [], + selectimg: '', + printMode: 'normal' + } + + UNSAFE_componentWillMount() { + let _verify = this.props.card.verify || {} + + _verify.Template = _verify.Template || '' + _verify.printerTypeList = _verify.printerTypeList || [] + _verify.linkType = _verify.linkType || 'system' + _verify.printMode = _verify.printMode || 'normal' + + this.setState({ + verify: _verify, + linkType: _verify.linkType, + printMode: _verify.printMode, + printFunc: _verify.printFunc || '// Function(data, form, printer, notification) data-鎵撳嵃鏁版嵁鍒楄〃锛宖orm-琛ㄥ崟淇℃伅锛堜笉瀛樺湪鏃朵负{}锛夛紝printer-鎵撳嵃璁剧疆锛宯otification-淇℃伅鎻愮ず鎺т欢' + }) + + _printFunc = _verify.printFunc || '' + } + + componentDidMount() { + let _sql = `select PrintTempNO,Images,PrintTempNO+PrintTempName as PN from sPrintTemplate + where appkey= @appkey@ and Deleted=0 + union select ID,Images,a.PrintTempNO+PrintTempName as PN + from (select * from sPrintTemplate where appkey= '' and Deleted=0 ) a + left join (select PrintTempNO from sPrintTemplate where appkey= @appkey@ and Deleted=0 ) b + on a.PrintTempNO=b.PrintTempNO + left join (select Srcid from sPrintTemplate_Log where appkey='' and apicode= @appkey@ and Deleted=0 ) c + on a.ID=c.Srcid where b.PrintTempNO is null and c.Srcid is null` + + let param = { + func: 'sPC_Get_SelectedList', + LText: Utils.formatOptions(_sql), + obj_name: 'data', + arr_field: 'PN,PrintTempNO,Images' + } + + param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' + param.secretkey = Utils.encrypt(param.LText, param.timestamp) + + Api.getSystemConfig(param).then(res => { + if (res.status) { + let temps = res.data.map(temp => { + return { + value: temp.PrintTempNO, + text: temp.PN, + img: temp.Images + } + }) + + let Template = this.state.verify.Template + let selectimg = '' + let selectTemp = temps.filter(temp => temp.value === Template)[0] + + if (!selectTemp) { + Template = '' + } else { + selectimg = selectTemp.img + } + + this.setState({ + selectimg: selectimg, + templates: temps, + verify: { + ...this.state.verify, + Template: Template + } + }) + } else { + notification.warning({ + top: 92, + message: res.message, + duration: 5 + }) + } + }) + } + + showError = (errorType) => { + if (errorType === 'S') { + notification.success({ + top: 92, + message: '鎵ц鎴愬姛锛�', + duration: 2 + }) + } else if (errorType === 'Y') { + Modal.success({ + title: '鎵ц鎴愬姛锛�' + }) + } else if (errorType === 'F') { + notification.error({ + className: 'notification-custom-error', + top: 92, + message: '鎵ц澶辫触锛�', + duration: 10 + }) + } else if (errorType === 'N') { + notification.error({ + top: 92, + message: '鎵ц澶辫触锛�', + duration: 10 + }) + } else if (errorType === 'E') { + Modal.error({ + title: '鎵ц澶辫触锛�' + }) + } else if (errorType === 'NM') { + message.error('鎵ц澶辫触锛�') + } + } + + timeChange = (val, type) => { + const { verify } = this.state + + this.setState({ + verify: {...verify, [type]: val} + }) + } + + changeTemplate = (val) => { + const { templates } = this.state + + let temp = templates.filter(temp => temp.value === val)[0] + + this.setState({ + selectimg: temp.img + }) + } + + handleConfirm = () => { + const { verify } = this.state + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + let _verify = {...verify, ...values, printFunc: _printFunc} + + if (this.refs.editTable && this.refs.editTable.state) { + let printTypes = this.refs.editTable.state.dataSource + + let emptys = printTypes.filter(item => !item.Value || !item.Text) + let valMap = new Map() + let isvalid = true + + printTypes.forEach(item => { + if (valMap.has(item.Value)) { + isvalid = false + } else { + valMap.set(item.Value, item.Text) + } + }) + + if (emptys.length > 0) { + notification.warning({ + top: 92, + message: '鎵撳嵃绫诲瀷琛ㄦ牸涓璙alue銆乀ext瀛楁涓嶅彲涓虹┖!', + duration: 5 + }) + return + } else if (!isvalid) { + notification.warning({ + top: 92, + message: '鎵撳嵃绫诲瀷琛ㄦ牸涓璙alue瀛楁涓嶅彲閲嶅!', + duration: 5 + }) + return + } + + _verify.printerTypeList = printTypes + } + + resolve(_verify) + } else { + notification.warning({ + top: 92, + message: '閾炬帴鍦板潃涓庢墦鍗版ā鏉夸笉鍙负绌�!', + duration: 5 + }) + } + }) + }) + } + + changePrintMode = (e) => { + let value = e.target.value + + this.setState({ + printMode: value + }) + } + + changeLinkType = (e) => { + let value = e.target.value + + this.setState({ + linkType: value + }, () => { + if (value === 'system') { + this.props.form.setFieldsValue({ + linkUrl: '127.0.0.1:13529' + }) + } + }) + } + + render() { + const { getFieldDecorator } = this.props.form + + const { verify, linkType, printMode, printFunc } = this.state + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <div id="verify-card-box-tab"> + <Tabs defaultActiveKey="1" className="verify-card-print-box" onChange={this.tabchange}> + <TabPane tab="鎵撳嵃楠岃瘉" key="1"> + <Form {...formItemLayout}> + <Row gutter={24}> + <Col span={8}> + <Form.Item label={'鎵撳嵃妯″紡'}> + {getFieldDecorator('printMode', { + initialValue: printMode || 'normal' + })( + <Radio.Group onChange={this.changePrintMode}> + <Radio value="normal">鏍囧噯</Radio> + <Radio value="custom">鑷畾涔�</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + <Col span={8}> + <Form.Item label={'閾炬帴绫诲瀷'}> + {getFieldDecorator('linkType', { + initialValue: linkType || 'system' + })( + <Radio.Group onChange={this.changeLinkType}> + <Radio value="system">绯荤粺</Radio> + <Radio value="custom">鑷畾涔�</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + <Col span={8}> + <Form.Item label={'閾炬帴鍦板潃'}> + {getFieldDecorator('linkUrl', { + initialValue: verify.linkUrl || '127.0.0.1:13529', + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '閾炬帴鍦板潃!' + } + ] + })(<Input placeholder="" autoComplete="off" disabled={linkType === 'system'} />)} + </Form.Item> + </Col> + {printMode === 'custom' ? <Col span={24}> + <Form.Item label={'澶勭悊鍑芥暟'} className="printFunc"> + {getFieldDecorator('printFunc', { + initialValue: printFunc || '', + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '澶勭悊鍑芥暟!' + } + ] + })( + <CodeMirror + className="code-mirror-area" + options={{ + mode: 'text/javascript', + theme: 'cobalt', + lineNumbers: true, + lineWrapping: true + }} + onBeforeChange={() => {}} + onBlur={(editor) => { + _printFunc = editor.getValue() + }} + /> + )} + </Form.Item> + </Col> : null} + {printMode === 'normal' ? <Col span={8}> + <Form.Item label={'鎵撳嵃妯℃澘'}> + {getFieldDecorator('Template', { + initialValue: verify.Template || '', + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + '鎵撳嵃妯℃澘!' + } + ] + })( + <Select onChange={this.changeTemplate}> + {this.state.templates.map((option, key) => + <Select.Option id={key} key={key} value={option.value}> + {option.text} + </Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> : null } + {printMode === 'normal' ? <Col span={8} offset={8}> + <img className="legend" src={this.state.selectimg} alt=""/> + </Col> : null } + </Row> + </Form> + </TabPane> + <TabPane tab="鎵撳嵃绫诲瀷" key="2"> + <Form {...formItemLayout}> + <Row gutter={24}> + <Col span={24} className="print-tip"> + <Form.Item label={'鎻愮ず'}> + 濡傛灉姝ゆ寜閽殑鎵撳嵃鍔熻兘娑夊強澶氱鎵撳嵃绫诲瀷锛屼笖涓嶅悓绫诲瀷闇�瑕佽缃笉鍚岀殑鎵撳嵃鏈烘椂锛屽彲浠ユ坊鍔犳墦鍗扮被鍨嬫帶鍒朵俊鎭紝 + 璁剧疆瀹屾垚鍚庯紝鐢ㄦ埛鍙拡瀵逛笉鍚岀殑绫诲瀷璁剧疆瀵瑰簲鐨勬墦鍗版満銆傛敞锛氬湪杩斿洖鏁版嵁椤跺眰缁撴瀯涓坊鍔� printType銆乸rintCount銆乼emplateID 瀛楁锛屽彲鍒嗗埆鎺у埗鎵撳嵃绫诲瀷銆佹墦鍗版暟閲忓拰鎵撳嵃妯℃澘銆� + </Form.Item> + </Col> + <Col span={24}> + <EditTable data={verify.printerTypeList} dict={this.props.dict} ref="editTable"/> + </Col> + </Row> + </Form> + </TabPane> + <TabPane tab="淇℃伅鎻愮ず" key="7"> + <Form {...formItemLayout}> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> S </span> + <Button onClick={() => {this.showError('S')}} type="primary" size="small"> + 鏌ョ湅 + </Button> + </Form.Item> + </Col> + <Col span={8}> + <Form.Item label={'鍋滅暀鏃堕棿'}> + <InputNumber defaultValue={verify.stime || 2} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'stime')}} /> + </Form.Item> + </Col> + </Row> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> Y </span> + <Button onClick={() => {this.showError('Y')}} type="primary" size="small"> + 鏌ョ湅 + </Button> + </Form.Item> + </Col> + </Row> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> N </span> + <Button onClick={() => {this.showError('N')}} type="primary" size="small"> + 鏌ョ湅 + </Button> + </Form.Item> + </Col> + <Col span={8}> + <Form.Item label={'鍋滅暀鏃堕棿'}> + <InputNumber defaultValue={verify.ntime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ntime')}} /> + </Form.Item> + </Col> + </Row> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> F </span> + <Button onClick={() => {this.showError('F')}} type="primary" size="small"> + 鏌ョ湅 + </Button> + </Form.Item> + </Col> + <Col span={8}> + <Form.Item label={'鍋滅暀鏃堕棿'}> + <InputNumber defaultValue={verify.ftime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ftime')}} /> + </Form.Item> + </Col> + </Row> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> E </span> + <Button onClick={() => {this.showError('E')}} type="primary" size="small"> + 鏌ョ湅 + </Button> + </Form.Item> + </Col> + </Row> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> NM </span> + <Button onClick={() => {this.showError('NM')}} type="primary" size="small"> + 鏌ョ湅 + </Button> + </Form.Item> + </Col> + </Row> + <Row gutter={24}> + <Col offset={6} span={6}> + <Form.Item label={'鎻愮ず缂栫爜'}> + <span className="errorval"> -1 </span> + 涓嶆彁绀� + </Form.Item> + </Col> + </Row> + </Form> + </TabPane> + </Tabs> + </div> + ) + } +} + +export default Form.create()(VerifyCard) \ No newline at end of file diff --git a/src/templates/sharecomponent/actioncomponent/verifyprint/index.scss b/src/templates/sharecomponent/actioncomponent/verifyprint/index.scss new file mode 100644 index 0000000..6b181b0 --- /dev/null +++ b/src/templates/sharecomponent/actioncomponent/verifyprint/index.scss @@ -0,0 +1,60 @@ +.verify-card-print-box { + .ant-tabs-nav-scroll { + text-align: center; + } + .ant-tabs-content { + min-height: 40vh; + .ant-form-item { + margin-bottom: 10px; + } + } + .ant-input-disabled { + color: rgba(0, 0, 0, 0.65); + cursor: default; + } + .errorval { + display: inline-block; + width: 30px; + } + .operation-btn { + display: inline-block; + font-size: 16px; + padding: 0 5px; + cursor: pointer; + } + .legend { + width: 100%; + margin-bottom: 25px; + margin-left: -2px; + box-shadow: 0px 0px 2px #bcbcbc; + } + .printFunc { + .ant-form-item-label { + width: 10.7%; + } + .ant-form-item-control-wrapper { + width: 89.3%; + } + } + .code-mirror-area { + font-size : 14px; + line-height : 25px; + + .CodeMirror { + height: calc(100vh - 360px); + } + } + .print-tip { + margin-bottom: 25px; + .ant-form-item-label { + width: 10.5%; + line-height: 25px; + } + .ant-form-item-control-wrapper { + width: 89.5%; + .ant-form-item-children { + line-height: 25px; + } + } + } +} \ No newline at end of file diff --git a/src/templates/sharecomponent/chartgroupcomponent/chartform/index.jsx b/src/templates/sharecomponent/chartgroupcomponent/chartform/index.jsx new file mode 100644 index 0000000..0d0c26d --- /dev/null +++ b/src/templates/sharecomponent/chartgroupcomponent/chartform/index.jsx @@ -0,0 +1,379 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input, Select, InputNumber, Radio, Tooltip, Icon } from 'antd' + +import { formRule } from '@/utils/option.js' +import line1 from '@/assets/img/line1.png' +import line2 from '@/assets/img/line2.png' +import line3 from '@/assets/img/line3.png' +import line4 from '@/assets/img/line4.png' +import bar1 from '@/assets/img/bar1.png' +import bar2 from '@/assets/img/bar2.png' +import bar3 from '@/assets/img/bar3.png' +import bar4 from '@/assets/img/bar4.png' +import pie1 from '@/assets/img/pie1.png' +import pie2 from '@/assets/img/pie2.png' +import './index.scss' + +const syslegends = { + line: [ + { + uuid: 'line1', + url: line1, + options: { + shape: 'line', + coordinate: 'angle' + } + }, + { + uuid: 'line2', + url: line2, + options: { + shape: 'smooth', + coordinate: 'angle' + } + }, + { + uuid: 'line3', + url: line3, + options: { + shape: 'hv', + coordinate: 'angle' + } + }, + { + uuid: 'line4', + url: line4, + options: { + shape: 'smooth', + coordinate: 'polar' + } + } + ], + bar: [ + { + uuid: 'bar1', + url: bar1, + options: { + shape: 'rect', + adjust: 'dodge', + transpose: 'false' + } + }, + { + uuid: 'bar2', + url: bar2, + options: { + shape: 'rect', + adjust: 'dodge', + transpose: 'false' + } + }, + { + uuid: 'bar3', + url: bar3, + options: { + shape: 'rect', + adjust: 'stack', + transpose: 'false' + } + }, + { + uuid: 'bar4', + url: bar4, + options: { + shape: 'rect', + adjust: 'dodge', + transpose: 'true' + } + } + ], + pie: [ + { + uuid: 'pie1', + url: pie1, + options: { + shape: 'pie' + } + }, + { + uuid: 'pie2', + url: pie2, + options: { + shape: 'ring' + } + } + ] +} + +class ChartForm extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + MenuID: PropTypes.any, + formlist: PropTypes.any, + card: PropTypes.any, + inputSubmit: PropTypes.any // 鍥炶溅鎻愪氦浜嬩欢 + } + + state = { + formlist: null, + legends: null, + selectlegend: null + } + + UNSAFE_componentWillMount () { + const { card } = this.props + + let _type = card.chartType || 'line' + let _legends = null + let _selectlegend = null + + if (_type === 'line' || _type === 'bar' || _type === 'line') { + _legends = syslegends[_type] + _selectlegend = _legends.filter(item => item.uuid === card.modelId)[0] + + if (!_selectlegend) { + _selectlegend = _legends[0] + } + } + + this.setState({ + legends: _legends, + selectlegend: _selectlegend + }) + } + + componentDidMount () { + const { card } = this.props + + if (!card.chartType) { + try { + let _form = document.getElementById('title') + _form.select() + } catch { + console.warn('琛ㄥ崟focus澶辫触锛�') + } + } + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + typeChange = (key, value) => { + if (key === 'chartType') { + this.setState({ + legends: syslegends[value] || null, + selectlegend: syslegends[value][0] + }) + } + } + + changeSelectLegend = (item) => { + this.setState({ + selectlegend: item + }) + } + + getFields() { + const { getFieldDecorator } = this.props.form + const fields = [] + this.props.formlist.forEach((item, index) => { + if (item.hidden) return + + if (item.type === 'text') { // 鏂囨湰鎼滅储 + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} 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 + '!' + }, + { + max: formRule.input.max, + message: formRule.input.message + } + ] + })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + ) + } else if (item.type === 'number') { + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}> + <Icon type="question-circle" /> + {item.label} + </Tooltip> : item.label + }> + {getFieldDecorator(item.key, { + initialValue: item.initVal, + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.input'] + item.label + '!' + } + ] + })(<InputNumber min={item.min} max={item.max} precision={item.decimal} />)} + </Form.Item> + </Col> + ) + } else if (item.type === 'select') { // 涓嬫媺鎼滅储 + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.label}> + {getFieldDecorator(item.key, { + initialValue: item.initVal || '', + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.select'] + item.label + '!' + } + ] + })( + <Select + showSearch + disabled={!!item.readonly} + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + onChange={(value) => {this.typeChange(item.key, value)}} + getPopupContainer={() => document.getElementById('chartwinter')} + > + {item.options.map((option, index) => + <Select.Option id={`${index}`} title={option.text} key={`${index}`} value={option.value}> + {option.text} + </Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + ) + } else if (item.type === 'radio') { + 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 + '!' + } + ] + })( + <Radio.Group> + { + item.options.map(option => { + return ( + <Radio key={option.value} value={option.value}>{option.text}</Radio> + ) + }) + } + </Radio.Group> + )} + </Form.Item> + </Col> + ) + } else if (item.type === 'multiselect') { // 澶氶�� + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.label}> + {getFieldDecorator(item.key, { + initialValue: item.initVal || [] + })( + <Select + showSearch + mode="multiple" + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + > + {item.options.map((option, i) => + <Select.Option id={i} key={i} value={option.value}>{option.text}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + ) + } + }) + return fields + } + + handleConfirm = () => { + const { selectlegend } = this.state + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + let result = {...this.props.card, ...values} + + let icons = { + table: 'table', + line: 'line-chart', + bar: 'bar-chart', + pie: 'pie-chart' + } + + if (selectlegend && this.props.card.modelId !== selectlegend.uuid) { + result = {...result, ...selectlegend.options} + } + + if (selectlegend) { + result.modelId = selectlegend.uuid + } + + if (result.chartType !== 'pie' && result.Yaxis && typeof(result.Yaxis) === 'string') { + result.Yaxis = [result.Yaxis] + } else if (result.chartType === 'pie' && result.Yaxis && typeof(result.Yaxis) === 'object') { + result.Yaxis = result.Yaxis[0] || '' + } + + result.icon = icons[result.chartType] + + resolve(result) + } else { + reject(err) + } + }) + }) + } + + render() { + const { legends, selectlegend } = this.state + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 6 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 18 } + } + } + return ( + <Form {...formItemLayout} className="chart-edit-form" id="chartwinter"> + <Row gutter={24}>{this.getFields()}</Row> + {legends ? <Row gutter={24} className="chart-model-image"> + {legends.map(item => <Col span={6} key={item.uuid}> + <img onClick={() => this.changeSelectLegend(item)} src={item.url} className={selectlegend.uuid === item.uuid ? 'active' : ''} alt=""/> + </Col>)} + </Row> : null} + </Form> + ) + } +} + +export default Form.create()(ChartForm) \ No newline at end of file diff --git a/src/templates/sharecomponent/chartgroupcomponent/chartform/index.scss b/src/templates/sharecomponent/chartgroupcomponent/chartform/index.scss new file mode 100644 index 0000000..a1778ca --- /dev/null +++ b/src/templates/sharecomponent/chartgroupcomponent/chartform/index.scss @@ -0,0 +1,25 @@ +.chart-edit-form { + min-height: 190px; + .ant-form-item { + .ant-input-number { + width: 100%; + } + } + .anticon-question-circle { + color: #c49f47; + position: relative; + left: -3px; + } + .chart-model-image { + img { + max-width: 100%; + cursor: pointer; + border: 1px solid #ebedf0; + transition: all .3s; + } + img.active { + background-color: rgba(135,59,244,.1); + border-color: #873bf4; + } + } +} diff --git a/src/templates/sharecomponent/chartgroupcomponent/dragchartview/card.jsx b/src/templates/sharecomponent/chartgroupcomponent/dragchartview/card.jsx new file mode 100644 index 0000000..b44ab02 --- /dev/null +++ b/src/templates/sharecomponent/chartgroupcomponent/dragchartview/card.jsx @@ -0,0 +1,48 @@ +import React from 'react' +import { useDrag, useDrop } from 'react-dnd' +import { Icon } from 'antd' +import './index.scss' + +const Card = ({ id, card, moveCard, findCard, editCard, delCard }) => { + const originalIndex = findCard(id).index + + const [{ isDragging }, drag] = useDrag({ + item: { type: 'chart', id, originalIndex }, + collect: monitor => ({ + isDragging: monitor.isDragging(), + }), + }) + + const opacity = isDragging ? 0 : 1 + + const edit = () => { + editCard(id) + } + + const del = () => { + delCard(id) + } + + const [, drop] = useDrop({ + accept: 'chart', + canDrop: () => true, + hover({ id: draggedId }) { + if (!draggedId) return + if (draggedId !== id) { + const { index: overIndex } = findCard(id) + moveCard(draggedId, overIndex) + } + } + }) + + return ( + <div className="chart-tab" style={{ opacity: opacity}}> + <div ref={node => drag(drop(node))}> + <Icon type={card.icon} /> + </div> + <Icon className="edit" title="缂栬緫" type="edit" onClick={edit} /> + {card.chartType !== 'table' ? <Icon className="edit close" title="鍒犻櫎" type="close" onClick={del} /> : null} + </div> + ) +} +export default Card diff --git a/src/templates/sharecomponent/chartgroupcomponent/dragchartview/index.jsx b/src/templates/sharecomponent/chartgroupcomponent/dragchartview/index.jsx new file mode 100644 index 0000000..93d800b --- /dev/null +++ b/src/templates/sharecomponent/chartgroupcomponent/dragchartview/index.jsx @@ -0,0 +1,74 @@ +import React, { useState } from 'react' +import { useDrop } from 'react-dnd' +import { is, fromJS } from 'immutable' +import update from 'immutability-helper' +import { Tabs } from 'antd' +import Card from './card' +import './index.scss' + +const { TabPane } = Tabs + +const Container = ({activeKey, list, expand, handleList, handleMenu, deleteMenu, changetabview }) => { + const [cards, setCards] = useState(list) + const moveCard = (id, atIndex) => { + const { card, index } = findCard(id) + 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) + handleMenu(card) + } + + const delCard = id => { + const { card } = findCard(id) + deleteMenu(card) + } + + const changetab = id => { + if (activeKey === 'all') return + + changetabview(id) + } + + const [, drop] = useDrop({ + accept: 'chart' + }) + + return ( + <div ref={drop} className="ant-row chart-edit-tab-box"> + <Tabs activeKey={!expand ? activeKey : ''} onChange={changetab}> + {cards.map(card => ( + <TabPane tab={ + <div key={card.uuid}> + <Card + key={card.uuid} + id={card.uuid} + card={card} + moveCard={moveCard} + editCard={editCard} + delCard={delCard} + findCard={findCard} + /> + </div> + } key={card.uuid}></TabPane> + ))} + </Tabs> + </div> + ) +} +export default Container diff --git a/src/templates/sharecomponent/chartgroupcomponent/dragchartview/index.scss b/src/templates/sharecomponent/chartgroupcomponent/dragchartview/index.scss new file mode 100644 index 0000000..91c831e --- /dev/null +++ b/src/templates/sharecomponent/chartgroupcomponent/dragchartview/index.scss @@ -0,0 +1,41 @@ +.chart-edit-tab-box { + padding-right: 100px; + display: inline-block; + + .ant-tabs-bar { + border: 0; + } + .ant-tabs-tab { + margin: 0px; + padding: 0px; + } + .ant-tabs-ink-bar { + display: none!important; + } + .chart-tab { + position: relative; + width: 40px; + padding-top: 15px; + text-align: center; + display: inline-block; + + .edit { + position: absolute; + left: 0; + top: 0px; + color: #1890ff; + cursor: pointer; + display: none; + } + .edit.close { + left: 20px; + color: #ff4d4f; + } + } + + .chart-tab:hover { + .edit { + display: inline-block; + } + } +} \ No newline at end of file diff --git a/src/templates/sharecomponent/chartgroupcomponent/index.jsx b/src/templates/sharecomponent/chartgroupcomponent/index.jsx new file mode 100644 index 0000000..23be259 --- /dev/null +++ b/src/templates/sharecomponent/chartgroupcomponent/index.jsx @@ -0,0 +1,234 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Modal } from 'antd' + +import Utils from '@/utils/utils.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import { getChartViewForm } from '@/templates/zshare/formconfig' + +import ChartForm from './chartform' +import DragChartView from './dragchartview' +import './index.scss' + +const { confirm } = Modal + +// **鎮茶鑰呭線寰�姝g‘锛屼箰瑙傝�呭線寰�鎴愬姛 +class ChartGroupComponent extends Component { + static propTpyes = { + config: PropTypes.object, // 鑿滃崟閰嶇疆淇℃伅 + sysRoles: PropTypes.array, // 瑙掕壊鍒楄〃锛岄粦鍚嶅崟浣跨敤 + updatechartgroup: PropTypes.func // 鍥捐〃鏇存柊 + } + + state = { + dict: (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS, + chartlist: null, // 鍥捐〃闆� + card: null, // 缂栬緫涓厓绱� + formlist: null, // 琛ㄥ崟淇℃伅 + modaltype: '', // 妯℃�佹鎺у埗 + chartview: null // 娲诲姩鍥捐〃 + } + + /** + * @description 鍥捐〃鍒濆鍖� + */ + UNSAFE_componentWillMount () { + this.setState({ + chartlist: fromJS(this.props.config.charts).toJS(), + chartview: this.props.config.charts[0].uuid + }) + } + + /** + * @description 鍥捐〃淇℃伅淇敼鏃舵洿鏂� chartlist + */ + UNSAFE_componentWillReceiveProps (nextProps) { + const { chartlist } = this.state + + if (nextProps.config && nextProps.config.charts && !is(fromJS(nextProps.config.charts), fromJS(chartlist))) { + this.setState({ + chartlist: fromJS(nextProps.config.charts).toJS() + }) + } + } + + /** + * @description 鍥捐〃椤哄簭璋冩暣锛屾垨鎷栨嫿娣诲姞 + */ + handleList = (list) => { + const { config } = this.props + + this.setState({chartlist: list}) + this.props.updatechartgroup({...config, charts: list}, this.state.chartview) + } + + /** + * @description 鍙栨秷淇濆瓨锛屽叧闂ā鎬佹 + */ + editModalCancel = () => { + this.setState({ + card: null, + modaltype: '' + }) + } + + /** + * @description 娣诲姞鎴栦慨鏀瑰浘琛� + */ + handleChart = (item) => { + let _type = 'editChart' + if (!item) { + _type = 'addChart' + item = { + uuid: Utils.getuuid(), + label: '', + title: '', + chartType: 'line', + icon: 'line-chart', + Hide: 'false', + blacklist: [] + } + } + + this.setState({ + card: item, + modaltype: _type, + formlist: getChartViewForm(item, this.props.sysRoles) + }) + } + + /** + * @description 鍥捐〃淇℃伅淇敼鍚庯紝鎻愪氦淇濆瓨 + */ + submitChart = () => { + const { config } = this.props + const { modaltype } = this.state + let _chartlist = fromJS(this.state.chartlist).toJS() + let _chartview = this.state.chartview + + this.chartFormRef.handleConfirm().then(res => { + if (modaltype === 'addChart') { + _chartlist.push(res) + _chartview = res.uuid + } else { + _chartlist = _chartlist.map(item => { + if (item.uuid === res.uuid) { + if (!is(fromJS(item), fromJS(res))) { + let _element = document.getElementById(res.uuid) + if (_element) { + _element.innerHTML = '' + } + } + return res + } + return item + }) + } + + this.setState({ + card: null, + chartview: _chartview, + modaltype: '', + chartlist: _chartlist + }) + + this.props.updatechartgroup({...config, charts: _chartlist}, _chartview) + }) + } + + /** + * @description 鍥捐〃灞曞紑鏀惰捣鍒囨崲 + */ + onChartChange = (e) => { + const { config } = this.props + e.stopPropagation() + + this.props.updatechartgroup({...config, expand: !config.expand}, this.state.chartview) + } + + /** + * @description 鍥捐〃鍒犻櫎 + */ + deletechart = (plot) => { + const { config } = this.props + const { dict } = this.state + let _this = this + + confirm({ + content: dict['model.confirm'] + dict['model.delete'] + ` ${plot.title} 锛焋, + okText: dict['model.confirm'], + cancelText: dict['header.cancel'], + onOk() { + let _chartlist = fromJS(_this.state.chartlist).toJS() + let _chartview = this.state.chartview + + _chartlist = _chartlist.filter(item => item.uuid !== plot.uuid) + + if (_chartview === plot.uuid) { + _chartview = _chartlist[0].uuid + } + + _this.setState({ + chartlist: _chartlist, + chartview: _chartview + }) + _this.props.updatechartgroup({...config, charts: _chartlist}, _chartview) + }, + onCancel() {} + }) + } + + changetabview = (id) => { + const { config } = this.props + + this.setState({ + chartview: id + }) + + this.props.updatechartgroup(config, id) + } + + + render() { + const { config } = this.props + const { dict, chartlist, modaltype, card, chartview } = this.state + + return ( + <div className="model-table-chartview-list"> + <Icon type="plus" onClick={() => this.handleChart()} /> + {chartlist.length > 1 ? <Icon type={config.expand ? 'up' : 'down'} onClick={this.onChartChange} /> : null} + {chartlist.length > 1 ? <DragChartView + activeKey={chartview} + list={chartlist} + expand={config.expand} + handleList={this.handleList} + changetabview={this.changetabview} + handleMenu={this.handleChart} + deleteMenu={this.deletechart} + /> : null} + {/* 鍚堝苟鍒楃紪杈� */} + <Modal + title={modaltype === 'addChart' ? '鍥捐〃-娣诲姞' : '鍥炬爣-缂栬緫'} + visible={modaltype === 'addChart' || modaltype === 'editChart'} + width={750} + maskClosable={false} + onOk={this.submitChart} + onCancel={this.editModalCancel} + destroyOnClose + > + <ChartForm + dict={dict} + card={card} + formlist={this.state.formlist} + inputSubmit={this.submitChart} + wrappedComponentRef={(inst) => this.chartFormRef = inst} + /> + </Modal> + </div> + ) + } +} + +export default ChartGroupComponent \ No newline at end of file diff --git a/src/templates/sharecomponent/chartgroupcomponent/index.scss b/src/templates/sharecomponent/chartgroupcomponent/index.scss new file mode 100644 index 0000000..e12939a --- /dev/null +++ b/src/templates/sharecomponent/chartgroupcomponent/index.scss @@ -0,0 +1,24 @@ +.model-table-chartview-list { + position: absolute; + right: 0; + top: -10px; + text-align: right; + z-index: 10; + > .anticon-plus { + position: absolute; + right: 17px; + z-index: 11; + color: #26C281; + cursor: pointer; + font-size: 18px; + margin-top: 15px; + } + .anticon-down, .anticon-up { + position: absolute; + right: 55px; + z-index: 11; + cursor: pointer; + font-size: 16px; + margin-top: 18px; + } +} \ No newline at end of file diff --git a/src/templates/sharecomponent/chartgroupcomponent/searcheditable/index.jsx b/src/templates/sharecomponent/chartgroupcomponent/searcheditable/index.jsx new file mode 100644 index 0000000..8abe02b --- /dev/null +++ b/src/templates/sharecomponent/chartgroupcomponent/searcheditable/index.jsx @@ -0,0 +1,265 @@ +import React, {Component} from 'react' +import { is, fromJS } from 'immutable' +import { Table, Input, Button, Popconfirm, Form, Icon } from 'antd' +import Utils from '@/utils/utils.js' +import './index.scss' + +const EditableContext = React.createContext() + +const EditableRow = ({ form, index, ...props }) => ( + <EditableContext.Provider value={form}> + <tr {...props} /> + </EditableContext.Provider> +) + +const EditableFormRow = Form.create()(EditableRow) + +class EditableCell extends Component { + state = { + editing: false + } + + toggleEdit = () => { + const editing = !this.state.editing + this.setState({ editing }, () => { + if (editing && this.input && this.input.select) { + this.input.select() + } else if (editing && this.input && this.input.focus) { + this.input.focus() + } + }) + } + + save = e => { + const { record, handleSave } = this.props + this.form.validateFields((error, values) => { + handleSave({ ...record, ...values }) + if (error && error[e.currentTarget.id]) { + return + } + this.toggleEdit() + }) + } + + renderCell = form => { + this.form = form + const { children, dataIndex, record } = this.props + const { editing } = this.state + return editing ? ( + <Form.Item style={{ margin: 0 }}> + {form.getFieldDecorator(dataIndex, { + rules: [ + { + required: true, + message: 'NOT NULL.', + }, + ], + initialValue: record[dataIndex] + })(<Input ref={node => (this.input = node)} autoComplete="off" onPressEnter={this.save} onBlur={this.save} />)} + </Form.Item> + ) : ( + <div + className="editable-cell-value-wrap" + onClick={this.toggleEdit} + > + {children} + </div> + ) + } + + render() { + const { + editable, + dataIndex, + title, + record, + index, + handleSave, + children, + ...restProps + } = this.props + return ( + <td {...restProps}> + {editable ? ( + <EditableContext.Consumer style={{padding: 0}}>{this.renderCell}</EditableContext.Consumer> + ) : ( + children + )} + </td> + ) + } +} + +class EditTable extends Component { + constructor(props) { + super(props) + let columns = [ + { + title: 'Value', + dataIndex: 'Value', + width: props.type === 'link' ? '27%' : '40%', + editable: true + }, + { + title: 'Text', + dataIndex: 'Text', + width: props.type === 'link' ? '27%' : '40%', + editable: true + }, + { + title: 'Action', + align: 'center', + dataIndex: 'operation', + render: (text, record) => + this.state.dataSource.length >= 1 ? ( + <Popconfirm title="Sure to delete?" onConfirm={() => this.handleDelete(record.key)}> + <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span> + </Popconfirm> + ) : null, + } + ] + + if (props.type === 'link') { + columns.unshift({ + title: 'ParentID', + dataIndex: 'ParentID', + width: '27%', + editable: true + }) + } + + this.state = { + columns: columns, + dataSource: props.data, + count: props.data.length, + type: props.type + } + } + + handleDelete = key => { + const dataSource = [...this.state.dataSource] + this.setState({ dataSource: dataSource.filter(item => item.key !== key) }) + } + + handleAdd = () => { + const { type, count, dataSource } = this.state + const newData = { + key: Utils.getuuid(), + Value: `${count}`, + Text: `${count}` + } + if (type === 'link') { + newData.ParentID = `${count}` + } + this.setState({ + dataSource: [...dataSource, newData], + count: count + 1 + }) + } + + handleSave = row => { + const newData = [...this.state.dataSource] + const index = newData.findIndex(item => row.key === item.key) + const item = newData[index] + newData.splice(index, 1, { + ...item, + ...row + }) + this.setState({ dataSource: newData }) + } + + resetColumn = (type) => { + let columns = [ + { + title: 'Value', + dataIndex: 'Value', + width: type === 'link' ? '27%' : '40%', + editable: true + }, + { + title: 'Text', + dataIndex: 'Text', + width: type === 'link' ? '27%' : '40%', + editable: true + }, + { + title: 'Action', + align: 'center', + dataIndex: 'operation', + render: (text, record) => + this.state.dataSource.length >= 1 ? ( + <Popconfirm title="Sure to delete?" onConfirm={() => this.handleDelete(record.key)}> + <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span> + </Popconfirm> + ) : null, + } + ] + + if (type === 'link') { + columns.unshift({ + title: 'ParentID', + dataIndex: 'ParentID', + width: '27%', + editable: true + }) + } + + this.setState({ + columns: columns, + type: type + }) + } + + UNSAFE_componentWillReceiveProps (nextProps) { + if (this.props.type !== nextProps.type) { + this.resetColumn(nextProps.type) + } else if (!is(fromJS(this.props.data), fromJS(nextProps.data))) { + this.setState({ + dataSource: nextProps.data, + count: nextProps.data.length + }) + } + } + + render() { + const { dataSource } = this.state + const components = { + body: { + row: EditableFormRow, + cell: EditableCell + } + } + const columns = this.state.columns.map(col => { + if (!col.editable) { + return col + } + return { + ...col, + onCell: record => ({ + record, + editable: col.editable, + dataIndex: col.dataIndex, + title: col.title, + handleSave: this.handleSave, + }) + } + }) + return ( + <div className="common-modal-edit-table"> + <Button onClick={this.handleAdd} type="primary" className="add-row"> + Add + </Button> + <Table + components={components} + rowClassName={() => 'editable-row'} + bordered + dataSource={dataSource} + columns={columns} + pagination={false} + /> + </div> + ) + } +} + +export default EditTable \ No newline at end of file diff --git a/src/templates/sharecomponent/chartgroupcomponent/searcheditable/index.scss b/src/templates/sharecomponent/chartgroupcomponent/searcheditable/index.scss new file mode 100644 index 0000000..f8f0942 --- /dev/null +++ b/src/templates/sharecomponent/chartgroupcomponent/searcheditable/index.scss @@ -0,0 +1,36 @@ +.common-modal-edit-table { + .add-row { + position: absolute; + z-index: 1; + right: 12px; + top: -40px; + } + .ant-table-thead > tr > th { + padding: 10px 16px; + } + .ant-table-tbody > tr > td { + padding: 0px 16px; + } + .editable-cell-value-wrap { + cursor: pointer; + height: 40px; + width: 100px; + display: table-cell; + vertical-align: middle; + word-wrap: break-word; + word-break: break-word; + .ant-input { + height: 30px; + padding: 0 11px; + } + } + .ant-form-item-control-wrapper { + width: 100%; + } + .ant-table-placeholder { + padding: 5px 16px; + .ant-empty-normal { + margin: 0; + } + } +} diff --git a/src/templates/sharecomponent/chartgroupcomponent/searchform/index.jsx b/src/templates/sharecomponent/chartgroupcomponent/searchform/index.jsx new file mode 100644 index 0000000..e7941ec --- /dev/null +++ b/src/templates/sharecomponent/chartgroupcomponent/searchform/index.jsx @@ -0,0 +1,475 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input, Select, Icon, Radio, notification, Tooltip, InputNumber } from 'antd' +import { dateOptions, matchReg, formRule } from '@/utils/option.js' +import EditTable from '../searcheditable' +import Utils from '@/utils/utils.js' +import './index.scss' + +const { TextArea } = Input + +class MainSearch extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + formlist: PropTypes.any, // 琛ㄥ崟 + optionLibs: PropTypes.any, // 鑷畾涔変笅鎷夐泦 + card: PropTypes.object, // 鎼滅储鏉′欢淇℃伅 + inputSubmit: PropTypes.any // 鍥炶溅鎻愪氦浜嬩欢 + } + + state = { + openType: null, // 鎼滅储鏉′欢鏄剧ず绫诲瀷 + resourceType: null, // 涓嬫媺鎼滅储鏃讹紝閫夐」鏉ユ簮绫诲瀷 + formlist: null // 琛ㄥ崟 + } + + /** + * @description 琛ㄥ崟棰勫鐞� + * 1銆佹牴鎹〃鍗曠被鍨嬶紝鏄剧ず琛ㄥ崟鍙紪杈戦」 + * 2銆佷笅鎷夐�夋嫨锛屾牴鎹暟鎹簮绫诲瀷鏄剧ず鐩稿叧閰嶇疆 + */ + UNSAFE_componentWillMount () { + const { formlist, optionLibs } = this.props + + let type = formlist.filter(cell => cell.key === 'type')[0].initVal + let resourceType = formlist.filter(cell => cell.key === 'resourceType')[0].initVal + let _options = ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required'] // 榛樿鏄剧ず椤� + + if ((type === 'multiselect' || type === 'select' || type === 'link') && resourceType === '0') { // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓鸿嚜瀹氫箟璧勬簮 + _options = [..._options, 'resourceType', 'options', 'display', 'quick'] + } else if ((type === 'multiselect' || type === 'select' || type === 'link') && resourceType === '1') { // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓哄悗鍙版暟鎹簮涓幏鍙� + _options = [..._options, 'resourceType', 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'display', 'database'] + } + + if (type === 'select' || type === 'link') { + _options.push('setAll') + } + + if (type === 'link') { // 鍏宠仈绫诲瀷銆佸鍔犲叧鑱斾笂绾х殑瀛楁鍚� + _options = [..._options, 'linkField'] + } + + this.setState({ + openType: type, + resourceType: resourceType, + formlist: formlist.map(form => { + // 琛ㄥ崟涓哄垵濮嬪�煎瓧娈碉紝涓旀暟鎹被鍨嬪睘浜庢椂闂寸被鍨嬫椂锛岃缃垵濮嬪�间负涓嬫媺閫夋嫨锛屽苟閲嶇疆閫夋嫨椤� + if (form.key === 'initval' && dateOptions.hasOwnProperty(type)) { + form.options = dateOptions[type] + form.type = 'select' + } + // 琛ㄥ崟涓哄尮閰嶅瓧娈垫椂锛屾牴鎹笉鍚岀殑绫诲瀷锛屾樉绀哄搴旂殑鍖归厤瑙勫垯 + if (form.key === 'match') { + if (type === 'text') { + form.options = matchReg.text + } else if (type === 'multiselect') { + form.options = matchReg.multiselect + } else if (type === 'select' || type === 'link') { + form.options = matchReg.select + } else if (type === 'date') { + form.options = matchReg.date + } else if (type === 'datemonth') { + form.options = matchReg.datemonth + } else if (type === 'dateweek' || type === 'daterange') { + form.options = matchReg.daterange + } + } else if (form.key === 'quick') { + form.options = [...optionLibs.values()].map(cell => { + return { + value: cell.uuid, + text: cell.label + '(' + cell.parname + ')' + } + }) + } + form.hidden = !_options.includes(form.key) + return form + }) + }) + } + + componentDidMount () { + const { card } = this.props + + if (card.focus) { + try { + let _form = document.getElementById('label') + _form.select() + } catch { + console.warn('琛ㄥ崟focus澶辫触锛�') + } + } + } + + /** + * @description 鎼滅储鏉′欢绫诲瀷鍒囨崲 + */ + openTypeChange = (key, value) => { + const { resourceType } = this.state + + if (key === 'type') { + let _options = ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required'] + + if ((value === 'multiselect' || value === 'select' || value === 'link') && resourceType === '0') { // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓鸿嚜瀹氫箟璧勬簮 + _options = [..._options, 'resourceType', 'options', 'display', 'quick'] + } else if ((value === 'multiselect' || value === 'select' || value === 'link') && resourceType === '1') { // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓哄悗鍙版暟鎹簮涓幏鍙� + _options = [..._options, 'resourceType', 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'display', 'database'] + } + + if (value === 'select' || value === 'link') { + _options.push('setAll') + } + + if (value === 'link') { + _options = [..._options, 'linkField'] + } + + this.setState({ + openType: value, + formlist: this.state.formlist.map(form => { + form.hidden = !_options.includes(form.key) // 闅愯棌琛ㄥ崟 + + if (form.key === 'initval') { + if (dateOptions.hasOwnProperty(value)) { // 鏍规嵁鎼滅储鏉′欢绫诲瀷锛岄�夋嫨鍒濆鍊肩殑绫诲瀷鍙婃暟鎹� + form.options = dateOptions[value] + form.type = 'select' + } else { + form.type = 'text' + } + form.initVal = '' // 鎼滅储鏉′欢绫诲瀷鍒囨崲鏃讹紝鍒濆鍊肩疆绌� + form.hidden = true + } else if (form.key === 'match') { // 鎼滅储鏉′欢绫诲瀷鍒囨崲鏃讹紝鍖归厤瑙勫垯绫诲瀷瀵瑰簲鍒囨崲 + if (value === 'text') { + form.options = matchReg.text + } else if (value === 'multiselect') { + form.options = matchReg.multiselect + } else if (value === 'select' || value === 'link') { + form.options = matchReg.select + } else if (value === 'date') { + form.options = matchReg.date + } else if (value === 'datemonth') { + form.options = matchReg.datemonth + } else if (value === 'dateweek' || value === 'daterange') { + form.options = matchReg.daterange + } + form.hidden = true + } + + return form + }) + }, () => { + this.setState({ + formlist: this.state.formlist.map(form => { + + if (form.key === 'initval') { + form.hidden = false + } else if (form.key === 'match') { + form.initVal = form.options[0].value + form.hidden = false + } + + return form + }) + }) + }) + } else if (key === 'quick') { + let option = this.props.optionLibs.get(value) + + this.setState({ + formlist: this.state.formlist.map(form => { + if (form.key === 'options') { + form.initVal = option.options + } + + return form + }) + }) + } + } + + /** + * @description 鏁版嵁婧愮被鍨嬪垏鎹� + */ + onChange = (e, key) => { + const { openType } = this.state + let value = e.target.value + + if (key === 'resourceType') { + let _options = ['label', 'field', 'initval', 'type', 'match', 'resourceType', 'display', 'ratio', 'blacklist', 'required'] + + if (value === '0') { + _options = [..._options, 'options', 'quick'] + } else if (value === '1') { + _options = [..._options, 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'database'] + } + + if (openType === 'select' || openType === 'link') { + _options.push('setAll') + } + + if (openType === 'link') { + _options = [..._options, 'linkField'] + } + + this.setState({ + resourceType: value, + formlist: this.state.formlist.map(form => { + form.hidden = !_options.includes(form.key) + return form + }) + }) + } + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + getFields() { + const { getFieldDecorator } = this.props.form + const fields = [] + this.state.formlist.forEach((item, index) => { + if (item.hidden) return + + if (item.type === 'text') { // 鏂囨湰鎼滅储 + let rules = [] + if (item.key === 'field') { + rules = [{ + pattern: formRule.field.pattern, + message: formRule.field.message + }, { + max: formRule.field.max, + message: formRule.field.maxMessage + }] + } else { + rules = [{ + max: formRule.input.max, + message: formRule.input.message + }] + } + + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} 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 + '!' + }, + ...rules + ] + })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)} + </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 || 6, + rules: [ + { + required: item.required, + message: this.props.dict['form.required.input'] + item.label + '!' + } + ] + })(<InputNumber min={item.min} max={item.max} precision={0} />)} + </Form.Item> + </Col> + ) + } else if (item.type === 'select') { // 涓嬫媺鎼滅储 + 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 + '!' + } + ] + })( + <Select + showSearch + filterOption={(input, option) => option.props.children[2].toLowerCase().indexOf(input.toLowerCase()) >= 0} + onChange={(value) => {this.openTypeChange(item.key, value)}} + getPopupContainer={() => document.getElementById('commontable-search-form-box')} + > + {item.options.map(option => + <Select.Option id={option.value} title={option.text} key={option.value} value={option.value}> + {item.key === 'icon' && <Icon type={option.text} />} {option.text} + </Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + ) + } else if (item.type === 'radio') { + 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 + '!' + } + ] + })( + <Radio.Group onChange={(e) => {this.onChange(e, item.key)}}> + { + item.options.map(option => { + return ( + <Radio key={option.value} value={option.value}>{option.text}</Radio> + ) + }) + } + </Radio.Group>, + )} + </Form.Item> + </Col> + ) + } else if (item.type === 'textarea') { + fields.push( + <Col span={20} offset={4} key={index}> + <Form.Item className="text-area"> + {getFieldDecorator(item.key, { + initialValue: item.initVal, + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.input'] + item.label + '!' + } + ] + })(<TextArea rows={4} />)} + </Form.Item> + </Col> + ) + } else if (item.type === 'options') { + fields.push( + <Col span={20} offset={4} key={index}> + <EditTable data={item.initVal} type={this.state.openType} ref="editTable"/> + </Col> + ) + } else if (item.type === 'multiselect') { // 澶氶�� + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.label}> + {getFieldDecorator(item.key, { + initialValue: item.initVal || [] + })( + <Select + showSearch + mode="multiple" + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + > + {item.options.map((option, i) => + <Select.Option id={i} key={i} value={option.value}>{option.text}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + ) + } + }) + + return fields + } + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + let isvalid = true + values.uuid = this.props.card.uuid + // 涓嬫媺鑿滃崟鎴栧叧鑱旇彍鍗� + if ((values.type === 'multiselect' || values.type === 'select' || values.type === 'link') && values.resourceType === '0') { + values.options = this.refs.editTable.state.dataSource + values.dataSource = '' + let emptys = [] + if (values.type === 'multiselect' || values.type === 'select') { + emptys = values.options.filter(op => !(op.Value && op.Text)) + } else { + emptys = values.options.filter(op => !(op.Value && op.Text && op.ParentID)) + } + if (emptys.length > 0) { + isvalid = false + } + } else if ((values.type === 'multiselect' || values.type === 'select' || values.type === 'link') && values.resourceType === '1') { + values.options = [] + } + + if (isvalid) { + ['linkField', 'valueField', 'valueText', 'orderBy'].forEach(item => { + if (values[item]) { + values[item] = values[item].replace(/\s* | \t* | \v* | \r*/ig, '') + } + }) + + let error = Utils.verifySql(values.dataSource) + + if (error) { + notification.warning({ + top: 92, + message: '鏁版嵁婧愪腑涓嶅彲浣跨敤' + error, + duration: 5 + }) + return + } + + resolve(values) + } else { + notification.warning({ + top: 92, + message: this.props.dict['header.form.selectItem.error'], + duration: 5 + }) + } + } else { + reject(err) + } + }) + }) + } + + render() { + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + return ( + <Form {...formItemLayout} className="ant-advanced-search-form commontable-search-form" id="commontable-search-form-box"> + <Row gutter={24}>{this.getFields()}</Row> + </Form> + ) + } +} + +export default Form.create()(MainSearch) \ No newline at end of file diff --git a/src/templates/sharecomponent/chartgroupcomponent/searchform/index.scss b/src/templates/sharecomponent/chartgroupcomponent/searchform/index.scss new file mode 100644 index 0000000..b027f37 --- /dev/null +++ b/src/templates/sharecomponent/chartgroupcomponent/searchform/index.scss @@ -0,0 +1,24 @@ +.ant-advanced-search-form.commontable-search-form { + min-height: 180px; + .ant-col-offset-4 { + padding-left: 6px!important; + padding-bottom: 20px; + } + // .ant-form-item { + // margin-bottom: 10px; + // } + .ant-form-item.text-area { + margin-bottom: 0px; + .ant-form-item-control-wrapper { + width: 100%; + } + } + .anticon-question-circle { + color: #c49f47; + position: relative; + left: -3px; + } + .ant-input-number { + width: 100%; + } +} \ No newline at end of file diff --git a/src/templates/sharecomponent/columncomponent/colspanform/index.jsx b/src/templates/sharecomponent/columncomponent/colspanform/index.jsx new file mode 100644 index 0000000..670f462 --- /dev/null +++ b/src/templates/sharecomponent/columncomponent/colspanform/index.jsx @@ -0,0 +1,193 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input, InputNumber, Select, Radio } from 'antd' +import { formRule } from '@/utils/option.js' +import TransferForm from '@/templates/zshare/transferform' +import './index.scss' + +class MainSearch extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + columns: PropTypes.array, + card: PropTypes.any, + inputSubmit: PropTypes.any // 鍥炶溅鎻愪氦浜嬩欢 + } + + componentDidMount () { + try { + let _form = document.getElementById('label') + if (_form && _form.select) { + _form.select() + } + } catch { + console.warn('琛ㄥ崟focus澶辫触锛�') + } + } + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + let targetKeys = this.refs['column-transfer'].state.targetKeys + + delete values.type // 鍒犻櫎type锛屾澶勫�间负'鍚堝苟鍒�'鏂囧瓧 + + let subfield = [] // 鐢ㄤ簬鏌ョ湅鍚堝苟鍒楀瓧娈� + this.props.columns.forEach(col => { + if (col.field && targetKeys.includes(col.uuid)) { + subfield.push(col.field) + } + }) + subfield = subfield.join(', ') + + let _card = {...this.props.card, ...values, sublist: targetKeys, subfield: subfield} + + delete _card.focus + + resolve(_card) + } else { + reject(err) + } + }) + }) + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + render() { + const { getFieldDecorator } = this.props.form + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 6 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 18 } + } + } + return ( + <Form {...formItemLayout} className="commontable-cospan-column-form" id="columncolspan"> + <Row gutter={24}> + <Col span={12}> + <Form.Item label={this.props.dict['header.form.name']}> + {getFieldDecorator('label', { + initialValue: this.props.card.label, + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + this.props.dict['header.form.name'] + '!' + }, + { + max: formRule.input.max, + message: formRule.input.message + } + ] + })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={this.props.dict['header.form.type']}> + {getFieldDecorator('type', { + initialValue: this.props.dict['header.form.colspan'], + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + this.props.dict['header.form.type'] + '!' + } + ] + })(<Input placeholder="" autoComplete="off" disabled={true}/>)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={this.props.dict['header.form.align']}> + {getFieldDecorator('Align', { + initialValue: this.props.card.Align, + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + this.props.dict['header.form.align'] + '!' + } + ] + })( + <Select + getPopupContainer={() => document.getElementById('columncolspan')} + > + <Select.Option value="left">{this.props.dict['header.form.alignLeft']}</Select.Option> + <Select.Option value="right">{this.props.dict['header.form.alignRight']}</Select.Option> + <Select.Option value="center">{this.props.dict['header.form.alignCenter']}</Select.Option> + </Select> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={this.props.dict['header.form.columnWidth']}> + {getFieldDecorator('Width', { + initialValue: this.props.card.Width, + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + this.props.dict['header.form.columnWidth'] + '!' + } + ] + })(<InputNumber min={1} max={1000} precision={0} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={this.props.dict['header.form.Hide']}> + {getFieldDecorator('Hide', { + initialValue: this.props.card.Hide, + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + this.props.dict['header.form.Hide'] + '!' + } + ] + })( + <Radio.Group> + <Radio value="true">{this.props.dict['header.form.true']}</Radio> + <Radio value="false">{this.props.dict['header.form.false']}</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={this.props.dict['header.form.order']}> + {getFieldDecorator('order', { + initialValue: this.props.card.order, + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + this.props.dict['header.form.order'] + '!' + } + ] + })( + <Select + getPopupContainer={() => document.getElementById('columncolspan')} + > + <Select.Option value="vertical">{this.props.dict['header.form.vertical']}</Select.Option> + <Select.Option value="horizontal">{this.props.dict['header.form.horizontal']}</Select.Option> + <Select.Option value="vertical2">{this.props.dict['header.form.vertical2']}</Select.Option> + <Select.Option value="topPicBottomText">{this.props.dict['header.form.topPicBottomText']}</Select.Option> + <Select.Option value="leftPicRightText">{this.props.dict['header.form.leftPicRightText']}</Select.Option> + </Select> + )} + </Form.Item> + </Col> + <Col span={24}> + <TransferForm dict={this.props.dict} columns={this.props.columns} ref="column-transfer" selected={this.props.card.sublist}/> + </Col> + </Row> + </Form> + ) + } +} + +export default Form.create()(MainSearch) \ No newline at end of file diff --git a/src/templates/sharecomponent/columncomponent/colspanform/index.scss b/src/templates/sharecomponent/columncomponent/colspanform/index.scss new file mode 100644 index 0000000..d6690dc --- /dev/null +++ b/src/templates/sharecomponent/columncomponent/colspanform/index.scss @@ -0,0 +1,8 @@ +.commontable-cospan-column-form { + min-height: 190px; + .ant-form-item { + .ant-input-number { + width: 100%; + } + } +} \ No newline at end of file diff --git a/src/templates/sharecomponent/columncomponent/columnform/index.jsx b/src/templates/sharecomponent/columncomponent/columnform/index.jsx new file mode 100644 index 0000000..e8674c3 --- /dev/null +++ b/src/templates/sharecomponent/columncomponent/columnform/index.jsx @@ -0,0 +1,376 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input, Select, InputNumber, Radio, Tooltip, Icon, Cascader, notification } from 'antd' + +import { formRule } from '@/utils/option.js' +import options from '@/store/options.js' +import Api from '@/api' +import './index.scss' + +const columnTypeOptions = { + text: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'matchVal', 'color', 'fieldlength', 'blacklist', 'linkmenu'], + number: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'decimal', 'format', 'prefix', 'postfix', 'match', 'matchVal', 'color', 'blacklist', 'linkmenu'], + textarea: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'matchVal', 'color', 'fieldlength', 'blacklist'], + picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'fieldlength', 'blacklist', 'scale', 'maxHeight'] +} + +class MainSearch extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + MenuID: PropTypes.any, + formlist: PropTypes.any, + card: PropTypes.any, + inputSubmit: PropTypes.any // 鍥炶溅鎻愪氦浜嬩欢 + } + + state = { + formlist: null, + menulist: null + } + + UNSAFE_componentWillMount () { + let _type = this.props.formlist.filter(form => form.key === 'type')[0].initVal + let _menulist = this.props.formlist.filter(form => form.key === 'linkmenu')[0] || '' + + let _options = JSON.parse(JSON.stringify(columnTypeOptions[_type])) + + this.setState({ + menulist: _menulist.options || [], + formlist: this.props.formlist.map(item => { + item.hidden = !_options.includes(item.key) + if (item.key === 'matchVal' && (_type === 'text' || _type === 'textarea')) { + item.type = 'text' + } else if (item.key === 'matchVal' && _type === 'number') { + item.type = 'number' + } + return item + }) + }) + } + + componentDidMount () { + const { card } = this.props + + if (card.focus) { + try { + let _form = document.getElementById('label') + _form.select() + } catch { + console.warn('琛ㄥ崟focus澶辫触锛�') + } + } + } + + typeChange = (key, value) => { + if (key === 'type') { + let _options = JSON.parse(JSON.stringify(columnTypeOptions[value])) + + this.setState({ + formlist: this.props.formlist.map(item => { + item.hidden = !_options.includes(item.key) + if (item.key === 'matchVal' && (value === 'text' || value === 'textarea')) { + item.type = 'text' + } else if (item.key === 'matchVal' && value === 'number') { + item.type = 'number' + item.initVal = '' + item.hidden = true + } else if (item.key === 'fieldlength') { + if (value === 'text') { + item.initVal = 50 + } else { + item.initVal = 512 + } + item.hidden = true + } + return item + }) + }, () => { + this.setState({ + formlist: this.props.formlist.map(item => { + if (item.key === 'matchVal' && value === 'number') { + item.hidden = false + } else if (item.key === 'fieldlength' && value !== 'number') { + item.hidden = false + } + return item + }) + }) + }) + } + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + getFields() { + const { getFieldDecorator } = this.props.form + const fields = [] + this.state.formlist.forEach((item, index) => { + if (item.hidden) return + + if (item.type === 'text') { // 鏂囨湰鎼滅储 + let rules = [] + if (item.key === 'field') { + rules = [{ + pattern: formRule.field.pattern, + message: formRule.field.message + }, { + max: formRule.field.max, + message: formRule.field.maxMessage + }] + } else { + rules = [{ + max: formRule.input.max, + message: formRule.input.message + }] + } + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} 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 + '!' + }, + ...rules + ] + })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + ) + } else if (item.type === 'number') { + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}> + <Icon type="question-circle" /> + {item.label} + </Tooltip> : item.label + }> + {getFieldDecorator(item.key, { + initialValue: item.initVal, + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.input'] + item.label + '!' + } + ] + })(<InputNumber min={item.min} max={item.max} precision={item.decimal} />)} + </Form.Item> + </Col> + ) + } else if (item.type === 'select') { // 涓嬫媺鎼滅储 + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.label}> + {getFieldDecorator(item.key, { + initialValue: item.initVal || '', + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.select'] + item.label + '!' + } + ] + })( + <Select + showSearch + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + onChange={(value) => {this.typeChange(item.key, value)}} + getPopupContainer={() => document.getElementById('columnwinter')} + > + {item.options.map((option, index) => + <Select.Option id={`${index}`} title={option.text} key={`${index}`} value={option.value}> + {option.text} + </Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + ) + } else if (item.type === 'radio') { + 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 + '!' + } + ] + })( + <Radio.Group> + { + item.options.map(option => { + return ( + <Radio key={option.value} value={option.value}>{option.text}</Radio> + ) + }) + } + </Radio.Group> + )} + </Form.Item> + </Col> + ) + } else if (item.type === 'multiselect') { // 澶氶�� + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.label}> + {getFieldDecorator(item.key, { + initialValue: item.initVal || [] + })( + <Select + showSearch + mode="multiple" + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + > + {item.options.map((option, i) => + <Select.Option id={i} key={i} value={option.value}>{option.text}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + ) + } else if (item.type === 'cascader') { // 澶氶�� + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.label}> + {getFieldDecorator(item.key, { + initialValue: item.initVal || [] + })( + <Cascader + options={this.state.menulist} + loadData={this.loadData} + placeholder="" + getPopupContainer={() => document.getElementById('columnwinter')} + /> + )} + </Form.Item> + </Col> + ) + } + }) + return fields + } + + loadData = selectedOptions => { + const { MenuID } = this.props + const targetOption = selectedOptions[selectedOptions.length - 1] + targetOption.loading = true + + let _param = { + func: 'sPC_Get_FunMenu', + ParentID: targetOption.value, + systemType: options.systemType, + debug: 'Y' + } + + Api.getSystemConfig(_param).then(result => { + if (result.status) { + targetOption.loading = false + targetOption.children = result.data.map(item => { + let submenu = { + value: item.ParentID, + label: item.MenuNameP, + children: item.FunMenu.map(cell => { + return { + value: cell.MenuID, + label: cell.MenuName, + MenuID: cell.MenuID, + MenuName: cell.MenuName, + MenuNo: cell.MenuNo, + Ot: cell.Ot, + PageParam: cell.PageParam, + LinkUrl: cell.LinkUrl, + disabled: cell.MenuID === MenuID + } + }) + } + + return submenu + }) + + this.setState({ + menulist: [...this.state.menulist] + }) + } else { + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + targetOption.loading = false + } + }) + } + + handleConfirm = () => { + const { menulist } = this.state + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + values.id = this.props.card.id + values.uuid = this.props.card.uuid + + if ((values.type === 'text' || values.type === 'number') && values.linkmenu && values.linkmenu.length > 0) { + let linkThdMenu = '' + menulist.forEach(menu => { + if (menu.value === values.linkmenu[0]) { + menu.children.forEach(item => { + if (item.value === values.linkmenu[1]) { + item.children.forEach(cell => { + if (cell.value === values.linkmenu[2]) { + linkThdMenu = cell + } + }) + } + }) + } + }) + values.linkThdMenu = linkThdMenu + } + + resolve(values) + } else { + reject(err) + } + }) + }) + } + + render() { + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 6 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 18 } + } + } + return ( + <Form {...formItemLayout} className="commontable-column-form" id="columnwinter"> + <Row gutter={24}>{this.getFields()}</Row> + </Form> + ) + } +} + +export default Form.create()(MainSearch) \ No newline at end of file diff --git a/src/templates/sharecomponent/columncomponent/columnform/index.scss b/src/templates/sharecomponent/columncomponent/columnform/index.scss new file mode 100644 index 0000000..fcf59ac --- /dev/null +++ b/src/templates/sharecomponent/columncomponent/columnform/index.scss @@ -0,0 +1,19 @@ +.commontable-column-form { + min-height: 190px; + .ant-form-item { + .ant-input-number { + width: 100%; + } + } + .anticon-question-circle { + color: #c49f47; + position: relative; + left: -3px; + } + .ant-cascader-menus { + padding: 5px 0px; + .ant-cascader-menu:last-child { + padding-right: 3px; + } + } +} diff --git a/src/templates/sharecomponent/columncomponent/dragcolumn/card.jsx b/src/templates/sharecomponent/columncomponent/dragcolumn/card.jsx new file mode 100644 index 0000000..a10ded7 --- /dev/null +++ b/src/templates/sharecomponent/columncomponent/dragcolumn/card.jsx @@ -0,0 +1,58 @@ +import React from 'react' +import { useDrag, useDrop } from 'react-dnd' +import { Icon } from 'antd' +import './index.scss' + +const Card = ({ id, card, showfield, moveCard, findCard, editCard, delCard, hasDrop }) => { + const originalIndex = findCard(id).index + const [{ isDragging }, drag] = useDrag({ + item: { type: 'columns', id, originalIndex }, + collect: monitor => ({ + isDragging: monitor.isDragging(), + }), + }) + const [, drop] = useDrop({ + accept: 'columns', + canDrop: () => true, + drop: (item) => { + if (!item.hasOwnProperty('originalIndex')) { + hasDrop(card) + } + }, + hover({ id: draggedId }) { + if (!draggedId) return + if (draggedId !== id) { + const { index: overIndex } = findCard(id) + moveCard(draggedId, overIndex) + } + }, + }) + + const opacity = isDragging ? 0 : 1 + + return ( + <div className="page-card" style={{ flex: card.Width, opacity: opacity}}> + <div ref={node => drag(drop(node))}> + <span className="ant-table-header-column"> + <div className="ant-table-column-sorters" title={card.label} style={{textAlign: card.Align}}> + <span className="ant-table-column-title">{card.label}</span> + {card.IsSort === 'true' ? + <span className="ant-table-column-sorter"> + <Icon type="caret-up" /> + <Icon type="caret-down" /> + </span> : null + } + </div> + {showfield ? + <div className="ant-table-column-fields"> + <span className="ant-table-column-title">{card.type === 'colspan' ? card.subfield : card.field}</span> + </div> : null + } + </span> + </div> + <Icon className="edit" title="edit" type="edit" onClick={() => editCard(id)} /> + <Icon className="edit close" title="delete" type="close" onClick={() => delCard(id)} /> + </div> + ) +} +export default Card diff --git a/src/templates/sharecomponent/columncomponent/dragcolumn/index.jsx b/src/templates/sharecomponent/columncomponent/dragcolumn/index.jsx new file mode 100644 index 0000000..3c608b0 --- /dev/null +++ b/src/templates/sharecomponent/columncomponent/dragcolumn/index.jsx @@ -0,0 +1,165 @@ +import React, { useState } from 'react' +import { useDrop } from 'react-dnd' +import { is, fromJS } from 'immutable' +import update from 'immutability-helper' +import { Icon } from 'antd' +import Utils from '@/utils/utils.js' +import Card from './card' +import './index.scss' + +const Container = ({list, setting, gridBtn, showfield, placeholder, handleList, handleMenu, handleGridBtn, deleteMenu }) => { + let target = null + + const [cards, setCards] = useState(list) + const moveCard = (id, atIndex) => { + const { card, index } = findCard(id) + 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) + handleMenu(card) + } + + + const delCard = id => { + const { card } = findCard(id) + deleteMenu(card) + } + + const hasDrop = (item) => { + target = item + } + + const [, drop] = useDrop({ + accept: 'columns', + drop(item) { + if (item.hasOwnProperty('originalIndex')) { + return + } + + let newcard = {} + newcard.uuid = Utils.getuuid() + newcard.focus = true + + newcard.Align = 'left' + newcard.label = 'label' + newcard.field = '' + newcard.Hide = 'false' + newcard.IsSort = 'true' + newcard.type = item.subType + newcard.Width = 120 + if (item.subType === 'colspan') { + newcard.sublist = [] + newcard.subfield = [] + newcard.IsSort = 'false' + newcard.order = 'vertical' + } + + let targetId = cards.length > 0 ? cards[cards.length - 1].uuid : 0 + if (target) { + targetId = target.uuid + } + + const { index: overIndex } = findCard(`${targetId}`) + let targetIndex = overIndex + + targetIndex++ + + const _cards = update(cards, { $splice: [[targetIndex, 0, newcard]] }) + + handleList(_cards, newcard) + target = null + } + }) + + let columns = [] + let _colCards = [] + + // 杩囨护鍚堝苟鍒� + let _hideCol = [] + cards.forEach(col => { + if (col.type === 'colspan' && col.sublist) { + _hideCol.push(...col.sublist) + } + }) + cards.forEach(col => { + if (_hideCol.includes(col.uuid)) return + + _colCards.push(col) + }) + + // 鏄剧ず鍒楀垎琛� + if (_colCards.length > 10) { + let number = Math.ceil(_colCards.length / Math.ceil(_colCards.length / 10)) + for (let i = 0, len = _colCards.length; i < len; i += number) { + columns.push(_colCards.slice(i, i + number)) + } + } else { + columns.push(_colCards) + } + + return ( + <div ref={drop} className="ant-row"> + {columns.map((column, i) => ( + <div key={i} className="column-box"> + {/* 澶氶�� */} + {i === 0 && column.length > 0 && setting.tableType === 'checkbox' ? + <div className="page-card" style={{flex: 60}}> + <span className="ant-checkbox-inner"></span> + </div> : null + } + {/* 鍗曢�� */} + {i === 0 && column.length > 0 && setting.tableType === 'radio' ? + <div className="page-card" style={{flex: 60}}></div> : null + } + {column.map(card => ( + <Card + key={card.uuid} + id={card.uuid} + card={card} + showfield={showfield} + moveCard={moveCard} + editCard={editCard} + delCard={delCard} + findCard={findCard} + hasDrop={hasDrop} + /> + ))} + {i === (columns.length - 1) && gridBtn && gridBtn.display ? + <div className="page-card" style={{flex: gridBtn.Width}}> + <div style={{cursor: 'default'}}> + <span className="ant-table-header-column"> + <div className="ant-table-column-sorters" title={gridBtn.label} style={{textAlign: gridBtn.Align}}> + <span className="ant-table-column-title">{gridBtn.label}</span> + </div> + </span> + </div> + <Icon className="edit" type="edit" onClick={handleGridBtn}/> + </div> : null + } + </div> + ))} + + {cards.length === 0 ? + <div className="common-drawarea-placeholder"> + {placeholder} + </div> : null + } + </div> + ) +} +export default Container diff --git a/src/templates/sharecomponent/columncomponent/dragcolumn/index.scss b/src/templates/sharecomponent/columncomponent/dragcolumn/index.scss new file mode 100644 index 0000000..369ae98 --- /dev/null +++ b/src/templates/sharecomponent/columncomponent/dragcolumn/index.scss @@ -0,0 +1,6 @@ +.common-drawarea-placeholder { + width: 100%; + line-height: 65px; + text-align: center; + color: #bcbcbc; +} \ No newline at end of file diff --git a/src/templates/sharecomponent/columncomponent/gridbtnform/index.jsx b/src/templates/sharecomponent/columncomponent/gridbtnform/index.jsx new file mode 100644 index 0000000..09eae88 --- /dev/null +++ b/src/templates/sharecomponent/columncomponent/gridbtnform/index.jsx @@ -0,0 +1,218 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input, Select, InputNumber, Radio } from 'antd' +import { formRule } from '@/utils/option.js' +import './index.scss' + +class MainSearch extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + card: PropTypes.any, + inputSubmit: PropTypes.any // 鍥炶溅鎻愪氦浜嬩欢 + } + + state = { + formlist: [ + { + type: 'text', + key: 'label', + label: this.props.dict['header.form.name'], + initVal: this.props.card.label, + required: true + }, + { + type: 'select', + key: 'Align', + label: this.props.dict['header.form.align'], + initVal: this.props.card.Align, + required: true, + options: [{ + MenuID: 'left', + text: this.props.dict['header.form.alignLeft'] + }, { + MenuID: 'right', + text: this.props.dict['header.form.alignRight'] + }, { + MenuID: 'center', + text: this.props.dict['header.form.alignCenter'] + }] + }, + { + type: 'number', + key: 'Width', + decimal: 0, + label: this.props.dict['header.form.columnWidth'], + initVal: this.props.card.Width, + required: true + }, + { + type: 'select', + key: 'style', + label: this.props.dict['header.form.style'], + initVal: this.props.card.style, + required: true, + options: [{ + MenuID: 'button', + text: this.props.dict['header.form.button'] + }, { + MenuID: 'text', + text: this.props.dict['header.form.text'] + }] + }, + { + type: 'select', + key: 'show', + label: this.props.dict['header.form.order'], + initVal: this.props.card.show, + required: true, + options: [{ + MenuID: 'horizontal', + text: this.props.dict['header.form.horizontal'] + }, { + MenuID: 'vertical', + text: this.props.dict['header.form.vertical'] + }] + } + ] + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + getFields() { + const { getFieldDecorator } = this.props.form + const fields = [] + this.state.formlist.forEach((item, index) => { + if (item.type === 'text') { // 鏂囨湰鎼滅储 + 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.input'] + item.label + '!' + }, + { + max: formRule.input.max, + message: formRule.input.message + } + ] + })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + ) + } else if (item.type === 'number') { // 鏂囨湰鎼滅储 + 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.input'] + item.label + '!' + } + ] + })(<InputNumber min={1} max={1000} precision={item.decimal} />)} + </Form.Item> + </Col> + ) + } else if (item.type === 'select') { // 涓嬫媺鎼滅储 + 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 + '!' + } + ] + })( + <Select + showSearch + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + getPopupContainer={() => document.getElementById('gridbtncolumnwinter')} + > + {item.options.map(option => + <Select.Option id={option.MenuID} title={option.text} key={option.MenuID} value={option.MenuID}> + {option.text} + </Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + ) + } else if (item.type === 'radio') { + 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 + '!' + } + ] + })( + <Radio.Group> + { + item.options.map(option => { + return ( + <Radio key={option.MenuID} value={option.MenuID}>{option.text}</Radio> + ) + }) + } + </Radio.Group> + )} + </Form.Item> + </Col> + ) + } + }) + return fields + } + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + resolve({...this.props.card, ...values}) + } else { + reject(err) + } + }) + }) + } + + render() { + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 6 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 18 } + } + } + return ( + <Form {...formItemLayout} className="commontable-gridbtn-column-form" id="gridbtncolumnwinter"> + <Row gutter={24}>{this.getFields()}</Row> + </Form> + ) + } +} + +export default Form.create()(MainSearch) \ No newline at end of file diff --git a/src/templates/sharecomponent/columncomponent/gridbtnform/index.scss b/src/templates/sharecomponent/columncomponent/gridbtnform/index.scss new file mode 100644 index 0000000..abb563c --- /dev/null +++ b/src/templates/sharecomponent/columncomponent/gridbtnform/index.scss @@ -0,0 +1,8 @@ +.commontable-gridbtn-column-form { + min-height: 190px; + .ant-form-item { + .ant-input-number { + width: 100%; + } + } +} \ No newline at end of file diff --git a/src/templates/sharecomponent/columncomponent/index.jsx b/src/templates/sharecomponent/columncomponent/index.jsx new file mode 100644 index 0000000..aa07790 --- /dev/null +++ b/src/templates/sharecomponent/columncomponent/index.jsx @@ -0,0 +1,437 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Tooltip, Modal, notification, Switch, message, Spin } from 'antd' + +import Api from '@/api' +import options from '@/store/options.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import { getColumnForm } from '@/templates/zshare/formconfig' + +import ColumnForm from './columnform' +import ColspanForm from './colspanform' +import GridBtnForm from './gridbtnform' +import DragElement from './dragcolumn' +import './index.scss' + +const { confirm } = Modal + +// **鎮茶鑰呭線寰�姝g‘锛屼箰瑙傝�呭線寰�鎴愬姛 +class ColumnComponent extends Component { + static propTpyes = { + menu: PropTypes.object, // 涓夌骇鑿滃崟淇℃伅 + config: PropTypes.object, // 閰嶇疆淇℃伅 + pasteContent: PropTypes.object, // 绮樿创閰嶇疆淇℃伅 + sysRoles: PropTypes.array, // 瑙掕壊鍒楄〃锛屾潈闄愬垎閰� + updatecolumn: PropTypes.func // 鏇存柊 + } + + state = { + dict: (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS, + columnlist: null, // 鏄剧ず鍒� + loading: false, // 鏌ヨ鏄剧ず鍒楀叧鑱旇彍鍗� + showField: false, // 鏄剧ず鍒楀瓧娈� + modaltype: '', // 妯℃�佹鎺у埗 + card: null // 缂栬緫涓厓绱� + } + + /** + * @description 鏄剧ず鍒楀垵濮嬪寲 + */ + UNSAFE_componentWillMount () { + this.setState({ + columnlist: fromJS(this.props.config.columns).toJS() + }) + } + + /** + * @description 鐩戝惉鍒版樉绀哄垪澶嶅埗鏃讹紝瑙﹀彂鏄剧ず鍒楃紪杈� + */ + UNSAFE_componentWillReceiveProps (nextProps) { + const { columnlist } = this.state + + if ( + nextProps.pasteContent && + columnlist.length === 0 && + nextProps.pasteContent.columns && + nextProps.pasteContent.copyType === 'columns' && + nextProps.pasteContent.columns.length > 0 + ) { + this.setState({columnlist: nextProps.pasteContent.columns}) + } else if (!is(fromJS(nextProps.config.columns), fromJS(this.props.config.columns)) && !is(fromJS(nextProps.config.columns), fromJS(columnlist))) { + this.setState({columnlist: nextProps.config.columns}) + } + } + + /** + * @description 鏄剧ず鍒楅『搴忚皟鏁达紝鎴栨嫋鎷芥坊鍔� + */ + handleList = (list, card) => { + const { config } = this.props + + if (card) { + this.setState({columnlist: list}) + this.handleColumn(card) + } else { + this.setState({columnlist: list}) + this.props.updatecolumn({...config, search: list}) + } + } + + /** + * @description 鏄剧ず鍒椾笌鍚堝苟鍒楃紪杈戯紝鑾峰彇琛ㄥ崟淇℃伅 + */ + handleColumn = (card) => { + const { menu } = this.props + + if (card.type !== 'colspan') { + let menulist = menu.fstMenuList.map(item => { + return { + value: item.MenuID, + label: item.text, + isLeaf: false + } + }) + + if ((card.type === 'text' || card.type === 'number') && card.linkmenu && card.linkmenu.length > 0) { + let _param = { + func: 'sPC_Get_FunMenu', + ParentID: card.linkmenu[0], + systemType: options.systemType, + debug: 'Y' + } + + this.setState({ + loading: true + }) + + Api.getSystemConfig(_param).then(result => { + if (result.status) { + menulist = menulist.map(item => { + if (item.value === card.linkmenu[0]) { + item.children = result.data.map(item => { + let submenu = { + value: item.ParentID, + label: item.MenuNameP, + children: item.FunMenu.map(cell => { + return { + value: cell.MenuID, + label: cell.MenuName, + MenuID: cell.MenuID, + MenuName: cell.MenuName, + MenuNo: cell.MenuNo, + Ot: cell.Ot, + PageParam: cell.PageParam, + LinkUrl: cell.LinkUrl, + disabled: cell.MenuID === menu.MenuID + } + }) + } + + return submenu + }) + } + return item + }) + } else { + notification.warning({ + top: 92, + message: result.message, + duration: 5 + }) + } + + this.setState({ + loading: false, + modaltype: 'columns', + card: card, + formlist: getColumnForm(card, this.props.sysRoles, menulist) + }) + }) + } else { + this.setState({ + modaltype: 'columns', + card: card, + formlist: getColumnForm(card, this.props.sysRoles, menulist) + }) + } + } else { + this.setState({ + modaltype: 'colspan', + card: card + }) + } + } + + /** + * @description 鎿嶄綔鍒楃紪杈� + */ + handleGridBtn = () => { + this.setState({ + modaltype: 'gridbtn' + }) + } + + /** + * @description 鍙栨秷淇濆瓨锛屽鏋滃厓绱犱负鏂版坊鍏冪礌锛屽垯浠庡簭鍒椾腑鍒犻櫎 + */ + editModalCancel = () => { + const { card } = this.state + + if (card.focus) { + let _columnlist = fromJS(this.state.columnlist).toJS() + + _columnlist = _columnlist.filter(item => item.uuid !== card.uuid) + + this.setState({ + card: null, + modaltype: '', + columnlist: _columnlist + }) + } else { + this.setState({ + card: null, + modaltype: '' + }) + } + } + + /** + * @description 鎼滅储淇敼鍚庢彁浜や繚瀛� + * 1銆佸幓闄ょ郴缁熼粯璁ゆ樉绀哄垪 + * 2銆佸瓧娈靛強鎻愮ず鏂囧瓧閲嶅鏍¢獙 + * 3銆佹洿鏂颁笅鎷夎彍鍗曞彲閫夐泦鍚� + * 4銆佷笅鎷夎彍鍗曟暟鎹簮璇硶楠岃瘉 + */ + handleSubmit = () => { + const { config } = this.props + const { modaltype } = this.state + + let _columnlist = fromJS(this.state.columnlist).toJS() + + if (modaltype === 'columns' || modaltype === 'colspan') { + this.columnFormRef.handleConfirm().then(res => { + let fieldrepet = false // 瀛楁閲嶅 + let labelrepet = false // 鎻愮ず鏂囧瓧閲嶅 + + _columnlist = _columnlist.filter(item => !item.origin || item.uuid === res.uuid) // 鍘婚櫎鍒濆鍒� + + _columnlist = _columnlist.map(item => { + if (item.uuid !== res.uuid && res.field && item.field) { + if (item.field === res.field) { + fieldrepet = true + } else if (item.label === res.label) { + labelrepet = true + } + } + + if (item.uuid === res.uuid) { + return res + } else { + return item + } + }) + + if (fieldrepet) { + notification.warning({ + top: 92, + message: this.state.dict['model.field.exist'] + ' !', + duration: 5 + }) + return + } else if (labelrepet) { + notification.warning({ + top: 92, + message: this.state.dict['model.name.exist'] + ' !', + duration: 5 + }) + return + } + + this.setState({ + columnlist: _columnlist, + modaltype: '' + }) + this.props.updatecolumn({...config, columns: _columnlist}) + }) + } else if (modaltype === 'gridbtn') { + this.gridBtnFormRef.handleConfirm().then(res => { + this.setState({ + modaltype: '' + }) + + this.props.updatecolumn({...config, gridBtn: res}) + }) + } + } + + /** + * @description 鏄剧ず鍒楀垹闄� + */ + deleteElement = (card) => { + const { config } = this.props + const { dict } = this.state + let _this = this + + confirm({ + content: dict['model.confirm'] + dict['model.delete'] + ` - ${card.label} 锛焋, + okText: dict['model.confirm'], + cancelText: this.state.dict['header.cancel'], + onOk() { + let _columnlist = fromJS(_this.state.columnlist).toJS() + + _columnlist = _columnlist.filter(item => item.uuid !== card.uuid) + + _this.setState({ + columnlist: _columnlist + }) + _this.props.updatecolumn({...config, columns: _columnlist}) + }, + onCancel() {} + }) + } + + /** + * @description 鏄剧ず鍒楀鍒� + */ + copycolumn = () => { + const { columnlist } = this.state + + let oInput = document.createElement('input') + let val = { + copyType: 'columns', + columns: columnlist + } + + 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' + + message.success('澶嶅埗鎴愬姛銆�') + + document.body.removeChild(oInput) + } + + /** + * @description 鏄剧ず鍒楀瓧娈靛悕鏄剧ず鎴栭殣钘忔帶鍒� + */ + onFieldChange = () => { + const { showField, columnlist } = this.state + + if (!showField) { + let fields = [] + columnlist.forEach(col => { + if (col.field) { + fields.push(col.field) + } + }) + + fields = fields.join(',') + + let textArea = document.createElement('textarea') + textArea.value = fields + document.body.appendChild(textArea) + textArea.select() + + try { + document.execCommand('copy') + document.body.removeChild(textArea) + } catch (err) { + document.body.removeChild(textArea) + } + } + + this.setState({ + showField: !showField + }) + } + + render() { + const { config } = this.props + const { modaltype, columnlist, dict, card } = this.state + + return ( + <div className="model-table-column-list"> + <Tooltip placement="bottomLeft" overlayClassName="middle" title={dict['model.tooltip.column.guide']}> + <Icon type="question-circle" /> + </Tooltip> + {columnlist && columnlist.length > 0 ? + <Icon className="column-copy" title="copy" type="copy" onClick={this.copycolumn} /> : null + } + <Switch checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={this.state.showField} onChange={this.onFieldChange} /> + <DragElement + list={columnlist} + setting={config.setting} + gridBtn={config.gridBtn} + handleList={this.handleList} + handleMenu={this.handleColumn} + deleteMenu={this.deleteElement} + handleGridBtn={this.handleGridBtn} + showfield={this.state.showField} + placeholder={this.state.dict['header.form.column.placeholder']} + /> + {/* 鏄剧ず鍒楃紪杈� */} + <Modal + title={dict['header.modal.column.edit']} + visible={modaltype === 'columns'} + width={750} + maskClosable={false} + onOk={this.handleSubmit} + onCancel={this.editModalCancel} + destroyOnClose + > + <ColumnForm + dict={dict} + card={card} + MenuID={this.props.menu.MenuID} + inputSubmit={this.handleSubmit} + formlist={this.state.formlist} + wrappedComponentRef={(inst) => this.columnFormRef = inst} + /> + </Modal> + {/* 鍚堝苟鍒楃紪杈� */} + <Modal + title={dict['header.modal.colspan.edit']} + visible={modaltype === 'colspan'} + width={750} + maskClosable={false} + onOk={this.handleSubmit} + onCancel={this.editModalCancel} + destroyOnClose + > + <ColspanForm + dict={dict} + card={card} + inputSubmit={this.handleSubmit} + columns={columnlist} + wrappedComponentRef={(inst) => this.columnFormRef = inst} + /> + </Modal> + {/* 鎿嶄綔鍒楃紪杈� */} + <Modal + title={dict['header.modal.gridbtn.edit']} + visible={modaltype === 'gridbtn'} + width={700} + maskClosable={false} + onOk={this.handleSubmit} + onCancel={this.editModalCancel} + destroyOnClose + > + <GridBtnForm + dict={dict} + inputSubmit={this.handleSubmit} + card={config.gridBtn} + wrappedComponentRef={(inst) => this.gridBtnFormRef = inst} + /> + </Modal> + {this.state.loading && <Spin size="large" />} + </div> + ) + } +} + +export default ColumnComponent \ No newline at end of file diff --git a/src/templates/sharecomponent/columncomponent/index.scss b/src/templates/sharecomponent/columncomponent/index.scss new file mode 100644 index 0000000..663681f --- /dev/null +++ b/src/templates/sharecomponent/columncomponent/index.scss @@ -0,0 +1,85 @@ +.model-table-column-list { + position: relative; + padding: 0px 20px 100px; + .ant-switch { + position: absolute; + right: 20px; + top: -10px; + } + .column-copy { + position: absolute; + font-size: 16px; + right: 75px; + top: -7px; + color: #26C281; + } + > .ant-row { + background: #fafafa; + border-radius: 4px; + min-height: 47px; + border: 1px solid #e8e8e8; + .column-box { + display: flex; + } + .column-box:not(:first-child) { + border-top: 1px solid #e8e8e8; + } + .page-card { + position: relative; + padding: 0px; + min-height: 45px; + > div { + padding: 12px 0px 0px; + cursor: move; + height: 100%; + .ant-table-column-sorters { + padding: 0px 8px 12px; + } + .ant-table-column-fields { + padding: 0px 8px 5px; + } + } + .ant-table-column-sorter { + position: relative; + display: inline-block; + width: 24px; + font-size: 12px; + color: #bfbfbf; + .anticon-caret-up { + position: relative; + left: 10px; + top: -3px; + } + .anticon-caret-down { + position: relative; + left: -2px; + top: 3px; + } + } + .edit { + position: absolute; + left: 0; + top: 0px; + color: #1890ff; + cursor: pointer; + display: none; + } + .edit.close { + left: 20px; + color: #ff4d4f; + } + .ant-checkbox-inner { + margin-top: 14px; + margin-left: calc(50% - 8px); + } + } + .page-card:hover { + .edit { + display: inline-block; + } + } + .page-card:not(:last-child) { + border-right: 1px solid #e8e8e8; + } + } +} \ No newline at end of file diff --git a/src/templates/sharecomponent/fieldscomponent/editcard/index.jsx b/src/templates/sharecomponent/fieldscomponent/editcard/index.jsx new file mode 100644 index 0000000..c0c579d --- /dev/null +++ b/src/templates/sharecomponent/fieldscomponent/editcard/index.jsx @@ -0,0 +1,157 @@ +import React, {Component} from 'react' +import { Row, Col, Icon, Radio, Input, Button } from 'antd' +import './index.scss' + +const { Search } = Input + +class EditCardCell extends Component { + constructor(props) { + super(props) + + let _type = props.card.type + if (props.type === 'columns') { + if (_type === 'date' || _type === 'datetime') { + _type = 'text' + } + } else if (props.type === 'search') { + if (_type === 'number') { + _type = 'text' + } else if (_type === 'datetime') { + _type = 'daterange' + } + } else if (props.type === 'form') { + + } + + this.state = { + card: {...props.card, type: _type}, + type: props.type + } + } + + changeSelect = () => { + const { card } = this.state + this.setState({ + card: {...card, selected: !card.selected} + }, () => { + this.props.changeCard(this.state.card) + }) + } + + changeType = (e) => { + const { card } = this.state + this.setState({ + card: {...card, type: e.target.value} + }, () => { + this.props.changeCard(this.state.card) + }) + } + + render() { + const { card, type } = this.state + return ( + <div className={'ant-card ant-card-bordered ' + (card.selected ? 'selected' : '')} > + <div className="base" onClick={this.changeSelect}> + <Icon type="check" /> + <p title={card.field}>{this.props.dict['header.form.field']}锛� <span>{card.field}</span></p> + <p title={card.label}>{this.props.dict['header.form.name']}锛� <span>{card.label}</span></p> + </div> + {type === 'search' ? + <Radio.Group onChange={this.changeType} value={card.type} disabled={!card.selected}> + <Radio value="text">text</Radio> + <Radio value="select">select</Radio> + <Radio value="daterange">dateRange</Radio> + </Radio.Group> : null + } + {type === 'columns' ? + <Radio.Group onChange={this.changeType} value={card.type} disabled={!card.selected}> + <Radio value="text">text</Radio> + <Radio value="number">number</Radio> + <Radio value="picture">picture</Radio> + </Radio.Group> : null + } + {type === 'form' ? + <Radio.Group onChange={this.changeType} value={card.type} disabled={!card.selected}> + <Radio value="text">text</Radio> + <Radio value="number">number</Radio> + <Radio value="select">select</Radio> + <Radio value="date">date</Radio> + </Radio.Group> : null + } + </div> + ) + } +} + +class EditCard extends Component { + constructor(props) { + super(props) + + this.state = { + dataSource: props.data, + selectCards: props.data.filter(item => item.selected), + type: props.type, + searchKey: '', + loading: false + } + } + + changeCard = (item) => { + let cards = JSON.parse(JSON.stringify(this.state.selectCards)) + + if (!item.selected) { + cards = cards.filter(card => card.field !== item.field) + } else { + cards.push(item) + } + + this.setState({ + selectCards: cards + }) + } + + reset = () => { + this.setState({ + searchKey: '', + loading: true + }, () => { + this.setState({ + loading: false + }) + }) + } + + render() { + const { dataSource, type, loading } = this.state + + return ( + <div className="common-modal-edit-card"> + <Row className="search-row"> + <Col span={8}> + {!loading ? <Search placeholder={this.props.dict['header.form.field.placeholder']} onSearch={value => {this.setState({searchKey: value})}} enterButton /> : null} + </Col> + <Col span={8}> + <Button onClick={this.reset}> + {this.props.dict['header.reset']} + </Button> + </Col> + </Row> + <Row> + {dataSource.map((item, index) => { + if (item.field.toLowerCase().indexOf(this.state.searchKey.toLowerCase()) >= 0) { + return ( + <Col key={index} span={8}> + <EditCardCell ref={'cellCard' + index} type={type} card={item} dict={this.props.dict} changeCard={this.changeCard} /> + </Col> + ) + } else { + return '' + } + })} + </Row> + </div> + ) + } +} + +export default EditCard \ No newline at end of file diff --git a/src/templates/sharecomponent/fieldscomponent/editcard/index.scss b/src/templates/sharecomponent/fieldscomponent/editcard/index.scss new file mode 100644 index 0000000..a504e4a --- /dev/null +++ b/src/templates/sharecomponent/fieldscomponent/editcard/index.scss @@ -0,0 +1,49 @@ +.common-modal-edit-card { + margin-left: -10px; + margin-right: -10px; + .ant-col { + padding: 10px; + .ant-card { + padding: 0px 10px 10px; + p { + margin-bottom: 5px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + label { + margin-right: 15px; + span.ant-radio + * { + padding-right: 0px; + padding-left: 4px; + } + } + .anticon { + position: absolute; + top: 10px; + right: 10px; + opacity: 0.4; + } + .base { + padding-top: 10px; + cursor: pointer; + } + } + .ant-card.selected { + border-color: #1890ff; + box-shadow: 0px 0px 4px #1890ff; + .anticon { + opacity: 1; + color: #1890ff; + } + p { + color: #1890ff; + } + } + } + .search-row { + .ant-col { + padding-top: 0px; + } + } +} diff --git a/src/templates/sharecomponent/fieldscomponent/index.jsx b/src/templates/sharecomponent/fieldscomponent/index.jsx new file mode 100644 index 0000000..31db78f --- /dev/null +++ b/src/templates/sharecomponent/fieldscomponent/index.jsx @@ -0,0 +1,252 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { fromJS } from 'immutable' +import { Button, Modal, Empty, notification } from 'antd' + +import Utils from '@/utils/utils.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import EditCard from './editcard' + +import './index.scss' + +// **鎮茶鑰呭線寰�姝g‘锛屼箰瑙傝�呭線寰�鎴愬姛 +class FieldsComponent extends Component { + static propTpyes = { + type: PropTypes.string, // 鎼滅储鏉′欢娣诲姞銆佹樉绀哄垪娣诲姞 + config: PropTypes.object, // 瀹瑰櫒Id + tableFields: PropTypes.string, // 宸查�夎〃瀛楁闆� + updatefield: PropTypes.func + } + + state = { + dict: (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS, + fields: [], // 瀛楁闆� + tableVisible: false, // 妯℃�佹鎺у埗 + } + + queryField = () => { + const { type, config, tableFields } = this.props + // 鍒ゆ柇鏄惁宸查�夋嫨琛ㄥ悕 + if (!config.tables || config.tables.length === 0) { + notification.warning({ + top: 92, + message: '璇烽�夋嫨琛ㄥ悕锛�', + duration: 5 + }) + return + } + + // 琛ㄥ瓧娈甸泦杞负map鏁版嵁 + let columns = new Map() + tableFields.forEach(table => { + table.columns.forEach(column => { + columns.set(column.field, column) + }) + }) + + if (type === 'search') { + // 娣诲姞鎼滅储鏉′欢锛屽瓧娈甸泦涓瓨鍦ㄦ悳绱㈡潯浠跺瓧娈碉紝浣跨敤鎼滅储鏉′欢瀵硅薄鏇挎崲瀛楁闆嗭紝璁剧疆鏁版嵁绫诲瀷 + config.search.forEach(item => { + if (columns.has(item.field)) { + let _datatype = columns.get(item.field).datatype + columns.set(item.field, {...item, selected: true, datatype: _datatype}) + } + }) + } else if (type === 'columns') { + // 娣诲姞鏄剧ず鍒楋紝瀛楁闆嗕腑瀛樺湪鏄剧ず鍒楀瓧娈碉紝浣跨敤鏄剧ず鍒楀璞℃浛鎹㈠瓧娈甸泦锛岃缃暟鎹被鍨� + config.columns.forEach(item => { + if (columns.has(item.field)) { + let _datatype = columns.get(item.field).datatype + columns.set(item.field, {...item, selected: true, datatype: _datatype}) + } + }) + } + + // 鏄剧ず瀛楁闆嗗脊绐� + this.setState({ + tableVisible: true, + fields: [...columns.values()] + }) + } + + addFieldSubmit = () => { + const { type } = this.props + // 瀛楁闆嗕负绌猴紝鍏抽棴寮圭獥 + if (!this.state.fields || this.state.fields.length === 0) { + this.setState({ + tableVisible: false + }) + } + + let config = fromJS(this.props.config).toJS() + + // 鑾峰彇宸查�夊瓧娈甸泦鍚� + let cards = this.refs.searchcard.state.selectCards + let columnsMap = new Map() + cards.forEach(card => { + columnsMap.set(card.field, card) + }) + + let items = [] + if (type === 'search') { + config.search.forEach(item => { + if (columnsMap.has(item.field)) { + let cell = columnsMap.get(item.field) + + if (cell.selected && cell.type === item.type) { // 鏁版嵁鏈慨鏀� + items.push(item) + } else if (cell.selected) { // 鏁版嵁绫诲瀷淇敼 + if (cell.type === 'select') { + item.match = '=' + } else if (cell.type === 'daterange') { + item.match = 'between' + } else { + cell.type = 'text' + item.match = 'like' + } + + item.type = cell.type + item.initval = '' + items.push(item) + } + columnsMap.delete(item.field) + } else if (!item.origin) { + items.push(item) + } + }) + + let _columns = [...columnsMap.values()] + + _columns.forEach(item => { + if (item.selected) { + let _match = '' + if (item.type === 'select') { + _match = '=' + } else if (item.type === 'daterange') { + _match = 'between' + } else { + item.type = 'text' + _match = 'like' + } + + let newcard = { + uuid: Utils.getuuid(), + label: item.label, + field: item.field, + initval: '', + type: item.type, + resourceType: '0', + setAll: 'false', + options: [], + dataSource: '', + linkField: '', + valueField: '', + valueText: '', + orderBy: '', + orderType: 'asc', + match: _match, + display: 'dropdown' + } + + items.push(newcard) + } + }) + } else if (type === 'columns') { + config.columns.forEach(item => { + if (columnsMap.has(item.field)) { + let cell = columnsMap.get(item.field) + + if (cell.selected) { + items.push(item) + } + columnsMap.delete(item.field) + } else if (!item.origin) { + items.push(item) + } + }) + + let _columns = [...columnsMap.values()] + + _columns.forEach(item => { + if (item.selected) { + let newcard = { + uuid: Utils.getuuid(), + Align: 'left', + label: item.label, + field: item.field, + Hide: 'false', + IsSort: item.type === 'picture' ? 'false' : 'true', + type: item.type, + Width: 120 + } + + items.push(newcard) + } + }) + } + + let _config = null + + if (type === 'search') { + _config = {...this.props.config, search: items} + } else if (type === 'columns') { + _config = {...this.props.config, columns: items} + } + + if (_config) { + this.props.updatefield(_config) + + notification.success({ + top: 92, + message: '鎿嶄綔鎴愬姛', + duration: 2 + }) + } + } + + + render() { + const { type } = this.props + const { dict, fields } = this.state + + let label = '' + if (type === 'search') { + label = dict['header.menu.search.add'] + } else if (type === 'columns') { + label = dict['header.menu.column.add'] + } + + return ( + <div> + <Button type="primary" block onClick={this.queryField}>{label}</Button> + {/* 鏍规嵁瀛楁鍚嶆坊鍔犳樉绀哄垪鍙婃悳绱㈡潯浠� */} + <Modal + wrapClassName="model-table-fieldmanage-modal" + title={dict['model.edit']} + visible={this.state.tableVisible} + width={'65vw'} + maskClosable={false} + style={{minWidth: '900px', maxWidth: '1200px'}} + cancelText={dict['header.close']} + onOk={this.addFieldSubmit} + onCancel={() => { // 鍙栨秷娣诲姞 + this.setState({ + tableVisible: false + }) + }} + destroyOnClose + > + {fields.length > 0 ? + <EditCard data={fields} ref="searchcard" type={type} dict={dict} /> : null + } + {(!fields || fields.length === 0) && + <Empty /> + } + </Modal> + </div> + ) + } +} + +export default FieldsComponent \ No newline at end of file diff --git a/src/templates/sharecomponent/fieldscomponent/index.scss b/src/templates/sharecomponent/fieldscomponent/index.scss new file mode 100644 index 0000000..eb8645e --- /dev/null +++ b/src/templates/sharecomponent/fieldscomponent/index.scss @@ -0,0 +1,27 @@ +.model-table-fieldmanage-modal { + .ant-modal { + top: 50px; + padding-bottom: 5px; + .ant-modal-body { + max-height: calc(100vh - 190px); + overflow-y: auto; + .ant-empty { + margin: 15vh 8px; + } + } + .ant-modal-body::-webkit-scrollbar { + width: 7px; + } + .ant-modal-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); + } + .ant-modal-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); + background: rgba(0, 0, 0, 0); + } + } +} \ No newline at end of file diff --git a/src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx b/src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx new file mode 100644 index 0000000..87b61b3 --- /dev/null +++ b/src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx @@ -0,0 +1,101 @@ +import React from 'react' +import { useDrag, useDrop } from 'react-dnd' +import { Icon, Select, DatePicker, Input } from 'antd' +import moment from 'moment' +import './index.scss' + +const { MonthPicker, WeekPicker, RangePicker } = DatePicker + +const Card = ({ id, card, moveCard, copyCard, findCard, editCard, delCard, hasDrop }) => { + const originalIndex = findCard(id).index + const [{ isDragging }, drag] = useDrag({ + item: { type: 'search', id, originalIndex }, + collect: monitor => ({ + isDragging: monitor.isDragging(), + }), + }) + const [, drop] = useDrop({ + accept: 'search', + canDrop: () => true, + drop: (item) => { + if (!item.hasOwnProperty('originalIndex')) { + hasDrop(card) + } + }, + hover({ id: draggedId }) { + if (!draggedId) return + if (draggedId !== id) { + const { index: overIndex } = findCard(id) + moveCard(draggedId, overIndex) + } + }, + }) + const opacity = isDragging ? 0 : 1 + + let _defaultValue = '' // 涓嬫媺鎼滅储銆佹椂闂磋寖鍥寸被鍨嬶紝鍒濆鍊奸渶瑕侀澶勭悊 + + if (card.type === 'multiselect' || card.type === 'select' || card.type === 'link') { + if (card.initval) { + let _option = card.options.filter(option => option.Value === card.initval)[0] + if (_option) { + _defaultValue = _option.Text || '' + } else { + _defaultValue = '' + } + } else if (card.setAll === 'true') { + _defaultValue = 'All' + } + } else if (card.type === 'daterange') { + _defaultValue = [null, null] + if (card.initval) { + try { + let _initval = JSON.parse(card.initval) + _defaultValue = [moment().subtract(_initval[0], 'days'), moment().subtract(_initval[1], 'days')] + } catch { + _defaultValue = [null, null] + } + } + } + + return ( + <div className="page-card" style={{ opacity: opacity}}> + <div ref={node => drag(drop(node))}> + <div className="ant-row ant-form-item"> + <div className="ant-col ant-form-item-label ant-col-xs-24 ant-col-sm-8"> + <label className={card.required === 'true' ? 'ant-form-item-required' : ''} title={card.label}>{card.label}</label> + </div> + <div className="ant-col ant-form-item-control-wrapper ant-col-xs-24 ant-col-sm-16"> + {card.type === 'text' ? + <Input style={{marginTop: '4px'}} 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 + } + <div className="input-mask"></div> + </div> + </div> + </div> + <Icon className="edit" title="edit" type="edit" onClick={() => editCard(id)} /> + <Icon className="edit copy" title="copy" type="copy" onClick={() => copyCard(id)} /> + <Icon className="edit close" title="delete" type="close" onClick={() => delCard(id)} /> + </div> + ) +} +export default Card diff --git a/src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx b/src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx new file mode 100644 index 0000000..0281328 --- /dev/null +++ b/src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx @@ -0,0 +1,155 @@ +import React, { useState } from 'react' +import { useDrop } from 'react-dnd' +import { is, fromJS } from 'immutable' +import update from 'immutability-helper' +import { Col } from 'antd' +import Utils from '@/utils/utils.js' +import Card from './card' +import './index.scss' + +const Container = ({list, placeholder, handleList, handleMenu, deleteMenu }) => { + let target = null + + const [cards, setCards] = useState(list) + const moveCard = (id, atIndex) => { + const { card, index } = findCard(id) + 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) + handleMenu(card) + } + + + const delCard = id => { + const { card } = findCard(id) + deleteMenu(card) + } + + const copyCard = id => { + const { card } = findCard(id) + let copycard = fromJS(card).toJS() + + copycard.uuid = Utils.getuuid() + copycard.origin = false + copycard.copyType = 'search' + copycard.label = copycard.label + '(copy)' + copycard.focus = true + + let _val = fromJS(copycard).toJS() + + try { + _val.uuid = Utils.getuuid() + _val = window.btoa(window.encodeURIComponent(JSON.stringify(_val))) + } catch { + console.warn('Stringify Failure') + _val = '' + } + + if (_val) { + let oInput = document.createElement('input') + oInput.value = _val + document.body.appendChild(oInput) + oInput.select() + document.execCommand('Copy') + document.body.removeChild(oInput) + } + + const { index: overIndex } = findCard(id) + + const _cards = update(cards, { $splice: [[overIndex + 1, 0, copycard]] }) + + handleList(_cards, copycard) + } + + const hasDrop = (item) => { + target = item + } + + const [, drop] = useDrop({ + accept: 'search', + drop(item) { + if (item.hasOwnProperty('originalIndex')) { + return + } + + let newcard = {} + newcard.uuid = Utils.getuuid() + newcard.focus = true + + let _match = 'like' + if (item.subType === 'select' || item.subType === 'link') { + _match = '=' + } else if (item.subType === 'date' || item.subType === 'datemonth') { + _match = '>=' + } else if (item.subType === 'dateweek' || item.subType === 'daterange') { + _match = 'between' + } + + newcard.label = 'label' + newcard.initval = '' + newcard.type = item.subType + newcard.resourceType = '0' + newcard.options = [] + newcard.setAll = 'false' + newcard.orderType = 'asc' + newcard.match = _match + newcard.display = 'dropdown' + + let targetId = cards.length > 0 ? cards[cards.length - 1].uuid : 0 + if (target) { + targetId = target.uuid + } + + const { index: overIndex } = findCard(`${targetId}`) + let targetIndex = overIndex + + targetIndex++ + + const _cards = update(cards, { $splice: [[targetIndex, 0, newcard]] }) + + handleList(_cards, newcard) + target = null + } + }) + + return ( + <div ref={drop} className="ant-row"> + {cards.map(card => ( + <Col key={card.uuid} span={card.ratio || 6}> + <Card + id={`${card.uuid}`} + card={card} + moveCard={moveCard} + copyCard={copyCard} + editCard={editCard} + delCard={delCard} + findCard={findCard} + hasDrop={hasDrop} + /> + </Col> + ))} + + {cards.length === 0 ? + <div className="common-drawarea-placeholder"> + {placeholder} + </div> : null + } + </div> + ) +} +export default Container diff --git a/src/templates/sharecomponent/searchcomponent/dragsearch/index.scss b/src/templates/sharecomponent/searchcomponent/dragsearch/index.scss new file mode 100644 index 0000000..369ae98 --- /dev/null +++ b/src/templates/sharecomponent/searchcomponent/dragsearch/index.scss @@ -0,0 +1,6 @@ +.common-drawarea-placeholder { + width: 100%; + line-height: 65px; + text-align: center; + color: #bcbcbc; +} \ No newline at end of file diff --git a/src/templates/sharecomponent/searchcomponent/index.jsx b/src/templates/sharecomponent/searchcomponent/index.jsx new file mode 100644 index 0000000..fa84f28 --- /dev/null +++ b/src/templates/sharecomponent/searchcomponent/index.jsx @@ -0,0 +1,280 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Tooltip, Modal, notification } from 'antd' +import moment from 'moment' + +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 { getSearchForm } from '@/templates/zshare/formconfig' + +import SearchForm from './searchform' +import DragElement from './dragsearch' +import './index.scss' + +const { confirm } = Modal + +// **鎮茶鑰呭線寰�姝g‘锛屼箰瑙傝�呭線寰�鎴愬姛 +class SearchComponent extends Component { + static propTpyes = { + menu: PropTypes.object, // 褰撳墠鑿滃崟淇℃伅 + config: PropTypes.object, // 閰嶇疆淇℃伅 + pasteContent: PropTypes.object, // 绮樿创閰嶇疆淇℃伅 + optionLibs: PropTypes.any, // 涓嬫媺瀛楀吀 + sysRoles: PropTypes.array, // 瑙掕壊鍒楄〃锛岄粦鍚嶅崟 + updatesearch: PropTypes.func // 鏇存柊 + } + + state = { + dict: (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS, + searchlist: null, // 鎼滅储鏉′欢闆� + sqlVerifing: false, // sql楠岃瘉涓� + visible: false, // 妯℃�佹鎺у埗 + card: null // 缂栬緫涓厓绱� + } + + /** + * @description 鎼滅储鏉′欢鍒濆鍖� + */ + UNSAFE_componentWillMount () { + this.setState({ + searchlist: fromJS(this.props.config.search).toJS() + }) + } + + /** + * @description 鐩戝惉鍒版悳绱㈡潯浠跺鍒舵椂锛岃Е鍙戞悳绱㈡潯浠剁紪杈� + */ + UNSAFE_componentWillReceiveProps (nextProps) { + const { searchlist } = this.state + + if (nextProps.pasteContent && nextProps.pasteContent.copyType === 'search') { + this.setState({searchlist: [...searchlist, nextProps.pasteContent]}) + this.handleSearch(nextProps.pasteContent) + } else if (!is(fromJS(nextProps.config.search), fromJS(this.props.config.search)) && !is(fromJS(nextProps.config.search), fromJS(searchlist))) { + this.setState({searchlist: nextProps.config.search}) + } + } + + /** + * @description 鎼滅储鏉′欢椤哄簭璋冩暣锛屾垨鎷栨嫿娣诲姞 + */ + handleList = (list, card) => { + const { config } = this.props + + if (card) { + this.setState({searchlist: list}) + this.handleSearch(card) + } else { + this.setState({searchlist: list}) + this.props.updatesearch({...config, search: list}) + } + } + + /** + * @description 鎼滅储鏉′欢缂栬緫锛岃幏鍙栨悳绱㈡潯浠惰〃鍗曚俊鎭� + */ + handleSearch = (card) => { + this.setState({ + visible: true, + card: card, + formlist: getSearchForm(card, this.props.sysRoles) + }) + } + + /** + * @description 鍙栨秷淇濆瓨锛屽鏋滃厓绱犱负鏂版坊鍏冪礌锛屽垯浠庡簭鍒椾腑鍒犻櫎 + */ + editModalCancel = () => { + const { card } = this.state + + if (card.focus) { + let searchlist = fromJS(this.state.searchlist).toJS() + + searchlist = searchlist.filter(item => item.uuid !== card.uuid) + + this.setState({ + card: null, + searchlist: searchlist, + visible: false + }) + } else { + this.setState({ + card: null, + visible: false + }) + } + } + + /** + * @description 鎼滅储淇敼鍚庢彁浜や繚瀛� + * 1銆佸幓闄ょ郴缁熼粯璁ゆ悳绱㈡潯浠� + * 2銆佸瓧娈靛強鎻愮ず鏂囧瓧閲嶅鏍¢獙 + * 3銆佹洿鏂颁笅鎷夎彍鍗曞彲閫夐泦鍚� + * 4銆佷笅鎷夎彍鍗曟暟鎹簮璇硶楠岃瘉 + */ + handleSubmit = () => { + const { optionLibs, menu, config } = this.props + let _searchlist = fromJS(this.state.searchlist).toJS() + + this.searchFormRef.handleConfirm().then(res => { + let fieldrepet = false // 瀛楁閲嶅 + let labelrepet = false // 鎻愮ず鏂囧瓧閲嶅 + + _searchlist = _searchlist.filter(item => !item.origin || item.uuid === res.uuid) // 鍘婚櫎绯荤粺椤� + + _searchlist = _searchlist.map(item => { // 鏁版嵁鏇存柊鍙婇噸澶嶆娴� + if (item.uuid !== res.uuid && res.field && item.field) { + if (item.field === res.field) { + fieldrepet = true + } else if (item.label === res.label) { + labelrepet = true + } + } + + if (item.uuid === res.uuid) { + return res + } else { + return item + } + }) + + if (fieldrepet) { + notification.warning({ + top: 92, + message: this.state.dict['model.field.exist'] + ' !', + duration: 5 + }) + return + } else if (labelrepet) { + notification.warning({ + top: 92, + message: this.state.dict['model.name.exist'] + ' !', + duration: 5 + }) + return + } + + if ( res.options && res.options.length > 0 ) { // 涓嬫媺鑿滃崟鍙�夐泦鍚� + optionLibs.set(menu.MenuID + res.uuid, { + uuid: menu.MenuID + res.uuid, + label: res.label, + parname: menu.MenuName, + type: 'search', + options: res.options + }) + } + + if ((res.type === 'select' || res.type === 'multiselect' || res.type === 'link') && res.resourceType === '1' && /\s/.test(res.dataSource)) { + this.setState({ + sqlVerifing: true + }) + + let param = { + func: 's_debug_sql', + LText: res.dataSource + } + param.LText = Utils.formatOptions(param.LText) + param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' + param.secretkey = Utils.encrypt(param.LText, 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, + searchlist: _searchlist, + visible: false + }) + this.props.updatesearch({...config, search: _searchlist}, optionLibs) + } else { + this.setState({sqlVerifing: false}) + + Modal.error({ + title: result.message + }) + } + }) + } else { + this.setState({ + searchlist: _searchlist, + visible: false + }) + this.props.updatesearch({...config, search: _searchlist}, optionLibs) + } + }) + } + + /** + * @description 鎼滅储鏉′欢鍒犻櫎 + */ + deleteElement = (card) => { + const { config } = this.props + const { dict } = this.state + let _this = this + + confirm({ + content: dict['model.confirm'] + dict['model.delete'] + ` - ${card.label} 锛焋, + okText: dict['model.confirm'], + cancelText: this.state.dict['header.cancel'], + onOk() { + let _searchlist = fromJS(_this.state.searchlist).toJS() + + _searchlist = _searchlist.filter(item => item.uuid !== card.uuid) + + _this.setState({ + searchlist: _searchlist + }, () => { + _this.props.updatesearch({...config, search: _searchlist}) + }) + }, + onCancel() {} + }) + } + + render() { + const { dict, searchlist, visible, sqlVerifing, card } = this.state + + return ( + <div className="model-table-search-list"> + <Tooltip placement="bottomLeft" overlayClassName="middle" title={dict['model.tooltip.search.guide']}> + <Icon type="question-circle" /> + </Tooltip> + <DragElement + list={searchlist} + handleList={this.handleList} + handleMenu={this.handleSearch} + deleteMenu={this.deleteElement} + placeholder={dict['header.form.search.placeholder']} + /> + {/* 缂栬緫鎼滅储鏉′欢 */} + <Modal + title={dict['model.searchCriteria'] + '-' + (card && card.copyType === 'search' ? dict['model.copy'] : dict['model.edit'])} + visible={visible} + width={750} + maskClosable={false} + onOk={this.handleSubmit} + confirmLoading={sqlVerifing} + onCancel={this.editModalCancel} + destroyOnClose + > + <SearchForm + dict={dict} + card={this.state.card} + formlist={this.state.formlist} + inputSubmit={this.handleSubmit} + optionLibs={this.props.optionLibs} + wrappedComponentRef={(inst) => this.searchFormRef = inst} + /> + </Modal> + </div> + ) + } +} + +export default SearchComponent \ No newline at end of file diff --git a/src/templates/sharecomponent/searchcomponent/index.scss b/src/templates/sharecomponent/searchcomponent/index.scss new file mode 100644 index 0000000..2463343 --- /dev/null +++ b/src/templates/sharecomponent/searchcomponent/index.scss @@ -0,0 +1,84 @@ +.model-table-search-list { + padding: 1px 24px 20px; + min-height: 87px; + border-bottom: 1px solid #d9d9d9; + > .ant-row { + min-height: 65px; + } + .ant-row .ant-col-6 { + padding: 0 12px!important; + } + .ant-row.ant-form-item .ant-col { + padding: 0; + } + .page-card { + position: relative; + background: #ffffff; + border-radius: 2px; + padding-top: 15px; + .ant-form-item { + cursor: move; + display: flex; + margin-bottom: 0px; + .ant-form-item-label { + height: 40px; + label { + width: 100%; + cursor: move; + overflow: hidden; + display: inline-block; + text-overflow: ellipsis; + white-space: nowrap; + } + } + .ant-form-item-control-wrapper { + flex: 1 1; + .ant-select { + width: 100%; + margin-top: 4px; + } + .ant-calendar-picker { + margin-top: 4px; + } + .input-mask { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + opacity: 0; + z-index: 2; + } + .data-range .ant-calendar-picker-input { + padding: 4px 20px 4px 5px; + font-size: 13px; + } + } + } + .edit { + position: absolute; + left: 0; + top: 5px; + color: #1890ff; + cursor: pointer; + display: none; + } + .edit.copy { + left: 20px; + color: #26C281; + } + .edit.close { + left: 40px; + color: #ff4d4f; + } + } + .page-card:hover { + .edit { + display: inline-block; + } + } + .ant-calendar-picker { + min-width: 100px!important; + width: 100%; + } +} \ No newline at end of file diff --git a/src/templates/sharecomponent/searchcomponent/searcheditable/index.jsx b/src/templates/sharecomponent/searchcomponent/searcheditable/index.jsx new file mode 100644 index 0000000..8abe02b --- /dev/null +++ b/src/templates/sharecomponent/searchcomponent/searcheditable/index.jsx @@ -0,0 +1,265 @@ +import React, {Component} from 'react' +import { is, fromJS } from 'immutable' +import { Table, Input, Button, Popconfirm, Form, Icon } from 'antd' +import Utils from '@/utils/utils.js' +import './index.scss' + +const EditableContext = React.createContext() + +const EditableRow = ({ form, index, ...props }) => ( + <EditableContext.Provider value={form}> + <tr {...props} /> + </EditableContext.Provider> +) + +const EditableFormRow = Form.create()(EditableRow) + +class EditableCell extends Component { + state = { + editing: false + } + + toggleEdit = () => { + const editing = !this.state.editing + this.setState({ editing }, () => { + if (editing && this.input && this.input.select) { + this.input.select() + } else if (editing && this.input && this.input.focus) { + this.input.focus() + } + }) + } + + save = e => { + const { record, handleSave } = this.props + this.form.validateFields((error, values) => { + handleSave({ ...record, ...values }) + if (error && error[e.currentTarget.id]) { + return + } + this.toggleEdit() + }) + } + + renderCell = form => { + this.form = form + const { children, dataIndex, record } = this.props + const { editing } = this.state + return editing ? ( + <Form.Item style={{ margin: 0 }}> + {form.getFieldDecorator(dataIndex, { + rules: [ + { + required: true, + message: 'NOT NULL.', + }, + ], + initialValue: record[dataIndex] + })(<Input ref={node => (this.input = node)} autoComplete="off" onPressEnter={this.save} onBlur={this.save} />)} + </Form.Item> + ) : ( + <div + className="editable-cell-value-wrap" + onClick={this.toggleEdit} + > + {children} + </div> + ) + } + + render() { + const { + editable, + dataIndex, + title, + record, + index, + handleSave, + children, + ...restProps + } = this.props + return ( + <td {...restProps}> + {editable ? ( + <EditableContext.Consumer style={{padding: 0}}>{this.renderCell}</EditableContext.Consumer> + ) : ( + children + )} + </td> + ) + } +} + +class EditTable extends Component { + constructor(props) { + super(props) + let columns = [ + { + title: 'Value', + dataIndex: 'Value', + width: props.type === 'link' ? '27%' : '40%', + editable: true + }, + { + title: 'Text', + dataIndex: 'Text', + width: props.type === 'link' ? '27%' : '40%', + editable: true + }, + { + title: 'Action', + align: 'center', + dataIndex: 'operation', + render: (text, record) => + this.state.dataSource.length >= 1 ? ( + <Popconfirm title="Sure to delete?" onConfirm={() => this.handleDelete(record.key)}> + <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span> + </Popconfirm> + ) : null, + } + ] + + if (props.type === 'link') { + columns.unshift({ + title: 'ParentID', + dataIndex: 'ParentID', + width: '27%', + editable: true + }) + } + + this.state = { + columns: columns, + dataSource: props.data, + count: props.data.length, + type: props.type + } + } + + handleDelete = key => { + const dataSource = [...this.state.dataSource] + this.setState({ dataSource: dataSource.filter(item => item.key !== key) }) + } + + handleAdd = () => { + const { type, count, dataSource } = this.state + const newData = { + key: Utils.getuuid(), + Value: `${count}`, + Text: `${count}` + } + if (type === 'link') { + newData.ParentID = `${count}` + } + this.setState({ + dataSource: [...dataSource, newData], + count: count + 1 + }) + } + + handleSave = row => { + const newData = [...this.state.dataSource] + const index = newData.findIndex(item => row.key === item.key) + const item = newData[index] + newData.splice(index, 1, { + ...item, + ...row + }) + this.setState({ dataSource: newData }) + } + + resetColumn = (type) => { + let columns = [ + { + title: 'Value', + dataIndex: 'Value', + width: type === 'link' ? '27%' : '40%', + editable: true + }, + { + title: 'Text', + dataIndex: 'Text', + width: type === 'link' ? '27%' : '40%', + editable: true + }, + { + title: 'Action', + align: 'center', + dataIndex: 'operation', + render: (text, record) => + this.state.dataSource.length >= 1 ? ( + <Popconfirm title="Sure to delete?" onConfirm={() => this.handleDelete(record.key)}> + <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span> + </Popconfirm> + ) : null, + } + ] + + if (type === 'link') { + columns.unshift({ + title: 'ParentID', + dataIndex: 'ParentID', + width: '27%', + editable: true + }) + } + + this.setState({ + columns: columns, + type: type + }) + } + + UNSAFE_componentWillReceiveProps (nextProps) { + if (this.props.type !== nextProps.type) { + this.resetColumn(nextProps.type) + } else if (!is(fromJS(this.props.data), fromJS(nextProps.data))) { + this.setState({ + dataSource: nextProps.data, + count: nextProps.data.length + }) + } + } + + render() { + const { dataSource } = this.state + const components = { + body: { + row: EditableFormRow, + cell: EditableCell + } + } + const columns = this.state.columns.map(col => { + if (!col.editable) { + return col + } + return { + ...col, + onCell: record => ({ + record, + editable: col.editable, + dataIndex: col.dataIndex, + title: col.title, + handleSave: this.handleSave, + }) + } + }) + return ( + <div className="common-modal-edit-table"> + <Button onClick={this.handleAdd} type="primary" className="add-row"> + Add + </Button> + <Table + components={components} + rowClassName={() => 'editable-row'} + bordered + dataSource={dataSource} + columns={columns} + pagination={false} + /> + </div> + ) + } +} + +export default EditTable \ No newline at end of file diff --git a/src/templates/sharecomponent/searchcomponent/searcheditable/index.scss b/src/templates/sharecomponent/searchcomponent/searcheditable/index.scss new file mode 100644 index 0000000..f8f0942 --- /dev/null +++ b/src/templates/sharecomponent/searchcomponent/searcheditable/index.scss @@ -0,0 +1,36 @@ +.common-modal-edit-table { + .add-row { + position: absolute; + z-index: 1; + right: 12px; + top: -40px; + } + .ant-table-thead > tr > th { + padding: 10px 16px; + } + .ant-table-tbody > tr > td { + padding: 0px 16px; + } + .editable-cell-value-wrap { + cursor: pointer; + height: 40px; + width: 100px; + display: table-cell; + vertical-align: middle; + word-wrap: break-word; + word-break: break-word; + .ant-input { + height: 30px; + padding: 0 11px; + } + } + .ant-form-item-control-wrapper { + width: 100%; + } + .ant-table-placeholder { + padding: 5px 16px; + .ant-empty-normal { + margin: 0; + } + } +} diff --git a/src/templates/sharecomponent/searchcomponent/searchform/index.jsx b/src/templates/sharecomponent/searchcomponent/searchform/index.jsx new file mode 100644 index 0000000..e7941ec --- /dev/null +++ b/src/templates/sharecomponent/searchcomponent/searchform/index.jsx @@ -0,0 +1,475 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input, Select, Icon, Radio, notification, Tooltip, InputNumber } from 'antd' +import { dateOptions, matchReg, formRule } from '@/utils/option.js' +import EditTable from '../searcheditable' +import Utils from '@/utils/utils.js' +import './index.scss' + +const { TextArea } = Input + +class MainSearch extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + formlist: PropTypes.any, // 琛ㄥ崟 + optionLibs: PropTypes.any, // 鑷畾涔変笅鎷夐泦 + card: PropTypes.object, // 鎼滅储鏉′欢淇℃伅 + inputSubmit: PropTypes.any // 鍥炶溅鎻愪氦浜嬩欢 + } + + state = { + openType: null, // 鎼滅储鏉′欢鏄剧ず绫诲瀷 + resourceType: null, // 涓嬫媺鎼滅储鏃讹紝閫夐」鏉ユ簮绫诲瀷 + formlist: null // 琛ㄥ崟 + } + + /** + * @description 琛ㄥ崟棰勫鐞� + * 1銆佹牴鎹〃鍗曠被鍨嬶紝鏄剧ず琛ㄥ崟鍙紪杈戦」 + * 2銆佷笅鎷夐�夋嫨锛屾牴鎹暟鎹簮绫诲瀷鏄剧ず鐩稿叧閰嶇疆 + */ + UNSAFE_componentWillMount () { + const { formlist, optionLibs } = this.props + + let type = formlist.filter(cell => cell.key === 'type')[0].initVal + let resourceType = formlist.filter(cell => cell.key === 'resourceType')[0].initVal + let _options = ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required'] // 榛樿鏄剧ず椤� + + if ((type === 'multiselect' || type === 'select' || type === 'link') && resourceType === '0') { // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓鸿嚜瀹氫箟璧勬簮 + _options = [..._options, 'resourceType', 'options', 'display', 'quick'] + } else if ((type === 'multiselect' || type === 'select' || type === 'link') && resourceType === '1') { // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓哄悗鍙版暟鎹簮涓幏鍙� + _options = [..._options, 'resourceType', 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'display', 'database'] + } + + if (type === 'select' || type === 'link') { + _options.push('setAll') + } + + if (type === 'link') { // 鍏宠仈绫诲瀷銆佸鍔犲叧鑱斾笂绾х殑瀛楁鍚� + _options = [..._options, 'linkField'] + } + + this.setState({ + openType: type, + resourceType: resourceType, + formlist: formlist.map(form => { + // 琛ㄥ崟涓哄垵濮嬪�煎瓧娈碉紝涓旀暟鎹被鍨嬪睘浜庢椂闂寸被鍨嬫椂锛岃缃垵濮嬪�间负涓嬫媺閫夋嫨锛屽苟閲嶇疆閫夋嫨椤� + if (form.key === 'initval' && dateOptions.hasOwnProperty(type)) { + form.options = dateOptions[type] + form.type = 'select' + } + // 琛ㄥ崟涓哄尮閰嶅瓧娈垫椂锛屾牴鎹笉鍚岀殑绫诲瀷锛屾樉绀哄搴旂殑鍖归厤瑙勫垯 + if (form.key === 'match') { + if (type === 'text') { + form.options = matchReg.text + } else if (type === 'multiselect') { + form.options = matchReg.multiselect + } else if (type === 'select' || type === 'link') { + form.options = matchReg.select + } else if (type === 'date') { + form.options = matchReg.date + } else if (type === 'datemonth') { + form.options = matchReg.datemonth + } else if (type === 'dateweek' || type === 'daterange') { + form.options = matchReg.daterange + } + } else if (form.key === 'quick') { + form.options = [...optionLibs.values()].map(cell => { + return { + value: cell.uuid, + text: cell.label + '(' + cell.parname + ')' + } + }) + } + form.hidden = !_options.includes(form.key) + return form + }) + }) + } + + componentDidMount () { + const { card } = this.props + + if (card.focus) { + try { + let _form = document.getElementById('label') + _form.select() + } catch { + console.warn('琛ㄥ崟focus澶辫触锛�') + } + } + } + + /** + * @description 鎼滅储鏉′欢绫诲瀷鍒囨崲 + */ + openTypeChange = (key, value) => { + const { resourceType } = this.state + + if (key === 'type') { + let _options = ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required'] + + if ((value === 'multiselect' || value === 'select' || value === 'link') && resourceType === '0') { // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓鸿嚜瀹氫箟璧勬簮 + _options = [..._options, 'resourceType', 'options', 'display', 'quick'] + } else if ((value === 'multiselect' || value === 'select' || value === 'link') && resourceType === '1') { // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓哄悗鍙版暟鎹簮涓幏鍙� + _options = [..._options, 'resourceType', 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'display', 'database'] + } + + if (value === 'select' || value === 'link') { + _options.push('setAll') + } + + if (value === 'link') { + _options = [..._options, 'linkField'] + } + + this.setState({ + openType: value, + formlist: this.state.formlist.map(form => { + form.hidden = !_options.includes(form.key) // 闅愯棌琛ㄥ崟 + + if (form.key === 'initval') { + if (dateOptions.hasOwnProperty(value)) { // 鏍规嵁鎼滅储鏉′欢绫诲瀷锛岄�夋嫨鍒濆鍊肩殑绫诲瀷鍙婃暟鎹� + form.options = dateOptions[value] + form.type = 'select' + } else { + form.type = 'text' + } + form.initVal = '' // 鎼滅储鏉′欢绫诲瀷鍒囨崲鏃讹紝鍒濆鍊肩疆绌� + form.hidden = true + } else if (form.key === 'match') { // 鎼滅储鏉′欢绫诲瀷鍒囨崲鏃讹紝鍖归厤瑙勫垯绫诲瀷瀵瑰簲鍒囨崲 + if (value === 'text') { + form.options = matchReg.text + } else if (value === 'multiselect') { + form.options = matchReg.multiselect + } else if (value === 'select' || value === 'link') { + form.options = matchReg.select + } else if (value === 'date') { + form.options = matchReg.date + } else if (value === 'datemonth') { + form.options = matchReg.datemonth + } else if (value === 'dateweek' || value === 'daterange') { + form.options = matchReg.daterange + } + form.hidden = true + } + + return form + }) + }, () => { + this.setState({ + formlist: this.state.formlist.map(form => { + + if (form.key === 'initval') { + form.hidden = false + } else if (form.key === 'match') { + form.initVal = form.options[0].value + form.hidden = false + } + + return form + }) + }) + }) + } else if (key === 'quick') { + let option = this.props.optionLibs.get(value) + + this.setState({ + formlist: this.state.formlist.map(form => { + if (form.key === 'options') { + form.initVal = option.options + } + + return form + }) + }) + } + } + + /** + * @description 鏁版嵁婧愮被鍨嬪垏鎹� + */ + onChange = (e, key) => { + const { openType } = this.state + let value = e.target.value + + if (key === 'resourceType') { + let _options = ['label', 'field', 'initval', 'type', 'match', 'resourceType', 'display', 'ratio', 'blacklist', 'required'] + + if (value === '0') { + _options = [..._options, 'options', 'quick'] + } else if (value === '1') { + _options = [..._options, 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'database'] + } + + if (openType === 'select' || openType === 'link') { + _options.push('setAll') + } + + if (openType === 'link') { + _options = [..._options, 'linkField'] + } + + this.setState({ + resourceType: value, + formlist: this.state.formlist.map(form => { + form.hidden = !_options.includes(form.key) + return form + }) + }) + } + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + getFields() { + const { getFieldDecorator } = this.props.form + const fields = [] + this.state.formlist.forEach((item, index) => { + if (item.hidden) return + + if (item.type === 'text') { // 鏂囨湰鎼滅储 + let rules = [] + if (item.key === 'field') { + rules = [{ + pattern: formRule.field.pattern, + message: formRule.field.message + }, { + max: formRule.field.max, + message: formRule.field.maxMessage + }] + } else { + rules = [{ + max: formRule.input.max, + message: formRule.input.message + }] + } + + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} 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 + '!' + }, + ...rules + ] + })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)} + </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 || 6, + rules: [ + { + required: item.required, + message: this.props.dict['form.required.input'] + item.label + '!' + } + ] + })(<InputNumber min={item.min} max={item.max} precision={0} />)} + </Form.Item> + </Col> + ) + } else if (item.type === 'select') { // 涓嬫媺鎼滅储 + 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 + '!' + } + ] + })( + <Select + showSearch + filterOption={(input, option) => option.props.children[2].toLowerCase().indexOf(input.toLowerCase()) >= 0} + onChange={(value) => {this.openTypeChange(item.key, value)}} + getPopupContainer={() => document.getElementById('commontable-search-form-box')} + > + {item.options.map(option => + <Select.Option id={option.value} title={option.text} key={option.value} value={option.value}> + {item.key === 'icon' && <Icon type={option.text} />} {option.text} + </Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + ) + } else if (item.type === 'radio') { + 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 + '!' + } + ] + })( + <Radio.Group onChange={(e) => {this.onChange(e, item.key)}}> + { + item.options.map(option => { + return ( + <Radio key={option.value} value={option.value}>{option.text}</Radio> + ) + }) + } + </Radio.Group>, + )} + </Form.Item> + </Col> + ) + } else if (item.type === 'textarea') { + fields.push( + <Col span={20} offset={4} key={index}> + <Form.Item className="text-area"> + {getFieldDecorator(item.key, { + initialValue: item.initVal, + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.input'] + item.label + '!' + } + ] + })(<TextArea rows={4} />)} + </Form.Item> + </Col> + ) + } else if (item.type === 'options') { + fields.push( + <Col span={20} offset={4} key={index}> + <EditTable data={item.initVal} type={this.state.openType} ref="editTable"/> + </Col> + ) + } else if (item.type === 'multiselect') { // 澶氶�� + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.label}> + {getFieldDecorator(item.key, { + initialValue: item.initVal || [] + })( + <Select + showSearch + mode="multiple" + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + > + {item.options.map((option, i) => + <Select.Option id={i} key={i} value={option.value}>{option.text}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + ) + } + }) + + return fields + } + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + let isvalid = true + values.uuid = this.props.card.uuid + // 涓嬫媺鑿滃崟鎴栧叧鑱旇彍鍗� + if ((values.type === 'multiselect' || values.type === 'select' || values.type === 'link') && values.resourceType === '0') { + values.options = this.refs.editTable.state.dataSource + values.dataSource = '' + let emptys = [] + if (values.type === 'multiselect' || values.type === 'select') { + emptys = values.options.filter(op => !(op.Value && op.Text)) + } else { + emptys = values.options.filter(op => !(op.Value && op.Text && op.ParentID)) + } + if (emptys.length > 0) { + isvalid = false + } + } else if ((values.type === 'multiselect' || values.type === 'select' || values.type === 'link') && values.resourceType === '1') { + values.options = [] + } + + if (isvalid) { + ['linkField', 'valueField', 'valueText', 'orderBy'].forEach(item => { + if (values[item]) { + values[item] = values[item].replace(/\s* | \t* | \v* | \r*/ig, '') + } + }) + + let error = Utils.verifySql(values.dataSource) + + if (error) { + notification.warning({ + top: 92, + message: '鏁版嵁婧愪腑涓嶅彲浣跨敤' + error, + duration: 5 + }) + return + } + + resolve(values) + } else { + notification.warning({ + top: 92, + message: this.props.dict['header.form.selectItem.error'], + duration: 5 + }) + } + } else { + reject(err) + } + }) + }) + } + + render() { + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + return ( + <Form {...formItemLayout} className="ant-advanced-search-form commontable-search-form" id="commontable-search-form-box"> + <Row gutter={24}>{this.getFields()}</Row> + </Form> + ) + } +} + +export default Form.create()(MainSearch) \ No newline at end of file diff --git a/src/templates/sharecomponent/searchcomponent/searchform/index.scss b/src/templates/sharecomponent/searchcomponent/searchform/index.scss new file mode 100644 index 0000000..b027f37 --- /dev/null +++ b/src/templates/sharecomponent/searchcomponent/searchform/index.scss @@ -0,0 +1,24 @@ +.ant-advanced-search-form.commontable-search-form { + min-height: 180px; + .ant-col-offset-4 { + padding-left: 6px!important; + padding-bottom: 20px; + } + // .ant-form-item { + // margin-bottom: 10px; + // } + .ant-form-item.text-area { + margin-bottom: 0px; + .ant-form-item-control-wrapper { + width: 100%; + } + } + .anticon-question-circle { + color: #c49f47; + position: relative; + left: -3px; + } + .ant-input-number { + width: 100%; + } +} \ No newline at end of file diff --git a/src/templates/sharecomponent/tablecomponent/index.jsx b/src/templates/sharecomponent/tablecomponent/index.jsx new file mode 100644 index 0000000..4a17396 --- /dev/null +++ b/src/templates/sharecomponent/tablecomponent/index.jsx @@ -0,0 +1,455 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { fromJS } from 'immutable' +import { Icon, Tooltip, Select, List, notification } from 'antd' +import moment from 'moment' + +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 { queryTableSql } from '@/utils/option.js' + +import './index.scss' + +const { Option } = Select + +// **鎮茶鑰呭線寰�姝g‘锛屼箰瑙傝�呭線寰�鎴愬姛 +class TablesComponent extends Component { + static propTpyes = { + config: PropTypes.object, // 瀹瑰櫒Id + containerId: PropTypes.string, // 瀹瑰櫒Id + updatetable: PropTypes.func + } + + state = { + dict: (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS, + tables: [], // 绯荤粺琛� + tableFields: [], // 宸查�夎〃瀛楁闆� + selectedTables: [], // 宸查�夎〃 + searchlist: null, // 鎼滅储鏉′欢闆� + visible: false // 妯℃�佹鎺у埗 + } + + /** + * @description 鎼滅储鏉′欢鍒濆鍖� + */ + UNSAFE_componentWillMount () { + const { config } = this.props + + this.setState({ + selectedTables: config.tables ? fromJS(config.tables).toJS() : [] + }, () => { + this.gettableFields() + }) + } + + componentDidMount () { + this.gettables() + } + + /** + * @description 鑾峰彇绯荤粺琛� + */ + gettables = () => { + 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') + '.000' + param.secretkey = Utils.encrypt(param.LText, param.timestamp) + + Api.getSystemConfig(param).then(res => { + if (res.status) { + this.setState({ + tables: res.data + }) + } else { + notification.warning({ + top: 92, + message: res.message, + duration: 5 + }) + } + }) + } + + gettableFields = () => { + let deffers = this.state.selectedTables.map(item => { + return new Promise(resolve => { + Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: item.TbName}).then(res => { + res.TBName = item.TbName + resolve(res) + }) + }) + }) + Promise.all(deffers).then(response => { + let _columns = [] + response.forEach(res => { + if (res.status) { + let tabmsg = { + tableName: res.TBName, + columns: res.FDName.map(item => { + let _type = item.FieldType.toLowerCase() + let _decimal = 0 + if (/^nvarchar/.test(_type)) { + _type = 'text' + } else if (/^int/.test(_type)) { + _type = 'number' + } else if (/^decimal/.test(_type)) { + _decimal = _type.split(',')[1] + _decimal = parseInt(_decimal) + if (_decimal > 4) { + _decimal = 4 + } + _type = 'number' + } else if (/^decimal/.test(_type)) { + _decimal = _type.split(',')[1] + _decimal = parseInt(_decimal) + if (_decimal > 4) { + _decimal = 4 + } + _type = 'number' + } else if (/^datetime/.test(_type)) { + _type = 'datetime' + } else if (/^date/.test(_type)) { + _type = 'date' + } else { + _type = 'text' + } + + return { + field: item.FieldName, + label: item.FieldDec, + type: _type, + datatype: _type, + decimal: _decimal + } + }) + } + _columns.push(tabmsg) + } else { + notification.warning({ + top: 92, + message: res.message, + duration: 5 + }) + } + }) + + this.setState({ + tableFields: _columns + }) + + this.props.updatetable(this.props.config, _columns) + }) + } + + queryField = (type) => { + const {selectedTables, tableFields, config} = this.state + // 鍒ゆ柇鏄惁宸查�夋嫨琛ㄥ悕 + if (selectedTables.length === 0) { + notification.warning({ + top: 92, + message: '璇烽�夋嫨琛ㄥ悕锛�', + duration: 5 + }) + return + } + + // 琛ㄥ瓧娈甸泦杞负map鏁版嵁 + let columns = new Map() + tableFields.forEach(table => { + table.columns.forEach(column => { + columns.set(column.field, column) + }) + }) + + if (type === 'search') { + // 娣诲姞鎼滅储鏉′欢锛屽瓧娈甸泦涓瓨鍦ㄦ悳绱㈡潯浠跺瓧娈碉紝浣跨敤鎼滅储鏉′欢瀵硅薄鏇挎崲瀛楁闆嗭紝璁剧疆鏁版嵁绫诲瀷 + config.search.forEach(item => { + if (columns.has(item.field)) { + let _datatype = columns.get(item.field).datatype + columns.set(item.field, {...item, selected: true, datatype: _datatype}) + } + }) + } else if (type === 'columns') { + // 娣诲姞鏄剧ず鍒楋紝瀛楁闆嗕腑瀛樺湪鏄剧ず鍒楀瓧娈碉紝浣跨敤鏄剧ず鍒楀璞℃浛鎹㈠瓧娈甸泦锛岃缃暟鎹被鍨� + config.columns.forEach(item => { + if (columns.has(item.field)) { + let _datatype = columns.get(item.field).datatype + columns.set(item.field, {...item, selected: true, datatype: _datatype}) + } + }) + } + + // 鏄剧ず瀛楁闆嗗脊绐� + this.setState({ + addType: type, + tableVisible: true, + fields: [...columns.values()] + }) + } + + addFieldSubmit = () => { + // 瀛楁闆嗕负绌猴紝鍏抽棴寮圭獥 + if (!this.state.fields || this.state.fields.length === 0) { + this.setState({ + tableVisible: false, + addType: '' + }) + } + + const {addType, config} = this.state + + // 鑾峰彇宸查�夊瓧娈甸泦鍚� + let cards = this.refs.searchcard.state.selectCards + let columnsMap = new Map() + cards.forEach(card => { + columnsMap.set(card.field, card) + }) + + let items = [] + if (addType === 'search') { + config.search.forEach(item => { + if (columnsMap.has(item.field)) { + let cell = columnsMap.get(item.field) + + if (cell.selected && cell.type === item.type) { // 鏁版嵁鏈慨鏀� + items.push(item) + } else if (cell.selected) { // 鏁版嵁绫诲瀷淇敼 + if (cell.type === 'select') { + item.match = '=' + } else if (cell.type === 'daterange') { + item.match = 'between' + } else { + cell.type = 'text' + item.match = 'like' + } + + item.type = cell.type + item.initval = '' + items.push(item) + } + columnsMap.delete(item.field) + } else if (!item.origin) { + items.push(item) + } + }) + + let _columns = [...columnsMap.values()] + + _columns.forEach(item => { + if (item.selected) { + let _match = '' + if (item.type === 'select') { + _match = '=' + } else if (item.type === 'daterange') { + _match = 'between' + } else { + item.type = 'text' + _match = 'like' + } + + let newcard = { + uuid: Utils.getuuid(), + label: item.label, + field: item.field, + initval: '', + type: item.type, + resourceType: '0', + setAll: 'false', + options: [], + dataSource: '', + linkField: '', + valueField: '', + valueText: '', + orderBy: '', + orderType: 'asc', + match: _match, + display: 'dropdown' + } + + items.push(newcard) + } + }) + } else { + config.columns.forEach(item => { + if (columnsMap.has(item.field)) { + let cell = columnsMap.get(item.field) + + if (cell.selected) { + items.push(item) + } + columnsMap.delete(item.field) + } else if (!item.origin) { + items.push(item) + } + }) + + let _columns = [...columnsMap.values()] + + _columns.forEach(item => { + if (item.selected) { + let newcard = { + uuid: Utils.getuuid(), + Align: 'left', + label: item.label, + field: item.field, + Hide: 'false', + IsSort: item.type === 'picture' ? 'false' : 'true', + type: item.type, + Width: 120 + } + + items.push(newcard) + } + }) + } + + this.setState({ + config: {...config, [addType]: items} + }) + + notification.success({ + top: 92, + message: '鎿嶄綔鎴愬姛', + duration: 2 + }) + } + + onTableChange = (value) => { + const { config } = this.props + const { tables, tableFields, selectedTables } = this.state + + let _table = tables.filter(item => item.TbName === value)[0] + let isSelected = !!selectedTables.filter(cell => cell.TbName === value)[0] + if (!isSelected) { + this.setState({ + selectedTables: [...selectedTables, _table] + }) + + let _config = {...config, tables: [...selectedTables, _table]} + + Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: value}).then(res => { + if (res.status) { + let tabmsg = { + tableName: _table.name, + columns: res.FDName.map(item => { + let _type = item.FieldType.toLowerCase() + let _decimal = 0 + if (/^nvarchar/.test(_type)) { + _type = 'text' + } else if (/^int/.test(_type)) { + _type = 'number' + } else if (/^decimal/.test(_type)) { + _decimal = _type.split(',')[1] + _decimal = parseInt(_decimal) + _type = 'number' + } else if (/^datetime/.test(_type)) { + _type = 'datetime' + } else if (/^date/.test(_type)) { + _type = 'date' + } else { + _type = 'text' + } + + return { + field: item.FieldName, + label: item.FieldDec, + type: _type, + datatype: _type, + decimal: _decimal + } + }) + } + this.setState({ + tableFields: [...tableFields, tabmsg] + }) + + this.props.updatetable(_config, [...tableFields, tabmsg]) + } else { + notification.warning({ + top: 92, + message: res.message, + duration: 5 + }) + } + }) + } + } + + deleteTable = (table) => { + const { config } = this.props + const {selectedTables, tableFields} = this.state + + let _tables = selectedTables.filter(item => item.TbName !== table.TbName) + let _fields = tableFields.filter(item => item.tableName !== table.TbName) + + this.setState({ + selectedTables: _tables, + tableFields: _fields + }) + + this.props.updatetable({...config, tables: _tables}, _fields) + } + + changeSetting = () => { + this.setState({ + settingVisible: true + }) + } + + render() { + const { containerId } = this.props + const { dict, tables, selectedTables } = this.state + + return ( + <div className="model-table-tablemanage-view"> + {/* 琛ㄥ悕娣诲姞 */} + <div className="ant-col ant-form-item-label"> + <label> + <Tooltip placement="topLeft" title={dict['model.tooltip.table.guide']}> + <Icon type="question-circle" /> + {dict['header.menu.table.add']} + </Tooltip> + </label> + </div> + <Select + showSearch + className="tables" + style={{ width: '100%' }} + optionFilterProp="children" + value={dict['header.menu.table.placeholder']} + onChange={this.onTableChange} + showArrow={false} + getPopupContainer={() => document.getElementById(containerId)} + filterOption={(input, option) => { + return option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 || + option.props.value.toLowerCase().indexOf(input.toLowerCase()) >= 0 + }} + > + {tables.map((table, index) => ( + <Option key={index} title={table.TbName} value={table.TbName}>{table.Remark}</Option> + ))} + </Select> + {selectedTables.length > 0 && <List + size="small" + bordered + dataSource={selectedTables} + renderItem={(item, index) => <List.Item key={index} title={item.Remark + ' (' + item.TbName + ')'}> + {item.Remark + ' (' + item.TbName + ')'} + <Icon type="close" onClick={() => this.deleteTable(item)}/> + <div className="bottom-mask"></div> + </List.Item>} + />} + </div> + ) + } +} + +export default TablesComponent \ No newline at end of file diff --git a/src/templates/sharecomponent/tablecomponent/index.scss b/src/templates/sharecomponent/tablecomponent/index.scss new file mode 100644 index 0000000..aa254b7 --- /dev/null +++ b/src/templates/sharecomponent/tablecomponent/index.scss @@ -0,0 +1,7 @@ +.model-table-tablemanage-view { + .tables { + .ant-select-selection-selected-value { + opacity: 0.4!important; + } + } +} \ No newline at end of file diff --git a/src/templates/subtableconfig/index.jsx b/src/templates/subtableconfig/index.jsx index dab3aa9..2b7b9df 100644 --- a/src/templates/subtableconfig/index.jsx +++ b/src/templates/subtableconfig/index.jsx @@ -4,39 +4,32 @@ import { is, fromJS } from 'immutable' import { DndProvider } from 'react-dnd' import HTML5Backend from 'react-dnd-html5-backend' -import { Button, Card, Modal, Collapse, notification, Spin, Select, List, Icon, Empty, Switch, Tooltip, message } from 'antd' +import { Button, Card, Modal, Collapse, notification, Spin, Icon, Switch, Tooltip, Col } from 'antd' import moment from 'moment' import Api from '@/api' -import options from '@/store/options.js' -import zhCN from '@/locales/zh-CN/comtable.js' -import enUS from '@/locales/en-US/comtable.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' import Utils from '@/utils/utils.js' -import { getSearchForm, getActionForm, getColumnForm } from '@/templates/zshare/formconfig' -import { queryTableSql } from '@/utils/option.js' -import ActionForm from './actionform' +import TableComponent from '@/templates/sharecomponent/tablecomponent' +import FieldsComponent from '@/templates/sharecomponent/fieldscomponent' +import ChartGroupComponent from '@/templates/sharecomponent/chartgroupcomponent' +import SearchComponent from '@/templates/sharecomponent/searchcomponent' +import ActionComponent from '@/templates/sharecomponent/actioncomponent' +import ColumnComponent from '@/templates/sharecomponent/columncomponent' + import SettingForm from './settingform' -import SearchForm from '@/templates/zshare/searchform' -import ColumnForm from '@/templates/zshare/columnform' -import DragElement from '@/templates/zshare/dragelement' -import ColspanForm from '@/templates/zshare/colspanform' -import GridBtnForm from '@/templates/zshare/gridbtnform' -import EditCard from '@/templates/zshare/editcard' -import VerifyCard from '@/templates/zshare/verifycard' -import VerifyCardPrint from '@/templates/zshare/verifycardprint' -import VerifyCardExcelIn from '@/templates/zshare/verifycardexcelin' -import VerifyCardExcelOut from '@/templates/zshare/verifycardexcelout' import MenuForm from '@/templates/zshare/menuform' import EditComponent from '@/templates/zshare/editcomponent' import SourceElement from '@/templates/zshare/dragelement/source' import CreateFunc from '@/templates/zshare/createfunc' import CreateInterface from '@/templates/zshare/createinterface' +import ChartComponent from '@/templates/zshare/chartcomponent' import Source from './source' import './index.scss' const { Panel } = Collapse -const { Option } = Select const { confirm } = Modal const CommonDict = (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS @@ -57,15 +50,11 @@ dict: CommonDict, // 瀛楀吀 config: null, // 椤甸潰閰嶇疆 visible: false, // 鎼滅储鏉′欢銆佹寜閽�佹樉绀哄垪锛屾ā鎬佹鏄剧ず鎺у埗 - modalTitle: '', // 妯℃�佹鐨勬爣棰� - tableVisible: false, // 鏁版嵁琛ㄥ瓧娈垫ā鎬佹 - addType: '', // 娣诲姞绫诲瀷-鎼滅储鏉′欢鎴栨樉绀哄垪 - tableColumns: [], // 琛ㄦ牸鏄剧ず鍒� + tableFields: [], // 宸查�夎〃瀛楁闆� fields: null, // 鎼滅储鏉′欢鍙婃樉绀哄垪锛屽彲閫夊瓧娈� menuformlist: null, // 鍩烘湰淇℃伅琛ㄥ崟瀛楁 formlist: null, // 鎼滅储鏉′欢銆佹寜閽�佹樉绀哄垪琛ㄥ崟瀛楁 formtemp: '', // 琛ㄥ崟绫诲瀷锛屾樉绀哄垪銆佹寜閽�佹悳绱㈡潯浠� - modaltype: '', // 妯℃�佹绫诲瀷锛屾帶鍒舵ā鎬佹鏄剧ず card: null, // 缂栬緫鍏冪礌 menuloading: false, // 鑿滃崟淇濆瓨涓� menucloseloading: false, // 鑿滃崟鍏抽棴鏃讹紝閫夋嫨淇濆瓨 @@ -78,13 +67,14 @@ originActions: null, // 鍘熷鎸夐挳淇℃伅锛屼娇鐢ㄥ凡鏈夌敤鎴锋ā鏉� delActions: [], // 鍒犻櫎鎸夐挳鍒楄〃 copyActions: [], // 澶嶅埗鎸夐挳缁� - showColumnName: false, // 鏄剧ず鍒楀瓧娈靛悕鎺у埗 tabviews: [], // 鎵�鏈夋爣绛鹃〉 profileVisible: false, // 楠岃瘉淇℃伅妯℃�佹 optionLibs: null, // 鑷畾涔変笅鎷夐�夐」搴� thawButtons: [], // 宸查�夋嫨瑕佽В鍐荤殑鎸夐挳 activeKey: '0', // 榛樿灞曞紑鍩烘湰淇℃伅 - sqlVerifing: false // sql楠岃瘉 + sqlVerifing: false, // sql楠岃瘉 + chartview: null, // 褰撳墠瑙嗗浘 + pasteContent: null // 绮樿创鍐呭 } /** @@ -142,7 +132,22 @@ let _activeKey = editSubTab ? editSubTab.activeKey : editTab.activeKey + // 鍏煎 + if (!_config.charts) { + _config.expand = false + _config.charts = [{ + uuid: Utils.getuuid(), + label: '', + title: '', + chartType: 'table', + icon: 'table', + Hide: 'false', + blacklist: [] + }] + } + this.setState({ + chartview: _config.charts[0].uuid, originActions: _oriActions, optionLibs: optionLibs, config: _config, @@ -184,148 +189,46 @@ * 2銆佹牴鎹厤缃俊鎭腑宸蹭娇鐢ㄨ〃鑾峰彇鐩稿叧瀛楁淇℃伅 */ componentDidMount () { - let param = { - func: 'sPC_Get_SelectedList', - LText: queryTableSql, - obj_name: 'data', - arr_field: 'TbName,Remark' - } - - param.LText = Utils.formatOptions(param.LText) - param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' - param.secretkey = Utils.encrypt(param.LText, param.timestamp) - - Api.getSystemConfig(param).then(res => { - if (res.status) { - this.setState({ - tables: res.data - }) - } else { - notification.warning({ - top: 92, - message: res.message, - duration: 5 - }) - } - }) - - let deffers = this.state.selectedTables.map(item => { - return new Promise(resolve => { - Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: item.TbName}).then(res => { - res.TBName = item.TbName - resolve(res) - }) - }) - }) - Promise.all(deffers).then(response => { - let _columns = [] - response.forEach(res => { - if (res.status) { - let tabmsg = { - tableName: res.TBName, - columns: res.FDName.map(item => { - let _type = item.FieldType.toLowerCase() - let _decimal = 0 - if (/^nvarchar/.test(_type)) { - _type = 'text' - } else if (/^int/.test(_type)) { - _type = 'number' - } else if (/^decimal/.test(_type)) { - _decimal = _type.split(',')[1] - _decimal = parseInt(_decimal) - if (_decimal > 4) { - _decimal = 4 - } - _type = 'number' - } else if (/^decimal/.test(_type)) { - _decimal = _type.split(',')[1] - _decimal = parseInt(_decimal) - if (_decimal > 4) { - _decimal = 4 - } - _type = 'number' - } else if (/^datetime/.test(_type)) { - _type = 'datetime' - } else if (/^date/.test(_type)) { - _type = 'date' - } else { - _type = 'text' - } - - return { - field: item.FieldName, - label: item.FieldDec, - type: _type, - datatype: _type, - decimal: _decimal - } - }) - } - _columns.push(tabmsg) - } else { - notification.warning({ - top: 92, - message: res.message, - duration: 5 - }) - } - }) - - this.setState({ - tableColumns: _columns - }) - }) - - Api.getSystemConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'tab'}).then(res => { - if (res.status) { - this.setState({ - tabviews: res.UserTemp.map(temp => { - return { - uuid: temp.MenuID, - value: temp.MenuID, - text: temp.MenuName, - type: temp.Template, - MenuNo: temp.MenuNo - } - }) - }) - } else { - notification.warning({ - top: 92, - message: res.message, - duration: 5 - }) - } - }) + this.reloadTab(false) } /** * @description 鍔犺浇鎴栧埛鏂版爣绛句俊鎭� */ - reloadTab = () => { + reloadTab = (type) => { this.setState({ - loading: true, + loading: type, tabviews: [] }) Api.getSystemConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'tab'}).then(res => { if (res.status) { + let _tabviews = [] + res.UserTemp.forEach(temp => { + let item = { + uuid: temp.MenuID, + value: temp.MenuID, + text: temp.MenuName, + type: temp.Template, + MenuNo: temp.MenuNo + } + + if (this.props.config && temp.MenuID === this.props.config.uuid) return + + _tabviews.push(item) + }) + this.setState({ loading: false, - tabviews: res.UserTemp.map(temp => { - return { - uuid: temp.MenuID, - value: temp.MenuID, - text: temp.MenuName, - type: temp.Template, - MenuNo: temp.MenuNo - } + tabviews: _tabviews + }) + + if (type) { + notification.success({ + top: 92, + message: '鍒锋柊鎴愬姛銆�', + duration: 2 }) - }) - notification.success({ - top: 92, - message: '鍒锋柊鎴愬姛銆�', - duration: 2 - }) + } } else { this.setState({ loading: false @@ -392,583 +295,6 @@ } /** - * @description 鍏冪礌娣诲姞鎴栨嫋鍔ㄦ椂椤哄簭鍙樺寲 - */ - handleList = (type, list, card) => { - const { config } = this.state - - if (list.length > config[type].length) { - list = list.filter(item => !item.origin) - - if (type === 'search') { - this.handleSearch(card) - } else if (type === 'action') { - this.handleAction(card) - } else if (type === 'columns') { - this.handleColumn(card) - } - } - - this.setState({config: {...config, [type]: list}}) - } - - /** - * @description 鎼滅储鏉′欢缂栬緫锛岃幏鍙栨悳绱㈡潯浠惰〃鍗曚俊鎭� - */ - handleSearch = (card) => { - this.setState({ - modaltype: 'search', - card: card, - formlist: getSearchForm(card, this.props.sysRoles) - }) - } - - /** - * @description 鎸夐挳缂栬緫锛岃幏鍙栨寜閽〃鍗曚俊鎭� - */ - handleAction = (card, type) => { - let ableField = this.props.permFuncField.join(', ') - let functip = <div> - <p style={{marginBottom: '5px'}}>{this.state.dict['header.modal.func.innerface'].replace('@ableField', ableField)}</p> - <p>{this.state.dict['header.modal.func.outface']}</p> - </div> - - this.setState({ - modaltype: type === 'copy' ? 'actionCopy' : 'actionEdit', - card: card, - formlist: getActionForm(card, functip, this.state.config, this.props.permFuncField) - }) - } - - /** - * @description 鏄剧ず鍒椾笌鍚堝苟鍒楃紪杈戯紝鑾峰彇琛ㄥ崟淇℃伅 - */ - handleColumn = (card) => { - const { menu } = this.props - - if (card.type !== 'colspan') { - let menulist = menu.fstMenuList.map(item => { - return { - value: item.MenuID, - label: item.text, - isLeaf: false - } - }) - - if ((card.type === 'text' || card.type === 'number') && card.linkmenu && card.linkmenu.length > 0) { - let _param = { - func: 'sPC_Get_FunMenu', - ParentID: card.linkmenu[0], - systemType: options.systemType, - debug: 'Y' - } - - this.setState({ - loading: true - }) - - Api.getSystemConfig(_param).then(result => { - if (result.status) { - menulist = menulist.map(item => { - if (item.value === card.linkmenu[0]) { - item.children = result.data.map(item => { - let submenu = { - value: item.ParentID, - label: item.MenuNameP, - children: item.FunMenu.map(cell => { - return { - value: cell.MenuID, - label: cell.MenuName, - MenuID: cell.MenuID, - MenuName: cell.MenuName, - MenuNo: cell.MenuNo, - Ot: cell.Ot, - PageParam: cell.PageParam, - LinkUrl: cell.LinkUrl, - disabled: cell.MenuID === menu.MenuID - } - }) - } - - return submenu - }) - } - return item - }) - } else { - notification.warning({ - top: 92, - message: result.message, - duration: 5 - }) - } - - this.setState({ - loading: false, - modaltype: 'columns', - card: card, - formlist: getColumnForm(card, this.props.sysRoles, menulist) - }) - }) - } else { - this.setState({ - modaltype: 'columns', - card: card, - formlist: getColumnForm(card, this.props.sysRoles, menulist) - }) - } - } else { - this.setState({ - modaltype: 'colspan', - card: card - }) - } - } - - /** - * @description 鎿嶄綔鍒楃紪杈� - */ - handleGridBtn = () => { - this.setState({ - modaltype: 'gridbtn' - }) - } - - /** - * @description 鎼滅储銆佹寜閽�佹樉绀哄垪淇敼鍚庢彁浜や繚瀛� - * 1銆佹悳绱㈡潯浠朵繚瀛橈紝褰撶被鍨嬩负涓嬫媺妗嗕笖瀛樺湪鏁版嵁婧愭椂锛屽皢鏌ヨ鏉′欢鎷兼帴涓簊ql锛屽苟鐢╞ase64杞爜 - * 2銆佹寜閽寘鎷甯哥紪杈戝拰澶嶅埗锛屽鍒舵椂,鎸夐挳鍒楁湯灏炬坊鍔� - * 3銆佹坊鍔犳垨缂栬緫鍒楋紝淇濆瓨鏃讹紝濡傛寜閽綅缃缃负琛ㄦ牸锛屽垯淇敼鎿嶄綔鍒楁樉绀虹姸鎬� - */ - handleSubmit = () => { - const { card, config, modaltype, optionLibs } = this.state - - if (modaltype === 'search') { - this.searchFormRef.handleConfirm().then(res => { - if ( // 鏇存柊涓嬫媺瀛楀吀 - (res.type === 'select' || res.type === 'multiselect' || res.type === 'link') && - res.resourceType === '0' && - res.options && res.options.length > 0 - ) { - optionLibs.set(config.uuid + res.uuid, { - uuid: config.uuid + res.uuid, - label: res.label, - parname: config.tabName, - type: 'search', - options: res.options - }) - } - - let fieldrepet = false // 瀛楁閲嶅 - let labelrepet = false // 鎻愮ず鏂囧瓧閲嶅 - - let _search = config.search.map(item => { - if (item.uuid !== res.uuid && res.field && item.field) { - if (item.field === res.field) { - fieldrepet = true - } else if (item.label === res.label) { - labelrepet = true - } - } - - if (item.uuid === res.uuid) { - return res - } else { - return item - } - }) - - if (fieldrepet) { - notification.warning({ - top: 92, - message: '瀛楁宸插瓨鍦紒', - duration: 5 - }) - return - } else if (labelrepet) { - notification.warning({ - top: 92, - message: '鍚嶇О宸插瓨鍦紒', - duration: 5 - }) - return - } - - _search = _search.filter(item => !item.origin) - - if ((res.type === 'select' || res.type === 'multiselect' || res.type === 'link') && res.resourceType === '1' && /\s/.test(res.dataSource)) { - this.setState({ - sqlVerifing: true - }) - - let param = { - func: 's_debug_sql', - LText: res.dataSource - } - param.LText = Utils.formatOptions(param.LText) - param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' - param.secretkey = Utils.encrypt(param.LText, 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, search: _search}, - optionLibs: optionLibs, - modaltype: '' - }) - } else { - this.setState({sqlVerifing: false}) - - Modal.error({ - title: result.message - }) - } - }) - } else { - this.setState({ - config: {...config, search: _search}, - optionLibs: optionLibs, - modaltype: '' - }) - } - }) - } else if (modaltype === 'actionEdit' || modaltype === 'actionCopy') { - this.actionFormRef.handleConfirm().then(res => { - let _action = config.action.map(item => { - if (item.uuid === res.uuid) { - return res - } else { - return item - } - }) - _action = _action.filter(item => !item.origin) - - if (modaltype === 'actionCopy') { - _action.push(res) - } - - // 澶嶅埗鎸夐挳鍓嶅悗鐨嗕负琛ㄥ崟鏃讹紝澶嶅埗琛ㄥ崟閰嶇疆淇℃伅锛宨d瀛樹簬澶嶅埗鍒楄〃 - if (res.OpenType === 'pop' && card.originCard && card.originCard.OpenType === 'pop') { - Api.getSystemConfig({ - func: 'sPC_Get_LongParam', - MenuID: card.originCard.uuid - }).then(result => { - if (result.status && result.LongParam) { - let _LongParam = '' - - // 瑙f瀽閰嶇疆锛屼慨鏀规ā鎬佹鏍囬鍚嶇О - if (result.LongParam) { - try { - _LongParam = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam))) - } catch (e) { - console.warn('Parse Failure') - _LongParam = '' - } - } - if (_LongParam && _LongParam.type === 'Modal') { - try { - _LongParam.setting.title = res.label - _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_LongParam))) - } catch { - console.warn('Stringify Failure') - _LongParam = '' - } - } else { - _LongParam = '' - } - - let param = { - func: 'sPC_ButtonParam_AddUpt', - ParentID: config.uuid, - MenuID: res.uuid, - MenuNo: config.tabNo, - Template: 'Modal', - MenuName: res.label, - PageParam: JSON.stringify({Template: 'Modal'}), - LongParam: _LongParam - } - Api.getSystemConfig(param).then(response => { - if (!response.status) { - notification.warning({ - top: 92, - message: response.message, - duration: 5 - }) - } else { - this.setState({ - copyActions: [...this.state.copyActions, res.uuid] - }) - } - }) - } - }) - } - - // 鍒ゆ柇鏄惁瀛樺湪鎿嶄綔鍒� - let _hasGridbtn = _action.filter(act => act.position === 'grid').length > 0 - let _gridBtn = config.gridBtn - - if (_gridBtn) { - _gridBtn.display = _hasGridbtn - } else { - _gridBtn = { - display: _hasGridbtn, - Align: 'center', - IsSort: 'false', - uuid: Utils.getuuid(), - label: this.state.dict['header.form.column.action'], - type: 'action', - style: 'button', - show: 'horizontal', - Width: 120 - } - } - - this.setState({ - config: {...config, action: _action, gridBtn: _gridBtn}, - modaltype: '' - }) - }) - } else if (modaltype === 'columns' || modaltype === 'colspan') { - this.columnFormRef.handleConfirm().then(res => { - let fieldrepet = false // 瀛楁閲嶅 - let labelrepet = false // 鎻愮ず鏂囧瓧閲嶅 - - let _columns = config.columns.map(item => { - if (item.uuid !== res.uuid && res.field && item.field) { - if (item.field === res.field) { - fieldrepet = true - } else if (item.label === res.label) { - labelrepet = true - } - } - - if (item.uuid === res.uuid) { - return res - } else { - return item - } - }) - - if (fieldrepet) { - notification.warning({ - top: 92, - message: '瀛楁宸插瓨鍦紒', - duration: 5 - }) - return - } else if (labelrepet) { - notification.warning({ - top: 92, - message: '鍚嶇О宸插瓨鍦紒', - duration: 5 - }) - return - } - - _columns = _columns.filter(item => !item.origin) - - this.setState({ - config: {...config, columns: _columns}, - modaltype: '' - }) - }) - } else if (modaltype === 'gridbtn') { - this.gridBtnFormRef.handleConfirm().then(res => { - this.setState({ - config: {...config, gridBtn: res}, - modaltype: '' - }) - }) - } - } - - /** - * @description 鍙栨秷淇濆瓨锛屽鏋滃厓绱犱负鏂版坊鍏冪礌锛屽垯浠庡簭鍒椾腑鍒犻櫎 - */ - editModalCancel = () => { - const { config, card, modaltype } = this.state - - if (card.focus) { - let _config = null - if (modaltype === 'search') { - let _search = config.search.filter(item => item.uuid !== card.uuid) - _config = {...config, search: _search} - } else if (modaltype === 'actionEdit') { - let _action = config.action.filter(item => item.uuid !== card.uuid) - _config = {...config, action: _action} - } else if (modaltype === 'columns' || modaltype === 'colspan') { - let _columns = config.columns.filter(item => item.uuid !== card.uuid) - _config = {...config, columns: _columns} - } else { - _config = config - } - - this.setState({ - card: null, - config: _config, - modaltype: '' - }) - } else { - this.setState({ - card: null, - modaltype: '' - }) - } - } - - /** - * @description 鍒涘缓鎸夐挳瀛樺偍杩囩▼ - */ - creatFunc = () => { - let _config = JSON.parse(JSON.stringify(this.state.config)) - - this.actionFormRef.handleConfirm().then(res => { - let btn = res // 鎸夐挳淇℃伅 - let newLText = '' // 鍒涘缓瀛樺偍杩囩▼sql - let DelText = '' // 鍒犻櫎瀛樺偍杩囩▼sql - - // 鍒涘缓瀛樺偍杩囩▼锛屽繀椤诲~鍐欏唴閮ㄥ嚱鏁板悕 - if (!btn.innerFunc) { - notification.warning({ - top: 92, - message: '璇峰~鍐欏唴閮ㄥ嚱鏁帮紒', - duration: 5 - }) - return - } - - new Promise(resolve => { - // 寮圭獥锛堣〃鍗曪級绫绘寜閽紝鍏堣幏鍙栨寜閽厤缃俊鎭紝濡傛灉灏氭湭閰嶇疆鎸夐挳鍒欎細鎶ラ敊骞剁粓姝€�� - // 鑾峰彇淇℃伅鍚庣敓鎴愬垹闄ゅ拰鍒涘缓瀛樺偍杩囩▼鐨勮鍙� - if (btn.OpenType === 'pop') { - Api.getSystemConfig({ - func: 'sPC_Get_LongParam', - MenuID: btn.uuid - }).then(res => { - let _LongParam = '' - if (res.status && res.LongParam) { - try { - _LongParam = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam))) - } catch (e) { - console.warn('Parse Failure') - _LongParam = '' - } - } - - if (_LongParam) { - let fields = [] - if (_LongParam.groups.length > 0) { - _LongParam.groups.forEach(group => { - fields = [...fields, ...group.sublist] - }) - } else { - fields = _LongParam.fields - } - - let _param = { - funcName: btn.innerFunc, - name: _config.setting.tableName || '', - fields: fields, - menuNo: _config.tabNo - } - newLText = Utils.formatOptions(Utils.getfunc(_param, btn, {MenuID: _config.uuid, MenuName: _config.tabName}, _config)) - DelText = Utils.formatOptions(Utils.dropfunc(_param.funcName)) - resolve(true) - } else { - notification.warning({ - top: 92, - message: '寮圭獥锛堣〃鍗曪級鎸夐挳锛岃鍏堥厤缃〃鍗曚俊鎭紒', - duration: 5 - }) - resolve(false) - } - }) - } else if (btn.OpenType === 'excelIn') { - if (btn.verify && btn.verify.sheet && btn.verify.columns && btn.verify.columns.length > 0) { - let _param = { - funcName: btn.innerFunc, - menuNo: _config.tabNo - } - newLText = Utils.formatOptions(Utils.getexcelInfunc(_param, btn, {MenuID: _config.uuid, MenuName: _config.tabName})) - DelText = Utils.formatOptions(Utils.dropfunc(_param.funcName)) - resolve(true) - } else { - notification.warning({ - top: 92, - message: '璇峰畬鍠勫鍏xcel楠岃瘉淇℃伅锛�', - duration: 5 - }) - resolve(false) - } - } else if (btn.OpenType === 'excelOut') { - let _param = { - innerFunc: btn.innerFunc - } - - newLText = Utils.formatOptions(Utils.getTableFunc(_param, {MenuID: _config.uuid, MenuName: _config.tabName, MenuNo: _config.tabNo}, _config)) // 鍒涘缓瀛樺偍杩囩▼sql - DelText = Utils.formatOptions(Utils.dropfunc(btn.innerFunc)) - - resolve(true) - } else { - let _param = { - funcName: btn.innerFunc, - name: _config.setting.tableName || '', - fields: '', - menuNo: _config.tabNo - } - newLText = Utils.formatOptions(Utils.getfunc(_param, btn, {MenuID: _config.uuid, MenuName: _config.tabName}, _config)) - DelText = Utils.formatOptions(Utils.dropfunc(_param.funcName)) - resolve(true) - } - }).then(res => { - if (!res) return - - this.refs.btnCreatFunc.exec(btn.innerFunc, newLText, DelText).then(result => { - if (result !== 'success') return - - _config.action = _config.action.map(item => { - if (item.uuid === btn.uuid) { - return btn - } else { - return item - } - }) - _config.action = _config.action.filter(item => !item.origin) - - // 鍒ゆ柇鏄惁瀛樺湪鎿嶄綔鍒� - let _hasGridbtn = _config.action.filter(act => act.position === 'grid').length > 0 - - if (_config.gridBtn) { - _config.gridBtn.display = _hasGridbtn - } else { - _config.gridBtn = { - display: _hasGridbtn, - Align: 'center', - IsSort: 'false', - uuid: Utils.getuuid(), - label: this.state.dict['header.form.column.action'], - type: 'action', - style: 'button', - show: 'horizontal', - Width: 120 - } - } - - this.setState({ - config: _config, - }) - }) - }) - }) - } - - /** * @description 鍒涘缓琛ㄦ牸瀛樺偍杩囩▼ */ tableCreatFunc = () => { @@ -999,90 +325,6 @@ }) } - deleteElement = (element) => { - const { thawButtons } = this.state - - let _this = this - confirm({ - content: `纭畾鍒犻櫎<<${element.card.label}>>鍚楋紵`, - okText: this.state.dict['header.confirm'], - cancelText: this.state.dict['header.cancel'], - onOk() { - let _config = JSON.parse(JSON.stringify(_this.state.config)) - _config[element.type] = _config[element.type].filter(item => { - if (item.uuid === element.card.uuid) { - return false - } else { - return true - } - }) - - // 鍒犻櫎鎸夐挳鍏冪礌 - let _delActions = _this.state.delActions - if (element.type === 'action') { - _delActions.push(element) - } - - _this.setState({ - config: _config, - delActions: _delActions, - thawButtons: thawButtons.filter(key => key !== element.card.uuid) - }) - }, - onCancel() {} - }) - } - - /** - * @description 楠岃瘉淇℃伅閰嶇疆 - */ - profileAction = (element) => { - this.setState({ - profileVisible: true, - card: element - }) - } - - /** - * @description 鎸夐挳鍙屽嚮瑙﹀彂瀛愰厤缃� - */ - btnDoubleClick = (element) => { - if (!element.origin && (element.OpenType === 'pop' || element.OpenType === 'popview' || element.OpenType === 'blank' || element.OpenType === 'tab')) { - this.setSubConfig(element) - } else { - notification.warning({ - top: 92, - message: '姝ゆ寜閽棤瀛愰厤缃」锛�', - duration: 5 - }) - } - } - - /** - * @description 楠岃瘉淇℃伅淇濆瓨 - */ - verifySubmit = () => { - const { card } = this.state - let config = JSON.parse(JSON.stringify(this.state.config)) - - this.verifyRef.handleConfirm().then(res => { - - config.action = config.action.map(item => { - if (item.uuid === card.uuid) { - item.verify = res - } - - return item - }) - - this.setState({ - profileVisible: false, - config: config, - card: '' - }) - }) - } - /** * @description 鏍囩椤典繚瀛� */ @@ -1102,17 +344,6 @@ if (config.columns[0] && config.columns[0].origin) { config.columns = config.columns.filter(item => !item.origin) } - } - - let btnNames = config.action.map(item => item.label) - btnNames = Array.from(new Set(btnNames)) - if (btnNames.length < config.action.length) { - notification.warning({ - top: 92, - message: '鎸夐挳鍚嶇О涓嶅彲鐩稿悓锛�', - duration: 5 - }) - return } let _LongParam = '' @@ -1563,7 +794,7 @@ if (originConfig.isAdd) { confirm({ content: '鑿滃崟灏氭湭鎻愪氦锛岀‘瀹氭斁寮冧繚瀛樺悧锛�', - okText: this.state.dict['header.confirm'], + okText: this.state.dict['model.confirm'], cancelText: this.state.dict['header.cancel'], onOk() { _this.handleViewBack() @@ -1587,265 +818,6 @@ }) }) } - } - - queryField = (type) => { - const {selectedTables, tableColumns, config} = this.state - // 鍒ゆ柇鏄惁宸查�夋嫨琛ㄥ悕 - if (selectedTables.length === 0) { - notification.warning({ - top: 92, - message: '璇烽�夋嫨琛ㄥ悕锛�', - duration: 5 - }) - return - } - - // 琛ㄥ瓧娈甸泦杞负map鏁版嵁 - let columns = new Map() - tableColumns.forEach(table => { - table.columns.forEach(column => { - columns.set(column.field, column) - }) - }) - - if (type === 'search') { - // 娣诲姞鎼滅储鏉′欢锛屽瓧娈甸泦涓瓨鍦ㄦ悳绱㈡潯浠跺瓧娈碉紝浣跨敤鎼滅储鏉′欢瀵硅薄鏇挎崲瀛楁闆嗭紝璁剧疆鏁版嵁绫诲瀷 - config.search.forEach(item => { - if (columns.has(item.field)) { - let _datatype = columns.get(item.field).datatype - columns.set(item.field, {...item, selected: true, datatype: _datatype}) - } - }) - } else if (type === 'columns') { - // 娣诲姞鏄剧ず鍒楋紝瀛楁闆嗕腑瀛樺湪鏄剧ず鍒楀瓧娈碉紝浣跨敤鏄剧ず鍒楀璞℃浛鎹㈠瓧娈甸泦锛岃缃暟鎹被鍨� - config.columns.forEach(item => { - if (columns.has(item.field)) { - let _datatype = columns.get(item.field).datatype - columns.set(item.field, {...item, selected: true, datatype: _datatype}) - } - }) - } - - // 鏄剧ず瀛楁闆嗗脊绐� - this.setState({ - addType: type, - tableVisible: true, - fields: [...columns.values()] - }) - } - - addFieldSubmit = () => { - // 瀛楁闆嗕负绌猴紝鍏抽棴寮圭獥 - if (!this.state.fields || this.state.fields.length === 0) { - this.setState({ - tableVisible: false, - addType: '' - }) - } - - const {addType, config} = this.state - const textmatch = { // 閫夋嫨text鏃跺尮閰嶈鍒� - text: 'like', - number: 'like', - datetime: 'like', - date: 'like' - } - const selectmatch = { // 閫夋嫨select鏃跺尮閰嶈鍒� - text: '=', - number: '=', - datetime: '=', - date: '=' - } - const datematch = { // 閫夋嫨dateRange鏃跺尮閰嶈鍒� - text: 'between', - number: 'between', - datetime: 'between', - date: 'between' - } - - // 鑾峰彇宸查�夊瓧娈甸泦鍚� - let cards = this.refs.searchcard.state.selectCards - let columnsMap = new Map() - cards.forEach(card => { - columnsMap.set(card.field, card) - }) - - let items = [] - if (addType === 'search') { - config.search.forEach(item => { - if (columnsMap.has(item.field)) { - let cell = columnsMap.get(item.field) - - if (cell.selected && cell.type === item.type) { // 鏁版嵁鏈慨鏀� - items.push(item) - } else if (cell.selected) { // 鏁版嵁绫诲瀷淇敼 - if (cell.type === 'text') { - item.match = textmatch[cell.datatype] - } else if (cell.type === 'select') { - item.match = selectmatch[cell.datatype] - } else if (cell.type === 'daterange') { - item.match = datematch[cell.datatype] - } else { - cell.type = 'text' - item.match = textmatch[cell.datatype] - } - - item.type = cell.type - item.initval = '' - items.push(item) - } - columnsMap.delete(item.field) - } else if (!item.origin) { - items.push(item) - } - }) - - let _columns = [...columnsMap.values()] - - _columns.forEach(item => { - if (item.selected) { - let _match = '' - if (item.type === 'text') { - _match = textmatch[item.datatype] - } else if (item.type === 'select') { - _match = selectmatch[item.datatype] - } else if (item.type === 'daterange') { - _match = datematch[item.datatype] - } else { - item.type = 'text' - _match = textmatch[item.datatype] - } - - let newcard = { - uuid: Utils.getuuid(), - label: item.label, - field: item.field, - initval: '', - type: item.type, - resourceType: '0', - setAll: 'false', - options: [], - dataSource: '', - linkField: '', - valueField: '', - valueText: '', - orderBy: '', - orderType: 'asc', - match: _match, - display: 'dropdown' - } - - items.push(newcard) - } - }) - } else { - config.columns.forEach(item => { - if (columnsMap.has(item.field)) { - let cell = columnsMap.get(item.field) - - if (cell.selected) { - items.push(item) - } - columnsMap.delete(item.field) - } else if (!item.origin) { - items.push(item) - } - }) - - let _columns = [...columnsMap.values()] - - _columns.forEach(item => { - if (item.selected) { - let newcard = { - uuid: Utils.getuuid(), - Align: 'left', - label: item.label, - field: item.field, - Hide: 'false', - IsSort: item.type === 'picture' ? 'false' : 'true', - type: item.type, - Width: 120 - } - - items.push(newcard) - } - }) - } - - this.setState({ - config: {...config, [addType]: items} - }) - - notification.success({ - top: 92, - message: '鎿嶄綔鎴愬姛', - duration: 2 - }) - } - - onTableChange = (value) => { - const {tables, selectedTables, tableColumns} = this.state - - let _table = tables.filter(item => item.TbName === value)[0] - let isSelected = !!selectedTables.filter(cell => cell.TbName === value)[0] - if (!isSelected) { - this.setState({ - selectedTables: [...selectedTables, _table] - }) - Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: value}).then(res => { - if (res.status) { - let tabmsg = { - tableName: _table.name, - columns: res.FDName.map(item => { - let _type = item.FieldType.toLowerCase() - let _decimal = 0 - if (/^nvarchar/.test(_type)) { - _type = 'text' - } else if (/^int/.test(_type)) { - _type = 'number' - } else if (/^decimal/.test(_type)) { - _decimal = _type.split(',')[1] - _decimal = parseInt(_decimal) - _type = 'number' - } else if (/^datetime/.test(_type)) { - _type = 'datetime' - } else if (/^date/.test(_type)) { - _type = 'date' - } else { - _type = 'text' - } - - return { - field: item.FieldName, - label: item.FieldDec, - type: _type, - datatype: _type, - decimal: _decimal - } - }) - } - this.setState({ - tableColumns: [...tableColumns, tabmsg] - }) - } else { - notification.warning({ - top: 92, - message: res.message, - duration: 5 - }) - } - }) - } - } - - deleteTable = (table) => { - const {selectedTables, tableColumns} = this.state - - this.setState({ - selectedTables: selectedTables.filter(item => item.TbName !== table.TbName), - tableColumns: tableColumns.filter(item => item.tableName !== table.TbName) - }) } changeSetting = () => { @@ -2049,6 +1021,9 @@ } } + /** + * @description 鍒囨崲鏍囩鏄惁鍚敤 + */ onEnabledChange = () => { const { config } = this.state @@ -2069,66 +1044,6 @@ config: {...config, enabled: !config.enabled} }) } - } - - onColumnNameChange = () => { - const { showColumnName, config } = this.state - - if (!showColumnName) { - let fields = [] - config.columns.forEach(col => { - if (col.field) { - fields.push(col.field) - } - }) - - fields = fields.join(',') - - let textArea = document.createElement('textarea') - textArea.value = fields - document.body.appendChild(textArea) - textArea.select() - - try { - document.execCommand('copy') - document.body.removeChild(textArea) - } catch (err) { - document.body.removeChild(textArea) - } - } - - this.setState({ - showColumnName: !showColumnName - }) - } - - /** - * @description 鍒涘缓鎸夐挳鎺ュ彛锛堝啓鍏ワ級 - */ - btnCreatInterface = () => { - const { config } = this.state - - this.menuformRef.handleConfirm().then(res => { - this.actionFormRef.handleConfirm().then(result => { - if (!['pop', 'exec', 'prompt'].includes(result) || result.funcType || result.intertype !== 'inner' || result.innerFunc ) { - notification.warning({ - top: 92, - message: '鎵撳紑鏂瑰紡涓� 寮圭獥锛堣〃鍗曪級銆佹彁绀烘鎴栫洿鎺ユ墽琛岋紝涓斾娇鐢ㄧ郴缁熷嚱鏁版椂锛屾墠鍙互鍒涘缓鎺ュ彛锛�', - duration: 5 - }) - return - } - - let _menu = { - type: 'subtable', - MenuID: config.uuid, - menuName: res.tabName, - menuNo: res.tabNo - } - - this.refs.btnCreatInterface.triggerInInterface(result, config, _menu) - }) - }) } /** @@ -2161,27 +1076,9 @@ }) } - copycolumn = () => { - const { config } = this.state - - let oInput = document.createElement('input') - let val = { - copyType: 'columns', - columns: config.columns - } - - 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' - - message.success('澶嶅埗鎴愬姛銆�') - - document.body.removeChild(oInput) - } - + /** + * @description 缂栬緫鍔熻兘瀹屾垚鏇存柊锛屽寘鎷В鍐绘寜閽�佺矘璐淬�佹浛鎹㈢瓑 + */ updateConfig = (res) => { if (res.type === 'thaw') { this.setState({ @@ -2189,36 +1086,119 @@ config: res.config }) } else if (res.type === 'paste') { - if (res.copyType === 'action') { - this.handleAction(res.content, 'copy') - } else if (res.copyType === 'columns') { + this.setState({ + pasteContent: res.content + }, () => { this.setState({ - config: res.config + pasteContent: null }) - } + }) } } + /** + * @description 鍥捐〃閰嶇疆淇敼鍚庝繚瀛� + */ + updateChart = (plot) => { + const { config } = this.state + let _charts = JSON.parse(JSON.stringify(config.charts)) + + _charts = _charts.map(item => { + if (item.uuid === plot.uuid) { + if (!is(fromJS(item), fromJS(plot))) { + let _element = document.getElementById(plot.uuid) + if (_element) { + _element.innerHTML = '' + } + } + return plot + } + return item + }) + + this.setState({ + config: {...config, charts: _charts} + }) + } + + /** + * @description 鏇存柊鎼滅储鏉′欢閰嶇疆淇℃伅 + */ + updatesearch = (config, options) => { + const { optionLibs } = this.state + + this.setState({ + config: config, + optionLibs: options || optionLibs + }) + } + + /** + * @description 鏇存柊鎸夐挳閰嶇疆淇℃伅 + */ + updateaction = (config, copyId, delcard) => { + const { copyActions, delActions } = this.state + + this.setState({ + config: config, + copyActions: copyId ? [...copyActions, copyId] : copyActions, + delActions: delcard ? [...delActions, delcard] : delActions + }) + } + + /** + * @description 鏇存柊鏄剧ず鍒楅厤缃俊鎭� + */ + updatecolumn = (config) => { + this.setState({ + config: config + }) + } + + /** + * @description 鏇存柊鍥捐〃缁勯厤缃俊鎭� + */ + updatechartgroup = (config, _chartview) => { + this.setState({ + config: config, + chartview: _chartview + }) + } + + /** + * @description 鏇存柊甯哥敤琛ㄤ俊鎭紝蹇嵎娣诲姞鍚庢洿鏂伴厤缃俊鎭� + */ + updatetable = (config, fields) => { + const { tableFields } = this.state + + this.setState({ + config: config, + tableFields: fields ? fields : tableFields + }) + } + + /** + * @description 鎵归噺娣诲姞锛屾洿鏂伴厤缃俊鎭� + */ + updatefield = (config) => { + this.setState({ + config: config + }) + } + render () { - const { modaltype, activeKey, config } = this.state + const { activeKey, config, chartview } = this.state - const configAction = config.action.filter(_action => - !_action.origin && (_action.OpenType === 'pop' || _action.OpenType === 'popview' || _action.OpenType === 'blank' || _action.OpenType === 'tab') - ) - - let hasbtncrtinter = false - if (modaltype === 'actionEdit' && config.setting.interType === 'inner' && !config.setting.innerFunc && config.setting.dataresource) { - hasbtncrtinter = true - } + const confActions = config.action.filter(_action => !_action.origin && ['pop', 'popview', 'blank', 'tab'].includes(_action.OpenType)) return ( - <div className="common-table-board"> + <div className="model-subtable-board"> <DndProvider backend={HTML5Backend}> {/* 宸ュ叿鏍� */} <div className="tools"> <Collapse accordion defaultActiveKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}> {/* 鍩烘湰淇℃伅 */} - <Panel forceRender={true} header={'鏍囩鍩烘湰淇℃伅'} key="0" id="common-basedata"> + <Panel forceRender={true} header={'鏍囩鍩烘湰淇℃伅'} key="0" id="subtable-basedata"> {/* 鑿滃崟淇℃伅 */} <MenuForm dict={this.state.dict} @@ -2226,42 +1206,12 @@ wrappedComponentRef={(inst) => this.menuformRef = inst} /> {/* 琛ㄥ悕娣诲姞 */} - <div className="ant-col ant-form-item-label"> - <label> - <Tooltip placement="topLeft" title="姝ゅ鍙互娣诲姞閰嶇疆鐩稿叧鐨勫父鐢ㄨ〃锛屽湪娣诲姞鎼滅储鏉′欢鍜屾樉绀哄垪鏃讹紝鍙�氳繃宸ュ叿鏍忎腑鐨勬坊鍔犳寜閽紝鎵归噺娣诲姞琛ㄦ牸鐩稿叧瀛楁銆�"> - <Icon type="question-circle" /> - {this.state.dict['header.menu.table.add']} - </Tooltip> - </label> - </div> - <Select - showSearch - className="tables" - style={{ width: '100%' }} - optionFilterProp="children" - value={this.state.dict['header.menu.table.placeholder']} - onChange={this.onTableChange} - showArrow={false} - getPopupContainer={() => document.getElementById('common-basedata')} - filterOption={(input, option) => { - return option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 || - option.props.value.toLowerCase().indexOf(input.toLowerCase()) >= 0 - }} - > - {this.state.tables.map((table, index) => ( - <Option key={index} title={table.TbName} value={table.TbName}>{table.Remark}</Option> - ))} - </Select> - {this.state.selectedTables.length > 0 && <List - size="small" - bordered - dataSource={this.state.selectedTables} - renderItem={(item, index) => <List.Item key={index} title={item.Remark + ' (' + item.TbName + ')'}> - {item.Remark + ' (' + item.TbName + ')'} - <Icon type="close" onClick={() => this.deleteTable(item)}/> - <div className="bottom-mask"></div> - </List.Item>} - />} + <TableComponent + config={config} + containerId="subtable-basedata" + selectedTables={config.tables || []} + updatetable={this.updatetable} + /> </Panel> {/* 鎼滅储鏉′欢娣诲姞 */} <Panel header={this.state.dict['header.menu.search']} key="1"> @@ -2270,7 +1220,12 @@ return (<SourceElement key={index} content={item}/>) })} </div> - <Button type="primary" block onClick={() => this.queryField('search')}>{this.state.dict['header.menu.search.add']}</Button> + <FieldsComponent + config={config} + type="search" + tableFields={this.state.tableFields} + updatefield={this.updatefield} + /> </Panel> {/* 鎸夐挳娣诲姞 */} <Panel header={this.state.dict['header.menu.action']} key="2"> @@ -2280,7 +1235,7 @@ })} </div> <div className="config-btn"> - {configAction.length > 0 ? + {confActions.length > 0 ? <p className="config-btn-title"> <Tooltip placement="topLeft" title="鐐瑰嚮鎸夐挳锛屽彲瀹屾垚鎴栨煡鐪嬫寜閽厤缃俊鎭��"> <Icon type="question-circle" /> @@ -2289,7 +1244,7 @@ </p> : null } </div> - {configAction.map((item, index) => { + {confActions.map((item, index) => { return ( <div key={index}> <Button @@ -2309,7 +1264,12 @@ return (<SourceElement key={index} content={item}/>) })} </div> - <Button type="primary" block onClick={() => this.queryField('columns')}>{this.state.dict['header.menu.column.add']}</Button> + <FieldsComponent + config={config} + type="columns" + tableFields={this.state.tableFields} + updatefield={this.updatefield} + /> </Panel> </Collapse> </div> @@ -2317,7 +1277,7 @@ <Card title={ <div> 鏍囩锛堝瓙琛級椤甸潰閰嶇疆 - <Icon type="redo" style={{marginLeft: '10px'}} title="鍒锋柊鏍囩鍒楄〃" onClick={this.reloadTab} /> + <Icon type="redo" style={{marginLeft: '10px'}} title="鍒锋柊鏍囩鍒楄〃" onClick={() => this.reloadTab(true)} /> </div> } bordered={false} extra={ <div> @@ -2328,245 +1288,68 @@ </div> } style={{ width: '100%' }}> <Icon type="setting" onClick={this.changeSetting} /> - <div className="search-list"> - <Tooltip placement="bottomLeft" overlayClassName="middle" title="鍦ㄥ乏渚у伐鍏锋爮銆婃悳绱€�嬩腑锛岄�夋嫨瀵瑰簲鎼滅储妗嗘嫋鑷虫澶勬坊鍔狅紱鎴栫偣鍑绘寜閽�婃坊鍔犳悳绱㈡潯浠躲�嬫壒閲忔坊鍔狅紝閫夋嫨鎵归噺娣诲姞鏃讹紝闇�鎻愬墠閫夋嫨浣跨敤琛ㄣ��"> - <Icon type="question-circle" /> - </Tooltip> - <DragElement - type="search" - list={this.state.config.search} - handleList={this.handleList} - handleMenu={this.handleSearch} - deleteMenu={this.deleteElement} - placeholder={this.state.dict['header.form.search.placeholder']} + <SearchComponent + menu={{MenuID: this.state.config.uuid, MenuName: this.state.config.tabName}} + config={this.state.config} + pasteContent={this.state.pasteContent} + sysRoles={this.props.sysRoles} + optionLibs={this.state.optionLibs} + updatesearch={this.updatesearch} + /> + <div className="chart-view" style={{position: 'relative'}}> + {/* 瑙嗗浘缁� */} + <ChartGroupComponent + config={config} + sysRoles={this.props.sysRoles} + updatechartgroup={this.updatechartgroup} /> - </div> - {/* <div className="action-list"> - <DragElement - type="action" - list={this.state.config.action} - setting={this.state.config.setting} - handleList={this.handleList} - handleMenu={this.handleAction} - copyElement={(val) => this.handleAction(val, 'copy')} - deleteMenu={this.deleteElement} - profileMenu={this.profileAction} - doubleClickCard={this.btnDoubleClick} - placeholder={this.state.dict['header.form.action.placeholder']} - /> - </div> */} - <div className="action-list"> - <Tooltip placement="bottomLeft" overlayClassName="middle" title="鍦ㄥ乏渚у伐鍏锋爮銆婃寜閽�嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬寜閽嫋鑷虫澶勬坊鍔狅紝濡傞�夋嫨鎸夐挳绫诲瀷涓鸿〃鍗曘�佹柊鏍囩椤电瓑鍚湁閰嶇疆椤甸潰鐨勬寜閽紝鍙湪宸︿晶宸ュ叿鏍�-鎸夐挳-鍙厤缃寜閽锛岀偣鍑绘寜閽畬鎴愮浉鍏抽厤缃�傛敞锛氬綋璁剧疆鎸夐挳鏄剧ず浣嶇疆涓鸿〃鏍兼椂锛屾樉绀哄垪浼氬鍔犳搷浣滃垪銆�"> - <Icon type="question-circle" /> - </Tooltip> - <DragElement - type="action" - list={this.state.config.action} - setting={this.state.config.setting} - handleList={this.handleList} - handleMenu={this.handleAction} - copyElement={(val) => this.handleAction(val, 'copy')} - deleteMenu={this.deleteElement} - profileMenu={this.profileAction} - doubleClickCard={this.btnDoubleClick} - placeholder={this.state.dict['header.form.action.placeholder']} - /> - </div> - <div className="column-list"> - <Tooltip placement="bottomLeft" overlayClassName="middle" title="鍦ㄥ乏渚у伐鍏锋爮銆婃樉绀哄垪銆嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬樉绀哄垪鎷栬嚦姝ゅ娣诲姞锛涙垨鐐瑰嚮銆婃坊鍔犳樉绀哄垪銆嬫寜閽壒閲忔坊鍔狅紝閫夋嫨鎵归噺娣诲姞鏃讹紝闇�鎻愬墠閫夋嫨浣跨敤琛ㄣ�傛敞锛氭坊鍔犲悎骞跺垪鏃讹紝闇�璁剧疆鍙�夊垪銆�"> - <Icon type="question-circle" /> - </Tooltip> - {config.columns && config.columns.length > 0 ? <Icon className="column-copy" title="copy" type="copy" onClick={this.copycolumn} /> : null} - <Switch checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={this.state.showColumnName} onChange={this.onColumnNameChange} /> - <DragElement - type="columns" - list={this.state.config.columns} - setting={this.state.config.setting} - gridBtn={this.state.config.gridBtn} - handleList={this.handleList} - handleMenu={this.handleColumn} - deleteMenu={this.deleteElement} - handleGridBtn={this.handleGridBtn} - showfield={this.state.showColumnName} - placeholder={this.state.dict['header.form.column.placeholder']} - /> + {config.charts.map(item => { + if (!config.expand && chartview !== item.uuid) return '' + + if (item.chartType === 'table') { + return ( + <Col span={item.width || 24} key={item.uuid}> + {config.charts.length > 1 ? <p className="chart-title">{item.title}</p> : null} + <ActionComponent + type="subtable" + menu={{MenuID: config.uuid, MenuName: config.tabName, MenuNo: config.tabNo}} + config={config} + tabs={this.state.tabviews} + pasteContent={this.state.pasteContent} + usefulFields={this.props.permFuncField} + setSubConfig={this.setSubConfig} + updateaction={this.updateaction} + /> + <ColumnComponent + config={config} + menu={this.props.menu} + sysRoles={this.props.sysRoles} + pasteContent={this.state.pasteContent} + updatecolumn={this.updatecolumn} + /> + </Col> + ) + } else { + return ( + <Col span={item.width} key={item.uuid}> + <ChartComponent + type={item.chartType} + dict={this.state.dict} + columns={config.columns} + plotchange={this.updateChart} + plot={item} + /> + </Col> + ) + } + })} </div> </Card> </div> </DndProvider> - {/* 缂栬緫鎼滅储鏉′欢 */} - <Modal - title={this.state.dict['header.modal.search.edit']} - visible={modaltype === 'search'} - width={750} - maskClosable={false} - onOk={this.handleSubmit} - confirmLoading={this.state.sqlVerifing} - onCancel={this.editModalCancel} - destroyOnClose - > - <SearchForm - dict={this.state.dict} - card={this.state.card} - formlist={this.state.formlist} - inputSubmit={this.handleSubmit} - optionLibs={this.state.optionLibs} - wrappedComponentRef={(inst) => this.searchFormRef = inst} - /> - </Modal> - {/* 缂栬緫鎸夐挳锛氬鍒躲�佺紪杈� */} - <Modal - title={modaltype === 'actionEdit' ? this.state.dict['header.modal.action.edit'] : this.state.dict['header.modal.action.copy']} - visible={modaltype === 'actionEdit' || modaltype === 'actionCopy'} - width={750} - maskClosable={false} - onCancel={this.editModalCancel} - footer={[ - hasbtncrtinter ? <CreateInterface key="interface" dict={this.state.dict} ref="btnCreatInterface" trigger={this.btnCreatInterface}/> : null, - modaltype === 'actionEdit' ? <CreateFunc key="create" dict={this.state.dict} ref="btnCreatFunc" trigger={this.creatFunc}/> : null, - <Button key="cancel" onClick={this.editModalCancel}>{this.state.dict['header.cancel']}</Button>, - <Button key="confirm" type="primary" onClick={this.handleSubmit}>{this.state.dict['header.confirm']}</Button> - ]} - destroyOnClose - > - <ActionForm - dict={this.state.dict} - card={this.state.card} - tabs={this.state.tabviews} - formlist={this.state.formlist} - inputSubmit={this.handleSubmit} - setting={this.state.config.setting} - wrappedComponentRef={(inst) => this.actionFormRef = inst} - /> - </Modal> - {/* 鏄剧ず鍒楃紪杈� */} - <Modal - title={this.state.dict['header.modal.column.edit']} - visible={modaltype === 'columns'} - width={750} - maskClosable={false} - onOk={this.handleSubmit} - onCancel={this.editModalCancel} - destroyOnClose - > - <ColumnForm - dict={this.state.dict} - card={this.state.card} - MenuID={this.props.menu.MenuID} - inputSubmit={this.handleSubmit} - formlist={this.state.formlist} - wrappedComponentRef={(inst) => this.columnFormRef = inst} - /> - </Modal> - {/* 鍚堝苟鍒楃紪杈� */} - <Modal - title={this.state.dict['header.modal.colspan.edit']} - visible={modaltype === 'colspan'} - width={750} - maskClosable={false} - onOk={this.handleSubmit} - onCancel={this.editModalCancel} - destroyOnClose - > - <ColspanForm - dict={this.state.dict} - card={this.state.card} - inputSubmit={this.handleSubmit} - columns={this.state.config.columns} - wrappedComponentRef={(inst) => this.columnFormRef = inst} - /> - </Modal> - {/* 鎿嶄綔鍒楃紪杈� */} - <Modal - title={this.state.dict['header.modal.gridbtn.edit']} - visible={modaltype === 'gridbtn'} - width={700} - maskClosable={false} - onOk={this.handleSubmit} - onCancel={this.editModalCancel} - destroyOnClose - > - <GridBtnForm - dict={this.state.dict} - inputSubmit={this.handleSubmit} - card={this.state.config.gridBtn} - wrappedComponentRef={(inst) => this.gridBtnFormRef = inst} - /> - </Modal> - {/* 鏍规嵁瀛楁鍚嶆坊鍔犳樉绀哄垪鍙婃悳绱㈡潯浠� */} - <Modal - wrapClassName="common-table-fields-modal" - title={this.state.dict['header.edit']} - visible={this.state.tableVisible} - width={'65vw'} - maskClosable={false} - style={{minWidth: '900px', maxWidth: '1200px'}} - cancelText={this.state.dict['header.close']} - onOk={this.addFieldSubmit} - onCancel={() => { // 鍙栨秷娣诲姞 - this.setState({ - tableVisible: false, - addType: '' - }) - }} - destroyOnClose - > - {this.state.addType && this.state.fields.length > 0 ? - <EditCard data={this.state.fields} ref="searchcard" type={this.state.addType} dict={this.state.dict} /> : null - } - {(!this.state.fields || this.state.fields.length === 0) && - <Empty /> - } - </Modal> - {/* 鎸夐挳浣跨敤绯荤粺瀛樺偍杩囩▼鏃讹紝楠岃瘉淇℃伅妯℃�佹 */} - <Modal - wrapClassName="common-table-fields-modal" - title={'楠岃瘉淇℃伅'} - visible={this.state.profileVisible} - width={'75vw'} - maskClosable={false} - style={{minWidth: '900px', maxWidth: '1200px'}} - okText={this.state.dict['header.submit']} - onOk={this.verifySubmit} - onCancel={() => { this.setState({ profileVisible: false }) }} - destroyOnClose - > - {this.state.card && !this.state.card.execMode && this.state.card.OpenType !== 'excelIn' && this.state.card.OpenType !== 'excelOut' ? - <VerifyCard - floor="subtable" - card={this.state.card} - dict={this.state.dict} - columns={this.state.config.columns} - wrappedComponentRef={(inst) => this.verifyRef = inst} - /> : null - } - {this.state.card && this.state.card.execMode ? - <VerifyCardPrint - card={this.state.card} - dict={this.state.dict} - columns={config.columns} - wrappedComponentRef={(inst) => this.verifyRef = inst} - /> : null - } - {this.state.card && this.state.card.OpenType === 'excelIn' ? - <VerifyCardExcelIn - card={this.state.card} - dict={this.state.dict} - columns={this.state.config.columns} - wrappedComponentRef={(inst) => this.verifyRef = inst} - /> : null - } - {this.state.card && this.state.card.OpenType === 'excelOut' ? - <VerifyCardExcelOut - card={this.state.card} - dict={this.state.dict} - wrappedComponentRef={(inst) => this.verifyRef = inst} - /> : null - } - </Modal> {/* 璁剧疆鍏ㄥ眬閰嶇疆鍙婂垪琛ㄦ暟鎹簮 */} <Modal - title={this.state.dict['header.edit']} + title={this.state.dict['model.edit']} visible={this.state.settingVisible} width={750} maskClosable={false} @@ -2579,7 +1362,7 @@ <CreateInterface key="interface" dict={this.state.dict} ref="tableCreatInterface" trigger={this.tableCreatInterface}/>, <CreateFunc key="create" dict={this.state.dict} ref="tableCreatFunc" trigger={this.tableCreatFunc}/>, <Button key="cancel" onClick={() => { this.setState({ settingVisible: false }) }}>{this.state.dict['header.cancel']}</Button>, - <Button key="confirm" type="primary" loading={this.state.sqlVerifing} onClick={this.settingSave}>{this.state.dict['header.confirm']}</Button> + <Button key="confirm" type="primary" loading={this.state.sqlVerifing} onClick={this.settingSave}>{this.state.dict['model.confirm']}</Button> ]} destroyOnClose > diff --git a/src/templates/subtableconfig/index.scss b/src/templates/subtableconfig/index.scss index 6d596e6..3987f11 100644 --- a/src/templates/subtableconfig/index.scss +++ b/src/templates/subtableconfig/index.scss @@ -1,4 +1,4 @@ -.common-table-board { +.model-subtable-board { position: fixed; z-index: 1070; padding-top: 48px; @@ -58,11 +58,6 @@ margin-bottom: 10px; color: #1890ff; border-bottom: 1px solid #e8e8e8; - } - } - .tables { - .ant-select-selection-selected-value { - opacity: 0.4!important; } } .ant-list { @@ -133,7 +128,6 @@ position: relative; width: calc(100vw - 235px); height: 100%; - // overflow-y: hidden; background: #ffffff; .ant-switch.big { min-width: 60px; @@ -164,217 +158,23 @@ .ant-card-body { position: relative; padding: 0; + + .chart-view { + margin-bottom: 70px; - .search-list { - padding: 1px 24px 20px; - min-height: 87px; - border-bottom: 1px solid #d9d9d9; - > .ant-row { - min-height: 65px; - } - .ant-row .ant-col-6 { - padding: 0 12px!important; - } - .ant-row.ant-form-item .ant-col { - padding: 0; - } - .page-card { - position: relative; - background: #ffffff; - border-radius: 2px; - padding-top: 15px; - .ant-form-item { - cursor: move; - display: flex; - margin-bottom: 0px; - .ant-form-item-label { - // width: 100px; - height: 40px; - label { - width: 100%; - cursor: move; - overflow: hidden; - display: inline-block; - text-overflow: ellipsis; - white-space: nowrap; - } - } - .ant-form-item-control-wrapper { - flex: 1 1; - .ant-select { - width: 100%; - margin-top: 4px; - } - .ant-calendar-picker { - margin-top: 4px; - } - .input-mask { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - opacity: 0; - z-index: 2; - } - .data-range .ant-calendar-picker-input { - padding: 4px 20px 4px 5px; - font-size: 13px; - } - } - } - .edit { - position: absolute; - left: 0; - top: 5px; - color: #1890ff; - cursor: pointer; - display: none; - } - .edit.close { - left: 20px; - color: #ff4d4f; - } - } - .page-card:hover { - .edit { - display: inline-block; - } - } - .ant-calendar-picker { - min-width: 100px!important; - width: 100%; - } - } - .action-list { - padding: 0px 20px 15px; - min-height: 82px; - > .ant-row { - min-height: 80px; - } - .page-card { - display: inline-block; - margin: 0px 0px 0px 0px; - padding: 15px 10px 0 0; - position: relative; - div { - cursor: move; - } - .edit { - position: absolute; - left: 0; - top: 0px; - color: #1890ff; - cursor: pointer; - display: none; - } - .edit.close { - left: 40px; - color: #ff4d4f; - } - .edit.copy { - left: 20px; - color: #26C281; - } - button { - cursor: move; - .anticon-table { - font-size: 10px; - position: absolute; - right: 1px; - bottom: 0px; - } - } - } - .page-card:hover { - .edit { - display: inline-block; - } - } - } - .column-list { - position: relative; - padding: 0px 20px; - .ant-switch { - position: absolute; - right: 20px; - top: -10px; - } - .column-copy { - position: absolute; - font-size: 16px; - right: 75px; - top: -7px; - color: #26C281; - } - > .ant-row { - background: #fafafa; - border-radius: 4px; - min-height: 47px; - border: 1px solid #e8e8e8; - .column-box { - display: flex; - } - .column-box:not(:first-child) { - border-top: 1px solid #e8e8e8; - } - .page-card { - position: relative; - padding: 0px; - min-height: 45px; - > div { - padding: 12px 0px 0px; - cursor: move; - height: 100%; - .ant-table-column-sorters { - padding: 0px 8px 12px; - } - .ant-table-column-fields { - padding: 0px 8px 5px; - } - } - .ant-table-column-sorter { - position: relative; - display: inline-block; - width: 24px; - font-size: 12px; - color: #bfbfbf; - .anticon-caret-up { - position: relative; - left: 10px; - top: -3px; - } - .anticon-caret-down { - position: relative; - left: -2px; - top: 3px; - } - } - .edit { - position: absolute; - left: 0; - top: 0px; - color: #1890ff; - cursor: pointer; - display: none; - } - .edit.close { - left: 20px; - color: #ff4d4f; - } - .ant-checkbox-inner { - margin-top: 14px; - margin-left: calc(50% - 8px); - } - } - .page-card:hover { - .edit { - display: inline-block; - } - } - .page-card:not(:last-child) { - border-right: 1px solid #e8e8e8; - } + .chart-title { + margin-bottom: 15px; + color: rgba(0, 0, 0, 0.85); + font-weight: 400; + font-size: 18px; + line-height: 25px; + height: 35px; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + max-width: 50%; + padding-top: 10px; + padding-left: 30px; } } > .anticon-setting { @@ -416,33 +216,5 @@ position: absolute; margin-left: calc(50vw - 22px); margin-top: 30vh; - } -} - -.common-table-fields-modal { - .ant-modal { - top: 50px; - padding-bottom: 5px; - .ant-modal-body { - max-height: calc(100vh - 190px); - overflow-y: auto; - .ant-empty { - margin: 15vh 8px; - } - } - .ant-modal-body::-webkit-scrollbar { - width: 7px; - } - .ant-modal-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); - } - .ant-modal-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); - background: rgba(0, 0, 0, 0); - } } } diff --git a/src/templates/subtableconfig/source.jsx b/src/templates/subtableconfig/source.jsx index 9a6c5cc..ba636c4 100644 --- a/src/templates/subtableconfig/source.jsx +++ b/src/templates/subtableconfig/source.jsx @@ -1,6 +1,6 @@ import Utils from '@/utils/utils.js' -import zhCN from '@/locales/zh-CN/comtable.js' -import enUS from '@/locales/en-US/comtable.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' const CommonDict = (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS @@ -168,7 +168,17 @@ style: 'button', show: 'horizontal', Width: 120 - } + }, + expand: false, + charts: [{ + uuid: Utils.getuuid(), + label: '', + title: '', + chartType: 'table', + icon: 'table', + Hide: 'false', + blacklist: [] + }] } searchItems = [ diff --git a/src/templates/zshare/chartcompile/index.jsx b/src/templates/zshare/chartcompile/index.jsx new file mode 100644 index 0000000..3ea5f49 --- /dev/null +++ b/src/templates/zshare/chartcompile/index.jsx @@ -0,0 +1,213 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +// import { is, fromJS } from 'immutable' +import { Drawer, Form, Button, Col, Row, Select, Icon, Radio, Tooltip, Input, InputNumber } from 'antd' + +import { getChartOptionForm } from '@/templates/zshare/formconfig' +import './index.scss' + +class LineChartDrawerForm extends Component { + static propTpyes = { + type: PropTypes.string, + dict: PropTypes.object, + plot: PropTypes.object, + columns: PropTypes.array, + plotchange: PropTypes.func + } + + state = { + visible: false, + formlist: null + } + + showDrawer = () => { + const { columns, plot, type } = this.props + + this.setState({ + visible: true, + formlist: getChartOptionForm(plot, columns, type) + }) + } + + onClose = (type) => { + if (type !== 'submit') { + this.setState({ + visible: false + }) + return + } + + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + this.setState({ + visible: false + }) + this.props.plotchange(values) + } + }) + } + + getFields() { + const { formlist } = this.state + const { getFieldDecorator } = this.props.form + const fields = [] + + if (!formlist) { + return fields + } + + formlist.forEach((item, index) => { + if (item.hidden) return + + if (item.type === 'text') { // 鏂囨湰鎼滅储 + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" title={item.tooltip}> + <Icon type="question-circle" /> + {item.label} + </Tooltip> : item.label + }> + {getFieldDecorator(item.key, { + initialValue: item.initVal, + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.input'] + item.label + '!' + } + ] + })(<Input placeholder="" autoComplete="off" disabled={item.readonly}/>)} + </Form.Item> + </Col> + ) + } else if (item.type === 'number') { + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" title={item.tooltip}> + <Icon type="question-circle" /> + {item.label} + </Tooltip> : item.label + }> + {getFieldDecorator(item.key, { + initialValue: item.initVal, + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.input'] + item.label + '!' + } + ] + })(<InputNumber min={item.min} max={item.max} precision={item.decimal} />)} + </Form.Item> + </Col> + ) + } else if (item.type === 'select') { // 涓嬫媺鎼滅储 + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" title={item.tooltip}> + <Icon type="question-circle" /> + {item.label} + </Tooltip> : item.label + }> + {getFieldDecorator(item.key, { + initialValue: item.initVal, + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.select'] + item.label + '!' + } + ] + })( + <Select mode={item.multi ? 'multiple' : ''}> + {item.options.map((option, index) => + <Select.Option key={index} value={option.field}> + {option.label} + </Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + ) + } else if (item.type === 'radio') { + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.label}> + {getFieldDecorator(item.key, { + initialValue: item.initVal, + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.select'] + item.label + '!' + } + ] + })( + <Radio.Group> + {item.options.map(option => { + return ( + <Radio key={option.value} value={option.value}>{option.text}</Radio> + ) + })} + </Radio.Group> + )} + </Form.Item> + </Col> + ) + } + }) + return fields + } + + render() { + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 6 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 18 } + } + } + + return ( + <div className="line-chart-drawer-form"> + <Icon type="edit" onClick={this.showDrawer} /> + <Drawer + title="鍥捐〃缂栬緫" + className="chart-drawer-form" + width={720} + onClose={this.onClose} + visible={this.state.visible} + bodyStyle={{ paddingBottom: 80 }} + > + <Form {...formItemLayout}> + <Row gutter={16}>{this.getFields()}</Row> + </Form> + <div + style={{ + position: 'absolute', + right: 0, + bottom: 0, + width: '100%', + borderTop: '1px solid #e9e9e9', + padding: '10px 16px', + background: '#fff', + textAlign: 'right', + }} + > + <Button onClick={this.onClose} style={{ marginRight: 8 }}> + 鍙栨秷 + </Button> + <Button onClick={() => this.onClose('submit')} type="primary"> + 鎻愪氦 + </Button> + </div> + </Drawer> + </div> + ); + } +} + +export default Form.create()(LineChartDrawerForm) \ No newline at end of file diff --git a/src/templates/zshare/chartcompile/index.scss b/src/templates/zshare/chartcompile/index.scss new file mode 100644 index 0000000..1f17fc6 --- /dev/null +++ b/src/templates/zshare/chartcompile/index.scss @@ -0,0 +1,31 @@ +.line-chart-drawer-form { + position: absolute; + right: 10px; + + > .anticon-edit { + color: #1890ff; + font-size: 16px; + margin-right: 5px; + } +} + +.chart-drawer-form { + .ant-drawer-body { + max-height: calc(100vh - 60px); + overflow-y: auto; + } + .ant-drawer-body::-webkit-scrollbar { + width: 7px; + } + .ant-drawer-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); + } + .ant-drawer-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); + background: rgba(0, 0, 0, 0); + } +} diff --git a/src/templates/zshare/chartcomponent/index.jsx b/src/templates/zshare/chartcomponent/index.jsx new file mode 100644 index 0000000..08359f5 --- /dev/null +++ b/src/templates/zshare/chartcomponent/index.jsx @@ -0,0 +1,437 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Chart } from '@antv/g2' +import DataSet from '@antv/data-set' + +import ChartDrawerForm from '@/templates/zshare/chartcompile' +import './index.scss' + +class LineChart extends Component { + static propTpyes = { + type: PropTypes.string, + dict: PropTypes.object, + plot: PropTypes.object, + columns: PropTypes.array, + plotchange: PropTypes.func + } + + state = { + visible: true + } + + componentDidMount () { + this.viewrender() + } + + UNSAFE_componentWillReceiveProps (nextProps) { + if (!is(fromJS(this.props.plot), fromJS(nextProps.plot))) { + this.setState({}, () => { + this.viewrender() + }) + } + } + + getdata = (X_axis, Y_axis) => { + const { type } = this.props + let data = [] + let xdata = ['鍛ㄤ竴', '鍛ㄤ簩', '鍛ㄤ笁', '鍛ㄥ洓', '鍛ㄤ簲', '鍛ㄥ叚', '鍛ㄦ棩'] + let point = 7 + + if (type === 'pie') { + xdata = ['浜嬩緥涓�', '浜嬩緥浜�', '浜嬩緥涓�', '浜嬩緥鍥�', '浜嬩緥浜�'] + point = 5 + } + + for (let i = 0; i < point; i++) { + let item = {} + + item[X_axis] = xdata[i] + + if (typeof(Y_axis) === 'string') { + item[Y_axis] = Math.floor(Math.random() * 5 * (i + 1)) + i + } else { + Y_axis.forEach(y => { + item[y] = Math.floor(Math.random() * 5 * (i + 1)) + i + }) + } + + data.push(item) + } + + return data + } + + viewrender = () => { + const { type } = this.props + + if (type === 'line') { + this.linerender() + } else if (type === 'bar') { + this.barrender() + } else if (type === 'pie') { + this.pierender() + } + } + + linerender = () => { + const { plot, columns } = this.props + + let transfield = {} + columns.forEach(col => { + if (col.field) { + transfield[col.field] = col.label + } + }) + // const colors = ['#f49d37', '#f03838', '#35d1d1', '#5be56b', '#4e7af0', '#ebcc21'] + let X_axis = plot.Xaxis || 'x' + let Y_axis = plot.Yaxis || ['y'] + + let data = this.getdata(X_axis, Y_axis) + + const ds = new DataSet() + const dv = ds.createView().source(data) + + dv.transform({ + type: 'fold', + fields: [...Y_axis], + key: 'key', // key瀛楁 + value: 'value', // value瀛楁 + // retains: [], // 淇濈暀瀛楁闆嗭紝榛樿涓洪櫎 fields 浠ュ鐨勬墍鏈夊瓧娈� + }) + + if (plot.Xaxis) { + dv.transform({ + type: 'map', + callback(row) { + row.key = transfield[row.key] + return row + }, + }) + } + + const chart = new Chart({ + container: plot.uuid, + autoFit: true, + height: plot.height || 400 + }) + + chart.data(dv.rows) + + if (plot.coordinate !== 'polar') { + chart.scale(X_axis, { + range: [0, 1] + }) + } + chart.scale('value', { + nice: true + }) + + if (!plot.legend || plot.legend === 'hidden') { + chart.legend(false) + } else { + chart.legend({ + position: plot.legend + }) + } + + if (plot.tooltip !== 'true') { + chart.tooltip(false) + } else { + chart.tooltip({ + shared: true + }) + } + + if (plot.transpose === 'true') { + chart.coordinate().transpose() + } + + if (plot.coordinate === 'polar') { + chart.coordinate('polar', { + innerRadius: 0.1, + radius: 0.8 + }) + } + + let _chart = chart + .line() + .position(`${X_axis}*value`) + .color('key') + .shape(plot.shape || 'smooth') + + if (plot.label === 'true') { + _chart.label('value') + } + + if (plot.point === 'true') { + chart + .point() + .position(`${X_axis}*value`) + .color('key') + .size(3) + .shape('circle') + } + + // chart.interaction('element-active') + // chart.removeInteraction('legend-filter') // 鑷畾涔夊浘渚嬶紝绉婚櫎榛樿鐨勫垎绫诲浘渚嬬瓫閫変氦浜� + chart.render() + } + + barrender = () => { + const { plot, columns } = this.props + + let transfield = {} + columns.forEach(col => { + if (col.field) { + transfield[col.field] = col.label + } + }) + let X_axis = plot.Xaxis || 'x' + let Y_axis = plot.Yaxis || ['y'] + if (!plot.Yaxis && plot.modelId !== 'bar1') { + Y_axis = ['bar1', 'bar2'] + } + + let data = this.getdata(X_axis, Y_axis) + + const ds = new DataSet() + const dv = ds.createView().source(data) + + dv.transform({ + type: 'fold', + fields: [...Y_axis], + key: 'key', + value: 'value' + }) + + if (plot.Xaxis) { + dv.transform({ + type: 'map', + callback(row) { + row.key = transfield[row.key] + return row + }, + }) + } + + const chart = new Chart({ + container: plot.uuid, + autoFit: true, + height: plot.height || 400 + }) + + chart.data(dv.rows) + + chart.scale('value', { + nice: true + }) + + if (!plot.legend || plot.legend === 'hidden') { + chart.legend(false) + } else { + chart.legend({ + position: plot.legend + }) + } + + if (plot.tooltip !== 'true') { + chart.tooltip(false) + } else { + chart.tooltip({ + shared: true + }) + } + + if (plot.transpose === 'true') { + chart.coordinate().transpose() + } + + if (plot.coordinate === 'polar') { + chart.coordinate('polar', { + innerRadius: 0.1, + radius: 0.8 + }) + } + + if (plot.adjust !== 'stack') { + chart + .interval() + .position(`${X_axis}*value`) + .color('key') + .adjust([ + { + type: 'dodge', + marginRatio: 0 + } + ]) + .shape(plot.shape || 'rect') + } else if (plot.adjust === 'stack') { + chart + .interval() + .position(`${X_axis}*value`) + .color('key') + .adjust('stack') + .shape(plot.shape || 'rect') + } + + chart.render() + } + + pierender = () => { + const { plot, columns } = this.props + + let transfield = {} + columns.forEach(col => { + if (col.field) { + transfield[col.field] = col.label + } + }) + let X_axis = plot.Xaxis || 'x' + let Y_axis = plot.Yaxis || 'y' + + let data = this.getdata(X_axis, Y_axis) + + const ds = new DataSet() + const dv = ds.createView().source(data) + + if (plot.pieshow !== 'value') { + dv.transform({ + type: 'percent', + field: Y_axis, + dimension: X_axis, + as: 'percent' + }) + } + + const chart = new Chart({ + container: plot.uuid, + autoFit: true, + height: plot.height || 400 + }) + + chart.data(dv.rows) + + if (plot.pieshow !== 'value') { + chart.scale('percent', { + formatter: (val) => { + val = val * 100 + '%' + return val + } + }) + } + + chart.coordinate('theta', { + innerRadius: plot.shape === 'ring' ? 0.6 : 0, + radius: 0.75, + }) + + if (!plot.legend || plot.legend === 'hidden') { + chart.legend(false) + } else { + chart.legend({ + position: plot.legend + }) + } + + if (plot.tooltip !== 'true') { + chart.tooltip(false) + } else { + chart.tooltip({ + showTitle: false, + showMarkers: false + }) + } + + if (plot.pieshow !== 'value') { + let _chart = chart + .interval() + .adjust('stack') + .position('percent') + .color(X_axis) + .tooltip(X_axis + '*percent', (item, percent) => { + percent = (percent * 100).toFixed(2) + '%' + return { + name: item, + value: percent + } + }) + + if (plot.label === 'true') { + let setting = { + content: (data) => { + return `${data[X_axis]}: ${(data.percent * 100).toFixed(2)}%` + } + } + + if (plot.labelLayout === 'overlap') { + setting.type = 'pie' + setting.layout = { + type: 'overlap' + } + setting.offset = 0 + // setting.style = { + // textAlign: 'center', + // fontSize: 12, + // fill: '#535353' + // } + } + + _chart.label('percent', setting) + } + + } else { + let _chart = chart + .interval() + .adjust('stack') + .position(Y_axis) + .color(X_axis) + .tooltip(X_axis + '*' + Y_axis, (item, value) => { + return { + name: item, + value: value + } + }) + + if (plot.label === 'true') { + let setting = { + content: (data) => { + return `${data[X_axis]}: ${data[Y_axis]}` + } + } + + if (plot.labelLayout === 'overlap') { + setting.type = 'pie' + setting.layout = { + type: 'overlap' + } + setting.offset = 0 + } + + _chart.label(Y_axis, setting) + } + } + + chart.render() + } + + plotChange = (values) => { + const { plot } = this.props + + this.props.plotchange({...plot, ...values}) + } + + render() { + const { plot, type } = this.props + + return ( + <div className="line-chart-edit-box" style={{minHeight: plot.height ? plot.height + 50 : 450}}> + <p className="chart-title">{plot.title}</p> + <ChartDrawerForm type={type} columns={this.props.columns} dict={this.props.dict} plot={plot} plotchange={this.plotChange} /> + <div className="canvas" id={plot.uuid}></div> + </div> + ) + } +} + +export default LineChart \ No newline at end of file diff --git a/src/templates/zshare/chartcomponent/index.scss b/src/templates/zshare/chartcomponent/index.scss new file mode 100644 index 0000000..cc0be8c --- /dev/null +++ b/src/templates/zshare/chartcomponent/index.scss @@ -0,0 +1,7 @@ +.line-chart-edit-box { + margin-bottom: 30px; + + .canvas { + margin: 0 40px; + } +} diff --git a/src/templates/zshare/chartform/index.jsx b/src/templates/zshare/chartform/index.jsx new file mode 100644 index 0000000..0d0c26d --- /dev/null +++ b/src/templates/zshare/chartform/index.jsx @@ -0,0 +1,379 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input, Select, InputNumber, Radio, Tooltip, Icon } from 'antd' + +import { formRule } from '@/utils/option.js' +import line1 from '@/assets/img/line1.png' +import line2 from '@/assets/img/line2.png' +import line3 from '@/assets/img/line3.png' +import line4 from '@/assets/img/line4.png' +import bar1 from '@/assets/img/bar1.png' +import bar2 from '@/assets/img/bar2.png' +import bar3 from '@/assets/img/bar3.png' +import bar4 from '@/assets/img/bar4.png' +import pie1 from '@/assets/img/pie1.png' +import pie2 from '@/assets/img/pie2.png' +import './index.scss' + +const syslegends = { + line: [ + { + uuid: 'line1', + url: line1, + options: { + shape: 'line', + coordinate: 'angle' + } + }, + { + uuid: 'line2', + url: line2, + options: { + shape: 'smooth', + coordinate: 'angle' + } + }, + { + uuid: 'line3', + url: line3, + options: { + shape: 'hv', + coordinate: 'angle' + } + }, + { + uuid: 'line4', + url: line4, + options: { + shape: 'smooth', + coordinate: 'polar' + } + } + ], + bar: [ + { + uuid: 'bar1', + url: bar1, + options: { + shape: 'rect', + adjust: 'dodge', + transpose: 'false' + } + }, + { + uuid: 'bar2', + url: bar2, + options: { + shape: 'rect', + adjust: 'dodge', + transpose: 'false' + } + }, + { + uuid: 'bar3', + url: bar3, + options: { + shape: 'rect', + adjust: 'stack', + transpose: 'false' + } + }, + { + uuid: 'bar4', + url: bar4, + options: { + shape: 'rect', + adjust: 'dodge', + transpose: 'true' + } + } + ], + pie: [ + { + uuid: 'pie1', + url: pie1, + options: { + shape: 'pie' + } + }, + { + uuid: 'pie2', + url: pie2, + options: { + shape: 'ring' + } + } + ] +} + +class ChartForm extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + MenuID: PropTypes.any, + formlist: PropTypes.any, + card: PropTypes.any, + inputSubmit: PropTypes.any // 鍥炶溅鎻愪氦浜嬩欢 + } + + state = { + formlist: null, + legends: null, + selectlegend: null + } + + UNSAFE_componentWillMount () { + const { card } = this.props + + let _type = card.chartType || 'line' + let _legends = null + let _selectlegend = null + + if (_type === 'line' || _type === 'bar' || _type === 'line') { + _legends = syslegends[_type] + _selectlegend = _legends.filter(item => item.uuid === card.modelId)[0] + + if (!_selectlegend) { + _selectlegend = _legends[0] + } + } + + this.setState({ + legends: _legends, + selectlegend: _selectlegend + }) + } + + componentDidMount () { + const { card } = this.props + + if (!card.chartType) { + try { + let _form = document.getElementById('title') + _form.select() + } catch { + console.warn('琛ㄥ崟focus澶辫触锛�') + } + } + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + typeChange = (key, value) => { + if (key === 'chartType') { + this.setState({ + legends: syslegends[value] || null, + selectlegend: syslegends[value][0] + }) + } + } + + changeSelectLegend = (item) => { + this.setState({ + selectlegend: item + }) + } + + getFields() { + const { getFieldDecorator } = this.props.form + const fields = [] + this.props.formlist.forEach((item, index) => { + if (item.hidden) return + + if (item.type === 'text') { // 鏂囨湰鎼滅储 + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} 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 + '!' + }, + { + max: formRule.input.max, + message: formRule.input.message + } + ] + })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + ) + } else if (item.type === 'number') { + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.tooltip ? + <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}> + <Icon type="question-circle" /> + {item.label} + </Tooltip> : item.label + }> + {getFieldDecorator(item.key, { + initialValue: item.initVal, + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.input'] + item.label + '!' + } + ] + })(<InputNumber min={item.min} max={item.max} precision={item.decimal} />)} + </Form.Item> + </Col> + ) + } else if (item.type === 'select') { // 涓嬫媺鎼滅储 + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.label}> + {getFieldDecorator(item.key, { + initialValue: item.initVal || '', + rules: [ + { + required: !!item.required, + message: this.props.dict['form.required.select'] + item.label + '!' + } + ] + })( + <Select + showSearch + disabled={!!item.readonly} + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + onChange={(value) => {this.typeChange(item.key, value)}} + getPopupContainer={() => document.getElementById('chartwinter')} + > + {item.options.map((option, index) => + <Select.Option id={`${index}`} title={option.text} key={`${index}`} value={option.value}> + {option.text} + </Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + ) + } else if (item.type === 'radio') { + 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 + '!' + } + ] + })( + <Radio.Group> + { + item.options.map(option => { + return ( + <Radio key={option.value} value={option.value}>{option.text}</Radio> + ) + }) + } + </Radio.Group> + )} + </Form.Item> + </Col> + ) + } else if (item.type === 'multiselect') { // 澶氶�� + fields.push( + <Col span={12} key={index}> + <Form.Item label={item.label}> + {getFieldDecorator(item.key, { + initialValue: item.initVal || [] + })( + <Select + showSearch + mode="multiple" + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + > + {item.options.map((option, i) => + <Select.Option id={i} key={i} value={option.value}>{option.text}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + ) + } + }) + return fields + } + + handleConfirm = () => { + const { selectlegend } = this.state + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + let result = {...this.props.card, ...values} + + let icons = { + table: 'table', + line: 'line-chart', + bar: 'bar-chart', + pie: 'pie-chart' + } + + if (selectlegend && this.props.card.modelId !== selectlegend.uuid) { + result = {...result, ...selectlegend.options} + } + + if (selectlegend) { + result.modelId = selectlegend.uuid + } + + if (result.chartType !== 'pie' && result.Yaxis && typeof(result.Yaxis) === 'string') { + result.Yaxis = [result.Yaxis] + } else if (result.chartType === 'pie' && result.Yaxis && typeof(result.Yaxis) === 'object') { + result.Yaxis = result.Yaxis[0] || '' + } + + result.icon = icons[result.chartType] + + resolve(result) + } else { + reject(err) + } + }) + }) + } + + render() { + const { legends, selectlegend } = this.state + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 6 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 18 } + } + } + return ( + <Form {...formItemLayout} className="chart-edit-form" id="chartwinter"> + <Row gutter={24}>{this.getFields()}</Row> + {legends ? <Row gutter={24} className="chart-model-image"> + {legends.map(item => <Col span={6} key={item.uuid}> + <img onClick={() => this.changeSelectLegend(item)} src={item.url} className={selectlegend.uuid === item.uuid ? 'active' : ''} alt=""/> + </Col>)} + </Row> : null} + </Form> + ) + } +} + +export default Form.create()(ChartForm) \ No newline at end of file diff --git a/src/templates/zshare/chartform/index.scss b/src/templates/zshare/chartform/index.scss new file mode 100644 index 0000000..a1778ca --- /dev/null +++ b/src/templates/zshare/chartform/index.scss @@ -0,0 +1,25 @@ +.chart-edit-form { + min-height: 190px; + .ant-form-item { + .ant-input-number { + width: 100%; + } + } + .anticon-question-circle { + color: #c49f47; + position: relative; + left: -3px; + } + .chart-model-image { + img { + max-width: 100%; + cursor: pointer; + border: 1px solid #ebedf0; + transition: all .3s; + } + img.active { + background-color: rgba(135,59,244,.1); + border-color: #873bf4; + } + } +} diff --git a/src/templates/zshare/createinterface/index.jsx b/src/templates/zshare/createinterface/index.jsx index 1b3d1e2..568bd34 100644 --- a/src/templates/zshare/createinterface/index.jsx +++ b/src/templates/zshare/createinterface/index.jsx @@ -23,11 +23,17 @@ btn: null } + /** + * @description 瑙﹀彂鍒涘缓璇绘暟鎹帴鍙� + * @param { object } menu 鑿滃崟绫诲瀷锛堜笁绾ц彍鍗曟垨鏍囩椤碉級銆佽彍鍗旾D銆佽彍鍗曞弬鏁般�佽彍鍗曞悕绉� + * @param { object } config 鑿滃崟閰嶇疆淇℃伅 + */ triggerOutInterface = (menu, config) => { let _search = [] let _index = 1 if (menu.type !== 'main') { + // 瀛愯〃椤甸潰澧炲姞BID瀛楁锛屾暟鎹簮涓娇鐢ㄤ簡@BID@鏃讹紝BID绫诲瀷涓哄繀浼� if (config.setting.dataresource && /@BID@/ig.test(config.setting.dataresource)) { _search.push(`select 'BID' as searchfield,'BID' as label,'0' as Sort,'' as defaultvalue,'required' as DefaultType`) } else { @@ -283,7 +289,26 @@ }) } + /** + * @description 瑙﹀彂鍒涘缓鍐欏叆鎺ュ彛锛堟寜閽級 + */ triggerInInterface = (btn, config, menu) => { + if (!['pop', 'exec', 'prompt'].includes(btn.OpenType) || btn.funcType || btn.intertype !== 'inner' || btn.innerFunc ) { + notification.warning({ + top: 92, + message: '鎵撳紑鏂瑰紡涓� 寮圭獥锛堣〃鍗曪級銆佹彁绀烘鎴栫洿鎺ユ墽琛岋紝涓斾娇鐢ㄧ郴缁熷嚱鏁版椂锛屾墠鍙互鍒涘缓鎺ュ彛锛�', + duration: 5 + }) + return + } else if (btn.Ot === 'requiredOnce') { + notification.warning({ + top: 92, + message: '澶氳鎷兼帴鏃讹紝涓嶆敮鎸佸垱寤烘帴鍙o紒', + duration: 5 + }) + return + } + let param = { func: 's_get_para_for_in', Menuid: btn.uuid, @@ -343,6 +368,9 @@ }) } + /** + * @description 鎵ц鎺ュ彛鍒涘缓 + */ createBtnInterfaceExec = (param, config, btn) => { let formlist = [] let receipt = param.Return === 'Y' @@ -448,9 +476,14 @@ }) if (param.menuType !== 'main' && !_keys.includes('bid')) { + _keys.push('bid') param.Ltexttableparam.unshift(`select 'BID' as searchfield,'BID' as label,'0' as Sort,'nvarchar(50)' as fieldtype,'required' as requiredtype,'' as defaultvalue`) } + if (btn.Ot !== 'notRequired' && !_keys.includes(config.setting.primaryKey.toLowerCase())) { + param.Ltexttableparam.unshift(`select '${config.setting.primaryKey}' as searchfield,'${config.setting.primaryKey}' as label,'1' as Sort,'nvarchar(50)' as fieldtype,'required' as requiredtype,'' as defaultvalue`) + } + param.Ltexttableparam = param.Ltexttableparam.join(' union all ') if (receipt) { diff --git a/src/templates/zshare/editcomponent/index.jsx b/src/templates/zshare/editcomponent/index.jsx index cf54d8d..28f010d 100644 --- a/src/templates/zshare/editcomponent/index.jsx +++ b/src/templates/zshare/editcomponent/index.jsx @@ -141,7 +141,15 @@ }, () => { this.props.refresh({ type: 'paste', - copyType: 'action', + content: res + }) + }) + } else if (res.copyType === 'search') { + this.setState({ + pasteVisible: false + }, () => { + this.props.refresh({ + type: 'paste', content: res }) }) @@ -160,8 +168,7 @@ }, () => { this.props.refresh({ type: 'paste', - copyType: 'columns', - config: {...config, columns: res.columns} + content: res }) }) } else { @@ -179,7 +186,7 @@ <Menu onClick={this.handleMenuClick}> <Menu.Item key="thaw"><Icon type="unlock" />{this.props.dict['header.form.thawbutton']}</Menu.Item> <Menu.Item key="paste"><Icon type="snippets" />{this.props.dict['header.form.paste']}</Menu.Item> - <Menu.Item key="replace"><Icon type="retweet" />鏇挎崲</Menu.Item> + {/* <Menu.Item key="replace"><Icon type="retweet" />鏇挎崲</Menu.Item> */} </Menu> ) @@ -193,7 +200,7 @@ {/* 瑙e喕鎸夐挳妯℃�佹 */} <Modal title={this.props.dict['header.form.thawbutton']} - okText={this.props.dict['header.confirm']} + okText={this.props.dict['model.confirm']} cancelText={this.props.dict['header.cancel']} visible={this.state.thawVisible} onOk={this.thawBtnSubmit} diff --git a/src/templates/zshare/exceleditable/index.jsx b/src/templates/zshare/exceleditable/index.jsx index 332fe1b..0b5ceea 100644 --- a/src/templates/zshare/exceleditable/index.jsx +++ b/src/templates/zshare/exceleditable/index.jsx @@ -188,7 +188,7 @@ <span className="operation-btn" title={props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> <Popconfirm title={props.dict['header.form.query.delete']} - okText={props.dict['header.confirm']} + okText={props.dict['model.confirm']} cancelText={props.dict['header.cancel']} onConfirm={() => this.handleDelete(record.key) }> diff --git a/src/templates/zshare/formconfig.jsx b/src/templates/zshare/formconfig.jsx index d72cf10..371490a 100644 --- a/src/templates/zshare/formconfig.jsx +++ b/src/templates/zshare/formconfig.jsx @@ -1,5 +1,5 @@ -import zhCN from '@/locales/zh-CN/comtable.js' -import enUS from '@/locales/en-US/comtable.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' const Formdict = localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS @@ -252,8 +252,55 @@ * @param {*} functip 鐢熸垚瀛樺偍杩囩▼鎻愮ず * @param {*} config 椤甸潰閰嶇疆 * @param {*} permFuncField 瀛樺偍杩囩▼鍙敤鐨勫紑濮嬪瓧娈� + * @param {*} type 鎸夐挳绫诲瀷锛岀敤浜庡尯鍒嗗彲閫夌殑鎵撳紑鏂瑰紡 */ -export function getActionForm (card, functip, config, permFuncField) { +export function getActionForm (card, functip, config, permFuncField, type) { + let opentypes = [ + { + value: 'pop', + text: Formdict['header.form.popform'] + }, { + value: 'prompt', + text: Formdict['header.form.prompt'] + }, { + value: 'exec', + text: Formdict['header.form.exec'] + }, { + value: 'excelIn', + text: Formdict['header.form.excelIn'] + }, { + value: 'excelOut', + text: Formdict['header.form.excelOut'] + }, { + value: 'popview', + text: Formdict['header.form.popview'] + } + ] + + if (type === 'subtable') { + opentypes.push({ + value: 'funcbutton', + text: Formdict['header.form.funcbutton'] + }) + } else { + opentypes.push({ + value: 'tab', + text: Formdict['header.form.tab'] + }, { + value: 'blank', + text: Formdict['header.form.blank'] + }, { + value: 'innerpage', + text: Formdict['header.form.newpage.inner'] + }, { + value: 'outerpage', + text: Formdict['header.form.newpage.outer'] + }, { + value: 'funcbutton', + text: Formdict['header.form.funcbutton'] + }) + } + return [ { type: 'text', @@ -269,40 +316,7 @@ label: Formdict['header.form.openType'], initVal: card.OpenType, required: true, - options: [{ - value: 'pop', - text: Formdict['header.form.popform'] - }, { - value: 'prompt', - text: Formdict['header.form.prompt'] - }, { - value: 'exec', - text: Formdict['header.form.exec'] - }, { - value: 'excelIn', - text: Formdict['header.form.excelIn'] - }, { - value: 'excelOut', - text: Formdict['header.form.excelOut'] - }, { - value: 'popview', - text: Formdict['header.form.popview'] - }, { - value: 'tab', - text: Formdict['header.form.tab'] - }, { - value: 'blank', - text: Formdict['header.form.blank'] - }, { - value: 'innerpage', - text: Formdict['header.form.newpage.inner'] - }, { - value: 'outerpage', - text: Formdict['header.form.newpage.outer'] - }, { - value: 'funcbutton', - text: Formdict['header.form.funcbutton'] - }] + options: opentypes }, { type: 'select', @@ -871,6 +885,295 @@ } /** + * @description 鑾峰彇鍥捐〃瑙嗗浘澶栭儴閰嶇疆琛ㄥ崟 + * @param {*} card + */ +export function getChartViewForm (card, roleList = []) { + let _charts = [{ + value: 'line', + text: '鎶樼嚎鍥�' + }, { + value: 'bar', + text: '鏌辩姸鍥�' + }, { + value: 'pie', + text: '楗煎浘' + }] + + if (card.chartType === 'table') { + _charts = [{ + value: 'table', + text: '琛ㄦ牸' + }] + } + + return [ + { + type: 'text', + key: 'title', + label: Formdict['header.form.title'], + initVal: card.title, + required: false + }, + { + type: 'select', + key: 'chartType', + label: '鍥捐〃绫诲瀷', + initVal: card.chartType, + required: true, + readonly: card.chartType === 'table', + options: _charts + }, + { + type: 'number', + key: 'height', + min: 100, + max: 1000, + decimal: 0, + label: '楂樺害', + initVal: card.height || 400, + required: true + }, + { + type: 'number', + key: 'width', + min: 1, + max: 24, + decimal: 0, + label: '瀹藉害', + tooltip: '姣忚绛夊垎涓�24鍒楋紝24鍗充负100%銆�', + initVal: card.width || 24, + required: true + }, + { + type: 'radio', + key: 'Hide', + label: Formdict['header.form.Hide'], + initVal: card.Hide, + required: true, + options: [{ + value: 'true', + text: Formdict['header.form.true'] + }, { + value: 'false', + text: Formdict['header.form.false'] + }] + }, + { + type: 'multiselect', + key: 'blacklist', + label: Formdict['header.form.blacklist'], + initVal: card.blacklist || [], + required: false, + options: roleList + } + ] +} + +/** + * @description 鑾峰彇鍥捐〃瑙嗗浘閰嶇疆琛ㄥ崟 + * @param {*} card + */ +export function getChartOptionForm (card, columns, type) { + let shapes = [] + + if (type === 'line') { + shapes = [ + { field: 'smooth', label: 'smooth' }, + { field: 'line', label: 'line' }, + { field: 'dot', label: 'dot' }, + { field: 'dash', label: 'dash' }, + { field: 'hv', label: 'hv' }, + { field: 'vh', label: 'vh' }, + { field: 'hvh', label: 'hvh' }, + { field: 'vhv', label: 'vhv' } + ] + } else if (type === 'bar') { + shapes = [ + { field: 'rect', label: 'rect' }, + { field: 'hollow-rect', label: 'hollow-rect' }, + { field: 'line', label: 'line' }, + { field: 'tick', label: 'tick' }, + { field: 'funnel', label: 'funnel' }, + { field: 'pyramid', label: 'pyramid' } + ] + } else if (type === 'pie') { + shapes = [ + { field: 'pie', label: '楗煎浘' }, + { field: 'ring', label: '鐜浘' } + ] + } + + return [ + { + type: 'select', + key: 'Xaxis', + label: type === 'pie' ? 'Text' : 'X-杞�', + initVal: card.Xaxis || '', + required: true, + options: columns.filter(col => col.type === 'text') + }, + { + type: 'select', + key: 'Yaxis', + label: type === 'pie' ? 'Value' : 'Y-杞�', + initVal: type === 'pie' ? card.Yaxis || '' : card.Yaxis || [], + multi: type !== 'pie', + required: true, + options: columns.filter(col => col.type === 'number') + }, + { + type: 'select', + key: 'legend', + label: '鍥句緥浣嶇疆', + initVal: card.legend || 'bottom', + required: false, + options: [ + { field: 'top', label: 'top' }, + { field: 'top-left', label: 'top-left' }, + { field: 'top-right', label: 'top-right' }, + { field: 'right', label: 'right' }, + { field: 'right-top', label: 'right-top' }, + { field: 'right-bottom', label: 'right-bottom' }, + { field: 'left', label: 'left' }, + { field: 'left-top', label: 'left-top' }, + { field: 'left-bottom', label: 'left-bottom' }, + { field: 'bottom', label: 'bottom' }, + { field: 'bottom-left', label: 'bottom-left' }, + { field: 'bottom-right', label: 'bottom-right' }, + { field: 'hidden', label: 'hidden' } + ] + }, + { + type: 'select', + key: 'shape', + label: '褰㈢姸', + initVal: card.shape || (shapes[0] && shapes[0].field), + required: false, + hidden: !['line', 'bar', 'pie'].includes(type), + options: shapes + }, + { + type: 'radio', + key: 'tooltip', + label: '鎻愮ず淇℃伅', + initVal: card.tooltip || 'true', + required: false, + options: [{ + value: 'true', + text: '鏄剧ず' + }, { + value: 'false', + text: '闅愯棌' + }] + }, + { + type: 'radio', + key: 'coordinate', + label: '鍧愭爣', + initVal: card.coordinate || 'angle', + required: false, + hidden: !['line', 'bar'].includes(type), + options: [{ + value: 'angle', + text: '浜岀淮鍧愭爣' + }, { + value: 'polar', + text: '鏋佸潗鏍�' + }] + }, + { + type: 'radio', + key: 'point', + label: '鐐瑰浘', + initVal: card.point || 'false', + required: false, + hidden: !['line'].includes(type), + options: [{ + value: 'true', + text: '鏄剧ず' + }, { + value: 'false', + text: '闅愯棌' + }] + }, + { + type: 'radio', + key: 'transpose', + label: '鍙樻崲', + initVal: card.transpose || 'false', + required: false, + hidden: !['line', 'bar'].includes(type), + options: [{ + value: 'true', + text: Formdict['header.form.true'] + }, { + value: 'false', + text: Formdict['header.form.false'] + }] + }, + { + type: 'radio', + key: 'pieshow', + label: '鏄剧ず鍊�', + initVal: card.pieshow || 'percent', + required: false, + hidden: !['pie'].includes(type), + options: [{ + value: 'percent', + text: '鐧惧垎姣�' + }, { + value: 'value', + text: '鏁板��' + }] + }, + { + type: 'radio', + key: 'label', + label: '鏂囨湰鏍囩', + initVal: card.label || (type === 'pie' ? 'true' : 'false'), + required: false, + hidden: !['pie', 'line'].includes(type), + options: [{ + value: 'true', + text: '鏄剧ず' + }, { + value: 'false', + text: '闅愯棌' + }] + }, { + type: 'radio', + key: 'labelLayout', + label: '鏍囩甯冨眬', + initVal: card.labelLayout || 'normal', + required: false, + hidden: !['pie'].includes(type), + options: [{ + value: 'normal', + text: '甯歌' + }, { + value: 'overlap', + text: '闃查噸鍙�' + }] + }, { + type: 'radio', + key: 'adjust', + label: '澶氭煴鎺掑垪', + initVal: card.adjust || 'dodge', + required: false, + hidden: !['bar'].includes(type), + options: [{ + value: 'dodge', + text: '鍒嗙粍' + }, { + value: 'stack', + text: '鍫嗗彔' + }] + } + ] +} + +/** * @description 鑾峰彇琛ㄥ崟閰嶇疆淇℃伅 * @param {*} card * @param {*} inputfields diff --git a/src/templates/zshare/modaleditable/index.jsx b/src/templates/zshare/modaleditable/index.jsx index d2104a8..90119fb 100644 --- a/src/templates/zshare/modaleditable/index.jsx +++ b/src/templates/zshare/modaleditable/index.jsx @@ -158,7 +158,7 @@ <span className="operation-btn" title={props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> <Popconfirm title={props.dict['header.form.query.delete']} - okText={props.dict['header.confirm']} + okText={props.dict['model.confirm']} cancelText={props.dict['header.cancel']} onConfirm={() => this.handleDelete(record.key) }> @@ -364,7 +364,7 @@ <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> <Popconfirm title={this.props.dict['header.form.query.delete']} - okText={this.props.dict['header.confirm']} + okText={this.props.dict['model.confirm']} cancelText={this.props.dict['header.cancel']} onConfirm={() => this.handleDelete(record.key) }> diff --git a/src/templates/zshare/pasteform/index.jsx b/src/templates/zshare/pasteform/index.jsx index fcb82db..eb1632a 100644 --- a/src/templates/zshare/pasteform/index.jsx +++ b/src/templates/zshare/pasteform/index.jsx @@ -1,6 +1,7 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' import { Form, Row, Col, Input, notification } from 'antd' +import Utils from '@/utils/utils.js' import './index.scss' const { TextArea } = Input @@ -39,6 +40,10 @@ _config = '' } + if (_config && _config.uuid) { // 姣忔绮樿创鏃舵洿鏂癐D锛岄槻姝㈤噸澶嶇矘璐存椂id閲嶅 + _config.uuid = Utils.getuuid() + } + if (_config) { resolve(_config) } diff --git a/src/templates/zshare/tabdragelement/card.jsx b/src/templates/zshare/tabdragelement/card.jsx index 4ebb9de..81ec448 100644 --- a/src/templates/zshare/tabdragelement/card.jsx +++ b/src/templates/zshare/tabdragelement/card.jsx @@ -25,7 +25,7 @@ const { index: overIndex } = findCard(id) moveCard(draggedId, overIndex) } - }, + } }) const doubleClick = () => { diff --git a/src/templates/zshare/transferform/index.scss b/src/templates/zshare/transferform/index.scss index cedc47b..1ebb78b 100644 --- a/src/templates/zshare/transferform/index.scss +++ b/src/templates/zshare/transferform/index.scss @@ -8,7 +8,9 @@ } .ant-transfer-operation + .ant-transfer-list { .ant-transfer-list-content-item { - margin-right: 50px; + padding-right: 50px; + position: relative; + i { display: inline-block; } diff --git a/src/templates/zshare/verifycard/customform/index.jsx b/src/templates/zshare/verifycard/customform/index.jsx index eec4967..0065c37 100644 --- a/src/templates/zshare/verifycard/customform/index.jsx +++ b/src/templates/zshare/verifycard/customform/index.jsx @@ -12,6 +12,7 @@ class CustomForm extends Component { static propTpyes = { dict: PropTypes.object, // 瀛楀吀椤� + btn: PropTypes.object, // 鎸夐挳 usefulfields: PropTypes.string, // 鍙敤瀛楁 initsql: PropTypes.string, // 鍙敤瀛楁 customChange: PropTypes.func // 琛ㄥ崟 @@ -120,7 +121,7 @@ } render() { - const { usefulfields } = this.props + const { usefulfields, btn } = this.props const { getFieldDecorator } = this.props.form const formItemLayout = { labelCol: { @@ -157,6 +158,9 @@ <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green"> 淇濆瓨 </Button> + {btn.sql ? <div style={{marginTop: '31px'}}> + 琛ㄥ悕: <div style={{wordBreak: 'break-all'}}>{btn.sql}</div> + </div> : null} </Col> <Col span={7}> <Form.Item label={'缁撴灉澶勭悊'}> diff --git a/src/templates/zshare/verifycard/customscript/index.jsx b/src/templates/zshare/verifycard/customscript/index.jsx index 98977c0..b1fabe2 100644 --- a/src/templates/zshare/verifycard/customscript/index.jsx +++ b/src/templates/zshare/verifycard/customscript/index.jsx @@ -1,6 +1,6 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' -import { Form, Row, Col, Input, Button, notification, Modal, Select, Tooltip, Icon, Radio } from 'antd' +import { Form, Row, Col, Input, Button, notification, Modal, Menu, Tooltip, Icon, Radio, Dropdown } from 'antd' import moment from 'moment' import Utils from '@/utils/utils.js' @@ -12,6 +12,7 @@ class CustomForm extends Component { static propTpyes = { dict: PropTypes.object, // 瀛楀吀椤� + btn: PropTypes.object, // 鎸夐挳淇℃伅 usefulfields: PropTypes.string, // 鍙敤瀛楁 initsql: PropTypes.string, // sql鍓嶇紑 systemScripts: PropTypes.array, // 绯荤粺鑴氭湰 @@ -130,7 +131,11 @@ }) } - selectScript = (val, option) => { + selectScript = (e) => { + const { systemScripts } = this.props + + let option = systemScripts[+e.key] + let _sql = this.props.form.getFieldValue('sql') if (_sql) { _sql = _sql + ` @@ -139,10 +144,10 @@ } _sql = _sql.replace(/\s{6}$/, '') - _sql = _sql + `/*${option.props.title}*/ + _sql = _sql + `/*${option.name}*/ ` _sql = _sql.replace(/\s{4}$/, '') - _sql = _sql + val + _sql = _sql + option.value this.props.form.setFieldsValue({ sql: _sql @@ -150,7 +155,7 @@ } render() { - const { usefulfields, systemScripts } = this.props + const { usefulfields, systemScripts, btn } = this.props const { getFieldDecorator } = this.props.form const formItemLayout = { labelCol: { @@ -171,7 +176,7 @@ {usefulfields} </Form.Item> </Col> : null} - <Col span={8}> + <Col span={8} style={{whiteSpace: 'nowrap'}}> <Form.Item style={{marginBottom: 0}} label={ <Tooltip placement="bottomLeft" title={'鑷畾涔夎剼鏈笌榛樿sql浣嶇疆鍏崇郴銆�'}> <Icon type="question-circle" style={{color: '#c49f47', marginRight: '5px'}} /> @@ -189,27 +194,29 @@ )} </Form.Item> </Col> - <Col span={8}> - <Form.Item style={{marginBottom: 0}} label={ - <Tooltip placement="bottomLeft" title={'浠庣郴缁熷嚱鏁伴泦涓�夋嫨闇�瑕佺殑鍑芥暟锛屽彲蹇�熸坊鍔犺嚦sql涓��'}> - <Icon type="question-circle" style={{color: '#c49f47', marginRight: '5px'}} /> - 蹇嵎娣诲姞 - </Tooltip> - }> - <Select value="" onChange={this.selectScript}> + <Col span={4} style={{lineHeight: '40px', textAlign: 'center'}}> + <Dropdown trigger={['click']} overlayClassName="mk-normal-dropdown" overlay={ + <Menu onClick={this.selectScript}> {systemScripts.map((option, i) => - <Select.Option title={option.name} key={i} value={option.value}> - {option.name} - </Select.Option> + <Menu.Item key={i}>{option.name}</Menu.Item> )} - </Select> - </Form.Item> + </Menu> + }> + <span style={{color: '#1890ff', display: 'inline-block', cursor: 'pointer'}}> + 蹇嵎娣诲姞 <Icon type="down" style={{marginRight: '5px'}} /> + </span> + </Dropdown> </Col> <Col span={4} className="add"> <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}> 淇濆瓨 </Button> </Col> + <Col span={8} style={{textAlign: 'right'}}> + {btn.sql ? <span style={{maxWidth: '100%', display: 'inline-block', position: 'relative', top: '20px', whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden'}}> + 琛ㄥ悕: {btn.sql} + </span> : null} + </Col> <Col span={24} className="sql"> <Form.Item label={'sql'}> {getFieldDecorator('sql', { diff --git a/src/templates/zshare/verifycard/index.jsx b/src/templates/zshare/verifycard/index.jsx index 4bb5edf..0efe780 100644 --- a/src/templates/zshare/verifycard/index.jsx +++ b/src/templates/zshare/verifycard/index.jsx @@ -13,6 +13,7 @@ import BillcodeForm from './billcodeform' import VoucherForm from './voucherform' import './index.scss' +import { fromJS } from 'immutable'; const { TabPane } = Tabs const { confirm } = Modal @@ -23,7 +24,7 @@ btnTab: PropTypes.any, // 琛ㄥ崟鏍囩椤碉紙鎸夐挳锛夊弬鏁� config: PropTypes.any, // 琛ㄥ崟鏍囩椤靛弬鏁� dict: PropTypes.object, // 瀛楀吀椤� - card: PropTypes.object, + card: PropTypes.object, // 鎸夐挳淇℃伅 columns: PropTypes.array } @@ -32,6 +33,7 @@ verify: {}, fields: [], usefulfields: '', + defaultsql: '', // 榛樿Sql orderModular: [], orderModularDetail: [], voucher: [], @@ -79,13 +81,13 @@ dataIndex: 'operation', render: (text, record) => (<div> - <span className="operation-btn" title={this.props.dict['header.edit']} onClick={() => this.handleEdit(record, 'unique')} style={{color: '#1890ff'}}><Icon type="edit" /></span> + <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'unique')} style={{color: '#1890ff'}}><Icon type="edit" /></span> <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'unique', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span> <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'unique', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record, 'unique')} style={{color: '#8E44AD'}}><Icon type="swap" /></span> <Popconfirm title={this.props.dict['header.form.query.delete']} - okText={this.props.dict['header.confirm']} + okText={this.props.dict['model.confirm']} cancelText={this.props.dict['header.cancel']} onConfirm={() => this.handleDelete(record, 'unique') }> @@ -145,13 +147,13 @@ dataIndex: 'operation', render: (text, record) => (<div> - <span className="operation-btn" title={this.props.dict['header.edit']} onClick={() => this.handleEdit(record, 'contrast')} style={{color: '#1890ff'}}><Icon type="edit" /></span> + <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'contrast')} style={{color: '#1890ff'}}><Icon type="edit" /></span> <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'contrast', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span> <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'contrast', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record, 'contrast')} style={{color: '#8E44AD'}}><Icon type="swap" /></span> <Popconfirm title={this.props.dict['header.form.query.delete']} - okText={this.props.dict['header.confirm']} + okText={this.props.dict['model.confirm']} cancelText={this.props.dict['header.cancel']} onConfirm={() => this.handleDelete(record, 'contrast') }> @@ -206,13 +208,13 @@ dataIndex: 'operation', render: (text, record) => (<div> - <span className="operation-btn" title={this.props.dict['header.edit']} onClick={() => this.handleEdit(record, 'customverify')} style={{color: '#1890ff'}}><Icon type="edit" /></span> + <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'customverify')} style={{color: '#1890ff'}}><Icon type="edit" /></span> <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'customverify', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span> <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'customverify', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record, 'customverify')} style={{color: '#8E44AD'}}><Icon type="swap" /></span> <Popconfirm title={this.props.dict['header.form.query.delete']} - okText={this.props.dict['header.confirm']} + okText={this.props.dict['model.confirm']} cancelText={this.props.dict['header.cancel']} onConfirm={() => this.handleDelete(record, 'customverify') }> @@ -266,13 +268,13 @@ dataIndex: 'operation', render: (text, record) => (<div> - <span className="operation-btn" title={this.props.dict['header.edit']} onClick={() => this.handleEdit(record, 'scripts')} style={{color: '#1890ff'}}><Icon type="edit" /></span> + <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'scripts')} style={{color: '#1890ff'}}><Icon type="edit" /></span> <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'scripts', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span> <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'scripts', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record, 'scripts')} style={{color: '#8E44AD'}}><Icon type="swap" /></span> <Popconfirm title={this.props.dict['header.form.query.delete']} - okText={this.props.dict['header.confirm']} + okText={this.props.dict['model.confirm']} cancelText={this.props.dict['header.cancel']} onConfirm={() => this.handleDelete(record, 'scripts') }> @@ -370,13 +372,13 @@ dataIndex: 'operation', render: (text, record) => (<div> - <span className="operation-btn" title={this.props.dict['header.edit']} onClick={() => this.handleEdit(record, 'ordercode')} style={{color: '#1890ff'}}><Icon type="edit" /></span> + <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'ordercode')} style={{color: '#1890ff'}}><Icon type="edit" /></span> <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'ordercode', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span> <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'ordercode', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record, 'ordercode')} style={{color: '#8E44AD'}}><Icon type="swap" /></span> <Popconfirm title={this.props.dict['header.form.query.delete']} - okText={this.props.dict['header.confirm']} + okText={this.props.dict['model.confirm']} cancelText={this.props.dict['header.cancel']} onConfirm={() => this.handleDelete(record, 'ordercode') }> @@ -414,7 +416,8 @@ verify: _verify }) - if (this.props.card.btnType) { // 鎸夐挳-琛ㄥ崟鏍囩椤� + // 鎸夐挳-琛ㄥ崟鏍囩椤� + if (this.props.card.btnType) { let _fields = [] config.groups.forEach(group => { @@ -488,13 +491,118 @@ Select ${_select.join(', ')} ` + // 榛樿sql + let _insertsql = '' + let _updatesql = '' + + if (this.props.card.sqlType === 'insert' || this.props.card.sqlType === 'insertOrUpdate') { + let keys = [] + let values = [] + _fields.forEach(item => { + if (!item.field) return + + keys.push(item.field.toLowerCase()) + values.push('@' + item.field) + }) + + if (config.setting.primaryKey && !keys.includes(config.setting.primaryKey.toLowerCase())) { + keys.push(config.setting.primaryKey.toLowerCase()) + values.push('\'\'') + } + if (!keys.includes('createuserid')) { + keys.push('createuserid') + values.push('@userid@') + } + if (!keys.includes('createuser')) { + keys.push('createuser') + values.push('@username') + } + if (!keys.includes('createstaff')) { + keys.push('createstaff') + values.push('@fullname') + } + if (!keys.includes('bid')) { + keys.push('bid') + values.push('@BID@') + } + + keys = keys.join(',') + values = values.join(',') + _insertsql = `insert into ${this.props.card.sql} (${keys}) select ${values};` + } + + if (this.props.card.sqlType === 'update' || this.props.card.sqlType === 'insertOrUpdate') { + let _form = [] + let _arr = [] + + _fields.forEach(item => { + if (!item.field) return + + _arr.push(item.field.toLowerCase()) + _form.push(item.field + '=@' + item.field) + }) + + if (!_arr.includes('modifydate')) { + _form.push('modifydate=getdate()') + } + if (!_arr.includes('modifyuserid')) { + _form.push('modifyuserid=@userid@') + } + + if (_verify.voucher && _verify.voucher.enabled) { + if (!_arr.includes('bvoucher')) { + _form.push('BVoucher=@BVoucher') + } + if (!_arr.includes('fibvoucherdate')) { + _form.push('FIBVoucherDate=@FIBVoucherDate') + } + if (!_arr.includes('fiyear')) { + _form.push('FiYear=@FiYear') + } + } + + let primaryKeyName = config.setting.primaryKey + if (primaryKeyName && ['id', 'bid', 'loginuid', 'sessionuid', 'userid', 'appkey'].includes(primaryKeyName.toLowerCase())) { + primaryKeyName = primaryKeyName + '@' + } + + _form = _form.join(',') + _updatesql = `update ${this.props.card.sql} set ${_form} where ${config.setting.primaryKey}=@${primaryKeyName};` + } + + let _defaultsql = '' + + if (this.props.card.sqlType === 'insert') { + _defaultsql = _insertsql + } else if (this.props.card.sqlType === 'update') { + _defaultsql = _updatesql + } else if (this.props.card.sqlType === 'insertOrUpdate') { + _defaultsql += `select @tbid='' + select @tbid='X' from ${this.props.card.sql} where ${config.setting.primaryKey}=@ID@ + if @tbid='' + begin + ${_insertsql} + end + else + begin + ${_updatesql} + end + ` + } + this.setState({ fields: _fields, initsql: _sql, + defaultsql: _defaultsql, usefulfields: _usefulfields + }, () => { + this.getsysScript() }) + return } + + // 閫氱敤鎸夐挳 if (this.props.card.OpenType === 'pop') { Api.getSystemConfig({ func: 'sPC_Get_LongParam', @@ -511,7 +619,17 @@ } } - if (!_LongParam) return + if (!_LongParam) { + notification.warning({ + top: 92, + message: '琛ㄥ崟鏈坊鍔犳垨瑙f瀽閿欒锛岃妫�鏌ヨ〃鍗曡缃紒', + duration: 5 + }) + + this.getsysScript() + + return + } let _fields = [] if (_LongParam.groups.length > 0) { @@ -527,6 +645,7 @@ let _select = ['@UserName=\'\'', '@FullName=\'\'', '@ErrorCode=\'\'', '@retmsg=\'\''] let hasBid = false let fieldArr = _usefulfields.map(_f => _f.toLowerCase()) + let _defaultfields = fromJS(_fields).toJS() _fields.forEach(_f => { if (_f.field) { @@ -602,10 +721,89 @@ Select ${_select.join(', ')} ` + // 榛樿sql + let _defaultsql = '' + + if (this.props.card.sqlType === 'insert') { + let keys = [] + let values = [] + _defaultfields.forEach(item => { + if (!item.field) return + + keys.push(item.field.toLowerCase()) + values.push('@' + item.field) + }) + + if (config.setting.primaryKey && !keys.includes(config.setting.primaryKey.toLowerCase())) { + keys.push(config.setting.primaryKey.toLowerCase()) + values.push('\'\'') + } + if (!keys.includes('createuserid')) { + keys.push('createuserid') + values.push('@userid@') + } + if (!keys.includes('createuser')) { + keys.push('createuser') + values.push('@username') + } + if (!keys.includes('createstaff')) { + keys.push('createstaff') + values.push('@fullname') + } + if (!keys.includes('bid')) { + keys.push('bid') + values.push('@BID@') + } + + keys = keys.join(',') + values = values.join(',') + _defaultsql = `insert into ${this.props.card.sql} (${keys}) select ${values};` + } else if (this.props.card.sqlType === 'update') { + let _form = [] + let _arr = [] + + _defaultfields.forEach(item => { + if (!item.field) return + + _arr.push(item.field.toLowerCase()) + _form.push(item.field + '=@' + item.field) + }) + + if (!_arr.includes('modifydate')) { + _form.push('modifydate=getdate()') + } + if (!_arr.includes('modifyuserid')) { + _form.push('modifyuserid=@userid@') + } + + if (_verify.voucher && _verify.voucher.enabled) { + if (!_arr.includes('bvoucher')) { + _form.push('BVoucher=@BVoucher') + } + if (!_arr.includes('fibvoucherdate')) { + _form.push('FIBVoucherDate=@FIBVoucherDate') + } + if (!_arr.includes('fiyear')) { + _form.push('FiYear=@FiYear') + } + } + + let primaryKeyName = config.setting.primaryKey + if (primaryKeyName && ['id', 'bid', 'loginuid', 'sessionuid', 'userid', 'appkey'].includes(primaryKeyName.toLowerCase())) { + primaryKeyName = primaryKeyName + '@' + } + + _form = _form.join(',') + _defaultsql = `update ${this.props.card.sql} set ${_form} where ${config.setting.primaryKey}=@${primaryKeyName};` + } + this.setState({ fields: _fields, initsql: _sql, + defaultsql: _defaultsql, usefulfields: _usefulfields + }, () => { + this.getsysScript() }) } else { notification.warning({ @@ -613,6 +811,7 @@ message: res.message, duration: 5 }) + this.getsysScript() } }) } else { @@ -652,9 +851,36 @@ Select ${_select.join(', ')} ` + // 榛樿sql + let _defaultsql = '' + let primaryKeyName = config.setting.primaryKey + + if (primaryKeyName && ['id', 'bid', 'loginuid', 'sessionuid', 'userid', 'appkey'].includes(primaryKeyName.toLowerCase())) { + primaryKeyName = primaryKeyName + '@' + } + + if (this.props.card.sqlType === 'LogicDelete') { + _defaultsql = `update ${this.props.card.sql} set deleted=1,modifydate=getdate(),modifyuserid=@userid@ where ${config.setting.primaryKey}=@${primaryKeyName};` + } else if (this.props.card.sqlType === 'delete') { + let _msg = '' + if (columns && columns.length > 0 && this.props.card.Ot !== 'notRequired') { + let _index = 0 + columns.forEach(col => { + if (col.field && col.Hide !== 'true' && _index < 4) { + _msg += col.label + '=\'\',' + _index++ + } + }) + } + _defaultsql += `insert into snote (remark,createuserid,CreateUser,CreateStaff) select left('鍒犻櫎琛�:${this.props.card.sql} 鏁版嵁: ${_msg}${config.setting.primaryKey}='+@${primaryKeyName},200),@userid@,@username,@fullname delete ${this.props.card.sql} where ${config.setting.primaryKey}=@${primaryKeyName};` + } + this.setState({ initsql: _sql, + defaultsql: _defaultsql, usefulfields: _usefulfields + }, () => { + this.getsysScript() }) } } @@ -785,7 +1011,11 @@ voucherDetail: result[1].data }) }) - + } + + getsysScript = () => { + const { defaultsql } = this.state + let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from聽 s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort` _scriptSql = Utils.formatOptions(_scriptSql) @@ -802,13 +1032,26 @@ Api.getSystemConfig(_sParam).then(res => { if (res.status) { - this.setState({ - systemScripts: res.data.map(item => { - return { - name: item.funcname, - value: Utils.formatOptions(item.longparam, true) - } + let _scripts = [] + + if (defaultsql) { + _scripts.push({ + name: '榛樿sql', + value: defaultsql }) + } + + res.data.forEach(item => { + let _item = { + name: item.funcname, + value: Utils.formatOptions(item.longparam, true) + } + + _scripts.push(_item) + }) + + this.setState({ + systemScripts: _scripts }) } else { notification.warning({ @@ -1216,7 +1459,7 @@ if (_loading) { confirm({ content: `瀛樺湪鏈繚瀛橀」锛岀‘瀹氭彁浜ゅ悧锛焋, - okText: this.props.dict['header.confirm'], + okText: this.props.dict['model.confirm'], cancelText: this.props.dict['header.cancel'], onOk() { resolve(verify) @@ -1328,6 +1571,7 @@ <TabPane tab="鑷畾涔夐獙璇�" key="3"> <CustomForm dict={this.props.dict} + btn={this.props.card} initsql={this.state.initsql} usefulfields={this.state.usefulfields} customChange={this.customChange} @@ -1379,6 +1623,7 @@ usefulfields={this.state.usefulfields} initsql={this.state.initsql} dict={this.props.dict} + btn={this.props.card} customScripts={verify.scripts} systemScripts={this.state.systemScripts} scriptsChange={this.scriptsChange} diff --git a/src/templates/zshare/verifycardexcelin/index.jsx b/src/templates/zshare/verifycardexcelin/index.jsx index 5a81e00..9c38961 100644 --- a/src/templates/zshare/verifycardexcelin/index.jsx +++ b/src/templates/zshare/verifycardexcelin/index.jsx @@ -69,12 +69,12 @@ render: (text, record) => ( <div> - <span className="operation-btn" title={this.props.dict['header.edit']} onClick={() => this.handleEdit(record, 'columns')} style={{color: '#1890ff'}}><Icon type="edit" /></span> + <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'columns')} style={{color: '#1890ff'}}><Icon type="edit" /></span> <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'columns', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span> <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'columns', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> <Popconfirm title={this.props.dict['header.form.query.delete']} - okText={this.props.dict['header.confirm']} + okText={this.props.dict['model.confirm']} cancelText={this.props.dict['header.cancel']} onConfirm={() => this.handleDelete(record, 'columns') }> @@ -126,13 +126,13 @@ dataIndex: 'operation', render: (text, record) => (<div> - <span className="operation-btn" title={this.props.dict['header.edit']} onClick={() => this.handleEdit(record, 'unique')} style={{color: '#1890ff'}}><Icon type="edit" /></span> + <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'unique')} style={{color: '#1890ff'}}><Icon type="edit" /></span> <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'unique', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span> <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'unique', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record, 'unique')} style={{color: '#8E44AD'}}><Icon type="swap" /></span> <Popconfirm title={this.props.dict['header.form.query.delete']} - okText={this.props.dict['header.confirm']} + okText={this.props.dict['model.confirm']} cancelText={this.props.dict['header.cancel']} onConfirm={() => this.handleDelete(record, 'unique') }> @@ -178,13 +178,13 @@ dataIndex: 'operation', render: (text, record) => (<div> - <span className="operation-btn" title={this.props.dict['header.edit']} onClick={() => this.handleEdit(record, 'scripts')} style={{color: '#1890ff'}}><Icon type="edit" /></span> + <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'scripts')} style={{color: '#1890ff'}}><Icon type="edit" /></span> <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'scripts', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span> <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'scripts', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record, 'scripts')} style={{color: '#8E44AD'}}><Icon type="swap" /></span> <Popconfirm title={this.props.dict['header.form.query.delete']} - okText={this.props.dict['header.confirm']} + okText={this.props.dict['model.confirm']} cancelText={this.props.dict['header.cancel']} onConfirm={() => this.handleDelete(record, 'scripts') }> @@ -552,7 +552,7 @@ if (_loading) { confirm({ content: `瀛樺湪鏈繚瀛橀」锛岀‘瀹氭彁浜ゅ悧锛焋, - okText: this.props.dict['header.confirm'], + okText: this.props.dict['model.confirm'], cancelText: this.props.dict['header.cancel'], onOk() { resolve(_verify) diff --git a/src/templates/zshare/verifycardexcelout/index.jsx b/src/templates/zshare/verifycardexcelout/index.jsx index 8a660c3..cd33cc4 100644 --- a/src/templates/zshare/verifycardexcelout/index.jsx +++ b/src/templates/zshare/verifycardexcelout/index.jsx @@ -40,12 +40,12 @@ render: (text, record) => ( <div> - <span className="operation-btn" title={this.props.dict['header.edit']} onClick={() => this.handleEdit(record, 'columns')} style={{color: '#1890ff'}}><Icon type="edit" /></span> + <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'columns')} style={{color: '#1890ff'}}><Icon type="edit" /></span> <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'columns', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span> <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'columns', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> <Popconfirm title={this.props.dict['header.form.query.delete']} - okText={this.props.dict['header.confirm']} + okText={this.props.dict['model.confirm']} cancelText={this.props.dict['header.cancel']} onConfirm={() => this.handleDelete(record, 'columns') }> diff --git a/src/templates/zshare/verifycardprint/editable/index.jsx b/src/templates/zshare/verifycardprint/editable/index.jsx index fd98ed7..e328414 100644 --- a/src/templates/zshare/verifycardprint/editable/index.jsx +++ b/src/templates/zshare/verifycardprint/editable/index.jsx @@ -118,7 +118,7 @@ <span className="operation-btn" title={props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> <Popconfirm title={props.dict['header.form.query.delete']} - okText={props.dict['header.confirm']} + okText={props.dict['model.confirm']} cancelText={props.dict['header.cancel']} onConfirm={() => this.handleDelete(record.key) }> diff --git a/src/templates/zshare/viewdragelement/card.jsx b/src/templates/zshare/viewdragelement/card.jsx new file mode 100644 index 0000000..b44ab02 --- /dev/null +++ b/src/templates/zshare/viewdragelement/card.jsx @@ -0,0 +1,48 @@ +import React from 'react' +import { useDrag, useDrop } from 'react-dnd' +import { Icon } from 'antd' +import './index.scss' + +const Card = ({ id, card, moveCard, findCard, editCard, delCard }) => { + const originalIndex = findCard(id).index + + const [{ isDragging }, drag] = useDrag({ + item: { type: 'chart', id, originalIndex }, + collect: monitor => ({ + isDragging: monitor.isDragging(), + }), + }) + + const opacity = isDragging ? 0 : 1 + + const edit = () => { + editCard(id) + } + + const del = () => { + delCard(id) + } + + const [, drop] = useDrop({ + accept: 'chart', + canDrop: () => true, + hover({ id: draggedId }) { + if (!draggedId) return + if (draggedId !== id) { + const { index: overIndex } = findCard(id) + moveCard(draggedId, overIndex) + } + } + }) + + return ( + <div className="chart-tab" style={{ opacity: opacity}}> + <div ref={node => drag(drop(node))}> + <Icon type={card.icon} /> + </div> + <Icon className="edit" title="缂栬緫" type="edit" onClick={edit} /> + {card.chartType !== 'table' ? <Icon className="edit close" title="鍒犻櫎" type="close" onClick={del} /> : null} + </div> + ) +} +export default Card diff --git a/src/templates/zshare/viewdragelement/index.jsx b/src/templates/zshare/viewdragelement/index.jsx new file mode 100644 index 0000000..c09197a --- /dev/null +++ b/src/templates/zshare/viewdragelement/index.jsx @@ -0,0 +1,85 @@ +import React, { useState } from 'react' +import { useDrop } from 'react-dnd' +import { is, fromJS } from 'immutable' +import update from 'immutability-helper' +import { Tabs } from 'antd' +import Card from './card' +import './index.scss' + +const { TabPane } = Tabs + +const Container = ({activeKey, list, handleList, handleMenu, deleteMenu, changetabview }) => { + const [cards, setCards] = useState(list) + const moveCard = (id, atIndex) => { + const { card, index } = findCard(id) + 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) + handleMenu(card) + } + + const delCard = id => { + const { card } = findCard(id) + deleteMenu(card) + } + + const changetab = id => { + if (activeKey === 'all') return + + changetabview(id) + } + + const [, drop] = useDrop({ + accept: 'chart' + }) + + return ( + <div ref={drop} className="ant-row chart-edit-tab-box"> + <Tabs activeKey={activeKey} onChange={changetab}> + {cards.map(card => ( + <TabPane tab={ + <div key={card.uuid}> + <Card + key={card.uuid} + id={card.uuid} + card={card} + moveCard={moveCard} + editCard={editCard} + delCard={delCard} + findCard={findCard} + /> + </div> + } key={card.uuid}></TabPane> + ))} + </Tabs> + {/* {cards.map(card => ( + <Card + id={card.uuid} + key={card.uuid} + card={card} + moveCard={moveCard} + editCard={editCard} + delCard={delCard} + findCard={findCard} + /> + ))} */} + </div> + ) +} +export default Container diff --git a/src/templates/zshare/viewdragelement/index.scss b/src/templates/zshare/viewdragelement/index.scss new file mode 100644 index 0000000..91c831e --- /dev/null +++ b/src/templates/zshare/viewdragelement/index.scss @@ -0,0 +1,41 @@ +.chart-edit-tab-box { + padding-right: 100px; + display: inline-block; + + .ant-tabs-bar { + border: 0; + } + .ant-tabs-tab { + margin: 0px; + padding: 0px; + } + .ant-tabs-ink-bar { + display: none!important; + } + .chart-tab { + position: relative; + width: 40px; + padding-top: 15px; + text-align: center; + display: inline-block; + + .edit { + position: absolute; + left: 0; + top: 0px; + color: #1890ff; + cursor: pointer; + display: none; + } + .edit.close { + left: 20px; + color: #ff4d4f; + } + } + + .chart-tab:hover { + .edit { + display: inline-block; + } + } +} \ No newline at end of file diff --git a/src/utils/modelutils.js b/src/utils/modelutils.js new file mode 100644 index 0000000..eed79e0 --- /dev/null +++ b/src/utils/modelutils.js @@ -0,0 +1,1620 @@ +import moment from 'moment' +import md5 from 'md5' +import options from '@/store/options.js' + +const service = window.GLOB.service ? (/\/$/.test(window.GLOB.service) ? window.GLOB.service : window.GLOB.service + '/') : '' + +export default class Utils { + /** + * @description 鐢熸垚32浣島uid string + 鏃堕棿 + * @return {String} uuid + */ + static getuuid () { + let uuid = [] + let timestamp = new Date().getTime() + let options = '0123456789abcdefghigklmnopqrstuv' + for (let i = 0; i < 19; i++) { + uuid.push(options.substr(Math.floor(Math.random() * 0x20), 1)) + } + uuid = timestamp + uuid.join('') + return uuid + } + + /** + * @description 鐢熸垚GUID + * @return {String} guid + */ + static getguid () { + // 浜х敓涓�涓柊鐨凣UID鍊� + let uuid = [] + let d = new Date() + let options = '0123456789abcdefghigklmnopqrstuv' + for (let i = 0; i < 19; i++) { + uuid.push(options.substr(Math.floor(Math.random() * 0x20), 1)) + } + uuid = moment().format('YYYYMMDDHHmmss') + d.getMilliseconds() + uuid.join('') + return uuid.toUpperCase() + } + + /** + * @description md5鍔犲瘑 + * @return {String} str 鍔犲瘑涓� + * @return {String} timestamp 鏃堕棿鎴� + */ + static encrypt (str, timestamp) { + let salt = 'mingke' // 鐩愬�� + let _str = str + salt + timestamp + if (_str.length > 8000) { + _str = _str.slice(_str.length - 8000) + } + return md5(_str) + } + + /** + * @description sql璇硶楠岃瘉 + * @return {String} sql sql璇彞 + * @return {String} type 楠岃瘉绫诲瀷 + */ + static verifySql (sql, type) { + if (!sql) return '' + let chars = [ + {key: 'create', reg: /(^|\s)create\s/ig}, + {key: 'insert', reg: /(^|\s)insert\s/ig}, + {key: 'delete', reg: /(^|\s)delete\s/ig}, + {key: 'update', reg: /(^|\s)update\s/ig}, + {key: 'set', reg: /(^|\s)set\s/ig}, + {key: 'drop', reg: /(^|\s)drop\s/ig}, + {key: 'alter', reg: /(^|\s)alter\s/ig}, + {key: 'truncate', reg: /(^|\s)truncate\s/ig}, + {key: 'if', reg: /(^|\s)if\s/ig}, + {key: 'exec', reg: /exec/ig}, + {key: 'OBJECT', reg: /object/ig}, + {key: 'sys.', reg: /sys\./ig}, + {key: 'kill', reg: /kill/ig} + ] + + if (type === 'customscript') { + chars = chars.filter(char => !['insert', 'delete', 'update', 'set', 'if', 'exec'].includes(char.key)) + } + + let error = '' + chars.forEach(char => { + if (!error && char.reg.test(sql)) { + error = char.key + } + }) + + return error + } + + /** + * @description sql鍔犲瘑 + * @return {String} value + */ + static formatOptions (value, isUnFormat = false) { + if (!value) return '' + + let salt = 'minKe' // 鐩愬�� + // 鍏抽敭瀛楄浆鎹㈣鍒� + let format = [ + { key: 'select', value: ' msltk ' }, + { key: 'from', value: ' mfrmk ' }, + { key: 'where', value: ' mwhrk ' }, + { key: 'order by', value: ' modbk ' }, + { key: 'asc', value: ' modack ' }, + { key: 'desc', value: ' moddesk ' }, + { key: 'top', value: ' mtpk ' }, + { key: 'like', value: ' mlkk ' }, + { key: 'not like', value: ' mnlkk ' }, + { key: 'between', value: ' mbtnk ' }, + { key: 'and', value: ' madk ' }, + { key: 'insert', value: ' mistk ' }, + { key: 'into', value: ' mitk ' }, + { key: 'update', value: ' muptk ' }, + { key: 'delete', value: ' mdelk ' }, + { key: 'begin', value: ' mbgink ' }, + { key: 'end', value: ' medk ' }, + { key: 'if', value: ' mefk ' }, + { key: 'while', value: ' mwilk ' }, + { key: 'create', value: ' mcrtk ' }, + { key: 'alter', value: ' matek ' }, + { key: 'len', value: ' mlnk ' }, + { key: 'left', value: ' mlftk ' }, + { key: 'right', value: ' mritk ' }, + { key: 'union', value: ' munok ' }, + { key: 'varchar', value: ' mvcrk ' }, + { key: 'getdate', value: ' mgtdtk ' }, + { key: 'TRY', value: ' mtryonek ' }, + { key: 'TRAN', value: ' mtrnk ' }, + { key: 'goto', value: ' mgtk ' }, + { key: 'set', value: ' mstk ' }, + { key: 'ROLLBACK', value: ' mrlbkk ' } + ] + + if (!isUnFormat) { // 鍔犲瘑 + value = value.replace(/\n/ig, ' \n ') + // 鏇挎崲鍏抽敭瀛� + format.forEach(item => { + let reg = new RegExp('(^|\\s)' + item.key + '(\\s|$)', 'ig') + value = value.replace(reg, item.value) + }) + + // 1銆佹浛鎹�%绗︼紙鏁版嵁搴撲腑瑙f瀽鍚巗ql鎶ラ敊锛� + value = value.replace(/%/ig, ' mpercent ') + + // 1銆乪ncode缂栫爜锛堜腑鏂囧瓧绗﹁秴鍑篵ase64鍔犲瘑鑼冨洿锛夛紝2銆乥ase64鍔犲瘑 + value = window.btoa(window.encodeURIComponent(value)) + + // 鎻掑叆瀛楃 + let index = Math.floor(value.length / 2) + value = value.slice(0, index) + salt + value.slice(index) + + // base64鍔犲瘑 + value = window.btoa(value) + } else { // 瑙e瘑 + try { + value = window.atob(value) + value = value.replace(salt, '') + value = window.decodeURIComponent(window.atob(value)) + + value = value.replace(/\smpercent\s/g, '%') + + format.forEach(item => { + let reg = new RegExp(item.value, 'g') + value = value.replace(reg, ' ' + item.key + ' ') + }) + + value = value.replace(/\s\n\s/ig, '\n') + value = value.replace(/(^\s+|\s+$)/ig, '') + } catch { + console.warn('UnFormat Failure') + value = '' + } + } + + return value + } + + /** + * @description 鍒濆鍖栨悳绱㈡潯浠� + * @param {Array} searches 鎼滅储鏉′欢 + * @return {String} searches 鏍煎紡鍖栧悗缁撴灉 + */ + static initMainSearch (searches) { + if (!searches || searches.length === 0) return [] + + let newsearches = [] + searches.forEach(search => { + let item = { + key: search.field, + match: search.match, + type: search.type, + label: search.label, + value: search.initval, + required: search.required === 'true' + } + if (item.type === 'date') { + item.value = item.value ? moment().subtract(item.value, 'days').format('YYYY-MM-DD') : '' + } else if (item.type === 'datemonth') { + item.value = item.value ? moment().subtract(item.value, 'month').format('YYYY-MM') : '' + } else if (item.type === 'dateweek') { + item.value = item.value ? [moment().subtract(item.value * 7, 'days').startOf('week').format('YYYY-MM-DD'), + moment().subtract(item.value * 7, 'days').endOf('week').format('YYYY-MM-DD')] : '' + } else if (item.type === 'daterange') { + let _val = item.value + if (_val) { + try { + _val = JSON.parse(_val) + } catch { + _val = '' + } + } + item.value = _val ? [moment().subtract(_val[0], 'days').format('YYYY-MM-DD'), + moment().subtract(_val[1], 'days').format('YYYY-MM-DD')] : '' + } else if (item.type === 'multiselect') { + item.value = item.value ? item.value.split(',').filter(Boolean) : [] + } + newsearches.push(item) + }) + + return newsearches + } + + /** + * @description 鍒濆鍖栨悳绱㈡潯浠� + * @param {Array} searches 鎼滅储鏉′欢 + * @return {String} searches 鏍煎紡鍖栧悗缁撴灉 + */ + static formatCustomMainSearch (searches) { + if (!searches || searches.length === 0) return {} + + let newsearches = {} + searches.forEach(item => { + if (item.type === 'date') { + let timetail = '' + let _val = item.value + + if (item.match === '<' || item.match === '<=') { + timetail = ' 00:00:00.000' + if (_val) { + _val = moment(_val, 'YYYY-MM-DD').add(1, 'days').format('YYYY-MM-DD') + } + } else if (item.match === '>' || item.match === '>=') { + timetail = ' 00:00:00.000' + } + + if (newsearches[item.key]) { + newsearches[item.key + '1'] = _val ? _val + timetail : null + } else { + newsearches[item.key] = _val ? _val + timetail : null + } + } else if (item.type === 'datemonth') { + // 鏈�-杩囨护鏉′欢锛屼粠鏈堝紑濮嬭嚦缁撴潫 + let _startval = null + let _endval = null + + if (item.value) { + _startval = moment(item.value, 'YYYY-MM').startOf('month').format('YYYY-MM-DD') + ' 00:00:00.000' + _endval = moment(item.value, 'YYYY-MM').endOf('month').add(1, 'days').format('YYYY-MM-DD') + ' 00:00:00.000' + } + + newsearches[item.key] = _startval + newsearches[item.key + '1'] = _endval + } else if (item.type === 'dateweek') { + let _endval = '' + if (item.value) { + _endval = moment(item.value[1], 'YYYY-MM-DD').add(1, 'days').format('YYYY-MM-DD') + } + + newsearches[item.key] = item.value ? item.value[0] + ' 00:00:00.000' : null + newsearches[item.key + '1'] = item.value ? _endval + ' 00:00:00.000' : null + } else if (item.type === 'daterange') { + let _endval = '' + if (item.value) { + _endval = moment(item.value[1], 'YYYY-MM-DD').add(1, 'days').format('YYYY-MM-DD') + } + + newsearches[item.key] = item.value ? item.value[0] + ' 00:00:00.000' : null + newsearches[item.key + '1'] = item.value ? _endval + ' 00:00:00.000' : null + } else if (item.type === 'text') { + item.key.split(',').forEach(field => { // 缁煎悎鎼滅储锛屾墍瀛楁鎷兼帴 + newsearches[field] = item.value + }) + } else if (item.type === 'multiselect') { + newsearches[item.key] = item.value.join(',') + } else { + newsearches[item.key] = item.value + } + }) + + Object.keys(newsearches).forEach(key => { + if (!newsearches[key]) { + delete newsearches[key] + } + }) + + return newsearches + } + + /** + * @description 鎷兼帴鎼滅储鏉′欢main + * @param {Array} searches 鎼滅储鏉′欢 + * @return {String} searchText 鎷兼帴缁撴灉 + */ + static joinMainSearchkey (searches) { + if (!searches || searches.length === 0) return '' + + let searchText = '' + searches.forEach(item => { + if (!item.value || (item.type === 'multiselect' && item.value.length === 0)) return + + searchText += (searchText !== '' ? ' AND ' : '') + if (item.type === 'text') { + let str = item.match === '=' ? '' : '%' + let fields = item.key.split(',').map(field => { // 缁煎悎鎼滅储锛屾墍瀛楁鎷兼帴 + return field + ' ' + item.match + ' \'' + str + item.value + str + '\'' + }) + + searchText += '(' + fields.join(' OR ') + ')' + } else if (item.type === 'select') { + let str = item.match === '=' ? '' : '%' + + searchText += item.key + ' ' + item.match + ' \'' + str + item.value + str + '\'' + } else if (item.type === 'multiselect') { + + searchText += `'${item.value}' ` + item.match + ' \'%\'+' + item.key + '+\'%\'' + } else if (item.type === 'date') { + let _val = item.value + let timetail = ' 00:00:00.000' + let _match = item.match + + if (item.match === '<' || item.match === '<=') { // 鏃堕棿涓�<=鏃讹紝鍖归厤鍚庝竴澶╃殑0鐐癸紝鍖归厤鏂瑰紡涓�< + _match = '<' + _val = moment(_val, 'YYYY-MM-DD').add(1, 'days').format('YYYY-MM-DD') + } else if (item.match === '=') { + timetail = '' + } + + searchText += '(' + item.key + ' ' + _match + ' \'' + _val + timetail + '\')' + } else if (item.type === 'datemonth') { // 鏈�-杩囨护鏉′欢锛屼粠鏈堝紑濮嬭嚦缁撴潫锛岀粨鏉熸椂闂翠负鏈堟湯鍔犱竴澶╃殑0鐐癸紝鏂瑰紡涓�< + let _startval = moment(item.value, 'YYYY-MM').startOf('month').format('YYYY-MM-DD') + ' 00:00:00.000' + let _endval = moment(item.value, 'YYYY-MM').endOf('month').add(1, 'days').format('YYYY-MM-DD') + ' 00:00:00.000' + + searchText += '(' + item.key + ' >= \'' + _startval + '\' AND ' + item.key + ' < \'' + _endval + '\')' + } else if (item.type === 'dateweek') { // 鍛�-杩囨护鏉′欢 + let _startval = item.value[0] + ' 00:00:00.000' + let _endval = moment(item.value[1], 'YYYY-MM-DD').add(1, 'days').format('YYYY-MM-DD') + ' 00:00:00.000' + + searchText += '(' + item.key + ' >= \'' + _startval + '\' AND ' + item.key + ' < \'' + _endval + '\')' + } else if (item.type === 'daterange') { + let _startval = item.value[0] + ' 00:00:00.000' + let _endval = moment(item.value[1], 'YYYY-MM-DD').add(1, 'days').format('YYYY-MM-DD') + ' 00:00:00.000' + + searchText += '(' + item.key + ' >= \'' + _startval + '\' AND ' + item.key + ' < \'' + _endval + '\')' + } else { + searchText += '(' + item.key + ' ' + item.match + ' \'' + item.value + '\')' + } + }) + + return searchText + } + + /** + * @description 鎷兼帴鎼滅储鏉′欢datamanage + * @param {Array} searches 鎼滅储鏉′欢 + * @return {String} searchText 鎷兼帴缁撴灉 + */ + static jointsearchkey (searches) { + if (!searches || searches.length === 0) return '' + let searchText = '' + searches.forEach(item => { + if (!item.value) return + searchText += (searchText !== '' ? ' AND ' : '') + if (item.type === 'text') { + let options = item.key.split(',').map(op => { + // equal鏃朵笉娣诲姞% + let str = item.op === 'equal' ? '' : '%' + return op + ' ' + item.op + ' \'' + str + item.value + str + '\'' + }) + searchText += '(' + options.join(' OR ') + ')' + } else if (item.type === 'date') { + searchText += '(' + item.key + ' ' + item.op + ' \'' + item.value + '\')' + } else { + searchText += '(' + item.key + ' ' + item.op + ' \'' + item.value + '\')' + } + }) + return searchText + } + + /** + * @description 鑾峰彇鍥剧墖鐪熷疄璺緞 + * @return {String} url 鍥剧墖璺緞 + */ + static getrealurl (url) { + if (!url) return '' + + let baseurl = '' + if (process.env.NODE_ENV === 'production') { + baseurl = document.location.origin + '/' + service + } else { + baseurl = 'http://qingqiumarket.cn/' + service + } + // if (!/Content\/images\/upload\//.test(url)) { + // baseurl = baseurl + 'Content/images/upload/' + // } + let realurl = url.match(/^http/) || url.match(/^\/\//) ? url : baseurl + url + return realurl + } + + /** + * @description 鑾峰彇浜戠鍥剧墖鐪熷疄璺緞 + * @return {String} url 鍥剧墖璺緞 + */ + static getcloudurl (url) { + if (!url) return '' + + let baseurl = '' + + if (options.cloudServiceApi) { + baseurl = options.cloudServiceApi.replace(/webapi(.*)$/, '') + } else { + baseurl = document.location.origin + '/' + service + } + + return url.match(/^http/) || url.match(/^\/\//) ? url : baseurl + url + } + + /** + * @description 鑾峰彇涓嬫媺鎼滅储鏌ヨ鏉′欢 + * @return {String} item 鎼滅储鏉′欢淇℃伅 + */ + static getSelectQueryOptions (item) { + let arrfield = [item.valueField, item.valueText] + + if (item.type === 'link') { + arrfield.push(item.linkField) + } else if (item.type === 'select' && item.linkSubField && item.linkSubField.length > 0) { + arrfield.push(...item.linkSubField) + } + + arrfield = Array.from(new Set(arrfield)) + + let _datasource = item.dataSource + let sql = '' + + if (/\s/.test(_datasource)) { // 鎷兼帴鍒悕 + _datasource = '(' + _datasource + ') tb' + } + + arrfield = arrfield.join(',') + + if (item.orderBy) { + sql = 'select distinct ' + arrfield + ',' + item.orderBy + ' as orderfield from ' + _datasource + ' order by orderfield ' + item.orderType + } else { + sql = 'select distinct ' + arrfield + ' from ' + _datasource + } + + return { + sql: sql, + field: arrfield + } + } + + /** + * @description 鑾峰彇excel瀵煎叆鍙傛暟 + * @return {String} btn 鎸夐挳 + * @return {String} data excel鏁版嵁 + */ + static getExcelInSql (item, data, dict) { + let btn = item.verify + let keys = ['delete', 'drop', 'insert', 'truncate', 'update'] + + let errors = [] + let _topline = btn.range || 0 + let upId = this.getuuid() + + let _initCustomScript = '' // 鍒濆鍖栬剼鏈� + let _prevCustomScript = '' // 榛樿sql鍓嶆墽琛岃剼鏈� + let _backCustomScript = '' // 榛樿sql鍚庢墽琛岃剼鏈� + + if (btn.scripts) { + btn.scripts.forEach(script => { + if (script.status === 'false') return + + if (script.position === 'init') { + _initCustomScript += ` + ${script.sql} + ` + } else if (script.position === 'front') { + _prevCustomScript += ` + ${script.sql} + ` + } else { + _backCustomScript += ` + ${script.sql} + ` + } + }) + } + + let _Ltext = data.map((item, lindex) => { + let vals = btn.columns.map((col, cindex) => { + let val = item[col.Column] !== undefined ? item[col.Column] : '' + let _position = (_topline + lindex + 1) + dict['main.excel.line'] + ' ' + (cindex + 1) + dict['main.excel.column'] + ' ' + + if (/^Nvarchar/ig.test(col.type)) { + if (typeof(val) === 'number') { + val = val.toString() + } + + val = val.replace(/(^\s*$)|\t*|\v*/ig, '') + + if (!val && col.required === 'true') { // 蹇呭~鏍¢獙 + let _error = _position + dict['main.excel.content.emptyerror'] + errors.push(_error) + } else if (val.length > col.limit) { // 闀垮害鏍¢獙 + let _error = _position + dict['main.excel.content.maxlimit'] + errors.push(_error) + } else { // 鍏抽敭瀛楁牎楠� + keys.forEach(key => { + let _patten = new RegExp('(^' + key + '\\s+)|(\\s+' + key + '\\s+)', 'ig') + if (_patten.test(val)) { + let _error = _position + dict['main.excel.includekey'] + key + errors.push(_error) + } + }) + } + } else if (/^int/ig.test(col.type)) { + if (!val && val !== 0) { + let _error = _position + dict['main.excel.content.emptyerror'] + errors.push(_error) + } else { + let _val = val + '' + + if (!/^(([^0][0-9]+|0)$)|^(([1-9]+)$)/.test(_val)) { // 妫�楠屾槸鍚︿负鏁存暟 + let _error = _position + dict['main.excel.content.interror'] + errors.push(_error) + } else if ((col.min || col.min === 0) && val < col.min) { // 鏈�灏忓�兼楠� + let _error = _position + dict['main.excel.content.limitmin'] + errors.push(_error) + } else if ((col.max || col.max === 0) && val > col.max) { // 鏈�澶у�兼楠� + let _error = _position + dict['main.excel.content.limitmax'] + errors.push(_error) + } + } + } else if (/^Decimal/ig.test(col.type)) { + if (!val && val !== 0) { + let _error = _position + dict['main.excel.content.emptyerror'] + errors.push(_error) + } else { + let _val = val + '' + let _vals = _val.split('.') + + if (!/^(([^0][0-9]+|0)\.([0-9]+)$)|^(([^0][0-9]+|0)$)|^(([1-9]+)\.([0-9]+)$)|^(([1-9]+)$)/.test(_val)) { // 妫�楠屾槸鍚︿负娴偣鏁� + let _error = _position + dict['main.excel.content.floaterror'] + errors.push(_error) + } else if (_vals[0].length > 18) { // 妫�楠屾暣鏁颁綅 + let _error = _position + dict['main.excel.content.floatIntover'] + errors.push(_error) + } else if (_vals[1] && _vals[1].length > col.limit) { // 鏈�灏忓�兼楠� + let _error = _position + dict['main.excel.content.floatPointover'] + errors.push(_error) + } else if ((col.min || col.min === 0) && val < col.min) { // 鏈�灏忓�兼楠� + let _error = _position + dict['main.excel.content.limitmin'] + errors.push(_error) + } else if ((col.max || col.max === 0) && val > col.max) { // 鏈�澶у�兼楠� + let _error = _position + dict['main.excel.content.limitmax'] + errors.push(_error) + } + } + } + + return `'${val}' as ${col.Column}` + }) + + let _lineIndex = '0000' + (lindex + 1) + '0' + _lineIndex = _lineIndex.substring(_lineIndex.length - 6) + + vals.push(`'${upId + _lineIndex}' as jskey`) + + return `Select ${vals.join(',')}` + }) + + _Ltext = _Ltext.join(' Union all ') + + let _sql = '' + + if (item.intertype === 'inner' && !item.innerFunc) { + let _uniquesql = '' + if (btn.uniques && btn.uniques.length > 0) { + btn.uniques.forEach(unique => { + if (unique.status === 'false') return + + let _fields = unique.field.split(',') + let _fields_ = _fields.map(_field => { + return `a.${_field}=b.${_field}` + }) + _fields_ = _fields_.join(' and ') + + if (unique.verifyType !== 'physical') { + _fields_ += ' and b.deleted=0' + } + + _uniquesql += ` + Set @tbid='' + Select top 1 @tbid=${_fields.join('+\' \'+')} from (select 1 as n,${unique.field} from @${item.sheet} ) a group by ${unique.field} having sum(n)>1 + + If @tbid!='' + Begin + select @ErrorCode='${unique.errorCode}',@retmsg=@tbid+' 閲嶅' + goto aaa + end + + Set @tbid='' + Select top 1 @tbid=${_fields.join('+\' \'+')} from @${item.sheet} a + Inner join ${item.sheet} b on ${_fields_} + + If @tbid!='' + Begin + select @ErrorCode='${unique.errorCode}',@retmsg=@tbid+' 涓庡凡鏈夋暟鎹噸澶�' + goto aaa + end + ` + }) + + if (_uniquesql) { + _uniquesql = 'Declare @tbid Nvarchar(512)' + _uniquesql + } + } + + let declarefields = [] + let fields = [] + + btn.columns.forEach(col => { + declarefields.push(`${col.Column} ${col.type}`) + fields.push(col.Column) + }) + + fields = fields.join(',') + + let _insert = '' + + if (_prevCustomScript) { + _insert += _prevCustomScript + } + + if (btn.default !== 'false') { + _insert += ` + Insert into ${item.sheet} (${fields},createuserid,createuser,createstaff,bid) + Select ${fields},@userid@,@username,@fullname,@BID@ From @${item.sheet} + ` + } + + if (_backCustomScript) { + _insert += _backCustomScript + } + + _sql = `declare @${item.sheet} table (${declarefields.join(',')},jskey nvarchar(50) ) + Declare @UserName nvarchar(50),@FullName nvarchar(50),@ErrorCode nvarchar(50),@retmsg nvarchar(4000) + + Select @ErrorCode='', @retmsg='' + + select @UserName=UserName,@FullName=FullName from SUsers where UID=@UserID@ + ${_initCustomScript} + Insert into @${item.sheet} (${fields},jskey) + ${_Ltext} + ${_uniquesql} + ${_insert} + Delete @${item.sheet} + + aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg` + + } else { + _sql = _Ltext + } + + console.log(_sql) + return { + sql: _sql, + errors: errors.join('; ') + } + } + + /** + * @description 浣跨敤绯荤粺鍑芥暟鏃讹紙sPC_TableData_InUpDe 锛夛紝鐢熸垚sql璇彞 + * @return {String} type 鎵ц绫诲瀷 + * @return {String} table 琛ㄥ悕 + */ + static getSysDefaultSql (btn, setting, formdata, param, data, logcolumns, tab) { + let primaryId = param.ID + let BID = param.BID + let verify = btn.verify || {} + let _formFieldValue = {} + let _actionType = null + + if (verify.default !== 'false') { // 鍒ゆ柇鏄惁浣跨敤榛樿sql + _actionType = btn.sqlType + } + + let _initCustomScript = '' // 鍒濆鍖栬剼鏈� + let _prevCustomScript = '' // 榛樿sql鍓嶆墽琛岃剼鏈� + let _backCustomScript = '' // 榛樿sql鍚庢墽琛岃剼鏈� + + if (verify.scripts) { + verify.scripts.forEach(item => { + if (item.status === 'false') return + + if (item.position === 'init') { + _initCustomScript += ` + ${item.sql} + ` + } else if (item.position === 'front') { + _prevCustomScript += ` + ${item.sql} + ` + } else { + _backCustomScript += ` + ${item.sql} + ` + } + }) + } + + // 闇�瑕佸0鏄庣殑鍙橀噺闆� + // let _vars = ['tbid', 'ErrorCode', 'retmsg', 'BillCode', 'BVoucher', 'FIBVoucherDate', 'FiYear', 'UserName', 'FullName', 'ID', 'BID', 'LoginUID', 'SessionUid', 'UserID', 'Appkey'] + let _vars = ['tbid', 'errorcode', 'retmsg', 'billcode', 'bvoucher', 'fibvoucherdate', 'fiyear', 'username', 'fullname', 'modulardetailcode'] + + // 涓婚敭瀛楁 + let primaryKey = setting.primaryKey || 'id' + + // 绯荤粺鍙橀噺澹版槑涓庤缃垵濮嬪�� + let _sql = `Declare @tbid nvarchar(50),@ErrorCode nvarchar(50),@retmsg nvarchar(4000),@BillCode nvarchar(50),@BVoucher nvarchar(50),@FIBVoucherDate nvarchar(50), @FiYear nvarchar(50), @UserName nvarchar(50),@FullName nvarchar(50),@ModularDetailCode nvarchar(50) + ` + + // let _initvars = ['ID', 'BID', 'LoginUID', 'SessionUid', 'UserID', 'Appkey'] // 宸茶祴鍊煎瓧娈甸泦 + let _initvars = [] // 宸茶祴鍊煎瓧娈甸泦 + let _initfields = [] + let _declarefields = [] + + // 鑾峰彇瀛楁閿�煎 + if (formdata) { + formdata.forEach(form => { + _formFieldValue[form.key] = form.value + let _key = form.key.toLowerCase() + + if (!_initvars.includes(_key)) { + _initvars.push(_key) + + if (form.type === 'number' && typeof(form.value) === 'number') { + _initfields.push(`@${_key}=${form.value}`) + } else { + _initfields.push(`@${_key}='${form.value}'`) + } + } + + if (!_vars.includes(_key)) { + _vars.push(_key) + + if (form.fieldlen && form.fieldlen > 2048) { + form.fieldlen = 'max' + } + + let _type = `nvarchar(${form.fieldlen})` + + if (form.type.match(/date/ig)) { + _type = 'datetime' + } else if (form.type === 'number') { + _type = `decimal(18,${form.fieldlen})` + } + + _declarefields.push(`@${_key} ${_type}`) + } + }) + } + + // 娣诲姞鏁版嵁涓瓧娈碉紝琛ㄥ崟鍊间紭鍏�(鎸夐挳涓嶉�夎鏃惰烦杩�) + if (data && btn.Ot !== 'notRequired') { + _formFieldValue = {...data, ..._formFieldValue} + + if (logcolumns && logcolumns.length > 0) { + logcolumns.forEach(col => { + let _key = col.field.toLowerCase() + + if (!_initvars.includes(_key)) { + _initvars.push(_key) + + let _val = data.hasOwnProperty(col.field) ? data[col.field] : '' + + if (col.type === 'number' && typeof(_val) === 'number') { + _initfields.push(`@${_key}=${_val}`) + } else { + _initfields.push(`@${_key}='${_val}'`) + } + } + + if (!_vars.includes(_key)) { + _vars.push(_key) + + if (col.fieldlength && col.fieldlength > 2048) { + col.fieldlength = 'max' + } + + let _type = `nvarchar(${col.fieldlength || 50})` + + if (col.type === 'number') { + let _length = col.decimal ? col.decimal : 0 + _type = `decimal(18,${_length})` + } else if (col.type === 'picture' || col.type === 'textarea') { + _type = `nvarchar(${col.fieldlength || 512})` + } + + _declarefields.push(`@${_key} ${_type}`) + } + }) + } + } + + // 鍙橀噺澹版槑 + _declarefields = _declarefields.join(',') + if (_declarefields) { + _sql += `,${_declarefields} + ` + } + + // 鍙橀噺璧嬪�� + _initfields = _initfields.join(',') + if (_initfields) { + _sql += `select ${_initfields} + ` + } + + // 鍘婚櫎绂佺敤鐨勯獙璇� + if (verify.contrasts) { + verify.contrasts = verify.contrasts.filter(item => item.status !== 'false') + } + if (verify.uniques) { + verify.uniques = verify.uniques.filter(item => item.status !== 'false') + } + if (verify.customverifys) { + verify.customverifys = verify.customverifys.filter(item => item.status !== 'false') + } + if (verify.billcodes) { + verify.billcodes = verify.billcodes.filter(item => item.status !== 'false') + } + + let userName = sessionStorage.getItem('User_Name') || '' + let fullName = sessionStorage.getItem('Full_Name') || '' + + if (sessionStorage.getItem('isEditState') === 'true') { + userName = sessionStorage.getItem('CloudUserName') || '' + fullName = sessionStorage.getItem('CloudFullName') || '' + } + + // 鍒濆鍖栧嚟璇佸強鐢ㄦ埛淇℃伅瀛楁 + _sql += `select @BVoucher='',@FIBVoucherDate='',@FiYear='',@ErrorCode='',@retmsg='',@UserName='${userName}', @FullName='${fullName}' + ` + + if (_initCustomScript) { + _sql += _initCustomScript + } + + // 鍚敤璐︽湡楠岃瘉 + if (verify.accountdate === 'true') { + _sql += `exec s_FIBVoucherDateCheck @ErrorCode=@ErrorCode OUTPUT,@retmsg=@retmsg OUTPUT + if @ErrorCode!='' + GOTO aaa + ` + } + + // 澶辨晥楠岃瘉锛屾坊鍔犳暟鎹椂涓嶇敤 + if (btn.sqlType !== 'insert' && verify.invalid === 'true' && setting.dataresource) { + let datasource = setting.dataresource + if (/\s/.test(datasource)) { // 鎷兼帴鍒悕 + datasource = '(' + datasource + ') tb' + } + + _sql += `select @tbid='', @ErrorCode='',@retmsg='' + select @tbid=${primaryKey} from ${datasource} where ${primaryKey} ='${primaryId}' + If @tbid='' + Begin + select @ErrorCode='E',@retmsg='鏁版嵁宸插け鏁�' + goto aaa + end + ` + } + + // 姣旇緝楠岃瘉 + if (verify.contrasts && verify.contrasts.length > 0) { + verify.contrasts.forEach(item => { + _sql += `If ${item.frontfield} ${item.operator} ${item.backfield} + Begin + select @ErrorCode='${item.errorCode}',@retmsg='${item.errmsg}' + goto aaa + end + ` + }) + } + + // 鍞竴鎬ч獙璇侊紝蹇呴』瀛樺湪琛ㄥ崟锛堣〃鍗曞瓨鍦ㄦ椂锛屼富閿潎涓哄崟鍊硷級,蹇呴』濉啓鏁版嵁婧� + if (formdata && verify.uniques && verify.uniques.length > 0) { + let hasBid = false // 妫�楠岃〃鍗曞強鍒楀瓧娈典腑鏄惁鏈塨id + let _keys_ = Object.keys(_formFieldValue).map(key => key.toLowerCase()) + if (_keys_.includes('bid')) { + hasBid = true + } + + verify.uniques.forEach(item => { + let _fieldValue = [] // 琛ㄥ崟閿�煎field=value + let _value = [] // 琛ㄥ崟鍊硷紝鐢ㄤ簬閿欒鎻愮ず + let _labels = item.fieldlabel.split(',') // 琛ㄥ崟鎻愮ず鏂囧瓧 + let arr = [] // 楠岃瘉涓婚敭 + + item.field.split(',').forEach((_field, index) => { + let _fval = `'${_formFieldValue[_field]}'` + // if (['id', 'bid', 'loginuid', 'sessionuid', 'userid', 'appkey'].includes(_field.toLowerCase())) { + // _fval = '@' + _field + '@' + // } + if (_field.toLowerCase() === 'bid' && !hasBid) { // 琛ㄥ崟涓病鏈塨id鍒欎娇鐢ㄧ郴缁焍id鍙橀噺 + _fval = '@BID@' + } + arr.push(_field.toLowerCase()) + + _fieldValue.push(`${_field}=${_fval}`) + _value.push(`${_labels[index] || ''}锛�${_formFieldValue[_field] || ''}`) + }) + + let _verifyType = '' + if (item.verifyType === 'logic') { + _verifyType = ' and deleted=0' + } + + if (!arr.includes(primaryKey.toLowerCase())) { + _fieldValue.push(`${primaryKey} !='${primaryId}'`) + } + + _sql += `select @tbid='', @ErrorCode='',@retmsg='' + select @tbid='X' from ${btn.sql} where ${_fieldValue.join(' and ')}${_verifyType} + If @tbid!='' + Begin + select @ErrorCode='${item.errorCode}',@retmsg='${_value.join(', ')} 宸插瓨鍦�' + goto aaa + end + ` + }) + } + + // 鑷畾涔夐獙璇� + if (verify.customverifys && verify.customverifys.length > 0) { + verify.customverifys.forEach(item => { + _sql += `select @tbid='', @ErrorCode='',@retmsg='' + select top 1 @tbid='X' from (${item.sql}) a + If @tbid ${item.result === 'true' ? '!=' : '='}'' + Begin + select @ErrorCode='${item.errorCode}',@retmsg='${item.errmsg}' + goto aaa + end + ` + }) + } + + // 鍗曞彿鐢熸垚锛屼娇鐢ㄤ笂绾d锛圔ID锛夋垨鍒楄〃鏁版嵁锛屽0鏄庡彉閲忥紙妫�楠岋級 + let _billcodesSql = '' + if (verify.billcodes && verify.billcodes.length > 0) { + verify.billcodes.forEach(item => { + let _ModularDetailCode = '' + let _lpline = '' + if (item.TypeCharOne === 'Lp') { + if (item.linkField === 'BID' && BID) { // 鏇挎崲bid + _lpline = `set @ModularDetailCode= 'Lp'+ right('${item.mark || btn.uuid}'+@BID@,48)` + } else { + _lpline = `set @ModularDetailCode= 'Lp'+ right('${item.mark || btn.uuid}'+@${item.linkField},48)` + } + _ModularDetailCode = '@ModularDetailCode' + } else if (item.TypeCharOne === 'BN') { + let _val = '' + if (item.linkField === 'BID' && BID) { // 鏇挎崲bid + _val = BID + } else if (data && data.hasOwnProperty(item.linkField)) { + _val = data[item.linkField] + } + _ModularDetailCode = `'${item.TypeCharOne + _val}'` + } else { + _ModularDetailCode = `'${item.ModularDetailCode}'` + } + + let _declare = '' + let _key = item.field.toLowerCase() + + if (!_vars.includes(_key)) { + _declare = `Declare @${_key} nvarchar(50)` + _vars.push(_key) + } + + _billcodesSql += `${_declare} + select @BillCode='', @${_key}='', @ModularDetailCode='' + ${_lpline} + exec s_get_BillCode + @ModularDetailCode=${_ModularDetailCode}, + @Type=${item.Type}, + @TypeCharOne='${item.TypeCharOne}', + @TypeCharTwo ='${item.TypeCharTwo}', + @BillCode =@BillCode output, + @ErrorCode =@ErrorCode output, + @retmsg=@retmsg output + if @ErrorCode!='' + goto aaa + set @${_key}=@BillCode + ` + }) + + if (_actionType !== 'insertOrUpdate') { + _sql += _billcodesSql + } + } + + let hasvoucher = false + + // 鍑瘉-鏄剧ず鍒椾腑閫夊彇,蹇呴』閫夎 + if (verify.voucher && verify.voucher.enabled && data) { + let _voucher = verify.voucher + + hasvoucher = true + + _sql += `exec s_BVoucher_Create + @Bill ='${data[_voucher.linkField]}', + @BVoucherType ='${_voucher.BVoucherType}', + @VoucherTypeOne ='${_voucher.VoucherTypeOne}', + @VoucherTypeTwo ='${_voucher.VoucherTypeTwo}', + @Type =${_voucher.Type}, + @UserID=@UserID@, + @Username=@Username, + @FullName=@FullName, + @BVoucher =@BVoucher OUTPUT , + @FIBVoucherDate =@FIBVoucherDate OUTPUT , + @FiYear =@FiYear OUTPUT , + @ErrorCode =@ErrorCode OUTPUT, + @retmsg=@retmsg OUTPUT + if @ErrorCode!='' + GOTO aaa + ` + } + + let primaryKeyName = ['id', 'bid', 'loginuid', 'sessionuid', 'userid', 'appkey'].includes(primaryKey.toLowerCase()) ? primaryKey + '@' : primaryKey + + let _insertsql = '' + if (_actionType === 'insert' || _actionType === 'insertOrUpdate') { // 娣诲姞璇彞 + let keys = [] + let values = [] + + formdata.forEach(item => { + keys.push(item.key.toLowerCase()) + values.push('@' + item.key) + }) + + if (!keys.includes(primaryKey.toLowerCase())) { + keys.push(primaryKey.toLowerCase()) + values.push('\'' + primaryId + '\'') + } + if (!keys.includes('createuserid')) { + keys.push('createuserid') + values.push('@userid@') + } + if (!keys.includes('createuser')) { + keys.push('createuser') + values.push('@username') + } + if (!keys.includes('createstaff')) { + keys.push('createstaff') + values.push('@fullname') + } + if (!keys.includes('bid')) { + if (tab && tab.foreignKey && !keys.includes(tab.foreignKey.toLowerCase())) { + keys.push(tab.foreignKey) + } else { + keys.push('bid') + } + values.push('@BID@') + } else if (tab && tab.foreignKey && !keys.includes(tab.foreignKey.toLowerCase())) { + keys.push(tab.foreignKey) + values.push('@BID@') + } + + keys = keys.join(',') + values = values.join(',') + _insertsql = `insert into ${btn.sql} (${keys}) select ${values};` + } + + let _updatesql = '' + if (_actionType === 'update' || _actionType === 'insertOrUpdate') { // 淇敼璇彞 + let _form = [] + let _arr = [] + + formdata.forEach(item => { + _arr.push(item.key.toLowerCase()) + _form.push(item.key + '=@' + item.key) + }) + + if (!_arr.includes('modifydate')) { + _form.push('modifydate=getdate()') + } + if (!_arr.includes('modifyuserid')) { + _form.push('modifyuserid=@userid@') + } + if (hasvoucher) { + if (!_arr.includes('bvoucher')) { + _form.push('BVoucher=@BVoucher') + } + if (!_arr.includes('fibvoucherdate')) { + _form.push('FIBVoucherDate=@FIBVoucherDate') + } + if (!_arr.includes('fiyear')) { + _form.push('FiYear=@FiYear') + } + } + _form = _form.join(',') + _updatesql = `update ${btn.sql} set ${_form} where ${primaryKey}=@${primaryKeyName};` + } + + if (_prevCustomScript) { + _sql += _prevCustomScript + } + + // 娣诲姞銆佷慨鏀广�侀�昏緫鍒犻櫎銆佺墿鐞嗗垹闄� + if (_actionType === 'insert') { + _sql += _insertsql + } else if (_actionType === 'update') { + _sql += _updatesql + } else if (_actionType === 'LogicDelete') { // 閫昏緫鍒犻櫎 + _sql += `update ${btn.sql} set deleted=1,modifydate=getdate(),modifyuserid=@userid@ where ${primaryKey}=@${primaryKeyName};` + + } else if (_actionType === 'delete') { // 鐗╃悊鍒犻櫎 + let _msg = '' + if (data && logcolumns && logcolumns.length > 0) { + let _index = 0 + logcolumns.forEach(col => { + if (col.Hide !== 'true' && _index < 4) { + _msg += col.label + '=' + data[col.field] + ',' + _index++ + } + }) + } + _sql += `insert into snote (remark,createuserid,CreateUser,CreateStaff) select left('鍒犻櫎琛�:${btn.sql} 鏁版嵁: ${_msg}${primaryKey}='+@${primaryKeyName},200),@userid@,@username,@fullname delete ${btn.sql} where ${primaryKey}=@${primaryKeyName};` + } else if (_actionType === 'insertOrUpdate') { + _sql += `select @tbid='' + select @tbid='X' from ${btn.sql} where ${primaryKey}=@ID@ + if @tbid='' + begin + ${_billcodesSql} + ${_insertsql} + end + else + begin + ${_updatesql} + end + ` + } + + if (_backCustomScript) { + _sql += _backCustomScript + } + + _sql += ` + aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg` + console.log(_sql) + return _sql + } + + /** + * @description 鍒犻櫎瀛樺偍杩囩▼sql + * @return {String} name 瀛樺偍杩囩▼鍚嶇О + */ + static dropfunc (name) { + return `IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID('${name}') AND type in (N'P', N'PC')) mdrpk PROCEDURE ${name}` + } + + /** + * @description 鍒涘缓椤甸潰瀛樺偍杩囩▼ + * @return {String} + */ + static getTableFunc (param, menu, config) { + let form = '' + let formParam = '' + let _vars = ['bid', 'pageindex', 'pagesize', 'ordercol', 'ordertype', 'exceltype', 'septmenuno', 'lang', 'debug', 'loginuid', 'sessionuid', 'userid', 'errorcode', 'retmsg'] + let _columns = [] + let primaryKey = config.setting.primaryKey || 'ID' + + if (!_vars.includes(primaryKey.toLowerCase())) { + _vars.push(primaryKey.toLowerCase()) + formParam = `mchr13k@${primaryKey} nvarchar(50)='',` + } + + if (config.search && config.search.length > 0) { + let _fields = new Map() + config.search.forEach(item => { + if (item.field) { + let type = '' + + if (item.type.match(/date/ig)) { + type = 'datetime=null' + } else { + type = 'nvarchar(50)=\'\'' + } + + item.field.split(',').forEach(cell => { + let _f = cell + if (_fields.has(cell)) { + _f = _f + '1' + } + + _fields.set(cell, true) + + if (!_vars.includes(_f.toLowerCase())) { + _vars.push(_f.toLowerCase()) + formParam = formParam + `mchr13k@${_f} ${type},` + } + }) + } + }) + } + + if (config.columns && config.columns.length > 0) { + config.columns.forEach(item => { + if (item.field) { + _columns.push(`${item.field} as ${item.label}`) + } + }) + + form = ` + declare @dc table (${_columns.join(',')}) + + @tableid ='${menu.MenuID}' + ` + } + + let Ltext = `create proc ${param.innerFunc} + ( /*${menu.MenuName}*/ + @appkey nvarchar(50)='', + @BID nvarchar(50)='',${formParam} + @PageIndex nvarchar(50)='', + @PageSize nvarchar(50)='', + @OrderCol nvarchar(50)='', + @OrderType nvarchar(50)='', + @exceltype nvarchar(50)='', + @sEPTMenuNo nvarchar(50)='${menu.MenuNo}', + @lang nvarchar(50)='', + @debug nvarchar(50)='', + @LoginUID nvarchar(50)='', + @SessionUid nvarchar(50)='', + @UserID nvarchar(50), + @ErrorCode nvarchar(50) out, + @retmsg nvarchar(4000) out + ) + as + begin + declare @BegindateTest datetime,@EnddateTest datetime + select @BegindateTest=getdate() + set @ErrorCode='' + set @retmsg='' + BEGIN TRY + /*浜嬪姟鎿嶄綔*/ + BEGIN TRAN + /*鍏蜂綋涓氬姟鎿嶄綔*/ + + /* + select top 10 * from sProcExcep order by id desc + + declare @UserName nvarchar(50),@FullName nvarchar(50) + + select @UserName=UserName,@FullName=FullName from SUsers where UID=@UserID + ${form} + if 1=2 + begin + set @ErrorCode='E' + set @retmsg='鍦ㄦ鍐欐姤閿�' + goto GOTO_RETURN + end + + insert into sNote (remark,createuserid,CreateUser,CreateStaff) + select '鍦ㄦ鍐欐棩蹇�',@UserID,@UserName,@FullName + */ + + COMMIT TRAN + SET NOCOUNT ON + RETURN + END TRY + BEGIN CATCH + /*閿欒澶勭悊*/ + ROLLBACK TRAN + DECLARE @ErrorMessage NVARCHAR(4000); + DECLARE @ErrorSeverity INT; + DECLARE @ErrorState INT; + + /*鎶婅嚜瀹氫箟鐨勫弸濂界殑閿欒淇℃伅鎻愮ず鍔犱笂*/ + set @ErrorCode=cast(ERROR_NUMBER() as nvarchar(50)) + SET @retmsg=ERROR_MESSAGE(); + SELECT @ErrorMessage=ERROR_MESSAGE(), + @ErrorSeverity=ERROR_SEVERITY(), + @ErrorState=ERROR_STATE(); + + RAISERROR(@ErrorMessage, /*-- Message text.*/ + @ErrorSeverity, /*-- Severity.*/ + @ErrorState /*-- State.*/ + ); + END CATCH + + GOTO_RETURN: + ROLLBACK TRAN + + END` + + Ltext = Ltext.replace(/\n\s{4}/ig, 'mchr13k') + + return Ltext + } + + /** + * @description 鍒涘缓瀛樺偍杩囩▼ + * @return {String} + */ + static getfunc (param, btn, menu, config) { + let form = '' + let formParam = '' + let _vars = ['bid', 'septmenuno', 'lang', 'debug', 'loginuid', 'sessionuid', 'userid', 'errorcode', 'retmsg'] + let columns = config.columns + let primaryKey = config.setting.primaryKey || 'ID' + + if (!_vars.includes(primaryKey.toLowerCase())) { + _vars.push(primaryKey.toLowerCase()) + formParam = `mchr13k@${primaryKey} nvarchar(50)='',` + } + + if (param.fields && param.fields.length > 0) { + let _fields = [] + param.fields.forEach(item => { + if (item.field) { + let type = '' + if (item.type.match(/date/ig)) { + type = 'datetime=null' + } else if (item.type === 'number') { + type = `decimal(18,${item.decimal})=0` + } else { + type = 'nvarchar(50)=\'\'' + } + + if (!_vars.includes(item.field.toLowerCase())) { + _vars.push(item.field.toLowerCase()) + formParam = formParam + `mchr13k@${item.field} ${type},` + } + + _fields.push(item.field) + } + }) + + let field1 = _fields.join(',') + let field2 = _fields.join(',@') + let field3 = _fields.map(cell => { + return cell + '=@' + cell + }) + + field2 = field2 ? '@' + field2 : '' + field3 = field3.join(',') + + form = ` + insert into ${param.name} (${field1},createuserid) select ${field2},@UserID + + update ${param.name} set ${field3},modifydate=getdate(),modifyuserid=@UserID + ` + } else if (btn.OpenType === 'prompt' || btn.OpenType === 'exec') { + form = ` + update ${param.name} set ModifyDate=getdate(),ModifyUserID=@UserID where ${primaryKey}=@${primaryKey} + ` + } + + if (columns) { + let _col = [] + let _field = [] + columns.forEach(col => { + if (col.field) { + if (col.type === 'number') { + _col.push(col.field + ' decimal(18,2)') + } else { + _col.push(col.field + ' nvarchar(50)') + } + _field.push(col.field) + } + }) + _col = _col.join(',') + _field = _field.join(',') + + form = form + ` + declare @dc table (${_col}) + + insert into @dc (${_field}) + + @tableid ='${menu.MenuID}' + ` + } + + // 鎵撳嵃鑷畾涔夋ā鏉垮瓧娈垫彁绀� + let _printRemark = '' + if (btn.funcType === 'print') { + _printRemark = '/* 鑷畾涔夋暟鎹墦鍗版ā鏉挎椂锛岃浣跨敤TemplateID瀛楁 */' + } + + let Ltext = `create proc ${param.funcName} + ( /*${menu.MenuName} ${btn.label}*/ + @appkey nvarchar(50)='', + @BID nvarchar(50)='',${formParam} + @sEPTMenuNo nvarchar(50)='${param.menuNo}', + @lang nvarchar(50)='', + @debug nvarchar(50)='', + @LoginUID nvarchar(50)='', + @SessionUid nvarchar(50)='', + @UserID nvarchar(50), + @ErrorCode nvarchar(50) out, + @retmsg nvarchar(4000) out + ) + as + begin + declare @BegindateTest datetime,@EnddateTest datetime + select @BegindateTest=getdate() + set @ErrorCode='' + set @retmsg='' + BEGIN TRY + /*浜嬪姟鎿嶄綔*/ + BEGIN TRAN + /*鍏蜂綋涓氬姟鎿嶄綔*/ + ${_printRemark} + /* + select top 10 * from sProcExcep order by id desc + + declare @UserName nvarchar(50),@FullName nvarchar(50) + + select @UserName=UserName,@FullName=FullName from SUsers where UID=@UserID + ${form} + if 1=2 + begin + set @ErrorCode='E' + set @retmsg='鍦ㄦ鍐欐姤閿�' + goto GOTO_RETURN + end + + insert into sNote (remark,createuserid,CreateUser,CreateStaff) + select '鍦ㄦ鍐欐棩蹇�',@UserID,@UserName,@FullName + */ + + COMMIT TRAN + SET NOCOUNT ON + RETURN + END TRY + BEGIN CATCH + /*閿欒澶勭悊*/ + ROLLBACK TRAN + DECLARE @ErrorMessage NVARCHAR(4000); + DECLARE @ErrorSeverity INT; + DECLARE @ErrorState INT; + + /*鎶婅嚜瀹氫箟鐨勫弸濂界殑閿欒淇℃伅鎻愮ず鍔犱笂*/ + set @ErrorCode=cast(ERROR_NUMBER() as nvarchar(50)) + SET @retmsg=ERROR_MESSAGE(); + SELECT @ErrorMessage=ERROR_MESSAGE(), + @ErrorSeverity=ERROR_SEVERITY(), + @ErrorState=ERROR_STATE(); + + RAISERROR(@ErrorMessage, /*-- Message text.*/ + @ErrorSeverity, /*-- Severity.*/ + @ErrorState /*-- State.*/ + ); + END CATCH + + GOTO_RETURN: + ROLLBACK TRAN + + END` + + Ltext = Ltext.replace(/\n\s{4}/ig, 'mchr13k') + + return Ltext + } + + /** + * @description 鍒涘缓瀵煎叆瀛樺偍杩囩▼ + * @return {String} + */ + static getexcelInfunc (param, btn, menu) { + let _verify = btn.verify + + let _uniquesql = '' + if (_verify.uniques && _verify.uniques.length > 0) { + _verify.uniques.forEach(unique => { + if (unique.status === 'false') return + + let _fields = unique.field.split(',') + let _fields_ = _fields.map(_field => { + return `a.${_field}=b.${_field}` + }) + _fields_ = _fields_.join(' and ') + + if (unique.verifyType !== 'physical') { + _fields_ += ' and b.deleted=0' + } + + _uniquesql += ` + Set @tbid='' + Select top 1 @tbid=${_fields.join('+\' \'+')} from (select 1 as n,${unique.field} from @${btn.sheet} ) a group by ${unique.field} having sum(n)>1 + + If @tbid!='' + Begin + select @ErrorCode='${unique.errorCode}',@retmsg=@tbid+' 閲嶅' + goto aaa + end + + Set @tbid='' + Select top 1 @tbid=${_fields.join('+\' \'+')} from @${btn.sheet} a + Inner join ${btn.sheet} b on ${_fields_} + + If @tbid!='' + Begin + select @ErrorCode='${unique.errorCode}',@retmsg=@tbid+' 涓庡凡鏈夋暟鎹噸澶�' + goto aaa + end + ` + }) + + if (_uniquesql) { + _uniquesql = ` + Declare @tbid Nvarchar(512) + ${_uniquesql}` + } + } + + let declarefields = [] + let fields = [] + + _verify.columns.forEach(col => { + declarefields.push(`${col.Column} ${col.type}`) + fields.push(col.Column) + }) + + fields = fields.join(',') + + let _sql = `declare @${btn.sheet} table (${declarefields.join(',')},jskey nvarchar(50)) + Declare @UserName nvarchar(50),@FullName nvarchar(50) + + select @UserName=UserName,@FullName=FullName from SUsers where UID=@UserID + + Insert into @${btn.sheet} (${fields},jskey) + + exec s_KeyWords_Replace + @LText=@LText, @BID=@BID,@LoginUID=@LoginUID,@SessionUid=@SessionUid,@UserID=@UserID,@ID=@ID + ${_uniquesql} + Insert into ${btn.sheet} (${fields},createuserid,createuser,createstaff,bid) + Select ${fields},@userid,@username,@fullname,@BID From @${btn.sheet} + + Delete @${btn.sheet}` + + let Ltext = `create proc ${param.funcName} + ( /*${menu.MenuName} ${btn.label}*/ + @appkey nvarchar(50)='', + @ID nvarchar(50)='', + @BID nvarchar(50)='', + @Ltext nvarchar(max)='', + @sEPTMenuNo nvarchar(50)='${param.menuNo}', + @secretkey nvarchar(50)='', + @timestamp nvarchar(50)='', + @lang nvarchar(50)='', + @LoginUID nvarchar(50)='', + @SessionUid nvarchar(50)='', + @UserID nvarchar(50), + @ErrorCode nvarchar(50) out, + @retmsg nvarchar(4000) out + ) + as + begin + declare @BegindateTest datetime,@EnddateTest datetime + select @BegindateTest=getdate() + set @ErrorCode='' + set @retmsg='' + BEGIN TRY + /*浜嬪姟鎿嶄綔*/ + BEGIN TRAN + /*鍏蜂綋涓氬姟鎿嶄綔*/ + + /* + ${_sql} + */ + + COMMIT TRAN + SET NOCOUNT ON + RETURN + END TRY + BEGIN CATCH + /*閿欒澶勭悊*/ + ROLLBACK TRAN + DECLARE @ErrorMessage NVARCHAR(4000); + DECLARE @ErrorSeverity INT; + DECLARE @ErrorState INT; + + /*鎶婅嚜瀹氫箟鐨勫弸濂界殑閿欒淇℃伅鎻愮ず鍔犱笂*/ + set @ErrorCode=cast(ERROR_NUMBER() as nvarchar(50)) + SET @retmsg=ERROR_MESSAGE(); + SELECT @ErrorMessage=ERROR_MESSAGE(), + @ErrorSeverity=ERROR_SEVERITY(), + @ErrorState=ERROR_STATE(); + + RAISERROR(@ErrorMessage, /*-- Message text.*/ + @ErrorSeverity, /*-- Severity.*/ + @ErrorState /*-- State.*/ + ); + END CATCH + + GOTO_RETURN: + ROLLBACK TRAN + + END` + + Ltext = Ltext.replace(/\n\s{4}/ig, 'mchr13k') + + return Ltext + } +} \ No newline at end of file diff --git a/src/utils/utils.js b/src/utils/utils.js index 2a4bd06..eed79e0 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -74,7 +74,7 @@ ] if (type === 'customscript') { - chars = chars.map(char => !['insert', 'delete', 'update', 'set', 'if', 'exec'].includes(char.key)) + chars = chars.filter(char => !['insert', 'delete', 'update', 'set', 'if', 'exec'].includes(char.key)) } let error = '' -- Gitblit v1.8.0